RMS (pre version 18)
Subsurface Blockers & HyperShade

return to main index


This tutorial outlines a technique for applying blockers to a material with subsurface scattering attributes. The effect is shown in figures 1 and 2.

Figures 1 & 2
The blocking geometry in Maya and its effect in the final render.

Subsurface blocking can be achieved only if the blocking geometry bakes negative rgb radiance (aka brighness) values into the same pointcloud that is baked by the "host" SSS geometry's material. In order for primitives to "share" the same pointcloud they must use the same shadinggroup. Unfortunately, because the "host" SSS object bakes positive rgb radiance values into a pointcloud, the blocking geometry must be assigned its own shadinggroup and, consequently, it will be baked into a different pointcloud - a catch 22 situation "solved" by the custom shader presented in listing 1.

The shader works by explicitely baking data to a pointcloud whose path is specified by the parameter Bakename. However, the path must match that of the pointcloud being baked by the "host" geometry's shadinggroup. As explained next, the value of the Bakename parameter is given indirectly via a TCL expression.

Listing 1 (sssBlocker.sl)

sssBlocker(float   red = 1.2,   /* [label "Red" collection Absorption ] */
                   green = 1.5, /* [label "Green" collection Absorption] */
                   blue = 1.5,  /* [label "Blue" collection Absorption] */
                   Krgb = 1.0;  /* [label "Absorption Strength" collection Absorption 1 5 ] 
                                    The strength of the blocking will depend on the size <br>
                                    and placement of the blocking geometry to which this shader
                                    is attahced. */
           string  Bakename = "[PassFileName rmanSSRenderPass -mapname initialShadingGroup]"
                                /* Rename \"initialShadingGroup\" to match the name of the <br>
                                   SSS material's shadingGroup - otherwise blocking will not 
                                   occur. */)
float   a = area(P, "dicing");
normal  n = normalize(N);
float   r = -red * Krgb, 
        g = -green * Krgb, 
        b = -blue * Krgb;
string  str;
color   finalOpacity = Os;
color   finalColor = Cs * finalOpacity;
if(option("user:pass_class",str)) {
    if(str == "SSRender") {
                P, n, "interpolate", 1,
                "coordsystem", "world",
                "radiusscale", 1,
                   "_area", a,
                "_radiance_t", color(r,g,b), // negative values
                "_albedo", color(1,1,1),
                "_diffusemeanfreepath", color(1,1,1));
    if(str == "Final") {
        finalOpacity = 0;
        finalColor = Cs * finalOpacity;
Oi = finalOpacity;
Ci = finalColor;

The text shown above in green is part of a TCL expression that is evaluated, at render-time by Pixar's RfM plugin, and is substituted by the path to the pointcloud that is baked by the "host" primitives shadinggroup.

Work Flow

1     Create the "host" SSS geometry, for example, a deformed nurbs sphere.
2     Either keep it's "initialShadingGroup" or assign it an instance of Blinn.
3     Add SSS attributes to the material - figure 3.

Figure 3

4     Right mouse click in the "Scattering Map" and choose,
        Create SSMakeBrickmap.

Figure 4

5     Edit the values of the "Scattering Strength" and "Scattering Free Path".
      Their values will depend on the dimensions of the "host" geometry.

Figure 5

6     Create and position the "blocker" geometry, for example, a small nurbs sphere.
7     Assign the sssBlocker shader to the blocker.
8     Carefully edit the "Bakename" TCL expression - explained below.

Editing the TCL Expression

1    Go to the RenderMan Controls window and look for the "SSRender" category.

Figure 6 - Getting the name of the SSRenderPass.

Note the name of the pass, it might be "rmanSSRenderPass","rmanSSRenderPass1", "rmanSSRenderPass2" etc. Make sure the name in the expression matches the name of the SSRender pass.

Figure 7 - Using the name of the SSRenderPass.

2     Go to the the attributes editor for the "host" material and look for the name of its shadinggroup.

Figure 8 - Getting the name of the shadinggroup.

Note the name of the shadinggroup, it might be "blinn1SG", "blinn2SG", "blinn3SG" etc. Make sure the name in the expression matchs the name of the shadinggroup.

Figure 9 - Using the name of the shadinggroup.

Be careful not to delete the square brackets hilited in red above. The expression must begin and end with an open and close bracket.

Image Quality

If the "Scattering Strengh" and "Scattering Free Path" have been set appropriately for the size of the "host" geometry you should see the results of SSS. To improve the quality of the SSS, adjust the "Max Error" of the rmanSSMakeBrickmapPass from it's default of 0.0040 to 0.0004.

To improve the speed and quality of the blocking and the SSS requires two adjustments. Adjust the "Shading Rate" of the rmanSSRenderPass from it's default of 5.0 to 10.0. Finally, adust the "Max Solid Angle" of the rmanSSDiffusePass from its default of 1.0 to 0.1.

Final Render - Problems

If the blocker does not have any effect in the final render it is best to remove the SSS attributes from the "host" material, manually delete any SSRender passes in the RenderMan Controls window and then add the SSS attributes again to the "host" material - a rather drastic approach but one that will save you a lot of frustration!

© 2002- Malcolm Kesson. All rights reserved.