RSL
|
Topics |
Introduction
This tutorial focuses on some of the issues relating to the writing of directional light source shaders ie. those
that use the |
Parallel IlluminationListing 1 shows a slightly modified version of Pixar's classic "distantlight" shader. It is an example of a light source intended to mimic sunlight. |
Listing 1 (basic_distant.sl)
|
A rib file that implements a simple scene (figure 1) that can be used to test the shader is given in listing 2.
The reader should ensure the paths shown in red "point" to the directories in which they store their custom shaders, textures and archive (pre-baked) rib files. |
Listing 2 (basic_distant.rib)
|
But it Does Not Work in Maya & Houdini!
If the reader assigns the shader from listing 3 to a directional light source in Maya,
using RenderMan Studio, or in Houdini they will see the illumination is reversed - a
downward facing light will illuminate the scene as if it were pointing
upward! So why does the shader behave correctly when tested with the rib file shown in
listing 2 but not when used in Maya or Houdini?
TransformBegin Attribute "identifier" "string name" ["directionalLightShape1"] Transform [ 1 0 -0 0 -0 0 -1 0 0 1 0 0 0 0 0 1 ] Scale 1 1 -1 # ??? LightSource "basic_distant" "RenderManLight2" "float intensity" [1] "color lightcolor" [1 1 1] TransformEnd As a consequence, for the shader to behave correcly with Maya or Houdini it is necessary to declare the direction vector as pointing toward positive Z. vector direction = vector "shader" (0,0,1); This means the transform block containing the light in listing 2 must also apply a negative Z scaling. TransformBegin Rotate -90 1 0 0 Scale 1 1 -1 LightSource "basic_distant" 2 "intensity" 1 TransformEnd Thus proving that "two wrongs can make a right"! |
The solar() Function
At the heart of a directional light source shader is the solar(direction, 0.0) { Cl = intensity * lightcolor; }
There are two special global variables that can be accessed within the function's block of code.
It is the responsibility of the shader to assign
a color to |
Listing 4
In listing 4 an "angle" parameter has been added to the shader. The effect of different values of "angle" are shown in figure 5. For moderate values of "angle" the visual effect is to wrap the illumination around the sphere. However, for large values of "angle" the wrapping becomes noticably "distorted".
|
Shadows
Listing 5 demonstrates the use of the |
Listing 5 (shd_distant.sl)
The rib file shown below can be used to generate the two depth maps required for the beauty pass render - listing 7. |
Listing 6 (shadow_pass.rib)
|
Listing 7 (beauty_pass.rib)
Listing 7 will generate the image shown below.
|
Rendering a Shadow AOV
The shd_distant shader provides an opportunity to explore how data
calculated by a light source shader can be rendered into a secondary image. Although light
shaders can have parameters declared as output variables they cannot be
used directly as a source of data for secondary images. The
data assigned to a light's output variables can, however, be read
by a surface shader and then assigned to its output variables. Such outputs
are known as AOVs - arbitrary output variables. The reader should
refer to the tutorial
"RenderMan: AOVs - Secondary Images"
for background information on this topic.
|
Listing 8
|
Because the Listing 9 (diffuseAOV.sl)
|
The illuminance() loop
Although the
Within the illuminance block, the |
Listing 10
If the reader has Pixar's RenderMan Pro-Server and RenderMan Studio installed on their computer they can render both the beauty pass and the secondary images directly to an "it" (Image Tool) catalog. For example, Display "./shadow_test.tif" "it" "rgba" Display "+./shadow_test._inshadow" "it" "_inshadow"
Otherwise, it is necessary to render the secondary image as a image file, for example, Display "./shadow_test" "framebuffer" "rgba" Display "+./shadow_test._inshadow.tif" "tiff" "_inshadow" |
Occlusion Directional Light
The next illustration shows the "soft shadow" effect of a directional light that
outputs a color based on the use of the The source code of the light source shader, and a rib file suitable for testing it, are shown in listings 11 and 12. Listing 11 (occlusionlight.sl)
The Listing 12 (occlusionlight.rib)
|
Rim LightingThe tutorial "RSL:Edge Effects" demonstrated the use of the dot product to create fake rim lighting. Incidently, the same vector arithmetic is used by Maya's (HyperGraph) "facing ratio" node. Listing 9 (diffuseAOV.sl) also uses the dot product to scale the apparent intensity of the (Lambertan or diffuse) illumination received by a surface. However, the two vectors it uses are not those of the (reversed) view vector and the surface normal but the (reversed) light direction and the surface normal. In other words, what is referred to as Lambertian or diffuse illumination is the result of mulitplying the facing ratio of the light source by its color. Perhaps the illuminance loop used by the diffuseAOV shader should be re-written to make the use of the dot product more apparent ie. illuminance( P, n, PI/2 ) { float facing_ratio = normalize(L).n; diffusecolor += Cl * facing_ratio; } The next shader (listing 13) modifies the output color of a light by the dot product (aka facing ratio) of the surface normal and the view vector. However, because this is implemented by a directional light source the rim effect can be controlled by a lighting artist rather than a shading artist!
Listing 13 (distantrimlight.sl)
|
Light WrappingThis section is based on the Siggraph 2002 paper, "Renderman on Film" by Rob Bredow (Sony Pictures Imageworks). In his paper the author demonstrates the principles of a shading technique they used in the production of the movie "Stuart Little 2". Their system gave the illusion that illumination from a light source appeared to wrap around the curved surfaces of their characters as if they were lit by an area light source. |
|
|
Although the Siggraph paper explained their light-wrapping technique it did not provide the source code of their custom shaders. Consequently, the shaders given in listings 14 and 15 are, almost certainly, substantially different to those developed at Sony. The MathsFigure 13 shows four micropolygons, labeled a, b, c and d, on a sphere that is illuminated by a downward pointing directional light. The red lines represent vectors pointing toward the light source while the green lines represent the surface normals of each micropolygon. The dot product of the vectors and the normals at each of the sampled points is also given along with a "reminder" that the dot product represents the cosine of the angle between the vectors. For convenience, the angles are shown in degrees rather than in radians. |
|
A "regular" surface shader ie. no light wrapping, would assign maximum illumination to the micropolygon at point a and minimum illumination to point b. The terminator between light and dark would occur along the "equator" of the sphere. However, a surface shader that wraps by, say, 45 degrees would "push" the terminator to point c. |
The Role of the Surface Shader
Diffuse illumination is calculated by a surface shader either indirectly using
the color diffusecolor = 0; illuminance( P, n, PI/2 ) { diffusecolor += Cl * normalize(L).n; }
In figure 13 the "light" vector ( illuminance("wrapper", P, n, PI ) { lightsource("wrapAngle", wrap_angle); l = normalize(L); float dot = n.l; float minDot = cos(radians(90 + wrap_angle)); float clamped = clamp(dot, minDot , 1.0); float illum = (clamped - minDot)/(1.0 - minDot); diffuseColor += Cl * illum; } The Role of the Light Source Shader
Although light wrapping must be applied by a surface shader, it makes sense in a studio
for the wrap_angle to be determined by the lighting artists ie. controlled by the
light sources in a scene. Note that in listing
14 the illuminance loop queries the |
Listing 14 (wrappersurf.sl)
|
Listing 15 (wrapperlight.sl)
|
Listing 16 (wrapper.rib)
|
Volumetric Fog Effects
This section introduces the use of a very simple volume shader that works in conjunction
with a "tagged" custom directional light source. Strickly speaking, the volumetric fog effects
shown in figure 14 do not require a custom light. However, assigning a |
|
Immediately after a surface shader has determined the apparent color
and opacity of a micropolygon a volume shader can modify the
micropolygon's color in order to create the illusion that a scene is partially or fully
filled with a medium such as water, fog or smoke. For example,
the volume shader shown in the next listing steps along the viewing
vector ( |
|
Listing 17 (mkfog.sl)
|
The code for a light source that works in conjunction with the volume shader is shown next. Listing 18 (distantFoglight.sl)
|
The two frame rib file that can be used to test the shaders is given next. Listing 19
|
© 2002- Malcolm Kesson. All rights reserved.