/* * 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); }