Use virtual functions for variable inquiry. In the previous example, when the drawing port wants to know what variables a shader pipeline needs, it calls ShaderA::NeedNormal. The implementation of NeedNormal (shown in the code below) searches through all of the NeedNormal functions of the shaders in the pipeline and returns a correct Boolean value. The drawing port only calls this function once for a surface.
virtual Boolean ShaderA::NeedNormal()
{
//When NeedNormalForMyself is TRUE, the function returns.
return NeedNormalForMyself || GetChild()>NeedNormal();
}
To ensure that you design exceptionsafe shaders in a shader pipeline, construct a local instance that resides in the implementation of ComputeShade for swapping the variables to be modified. The exception handler calls the destructor when a software exception is raised, but the data in TShadingSample remains valid. The following code example defines the TSwapVariable class and rewrites ShaderB::ComputeShade to do an exceptionsafe swap.
class TSwapVariables
{
TSwapVariables( TShadingSample& shadingSample )
{
//Save variables
}
~TSwapVariables()
{
//Restore variables
}
};
shaderB::ComputeShade( TShadingSample& sSample, const TSceneBundle& )
{
TSwapVariables( TShadingSample* sSample );
*( sSample.fBaseColor ) *= 3.;
sSample.fShadingNormal *= 1.;
fShaderC>ComputeShade( TShadingSample& sSample, const TSceneBundle );
}