|
Last updated: May 15, 2003
Some of the following shaders are designed to be used with the PatchMesh object that Leveller creates when exporting a RIB file. Although they can be used on any object, doing so may create suboptimal results.
Elevation-based coloring The shaders are provided in commented source format to help you develop your own preferred heightfield shaders. As a filing aid, all our heightfield shaders start with the prefix 'levhf_'. The code is not warranted, but all the shaders were tested. Enjoy, and use at your own risk. The Renderman API is Copyright Pixar, Inc.
Elevation-based coloring Coloring a heightfield based on the altitude of its points is a standard way of communicating differences in elevation. In this example, we blend between two colors, the same way that Leveller does when using the 'App Default' colormap. The technique can also be used on bump maps to give richer effect to a texture.
/*
levhf_elev.sl
Version 1.0 by Daylon Graphics Ltd.
This is a simple matte shader that colors a point depending on
its elevation. The heightfield is assumed to be based on an object
(such as a "Pz" PatchMesh) where the elevations are oriented along
the Z axis in object space.
*/
surface levhf_elev(color ColorLo = color(0,0,1), ColorHi = color(1,1,1))
{
point where = transform("object", P);
color c = mix(ColorLo, ColorHi, zcomp(where));
normal Nf = faceforward(normalize(N),I);
Oi = Os;
Ci = c * Os * Cs * (1 * ambient() + 1 * diffuse(Nf));
}
Elevation-based gradient colormapping This type of coloring emulates Leveller's multistep colormaps. Note that in the case of the Spectrum colormap, a simple linear interpolation using the spline() function is adequate. For nonlinear gradients, a different approach (e.g., if-else blocks) may be necessary.
/*
levhf_elevgradient.sl
Version 1.0 by Daylon Graphics Ltd.
This is a simple matte shader that colors a point depending on
its elevation, using Leveller's "Spectrum" colormap. The heightfield
is assumed to be based on an object (such as a "Pz" PatchMesh) where
the elevations are oriented along the Z axis in object space.
*/
surface levhf_elevgradient()
{
point where = transform("object", P);
/*
According to the Renderman documentation, spline() returns
the second datum if f=0, and the second-to-last datum if
f=1. So we duplicate these items to get the desired interpolation.
*/
color c = spline(zcomp(where),
color(0,0,0),
color(0,0,0),
color(0,0,1),
color(0,.5,1),
color(0,.5,0),
color(1,.5,0),
color(1,0,0),
color(1,1,1),
color(1,1,1)
);
normal Nf = faceforward(normalize(N),I);
Oi = Os;
Ci = c * Os * Cs * (1 * ambient() + 1 * diffuse(Nf));
}
Slope-based coloring
/*
levhf_slope.sl
Version 1.0 by Daylon Graphics Ltd.
This is a simple matte shader that colors a point depending on
its slope. The heightfield is assumed to have its elevations
oriented along the Y axis in default (world) space.
*/
surface levhf_slope(
color ColorFlat = color(1, 1, 1);
color ColorSteep = color(0, 0, 1);
)
{
/*
Get the angle of the surface point's slope, which we assume
we can derive from the normal's Y element. The two statements below
are actually poor form; in a production shader, you would optimize
them to use ycomp(normalize(Ng)) directly -- there's no reason to
obtain degrees unless you absolutely need them.
*/
float angle = 90 - (asin(ycomp(normalize(Ng)))) * 180 / PI;
color c = mix(ColorFlat, ColorSteep, angle / 90);
normal Nf = faceforward(normalize(N),I);
Oi = Os;
Ci = c * Os * Cs * (1 * ambient() + 1 * diffuse(Nf));
}
Snowy peaks The Slope example blends between the two specified colors, which doesn't really give a good idea of how slope is used. This shader instead applies one color for one set of angles, and another color for the rest. The sharp break between the two colors shows exactly which slopes are being given which color.
/*
levhf_snowypeaks.sl
Version 1.0 by Daylon Graphics Ltd.
This is a simple matte shader that colors a point depending on
its slope, to simulate snow or other material deposited onto
a heightfield. The heightfield is assumed to have its elevations
oriented along the Y axis in default (world) space.
*/
surface levhf_snowypeaks(
color ColorSnow = color(1, 1, 1);
color ColorRock = color(.4, .4, .4);
float Angle = 45;
)
{
float angle = 90 - (asin(ycomp(normalize(Ng)))) * 180 / PI;
color c = angle < Angle ? ColorSnow : ColorRock;
normal Nf = faceforward(normalize(N),I);
Oi = Os;
Ci = c * Os * Cs * (1 * ambient() + 1 * diffuse(Nf));
}
Summertime snowy peaks The Snowy Peaks example puts snow on every surface of low slope. In the summertime, mountains only have snow above a certain elevation, where the air is sufficiently cold. Acheiving the effect, of course, is simple -- use elevation and slope together.
/*
levhf_summersnow.sl
Version 1.0 by Daylon Graphics Ltd.
This is a simple matte shader that colors a point depending on its
slope, to simulate snow or other material deposited onto a heightfield.
Slope is not considered if the elevation of the point is below a certain
threshold. The heightfield is assumed to have its elevations oriented
along the Y axis in default (world) space.
*/
surface levhf_summersnow(
color ColorSnow = color(1, 1, 1);
color ColorRock = color(.4, .4, .4);
float Angle = 45;
float Elev = .66;
)
{
float angle = 90 - (asin(ycomp(normalize(Ng)))) * 180 / PI;
float elev = zcomp(transform("object", P));
color c = elev > Elev && angle < Angle ? ColorSnow : ColorRock;
normal Nf = faceforward(normalize(N),I);
Oi = Os;
Ci = c * Os * Cs * (1 * ambient() + 1 * diffuse(Nf));
}
Quick Shading Sometimes you want illumination without shadows. This shader brightens or darkens the surface color depending on how each point is facing a specified vector. It emulates Leveller's Quick Shading mode which fakes shadows by simply darkening areas facing away from the Sun.
/*
levhf_qshade.sl
Version 1.0 by Daylon Graphics Ltd.
This is a simple color shader that brightens/darkens
a point depending on its relation to a given vector.
*/
surface levhf_qshade(
point SunDir = (.707, -.707,-.707); /* 45 degrees right, down, and south */
)
{
float f = faceforward(normalize(Ng), I).SunDir;
Oi = Os;
Ci = Os * Cs * (1-f);
}
Masked Texturing The default "paintedplastic" texturing shader ignores the texture's alpha channel, if one is present. Since Leveller supports masked textures, this shader is provided in the samples/ribshaders folder.
/* txalpha.sl - Alpha-channel texturing shader
* Copyright (C) 2003 Daylon Graphics Ltd.
* Written by Ray Gardener (support@daylongraphics.com)
*
* The RenderMan (R) Interface Procedures and RIB Protocol are:
* Copyright 1988, 1989, Pixar. All rights reserved.
* RenderMan (R) is a registered trademark of Pixar.
*
* DESCRIPTION:
* Apply a texture map to a plastic surface, indexing the texture
* by the s,t parameters of the surface. Alpha channel in the texture
* will blend the texture color with the primitive's color.
* Additionally, you can specify the strength of an overall
* blend between the texture and the surface color.
* If the alpha channel is all 1.0 and Ob is 0.5, results
* will match paintedplastic.
*
* PARAMETERS:
* Ka, Kd, Ks, roughness, specularcolor - the usual meaning.
* Ob - Overall texture/surface blending factor
* (0.0 prefers surface, 1.0 prefers texture).
* texturename - the name of the texture file.
*
*/
surface
txalpha ( float Ka = 1, Kd = .5, Ks = .5, roughness = .1;
color specularcolor = 1;
float Ob = 1;
string texturename = ""; )
{
normal Nf;
vector V;
color Ct;
float Ot;
float numChannels;
Ot = 1;
if (texturename != "")
{
Ct = color texture(texturename);
Ot = float texture(texturename[3]);
/* This part checks that texture has alpha, but it slows
down rendering (especially if the texture has its TIFF
directory holding unsorted tags, as warning messages
may display for every pixel access). This code could be
redundant since the renderer converts textures to
internal RGBA textures anyway.
if(1.0 == textureinfo(texturename, "channels", numChannels))
{
if(numChannels == 4)
Ot = float texture(texturename[3]);
}
*/
}
else
{
Ct = 1;
}
Nf = faceforward (normalize(N),I);
V = -normalize(I);
Oi = Os;
Ci = Os *
(mix(Cs, Ct, Ot * Ob) *
(Ka * ambient() + Kd * diffuse(Nf)) +
specularcolor * Ks * specular(Nf, V, roughness));
}
|