# Cellnoise

# Cellnoise

*December, 1995*

PhotoRealistic RenderMan 3.6 introduces a new function to Shading Language:
**cellnoise**. This application note describes what this function is good
for and how to use it.

### Motivation

The Shading Language **noise** function is used to introduce randomness
in shaders, to add complexity and visual realism. Generally, **noise** is
used for two different purposes. Sometimes, **noise** is used to generate a
continuous, pseudo-random, non-periodic function "field", which can be
used to attenuate surface bumps, mottle the color of an object, etc.

Another common usage of the **noise** function in Shading Language is to
generate discrete random deviations. These values are used, for example, to
color each brick on a wall differently, access a texture map from a different
place on each plank of a floor, color each petal on a flower differently, etc.
We use the term "cell" to mean each discrete entity (brick, plank, petal,
floor tile, etc.). In these cases, the noise value is usually taken from
the center or corner of the cell, so that the deviate remains constant over
that cell.

Here is an example of how one might compute a slightly different color for each brick in the wall:

brickrow = floor (t / brickheight); brickcolumn = floor (s / brickwidth); brickcolor = mix (color1, color2, noise (brickrow*50+brickcolumn+0.5));

The offset of 0.5 causes the noise function to be sampled between integers,
since on the integer lattice its value is always 0.5. So `noise(i+0.5)` is
something pseudo-random.

There are two problems with this scheme: (1) noise is rather expensive to
call. Much of the expense is in interpolating (making the noise function
continuous), but that isn't really needed if we are just sampling discrete
locations and don't need the usual continuity constraints. (2) the
distribution of noise values is highly biased toward staying close to 0.5 (see
Properties of Noise Functions for more details). For
the use of noise we're describing, it's much more likely that we want a
uniform distribution over `[0,1]`.

Some people try to get around problem (2) by making a construct like the following:

#define SMALL 0.05 n = noise (brickrow*50+brickcolumn+0.5); brickcolor = mix (color1, color2, mod (n, SMALL) / SMALL);

This has the effect of "wrapping noise around itself", giving a distribution a little more like what you'd want, but not perfect. But it is even more computation, and you lose more floating point accuracy.

So we decided we need a new shadeop that does what we wanted: to provide a
cheaper, non-interpolating, uniformly distributed deviate for each cell. Hence,
**cellnoise**.

### Cellnoise Basics

The **cellnoise** function is syntactically similar to **noise**. It can take
inputs of 1-4 dimensions:

**cellnoise**(*float*) - 1-D cell noise**cellnoise**(*float, float*) - 2-D cell noise**cellnoise**(*point*) - 3-D cell noise**cellnoise**(*point, float*) - 4-D cell noise

Like **noise**, **cellnoise** returns either a float, a point, or a
color, depending on its context. You can also explicitly ask for a particular
return type (this is strongly recommended to make your shader source
unambiguous):

**f = float cellnoise (...)****p = point cellnoise (...)****c = color cellnoise (...)**

#### Cellnoise Behavior

**Cellnoise** gets its name because it divides *n*-D space into
*cells*. The return value of **cellnoise** is constant over its
cell, discontinuous at cell borders, and uncorrelated between cells.

More formally, for all integers *i*, **cellnoise** is constant
on `[i,i+1)` and discontinuous at *i-eps*. Its range values are uniformly
distributed on `[0,1]`.

**Cellnoise** is considerably cheaper to call than **noise**. In
terms of the raw function speed, 1-D cellnoise is about 1.25 times faster to
compute than 1-D noise, 2-D cellnoise is twice as fast as 2-D noise, 3-D
cellnoise is almost 3 times faster than 3-D noise, and 4-D cellnoise is nearly
6 times faster than 4-D noise. In addition, since you save operations of
adding 0.5 and possibly multiplies and divides to fix the range distribution,
there's even more overhead that is avoided by using cellnoise.

### Sample cellnoise usage

**Pattern Variation:** you can use **cellnoise** to assign a
different color, offset, orientation, etc., to each discrete entity in a
collection. Examples include planks in a floor, bricks in a wall, petals in
a flower.

brickrow = floor (t / brickheight); brickcolumn = floor (s / brickwidth); brickcolor = mix (color1, color2, cellnoise (brickrow, brickcolumn)); brickroughness = cellnoise (brickrow+100, brickcolumn); /* offset of 100 makes roughness uncorrelated to color */

**Generating a random sequence:** You can generate a repeatable,
pseudo-random sequence by calling **cellnoise** in a loop:

for (i = 0; i < size; i += 1) { n = cellnoise(i); /* whatever */ }

If you want multiple random sequences, or different seeds, you can use the 2-D variant:

n = cellnoise(i,seed);