...
As mentioned above, integrators invoke RixBxdfFactory::BeginScatter()
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 GenerateSample
, EvaluateSample
, and EmitLocaland EmitLocal
. Any Any computations that the Bxdf needs need in order to efficient evaluate its closure functions should be computed once 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 geometric data, or built-in variables, such as the shading normal, geometric normal, and viewing direction, either BeginScatter()
or the Bxdf constructor itself will need to call RixShadingContext::GetBuiltinVar()
function for each such built-in variable.
...
Code Block | ||
---|---|---|
| ||
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; } |
In the following code from PxrDiffuse
, we demonstrate how its constructor sets up required geometric information that is later on used for sample generation and evaluation.
Code Block | ||
---|---|---|
| ||
PxrDiffuse(RixShadingContext const *sc, RixBxdfFactory *bx,
RixBXLobeTraits const &lobesWanted,
RtColorRGB const *emit,
RtColorRGB const *diff,
RtColorRGB const *trans,
RtNormal3 const *bumpNormal) :
RixBxdf(sc, bx),
m_lobesWanted(lobesWanted),
m_emit(emit),
m_diffuse(diff),
m_transmission(trans),
m_bumpNormal(bumpNormal)
{
RixBXLobeTraits lobes = s_reflDiffuseLobeTraits | s_albedoLobeTraits;
if (m_transmission)
lobes |= s_tranDiffuseLobeTraits;
m_lobesWanted &= lobes;
sc->GetBuiltinVar(RixShadingContext::k_P, &m_P);
if(m_bumpNormal)
m_Nn = bumpNormal;
else
sc->GetBuiltinVar(RixShadingContext::k_Nn, &m_Nn);
sc->GetBuiltinVar(RixShadingContext::k_Ngn, &m_Ngn);
sc->GetBuiltinVar(RixShadingContext::k_Tn, &m_Tn);
sc->GetBuiltinVar(RixShadingContext::k_Vn, &m_Vn);
}
|
BeginScatter()
is passed an instance data pointer created via CreateInstanceData
that can be used to cache and reuse certain calculations common amongst all factory instances of the same Bxdf; for more information, please consult the lightweight instancing discussion in RixShadingPlugin
.
BeginScatter()
is also passed two parameters that can be used as hints to optimize the calculation. RixBXLobeTraits const &lobesWanted
is a description of the Bxdf lobes that the renderer expects to generate or evaluate; this parameter can be used to avoid any computations not necessary for the requested lobes. RixSCShadingMode
will take either the value k_RixSCScatterQuery
, indicating that the factory should construct a Bxdf for scattering on the surface, or k_RixSCVolumeScatterQuery
, indicating that a Bxdf should be constructed for scattering on the inside of a volume.
RixBxdf
Once a RixBxdf
object is obtained, the integrator may invoke the following methods:
...