RManNotes

previous | next | regular patterns: contents | rmannotes: top

Transitions

A tile for a surface shader generally has some transition in color or opacity. A tile for a displacement shader has transitions in the amount of displacement. Transitions can be described functionally using simple, "building block" functions like step, smoothstep, and pulse. Once a tile has been created, it can easily be repeated using the mod function.

Some of the figures in this section were adapted from [Apodaca92].

Step

The step function acts like a switch jumping from 0 to 1 when the variable, x, is greater than some threshold, a.


step(a, x)

step is equivalent to a conditional statement. For example,

s = step(a, x)
is equivalent to the following code fragment:
if (x < a)
  s = 0;
else
  s = 1;

The primary motivation for considering step instead of conditionals is because step can be replaced functionally with the smoothstep function. step contains arbitrarily high frequency components meaning that shaders written with step (or conditionals) will almost always alias. smoothstep, however, does not contain arbitrarily high frequency components -- therefore smoothstep can be used to generate sharp transitions which do not alias.

Smoothstep

The smoothstep function is similar to step, but provides a smooth transition from 0 to 1. When the variable x is greater than the value a the function starts changing from 0 to 1. By the time the variable x reaches the value b, the transition has completed and the value of smoothstep is 1.


smoothstep(a, b, x)

For antialiasing purposes, we can think of the smoothstep function as the step function with a controllable amount of blurriness or "fuzz." If fuzz is set properly, we have a antaliased version of step. Note that if fuzz = 0, we have the original step function.

step and "fuzzy" step
step(a, x) smoothstep(a - fuzz, a, x)

Note: The reason for specifying the smooth transition from a - fuzz to a is described by Peachey in the subsection titled "Filter Position" in Chapter 2 (page 97) of [Ebert94].

Pulse

A pulse is one of the most commonly used building blocks in shaders. It represents a sharp, temporary transition defined over some range. A square pulse is created by subtracting one step function from another.


a square pulse, step(a, x) - step(b, x)

But, square pulses have the same problem with aliasing that individual step functions have. Fortunately, two smoothsteps can be combined in the same way to generate a rounded or smooth pulse. And like the "fuzzy step" function described above, we can think of a smooth pulse in terms of a square pulse with a controllable amount or "fuzz". Note that if fuzz = 0, we get a square pulse. If fuzz = (b - a) / 2, we get a completely rounded-off pulse (there is no flat portion on top).



smoothstep(a - fuzz, a, x) - smoothstep(b - fuzz, b, x)

RManNotes function

float pulse(float a, b, fuzz, x)

      A "fuzzy" pulse; it returns the value of smoothstep(a - fuzz, a, x) - smoothstep(b - fuzz, b, x).

"Cross" Tile

The horizontal and vertical bars in the tile below were generated using two pulses each in a different layer.


crosstile.sl

previous | next | regular patterns: contents | rmannotes: top

RManNotes is Copyright © 1995, 1996 Stephen F. May

Any comments or suggestions appreciated.

Steve May (smay@pixar.com)

Last Modified: 4/15/96