/*
* rustymetal.sl -- metal with specks of rust
*
* DESCRIPTION:
* A rough metal surface with controllable rust spots. The rust pattern
* is basically thresholded turbulence (summed abs(snoise)). Where it's
* rusty, shade like rust colored matte, and also make it bumpy (like
* the corrosion is kind of grainy). Where there is no rust, shade like
* regular metal. All computations are done in shader space.
*
* PARAMETERS
* metalKa, metalKs, metalroughness - control the appearance of the metal.
* rustKa, rustKd, rustcolor - control the appearance of the rust.
* txtscale - overall scaling factor of the rust pattern.
* rusty - 0=no rust, larger for more rust, 1=completely rusty
* rustbump - controls the "bumpiness" of the rusty areas.
*
* ANTIALIASING:
* The fractal sum used to determine the rust pattern chooses a number of
* octaves to sum based on the shader sampling rate. This helps to keep
* aliasing under control.
*
* AUTHOR: Larry Gritz, gritz AT seas DOT gwu DOT edu
* The George Washington University
*
* HISTORY:
* 19 Jan 1995 - gritz - created
*
* last modified 19 Jan 95
*/
/* Signed noise varies from -1 to 1 (like Perlin uses) */
#define snoise(x) (2*noise(x)-1)
/* Maximum number of octaves */
#define MAXOCTAVES 8
surface
LGRustyMetal (float metalKa = 1, metalKs = 1, metalroughness = .1;
float rustKa = 1, rustKd = 1;
color rustcolor = color (.437, .084, 0);
float txtscale = 1;
float rusty = 0.2;
float rustbump = 0.035;
)
{
point Nf, V; /* normal and view vector used for shading */
point Nrust; /* perturbed normal for the rusty areas */
point PP; /* shade space point */
float i, sum = 0, a = 1; /* Loop control for fractal sum */
float alimit; /* Limit sum to do simple antialiasing */
float rustiness; /* Result: how rusty is this point? */
color Cmetal = 0, Crust = 0; /* Computed colors of metal & rust */
/* Sum several octaves of abs(snoise), i.e. turbulence. Limit the
* number of octaves by the estimated change in PP between adjacent
* shading samples.
*/
PP = txtscale * transform ("shader", P);
alimit = sqrt (area(PP));
for (i = 0; i < MAXOCTAVES && a > alimit; i += 1) {
sum += a * abs(snoise(PP));
PP *= 2;
a /= 2;
}
/* If it's rusty, also add a high frequency bumpiness to the normal */
Nrust = calculatenormal (P + rustbump * snoise(PP) * normalize(N));
/* Scale the rust appropriately, modulate it by another noise
* computation, then sharpen it by squaring its value.
*/
rustiness = step (1-rusty, clamp (sum,0,1));
rustiness *= clamp (abs(snoise(PP)), 0, .08) / 0.08;
rustiness *= rustiness;
/* If we have any rust, calculate the color of the rust, taking into
* account the perturbed normal and shading like matte.
*/
if (rustiness > 0) {
Nf = faceforward (normalize(Nrust),I);
Crust = rustcolor * (rustKa*ambient() + rustKd*diffuse(Nf));
}
/* If we have any metal, calculate the color of the metal, using the
* original (smooth) normal and the usual metal illumination model.
*/
if (rustiness < 1) {
Nf = faceforward (normalize(N),I);
V = -normalize(I);
Cmetal = Cs * (metalKa*ambient() + metalKs*specular(Nf,V,metalroughness));
}
/* Now blend the metal and rust colors depending on the computed value
* of the rustiness.
*/
Oi = Os;
Ci = Oi * mix (Cmetal, Crust, rustiness);
}