RManNotes

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

Displacement Shaders

We can used the same divide and conquer approach with displacement shaders that we did with surface shaders. We will break down the surface displacement into simple layers and then composite the layers to create the final effect.

Variables

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

nametypedescription
surface_magfloatmagnitude of displacement for all composited layers
layer_magfloatmagnitude of displacement for current layers
Kmfloatoverall displacement scaling factor
ss,ttfloattexture coordinates of current layer (2D)
PPpointtexture coordinates of current layer (3D)

Layers, Compositing, Displacement

The local variable surface_mag will be used to represent the sum magnitude of surface displacement. Initially, we'll assign this a value (frequently zero) which represents the displacement for the background layer.


	surface_mag = 0;

For each layer in the displacement shader, we'll assign a value to layer_mag which will represent the amount of displacement contributed by that layer. One cool thing about displacement shaders is that there are many ways to composite the layers. Here are three:

  1. Just add. This gives a cumulative effect (as you would expect). Each layer will interfere with the others.
    
    surface_mag += layer_mag;
    
  2. Use max. This gives the effect of layers which don't interfere with other layers.
    surface_mag = max(surface_mag, layer_mag);
  3. Use max and add.
    surface_mag = max(surface_mag, layer_mag) + layer_mag;

When all the layers have been composited, we can move the surface point along the normal with a small amount of shader code shown in the fragment below. P and N are RSL global variables specifying the surface point and normal. Km is a local variable or more likely an instance parameter which allows the total surface displacement to be scaled by the user.


	P += P * Km * surface_mag * normalize(N);
	N = calculatenormal(P);

The table below shows 3 variations of the same shader. The only difference is in the way that the top-most layer (layer #2) is composited.

just addingmaxmax plus add

Dealing With Smooth-shaded Polygons

Smooth-shaded polygonal surfaces present a special problem with displacement shaders. Although the smooth shading surface normals give the polygonal data a smooth, non-faceted look with surface shaders, the polygons are still flat and therefore displacement of surface points in a displacement shader returns the faceted shading.

polygonal spherepolygonal sphere
w/smooth shading
polygonal sphere
w/smooth shading
& displacement shader

With smooth-shaded polygons, N (shading normal) will contain the smooth shading normal and Ng (geometric normal) will contain the face normal. We can solve the displacement problem by saving the difference between N and Ng and then adding it back in after we calculate the new normal. The code fragment below demonstrates this:


	point Ndiff;
	.
	.
	Ndiff = normalize(N) - normalize(Ng);
	P += P * Km * surface_mag * normalize(N);
	N = normalize(calculatenormal(P)) + Ndiff;

The image below shows a smooth-shaded polygonal sphere with the disp1.4.sl displacement shader applied to it. This shader is the same as disp1.3.sl modified with the code fragment given above. Note that the faceted look has disappeared!


disp1.4.sl

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/7/96