/* * stone.sl -- Surface shader for a stones. * * DESCRIPTION: * Makes a wall of stones. Need more be said? OK. It makes a good * looking staggered stone masonry. It is especially convincing when * used in conjunction with the "stonebump" displacement shader (and * identical parameters). Every other row of stones is staggered. * The staggering isn't exact, however, and this variance is controlled * by the "rowvary" parameter. * * PARAMETERS: * Ka, Kd The usual * stonecolor, mortarcolor Pretty obvious (default is gray stones) * stonevary How much does the stone color vary from * stone to stone? * stonewidth Width of a stone (in st space) * stoneheight Height of a stone (in st space) * mortarthickness Thickness of the mortar (in st space) * rowvary How much does each row shift? * jagged How much do stones deviate from squares? * * AUTHOR: written by Larry Gritz, gritzl@acm.org * * $Revision: 1.6 $ $Date: 1998-04-07 19:57:33-07 $ */ #include "noises.h" #include "patterns.h" surface stone ( float Ka = 1, Kd = 1; color stonecolor = color "rgb" (.3,.3,.3); color mortarcolor = color "rgb" (.1,.1,.1); float raggedamp = 0.04, raggedfreq = 12; float jagged = 0.006, stonevary = 0.6; float stonewidth = .28, stoneheight = .14; float mortarthickness = .007; float rowvary = .5; float pitting = 0.01; float pockfrequency = 10, groovedepth = 0.01; ) { #define sqr(x) ((x)*(x)) color bcolor, Ct; normal Nf; float sstone, tstone, w, h; float ss, tt; float swidth, twidth; uniform float BMWIDTH = (stonewidth+mortarthickness); uniform float BMHEIGHT = (stoneheight+mortarthickness); uniform float MWF = (mortarthickness*0.5/BMWIDTH); uniform float MHF = (mortarthickness*0.5/BMHEIGHT); float whichstone; float fact, disp; /* Determine how wide in s-t space one pixel projects to, relative * the the width and height of a stone. Overestimate the filter * size by a bit -- it makes the transitions between stone and mortar * a bit smoother. */ swidth = 1.5 * max (filterwidth(s), MINFILTWIDTH) / BMWIDTH; twidth = 1.5 * max (filterwidth(t), MINFILTWIDTH) / BMHEIGHT; basictile (s, t, BMWIDTH, BMHEIGHT, 0.5, 0.2, 1, jagged, sstone, tstone, ss, tt); /* Make the edges ragged, but different for each stone */ whichstone = 103*sstone + tstone; ss += raggedamp * snoisexy ((s+tstone*5.15)*raggedfreq, (t+sstone*23.8)*raggedfreq); tt += raggedamp * snoisexy ((s+tstone*11.4)*raggedfreq, (t+sstone*7.2)*raggedfreq); ss += raggedamp/2 * snoisexy ((s+tstone*5.15)*raggedfreq*2, (t+sstone*23.8)*raggedfreq*2); tt += raggedamp/2 * snoisexy ((s+tstone*11.4)*raggedfreq*2, (t+sstone*7.2)*raggedfreq*2); /* Choose a color for the surface */ if (swidth >= 1) w = 1 - 2*MWF; else w = clamp (filteredpulse (MWF, 1-MWF, ss, swidth), max(1-MWF/swidth,0), 1); if (twidth >= 1) h = 1 - 2*MHF; else h = clamp (filteredpulse (MHF, 1-MHF, tt, twidth), max(1-MHF/twidth,0), 1); fact = 1; disp = 0; if (tt < MHF) { /* We're in the top horizontal groove */ disp = groovedepth * (sqr((tt)/MHF) - 1); } else if (tt > (1.0-MHF)) { /* Bottom horizontal groove */ disp = groovedepth * (sqr((1-tt)/MHF) - 1); } if (ss < MWF) { disp = min (disp, 0.85 * groovedepth * (sqr(ss/MWF) - 1)); } else if (ss > (1.0-MWF)) { disp = min (disp, 0.85 * groovedepth * (sqr((1-ss)/MWF) - 1)); } fact = smoothstep (0, 1.3*MHF, tt) - smoothstep (1.0-1.3*MHF, 1, tt); fact *= (smoothstep (0, 1.3*MWF, ss) - smoothstep (1.0-1.3*MWF, 1, ss)); fact = pitting * (0.5 * fact + 0.5); disp -= fact * pow(noise ((ss+sstone)*pockfrequency/BMHEIGHT, (tt+tstone)*pockfrequency/BMWIDTH), 0.25); P += disp * normalize(N); N = calculatenormal (P); Nf = faceforward (normalize(N),I); /* Choose a stone color that varies from stone to stone */ bcolor = stonecolor * (1 + (stonevary * snoise (whichstone+0.5))); Ct = mix (mortarcolor, bcolor, w*h); Oi = Os; Ci = Os * Ct * (Ka * ambient() + Kd*diffuse(Nf)); }