/* * DESCRIPTION: * Opal-like surface obtained by severely abusing Voronoi cell noise. * Requires "noises.h" from BMRT distribution. * * PARAMETERS: * float Kd - the usual * float Ks - the usual * float roughness - the usual * float celljitter - alter shape of flakes * float normAdj - how much normal is twiddled to approximate flakes. 0.5 works well * color specularcolor - the usual * point scale - stretch space shader is in (object) * float flakeColorVary - how much color varies flake-to-flake * float flakeRough - 'roughness' of the flakes * color flakeColor - base color of flakes. * float flakeMix - mix two sets of flakes * * ANTIALIASING: * None. * (somewhat intentional. Aliasing gives a nice 'glitter' to the opal) * * AUTHOR: * Mark B. Allan * * HISTORY: * 02/13/00 - clean up * 02/15/00 - minor changes */ #include #define blend(a,b,x) ((a) * (1 - (x)) + (b) * (x)) /*--------------------------------------------------*/ color getFlakeColor( point PP; normal NN; vector nIn; float celljitter; float normAdj; float flakeColorVary; color flakeColor; vector flakeVector; float flakeRough; output color opacity; ) { normal Ntwid; /* twiddled norm */ point Nflake; point tmpP; point pos1; point Pflake; point snoiseCell; float tmpF; float f1; float Ndot; float fcOr; float fcOg; float fcOb; color flakeColorOut; color flakeSpec; color C; C = 0; /* we want these in a range of 0-1 */ float NflakeAmt = normAdj * 0.5; float CflakeVary = flakeColorVary * 0.5; /* get cell */ voronoi_f1_3d(PP*0.5, celljitter, f1, pos1); tmpF = float noise(pos1); if(tmpF < 0.4) Pflake = PP*0.6; else if (tmpF > 0.6) Pflake = PP*3.1; else Pflake = PP; voronoi_f1_3d(Pflake, celljitter, f1, pos1); snoiseCell = 2.0*(point noise(pos1+flakeVector)) - 1.0; /* calculate flake color */ tmpP = (1.0-CflakeVary)*point flakeColor + CflakeVary*normalize(snoiseCell); fcOr = xcomp(tmpP); fcOg = ycomp(tmpP); fcOb = zcomp(tmpP); if(fcOr < 0) fcOr = 0; if(fcOg < 0) fcOg = 0; if(fcOb < 0) fcOb = 0; flakeColorOut = ( color(normalize(point(fcOr, fcOg, fcOb)) ) ); /* get a 'normal' from voronoi cell centroid */ Nflake = faceforward(normalize(snoiseCell), I); Ndot = 1.0 - (NN . Nflake); Ntwid = normalize((1.0-NflakeAmt)*NN + NflakeAmt*Nflake); float atten = abs(nIn . NN); flakeSpec = specular(Ntwid, nIn, flakeRough); C = flakeColorOut * flakeSpec; opacity = flakeSpec; return C; } /*--------------------------------------------------*/ surface MBAOpal ( float Kd = 1.0; float Ks = 0.5; float roughness = 0.02; float celljitter = 1.0; float normAdj = 0.5; color specularcolor = 1.0; point scale = 5.0; float flakeColorVary = 1.0; float flakeRough = 0.2; color flakeColor = 1.0; float flakeMix = 0.5; ) { string space = "object"; normal Ntwid; /* twiddled norm */ normal NN = normalize(N); vector nIn = -normalize(I); point PP = scale * transform (space, P); point off = point(scale*0.82); vector flakeVector; color flakeFinalColor; color flake1Opacity; color flake2Opacity; color opacity; flakeVector = nIn; color flake2Color = getFlakeColor(PP, NN, nIn, celljitter, normAdj, flakeColorVary, flakeColor, nIn, flakeRough, flake1Opacity); flakeVector = nIn^NN; color flake1Color = getFlakeColor((PP+off)*0.9, NN, nIn, celljitter, normAdj, flakeColorVary, flakeColor, nIn, flakeRough, flake2Opacity); flakeFinalColor = mix(flake1Color, flake2Color, flakeMix); opacity = 0.5*(flake1Opacity+flake2Opacity); Ci = Kd*blend(Cs, flakeFinalColor, 0.8) + Ks*specularcolor*specular(faceforward(NN, I), nIn, roughness); Oi = Os; }