Adding child nodes

Introduction

../../_images/childnodesgui.png

Editing a SDK object child nodes

You may add child nodes to your type plugins, which are fully integrated in the graphical user interface and in the file formats, so that your plugin may use other ocean nodes.

This is done by overloading the functions addChildren. You also need to overload and prepare to retrieve pointers to the child nodes during initialization.

Example

We will show how to add a parameter to our BSDF plugin example. The original example had a fixed grey color, we would like the user to freely choose the color and reflectance level.

We start from the previous plugin code, copying the files to test2bsdf.cpp, test2bsdf.h, and the class to Test2Bsdf.

Implementation

addChild function

In IBsdfPlugin::addChildren(), we declare the child node, as a Filter shader, with a name “color”, and a default type Uniform filter shader;

void Test2Bsdf::addChildren(Ocean::Sdk::IAddChildContext * iChildAdd)
{
     iChildAdd->addFilterShader("color", "uniform");
}

prepare function

In IBsdfPlugin::prepare(), we retrieve a pointer on the child node.

As the shader is required in our example, we signal an error if we get a null pointer.

bool Test2Bsdf::prepare(const Ocean::Sdk::IPrepareContext * iPrepare)
{
     colorShader = iPrepare->getFilterShaderChild("color");
     return (colorShader!=0);
}

getValues function

In IBsdfPlugin::getValues(), instead of using R0 as the base reflection, we will use the shader values. We first ask the child shader to store its value in dest:

colorShader->getValues(dest, context);

Then we compute fr for each wavelength and store it in dest:

//Schlicks approximation
float omz5 = omz*omz*omz*omz*omz;
for(uint32_t i=0;i<n;++i)
{
    float R0 = dest[i];
    float fr = R0 + (1.0f-R0)*omz5;
    dest[i] = fr;
}

We do not multiply glossy by fr yet:

float glossy =   (e+1)*0.125f*M_1_PIf
               * std::pow(std::abs(ht[2]),e)
             / ( (kLt|ht) * std::max(cosL, cosE) );

We set the final BSDF values into dest:

for(uint32_t i=0;i<n;++i)
{
     dest[i] = dest[i]*glossy;
}

No change is required to sampling and pdf functions.

We then implement IBsdfPlugin::getParameters to declare the axis, as a vector parameter which is normalized (see IParamList::addUnitVector)

decay function

The decay depends on reflectance, thus on the diffuse shader. We use IFilterShader::decay return value as R0 for the decay calculation:

float Test2Bsdf::decay(const Ocean::Sdk::IShaderContext * context, const Vec3<float> & k1t) const
{
     //Schlicks approximation
     float omz = 1.0f-std::fabs(k1t[2]);
     float R0 = colorShader->decay(context);
     float fr = R0 + (1.0f-R0)*omz*omz*omz*omz*omz;
     return fr;
}

Result

The image shows the result with a red reflectance:

../../_images/childnodes.jpg

Example of a procedural environment plugin

Environment definition:

<material type="generic" name="previewmaterial">
     <bsdf type="sdktest/test2" name="bsdf">
             <filtershader type="uniform" name="color">
                     <spectrum type="rgb" name="spectrum" rgb="0.8 0.25 0" gamma="2.2"/>
             </filtershader>
     </bsdf>
</material>