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

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].
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.
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(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].
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). |

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