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