/*---------------------------------------------------------------------------- * SHADER: * water_ripple - water ripple shader. * - can create rippling water effect, as well as just watery appearance * * PARAMETERS: * Ka, Kd, Ks, specularcolor, roughness - the standard meaning. * Kr, Kt - Reflection coefficient & Refraction coefficient * period - controls the distance between ripples (as period gets * smaller, the ripples get closer). * swirl - the amount of turbulence in the ripple pattern. * swirlfreq - the relative frequency of the turbulence (i.e. waves vs. noise). * c0, c1 - two points on the center line of the water from which the * ripples originated. This shader creates concentric rings out from * this line. * ripplecolor - the fraction of Cs for the color of the ripple bands. *--------------------------------------------------------------------------*/ surface water_ripple(float Ka=1, Kd=.6, Ks=0.4, Kr=0.6, Kt=0.5, roughness=.2, period=1/5, swirl=0.25, swirlfreq=1; point c0=point "shader" (0,0,0), c1=point "shader" (0,0,1); color specularcolor = 1; float ripplecolor=0.3) { point cP, C1, C0, PP, Nf, V, newP; float dd, pd, alpha, nn; /* Perturbations to water */ color watercolor, mixcolor; float kr, kt; float eta = 1.33; /* Index of refraction */ vector IN; /* Normalized incident vector */ vector R, Rdir; /* Direction to cast the ray */ vector Rfldir, Rfrdir; /* Smooth reflection/refraction directions */ color ev = 0; /* Color of the environment reflections */ color cr = 0; /* Color of the refractions */ /* Construct a normalized incident vector */ IN = normalize(I); /* Construct a forward facing surface normal */ Nf = faceforward( normalize(N), I ); /* Construct a neg. normalized incident vector */ V = -normalize(I); /* Compute the reflection & refraction directions and amounts */ fresnel (IN, Nf, (I.N < 0) ? 1.0/eta : eta, kr, kt, Rfldir, Rfrdir); kr *= Kr; kt *= Kt; /* Compute the distance from P to the line (c0, c1). */ C1 = transform("shader",c1); C0 = transform("shader",c0); cP = normalize(C1 - C0); newP = transform("shader",P); PP = newP - C0; pd = PP.cP; dd = sqrt(abs(PP.PP - pd*pd)); /* add some turbulence */ nn = swirl*noise(swirlfreq*newP); nn += 0.5*swirl*noise(2.0*swirlfreq*newP); nn += 0.25*swirl*noise(4.0*swirlfreq*newP); nn += 0.125*swirl*noise(8.0*swirlfreq*newP); nn += 0.0625*swirl*noise(16.0*swirlfreq*newP); nn += 0.03125*swirl*noise(32.0*swirlfreq*newP); dd += nn; /* Compute the scale factor to be applied to the color to generate the ripple. The factor will vary between .5 and 1. */ alpha = mod(dd/period, 1); alpha *= alpha; alpha = (1-alpha)/5 + .8 - 0.3*noise(10.0*dd/period); /* force alpha between 0 and 1 */ alpha = (alpha-0.5)/0.5; /* including blurring effects as a function of swirl & swirlfreq would probably * be more appropriate, but too expensive for our purposes */ /* Calculate the reflection color */ if (kr > 0.001) { /* Rdir gets the perfect reflection direction */ Rdir = normalize (Rfldir); ev = kr * trace (P, Rdir); /* no blur effects */ } /* Calculate the refraction color */ if (kt > 0.001) { /* Rdir gets the perfect refraction direction */ Rdir = normalize (Rfrdir); cr = kt * trace (P, Rdir); } /* Finally, compute the output color. It is a specular surface scaled by the ripple pattern. The specularity also varies with the period: darker water is more specular */ /* mixcolor is fraction of Cs */ mixcolor = ripplecolor * Cs; watercolor = mix(mixcolor,Cs,alpha); Oi = Os; Ci = Os * (watercolor * ( Ka*ambient() + Kd*diffuse(Nf) ) + (1-alpha+0.75) * specularcolor * (ev + Ks*specular(Nf,V,roughness)) + watercolor * cr ); }