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 ); }