Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The RixBxdf interface characterizes the light-scattering behavior (sometimes referred to as material response) for a given point on the surface of an object.

Implementing the RixBxdfFactory Interface

RixBxdfFactory is a subclass of RixShadingPlugin, and therefore shares the same initializationsynchronization, and parameter table logic as other shading plugins. Therefore to start developing your own Bxdf, you can #include "RixBxdf.h" and make sure your bxdf factory class implements the required methods inherited from the RixShadingPlugin interface: Init()Finalize()Synchronize(), GetParamTable(), and CreateInstanceData().

Integrators (RixIntegrator) use RixBxdfFactory objects by invoking RixBxdfFactory::BeginScatter()  to obtain a  RixBxdf. Because a RixBxdf is expected to be a lightweight object that may be created many times over the course of the render, RixBxdfFactory is expected to take advantage of the lightweight instancing services provided by RixShadingPlugin. In particular, BeginScatter() is provided a pointer to an instance data that is created by RixBxdfFactory::CreateInstanceData(), which is called once per unique shading plugin instance, as defined by the unique set of parameters supplied to the material description. It is expected that the instance data will point to a private cached representation of any expensive setup which depends on the parameters, and BeginScatter() will reuse this cached representation many times over the course of the render to create RixBxdf objects.

The RIX_BXDFPLUGINCREATE() macro defines the CreateRixBxdfFactory() method, which is called by the renderer to create an instance of the bxdf plugin. Generally, the implementation of this method should simply return a new allocated copy of your bxdf factory class. Similarly, the RIX_BXDFPLUGINDESTROY() macro defines the DestroyRixBxdfFactory()  method called by the renderer to delete an instance of the bxdf plugin; a typical implementation of this method is to delete the passed in bxdf pointer:

Code Block
languagecpp
    RIX_BXDFPLUGINCREATE
    {
        return new MyBxdfFactory();
    }
    RIX_BXDFPLUGINDESTROY
    {
        delete ((MyBxdfFactory*)bxdf);
    }

RixBxdfFactory::BeginScatter()

As mentioned above, integrators invoke RixBxdfFactory  is expected to invoke  RixShadingContext::EvalParamBeginScatter() to invoke the relevant bxdf parameters. The bxdf acts as a closure, associated with a given shading context.  BeginScatter() will typically call a Bxdf constructor which will get the necessary to obtain a RixBxdf. The renderer's operating model is that the Bxdf that is obtained this way is a closure, with the closure functions being GenerateSampleEvaluateSample, and EmitLocal. Any computations that the Bxdf needs to efficient evaluate its closure functions should be computed inside RixBxdfFactory::BeginScatter(), and then saved in the overridden RixBxdf class. Critically, these computations include upstream evaluation of any pattern networks. Therefore, it is typical for BeginScatter() to invoke  RixShadingContext::EvalParam() in order to evaluate the relevant bxdf input parameters, and then pass the pointers returned from EvalParam to the Bxdf constructor. Since Bxdfs also generally require built-in variables such as the shading normal (Nn), geometric normal (Ngn), and viewing direction, either BeginScatter(Vn), etc., by calling the ) or the Bxdf constructor itself will need to call RixShadingContext::GetBuiltinVar() function for each such built-in variable.

The following code demonstrates a trivial constant Bxdf's implementation of BeginScatter(). Here, the parameter id for the emission color is passed to EvalParam() in order to get a pointer emitColor that is passed to the ConstantBxdf() constructor.

Code Block
languagecpp
RixBxdf *
PxrConstant::BeginScatter(RixShadingContext const *sCtx,
                          RixBXLobeTraits const &lobesWanted,
                          RixSCShadingMode sm,
                          RtPointer instanceData)
{
    // Get all input data
    RtColorRGB const* emitColor; 
    sCtx->EvalParam(k_emitColor, -1, &emitColor, &m_emitColor, true);
    RixShadingContext::Allocator pool(sCtx);
    void *mem = pool.AllocForBxdf<ConstantBxdf>(1);
    ConstantBxdf *eval = new (mem) ConstantBxdf(sCtx, this, lobesWanted, emitColor);
    return eval;
}


RixBxdf

Once a RixBxdf object is obtained, the integrator may invoke the following methods:

...