ReferenceExpressions

Introduction

This page presents a collection of expressions that can be used with source code for surface and displacement shaders. The expressions use the values of the global variables s and t, both of which by default are in the range 0 to 1, to calculate values in other ranges. Figure 1

Being able to conveniently convert one range of values into another range is very useful when, for example, the effect of a surface or displacement shader needs to be gradually modified towards the edges of a surface. Figure 2

Mapping 0 - 1 to 1 - 0 - 1

Deriving an expression that will convert values in one range to their associated values in another range can be visualized as a process of 'moving' and 'stretching' the initial range, say 0 to 1, along a fixed number line. Figure 3

For example, the diagram below shows the original range, 0 to 1, being mapped to the range 1 to 0 to 1. Figure 4

If the original range of values was represened by say the s texture coordinate, new values could be calculated using the following expression.
newValue = abs((s - 0.5) * 2);

The effect of using newValue to scale the displacement of a wave is shown below. Figure 5

Mapping 0 - 1 to 0 - 1 - 0

The diagram below shows the original range, 0 to 1, being mapped to the range 0 to 1 to 0. Figure 6

The equivalent expression is,
newValue = abs (abs(s - 0.5) * 2 - 1);

The effect of using newValue, calculated with both 's' and 't', to scale the displacement of a turbulance shader is shown below. Figure 7

Mapping a Subrange to 0 - 1 - 0

The diagrams show a subrange a to c being mapped to the range 0 to 1 to 0. It is assumed b is the midpoint of ac Figure 8 Figure 9

The equivalent expression is,
newValue = abs (abs((s - b) * 1/ab) - 1);

The effect of using this expression to calculate a displacement in both 's' and 't' is shown below. Figure 10

Using the Sine Function

The sine function is part of the maths library that is built into the shading language. The function returns a value that is the ratio of the length of a rotating line divided by its vertical height. The end of the rotating line sweeps out the circumference of a circle. If the line is one unit long the circumference of the circle is 2 x PI or 6.283185 units in length. Figure 11

In the diagram shown above the vertical height of the rotating line, itself 1 unit in length, can never be greater than +1 and never be less than -1. Consequently for any rotation of the line, measured by the distance its end has moved along the circumference of the circle, the sine function returns values in the range +1 to -1. The unit of measurement used to express the rotation is the radian.

To generate the sine wave shown above across a surface, say in the 's' direction, we must scale its value by 2PI ie. multiply by 6.283185.
waveHeight = sin (s * 6.283185);

The effect of using waveHeight in a displacement shader is shown below. Figure 12

To avoid negative numbers it is often necessary to keep waveHeight in the range 0 to 1. The following expression accomplishes this,
waveHeight = (sin(s * 6.283185) + 1) * 0.5; Figure 13

It is also useful to be able to shift the sine wave horizonally so that the wave begins and ends at a 'trough', a 'peak' or anywhere in between. The following expression introduces control over the phase of the wave.
waveHeight = (sin ((s - phase) * 6.283185) + 1.0) * 0.5;
when "phase" is 1.0 the wave is shifted one complete cycle. Figure 14

Often an arbitary number of cycles of the sine wave is required, the following expression includes a variable that controls the number of waves,
waveHeight = (sin((s-phase/cycles)*6.283185*cycles) + 1.0)*0.5; Figure 15

The effect of using this expression in a displacement shader is shown below. Figure 16

Occasionally it is necessary to modify the sine wave so that it produces only 'bumps'. Here is the expression,
waveHeight = abs (sin ((s - phase/cycles) * 6.282 * cycles));
Used in a displacement shader this expression produces the effect shown below. Figure 17

Using the Mod Function

The mod function divides one number by another but returns only the remainder. For example,
mod (3, 2);
would return the value 0.5, not 1.5.
The function can be used to map the range 0 to 1 to a sequence of repeating sub-ranges 0 to ~1. In each sub-range the maximum value becomes infinitly close to 1 but never actually reaches that value. Figure 18

The mod function is very useful when creating repeating patterns on a surface. In the diagram above, 4 sub-ranges have been created, however, the function can be used to make any number of repeats. To generate 8 repeated patterns, say in the 's' direction, the following expression would be applied.
ss = mod (s * 8, 1);
Using 1 as the divider ensures the number of 'repeats' is not altered. The effect of using mod in a displacement shader, in both the 's' and 't' directions is shown below. Figure 19