Page tree

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

Contents

Displacement shaders: moving surface points (and normals)

After a surface has been tessellated, its surface points can be moved by a displacement shader.  The displacement shader is executed on each vertex of the tessellated surface.  In general, each point can be moved by an arbitrary direction and amount:

  for (int i = 0; i < numPts; i++)
  {
    P[i] += <some offset vector>;
  }

Typically the offset vector is along the surface normal as in this example:

  for (int i = 0; i < numPts; i++)
  {
    P[i] += amplitude[i] * Nn[i];
  }

Figure ... shows a small grid of surface points before and after displacement.

TO DO: figure of 5x4 pt grid similar to figure 8.3 of ARM book.  But with points P and normals Nn shown(?).

After the displacement has been done, any smooth analytical normals that the original surface may have had (for example a smooth subdivision surface or NURBS patch) are no longer valid – they do not correspond to the displaced surface.  Each micropolygon has a geometric normal Ngn.  In addition, for some surface types a smooth shading normal will be automatically computed for each ray hit – this is done by considering the orientation of not only the micropolygon the the ray hit, but also the adjacent micropolygons.

Displaced polygon meshes deserve a special mention here.  Polygon meshes do not by themselves have smooth normals, but are often defined with a normal at each polygon mesh vertex point.  When a ray hits an undisplaced polygon mesh, the shading normal Nn can be computed by interpolation ... leading to a smooth appearence.

RixDisp() ?

Talk about common trick for adding back smoothness?  Also, 

Displacement bounds

BVH bbox tightening.  Not too large: important for ttfp.  Not too small: holes.

TO DO: Figure with holes due to too small displacement bound.

Example

Here is an example of a fragment of a rib file with a sphere being turned into a five-pointed star:

  Attribute "displacementbound" "float sphere" [0.21]
  Pattern "dispstar" "sin5theta" "float scale" 0.2
  Displace "PxrDisplace" "pxrdisp" "reference float dispScalar" "sin5theta:resultF"

The dispstar shader is a very simple shader written in Open Shading Language (OSL).  It computes a displacement amount depending on radial angle in the x-y plane.  When applied to a spherical shape, it produces a round star with five spikes.  When applied to a teapot (with higher frequency), it produces a pumpkin-like shape.

shader
dispstar(float scale = 1.0, float freq = 5.0,
         output float resultF = 0.0)
{
  vector Non;   // original, undisplaced normal
  getattribute("builtin", "Non", Non);

  // Convert Non from current (world) space to object space
  vector Nobj = transform("object", Non);

  // Compute displacement
  float angle = atan2(Nobj[1], Nobj[0]);
  float disp = scale * sin(freq*angle);

  resultF = disp;
}

In this example, the displacement amount computed by dispstar gets passed on to the PxrDisplace displacement shader, which does the actual displacement.  Here is an image of a sphere displaced with this combination of shaders:

TO DO: image of displaced sphere = star.

The seasoned RenderMan user will notice this is very similar to how displacement was done in the classic RenderMan Shading Language (RSL) – see for example Apodaca and Gritz, 2000 section 8.2.