RManNotes

previous | next | writing shaders: contents | rmannotes: top

Surface Shaders, Part I

This section describes some variable naming conventions, the construction and compositing of layers, and dealing with transparency in surface shaders. Surface Shaders, Part II discusses illumination in surface shaders.

Variables

The table below summarizes local variables that we'll use by convention in writing surface shaders.

Surface Shader Variables
nametypedescription
surface_colorcolorcolor of all composited layers
surface_opaccoloropacity of all composited layers
(needed for transparent surfaces only)
layer_colorcolorcolor of current layer
layer_opaccoloropacity of current layer
ss,ttfloattexture coordinates of current layer (2D)
PPpointtexture coordinates of current layer (3D)

Layers and Compositing

Most surface shaders will consist of multiple layers. The accumlated color of all layers will be stored in a variable called surface_color.

Initially, we'll assign a value directly to surface_color which will indicate the color of the background layer (layer 0). This value may fixed by the shader-writer or definable by the user of the shader using an instance variable or the global RSL variable Cs.


	/* background layer (layer 0) */

	surface_color = color (0.3, 0.3, 0.3); /* grey */

For each foreground layer, we'll use the variables layer_color and layer_opac to represent to color and opacity for the layer currently being defined (these variables will be reused for each layer).


	/* layer n */

	layer_color = color (0, 0, 1)             /* blue */
	layer_opac = pulse(0.35, 0.65, 0.02, s);  /* vertical stripe */
	surface_color = blend(surface_color, layer_color, layer_opac);

Each layer will be composited on top of the previous layers using the blend() function (which is just a vector version of the RSL function mix()).

RManNotes function

color blend(color a, color b, color x)

      Performs a component-wise linear interpolation between a and b based on the values in x. Note: blend() also supports the argument types supported by mix().

The shader below shows two stripes composited on a background layer. Note that the layer colors are constant and that the layer opacity specifies where the color will be applied for each layer. Also note that layer #2 is 50% transparent and there are no illumination computations. The shader is also available as surf1.1.sl.


#include "rmannotes.sl"

surface surf1_1()
{
  color surface_color, layer_color;
  color layer_opac;

  /* background layer (layer 0) */

  surface_color = color (0.3, 0.3, 0.3); /* grey */

  /* layer #1 */
  
  layer_color = color (0,0,1);  /* blue */
  layer_opac = pulse(0.35, 0.65, 0.02, s);
  surface_color = blend(surface_color, layer_color, layer_opac);
  
  /* layer #2 */
  
  layer_color = color (0,1,0);  /* green */
  layer_opac = pulse(0.35, 0.65, 0.02, t);
  layer_opac *= 0.5;
  surface_color = blend(surface_color, layer_color, layer_opac);
  
  /* output */
  
  Ci = surface_color;
}
layer 0layer 1layer 2all layers

Transparent Surfaces

The shader above uses layers to determine surface color. In that shader, the entire surface can be made uniformly transparent by setting the RSL global variable Os (if OiOi = Os).

A more sophisticated approach is to build up opacity using the individual layer opacities. This allows surfaces to be defined which have varying opacity.

We will use the variable surface_opac to store the opacity of the surface. When we use surface_opac, we'll assign an initial value to it which will represent the opacity of the background layer. For transparent surfaces, surface_opac should be initialized to a value less than 1. It can be initialized using Os, an instance parameter, or a fixed value.


	/* background layer (layer 0) */

	surface_color = ...
	surface_opac = Os;                     /* user-defined */

Compositing opacities is easy -- we just add the opacity of the current layer to the overall surface opacity (stored in surface_opac) and clamp the surface opacity to the range 0 to 1. The RManNotes union function can be used for this purpose.


	/* layer n */

	layer_color = ...
	layer_opac = ...
	surface_color = blend(...
	surface_opac = union(surface_opac, layer_opac);

The shader surf1.2.sl is identical to surf1.1.sl described above except that the surface opacity varies based on the layers and Cs and illumination has been added.

Os = (1,1,1)Os = (0,0,0)

previous | next | writing shaders: contents | rmannotes: top

RManNotes is Copyright © 1995, 1996 Stephen F. May

Any comments or suggestions appreciated.

Steve May (smay@pixar.com)

Last Modified: 5/6/96