| Physically Plausible Shading | 
| Introduction
			Over and above the complications of writing RSL2 shaders - compared to 
			writing classic shaders - coding a physically plausible shader presents a 
			significant challenge because of the need to understand the order in 
			which shader methods are called and how data is 
			accumulated as a result of a material, light sources and Pixar's "integrators"
			working cooperatively to form a shading pipeline.
			 public void diffuselighting(output color Ci, Oi) {
    printf("material: diffuselighting() start\n");
    printf("material: diffuselighting() calling directlighting()\n");
    Ci += directlighting(this, getlights());
    if(diffuseSamples > 0) {
        printf("material: diffuselighting() calling indirectspecular()\n");
        Ci += m_diffuse->m_diffColor * indirectdiffuse(P, m_shadingCtx->m_Nn, 
                                                               diffuseSamples);
        }
    printf("material: diffuselighting() finish\n");
    }
			The helloAS.sl (uses the Ashikhmin/Shirley shading model) and 
			plausibleArealight.sl source files were copied to Cutter's rsl source 
			directory and re-compiled.
			 
			 The rib file shown below was used to generate the output of the printf() statements. To reduce the quantity of text the material shader was assigned to a single point - it is shaded only once when the hider is set to "hidden". Listing 1 (dataflow.rib) 
 Because the edited versions of helloAS.sl and plausibleArealight.sl also printed the values of the data contained in the array of __radiancesample structs the "min" and "max" sampling of light were reduced to 4 and 8. Likewise, the rib values of "specularSamples" and "diffuseSamples" were reduced. | 
| private void printRadianceSamples(string label; __radiancesample samples[]) {
    uniform float i;
    if(m_print == 0)
        return;    
    printf("-----------%s------------\n", label);
    for(i = 0; i < arraylength(samples); i += 1) {
        printf("direction %1.3p\n", samples[i]->direction);
        printf("radiance %c\n", samples[i]->radiance);
        printf("materialResponse %c\n", samples[i]->materialResponse);
        printf("accumulatedMaterialResponse %c\n", samples[i]->accumulatedMaterialResponse);
        }
    printf("----------------------------\n");
    } | 
| The Calling of Pipeline Methods | 
| The pipeline methods implemented by plausibleArealight.sl are:     public void light(output vector L; output color Cl)
    public void construct()
    public void begin()
    public void prelighting(output color Ci, Oi)
    public void generateSamples(string integrationdomain; output __radiancesample rsamples [])
    public void evaluateSamples(string integrationdomain; output __radiancesample rsamples[])
The pipeline methods implemented by helloAS.sl are:     public void construct()
    public void begin()
    public void prelighting(output color Ci, Oi);
    public void lighting(output color Ci, Oi)
    public void diffuselighting(output color Ci, Oi)
    public void specularlighting(output color Ci, Oi)
    public void evaluateSamples(string distribution; output __radiancesample samples[])
    public void generateSamples(string type; output __radiancesample samples[]) | 
| The output of the printf() statements is shown below. The pipeline methods of helloAS.sl and plausibleArealight.sl are shown in blue while the integrator, and other RSL functions, that are called by the pipeline methods are shown in red. RENDER BEGIN________
light::construct()
material::construct()
material::begin()
material::prelighting()
material::lighting() start
material::lighting()   -calling directlighting()
   [directlighting() requests a list of samples from the material. Each
    sample represents a direction (vector). Later in the pipeline the light
    shader will calculate how much of its overall illumination contributes
    to the color of the light hitting a surface for each sample direction]
    material::generateSamples() start
    material::generateSamples()   -calling genSpecularSamps()
    material::generateSamples()   -genSpecularSamps() generated 4 samples
    material::generateSamples() finish
   [directlighting() next requests a list of samples from the light. Each
    sample represents a direction and a (radiance) color]
    light::begin()
    light::generateSamples() start
    light::generateSamples()   -generated 8 samples
    light::generateSamples() finish
   [directlighting() next requests a list of samples from the material. 
    Each sample represents the diffuse (materialResponse) color]
    material::evaluateSamples() start
    material::evaluateSamples()   -calling evalDiffuseSamps()
    material::evaluateSamples()   -8 samples were evaluated
    material::evaluateSamples() finish
   [directlighting() finally requests another list of samples from the 
    material. Each sample represents the combination of the diffuse 
    and specular contributions (accumulatedMaterialResponse) color]
    material::evaluateSamples() start
    material::evaluateSamples()   -calling evalSpecularSamps()
    material::evaluateSamples()   -8 samples were evaluated
    material::evaluateSamples() finish
    light::shadowSamples() start
    light::shadowSamples() finish
    light::evaluateSamples() start
    light::evaluateSamples() finish
    light::shadowSamples() start
    light::shadowSamples() finish
    material::lighting() directlighting() generated 4 samples
    material::lighting()   -calling indirectspecular()()
    material::lighting()   -indirectspecular() generated 4 samples
    material::lighting()   -calling indirectdiffuse()
material::lighting() finish
RENDER END__________
 | 
| Mixing Pipeline Methods and Hider Options
			The dataflow.rib file was rendered alternatively using, 
               lighting()   diffuselighting()   specularlighting()
    "hidden"      1               0                    0
    "raytrace"    0               1                    86
                            diffuselighting()   specularlighting()
    "hidden"                      1                    1
    "raytrace"                    1                    86
               lighting()   diffuselighting()   
    "hidden"      1               0                 
    "raytrace"    87              1                  
               lighting()                       specularlighting()
    "hidden"      1                                    0
    "raytrace"    87                                   0
 | ||
| Pipeline Methods and the Accumulation of Data
			The helloAS shader uses instances of several structs (aka databases) in which it 
			stores and manipulates data. This section looks at the use of the __radiancesample
			struct defined in,
			 
-----------MATERIAL generateSamples------------
    direction 0, 0, 0
    radiance 0, 0, 0
    materialResponse 0, 0, 0
    accumulatedMaterialResponse 0, 0, 0
    4 samples in total
-----------LIGHT generateSamples------------
    direction -0.497, 0.321, -0.806
    radiance 2, 2, 2
    materialResponse 0, 0, 0
    accumulatedMaterialResponse 0, 0, 0
    8 samples in total
-----------MATERIAL evaluateSamples------------
    direction -0.497, 0.321, -0.806121
    radiance 2, 2, 2
    materialResponse 0.0392593, 0.0392593, 0.0392593
    accumulatedMaterialResponse 0, 0, 0
    8 diffuse samples in total
-----------MATERIAL evaluateSamples------------
    direction -0.497085, 0.321053, -0.806121
    radiance 2, 2, 2
    materialResponse 0, 0, 0
    accumulatedMaterialResponse 0.0822628, 0.0822628, 0.0822628
    8 specular samples in total
 | 
© 2002- Malcolm Kesson. All rights reserved.