Displacement mapping is an alternative computer graphics technique in contrast to bump mapping,
normal mapping, and parallax mapping, using a (procedural-) texture- or height map to cause an
effect where the actual geometric position of points over the textured surface are displaced,
often along the local surface normal, according to the value the texture function evaluates to
at each point on the surface. It gives surfaces a great sense of depth and detail, permitting in
particular self-occlusion, self-shadowing and silhouettes.
(wikipedia)
|
Implementation in Renderman: |
||
displacement
displace_test(float Km = 0.1,
freq1 = 5,
freq2 = 5,
phase1 = 0,
phase2 = 0)
{
// Initialization ---------------------------
float hump = 0;
normal n = normalize(N);
// Calculating Displacement -----------------
float d = sqrt(pow(0.5-s,2)+pow(0.5-t,2));
float ang = (atan((t-0.5),(s-0.5)))/(PI);
hump += sin (2 * PI * d * freq1 + phase1)
* sin (2* PI * freq2 * ang + phase2);
P = P - n * hump * Km;
// Recalcilating Normals --------------------
N = calculatenormal(P);
}
|
In the case of Pixars prman renderer, each object in a 3D scene is sub-divided
into a fine mesh of micro-polygons after which, if a displacement shader has been
assigned to an object, they are "pushed" or "pulled" in a direction that is parallel
to the original surface normal of the micro-polygon. After displacing the micro-polygon
the orientation of the local surface normal(N) is recalculated.
(fundza) |
|
|
Result: |
||
![]() |
This is the result of applying the above shader "displace_test" to a simple plygon. |
Displacement shaders cannot accept any lighting or coloring information. But there are a few methods to use displacement shader in conjunction with a surface shader.
|
Displacement Hack! |
||
surface
hack_test(float Ka = 1,
Kd = 0.5,
Ks = 0.7,
Km = 0.1,
foamMin = 0.4,
foamMax = 0.6,
roughness = 0.1;
color hilitecolor = 1 )
{
// Calculating Displacement -----------------
normal n = normalize(N);
float hump = sin(s * 2 * PI * 3);
P = P + n * hump * Km;
N = calculatenormal(P);
// Coloration -------------------------------
color surfcolor = color(0.686,0.701,0.976);
float blend = smoothstep(foamMin, foamMax, hump);
surfcolor = mix(surfcolor, color(1,1,1), blend);
// Lighting ---------------------------------
color ambientcolor, diffusecolor, speccolor;
n = normalize(N);
normal nf = faceforward(n, I);
ambientcolor = Ka * ambient();
diffusecolor = Kd * diffuse(nf);
vector i = normalize(-I);
speccolor = Ks * specular(nf, i, roughness)
* hilitecolor;
// Outputs ----------------------------------
Oi = Os;
Ci = Oi * Cs * surfcolor
* (ambientcolor + diffusecolor + speccolor);
}
|
In this method (which is more like a hack) the displacing is done "inside" the
body of a surface shader. This method is not suggested though due to the problems it
might cause. In this code there is a block for displacement before calculating
coloration and lighting.
|
|
|
Shader Messaging |
||
displacement
fBmDisp (float Km = 0.1,
freq = 5,
oct = 5,
lac = 5,
gain = 0.5;
output varying float hump = 0)
{
normal n = normalize(N);
float amp=1;
point pp = transform("shader", P);
point ps = pp * freq;
uniform float i;
for( i = 0; i < oct; i += 1 )
{
hump += amp * (2*(float noise(ps))-1);
ps *= lac;
amp *= gain;
}
P = P + n * hump * Km;
N = calculatenormal(P);
}
|
In this method the surface shader "imports" certain parameters sent out by the displacement
shader and calculates lighting (and/or coloration) based on those parameters. |
|
surface
snow (float Ka = 0.2,
Kd = 0.8,
Ks = 0.2,
roughness = 0.1,
snowLine = 0.5,
snowBlend = 0.2,
snowNoise = 0.1,
snowFreq = 10;
color mountColor = 1,
snowColor = 0,
hilitecolor = 1)
{
// Initialization -----------------------------
color surfcolor = mountColor, ambientcolor, diffusecolor, speccolor;
normal n = normalize(N);
normal nf =faceforward(n,I;
// Coloration ---------------------------------
float bumpiness;
float NewSnowLine = 2 * (snowLine - 0.5);
if(displacement ("hump", bumpiness)==1){
float jitter = snowNoise * (noise (P * snowFreq) - 0.5);
if(bumpiness > (NewSnowLine-snowBlend-jitter)){
float blend = smoothstep(NewSnowLine-snowBlend, NewSnowLine+snowBlend, bumpiness + jitter);
surfcolor = mix(mountColor, snowColor, blend);
}
}
// Lighting -----------------------------------
ambientcolor = Ka * ambient();
diffusecolor = Kd * diffuse(nf);
vector i = normalize(-I);
speccolor = Ks * specular(nf, i, roughness)* hilitecolor;
// Output -------------------------------------
Oi = Os;
Ci = Oi * Cs * surfcolor * (ambientcolor + diffusecolor + speccolor);
}
|
In the surface shader code, there should be an "if" statement to explore the existance of such
parameter in the displacement shader; then assinging its value to another variable to do the rest
of calculation: |
|
