/*water ( float Ka = 0.2, Kd = 0.1, Ks = 0.5;
	float Kr = 0.9, Kt = 0.9, roughness = 0.05, blur = 0, eta = 1.33;
	color specularcolor = 1, transmitcolor = 0.7;
	float samples = 1; ) */

/*
 * water.sl -- Shiny reflective & refractive water, using ray tracing.
 *
 * DESCRIPTION:
 *   Makes semi-transparent water, using ray tracing to calculate
 *   reflections and refractions of the environment.
 * 
 * PARAMETERS:
 *    Ka, Kd, Ks, roughness, specularcolor - The usual meaning
 *    Kr - coefficient for mirror-like reflections of environment
 *    Kt - coefficient for refracted transmission
 *    transmitcolor - color of the water
 *    eta - the coefficient of refraction of the water
 *    blur - how blurry are the reflections/refractions? (0 = perfectly sharp)
 *    samples - set to higher than 1 for oversampling of blur
 *
 * AUTHOR: written by Larry Gritz, 1991
 * EDITOR: Yi-Ting Tung
 */

surface
water ( float Ka = 0.2, Kd = .15, Ks = 0.45;
	float Kr = 1, Kt = 1, roughness = 0.05, blur = 0, eta = 1.33;
	color specularcolor = 1, transmitcolor = color (0.85, 0.93, 1);
	float samples = 1; )
{
    normal Nf;               /* Forward facing normal vector */
    vector IN;               /* normalized incident vector */
    vector Rfldir, Rfrdir;   /* Smooth reflection/refraction directions */
    vector uoffset, voffset; /* Offsets for blur */
    color ev = 0;            /* Color of the environment reflections */
    color cr = 0;            /* Color of the refractions */
    vector R, Rdir;          /* Direction to cast the ray */
    uniform float i, j;
    float kr, kt;

    /* Construct a normalized incident vector */
    IN = normalize (I);

    /* Construct a forward facing surface normal */
    Nf = faceforward (normalize(N), 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;

    /* Calculate the reflection color */
    if (kr > 0.001) {
	/* Rdir gets the perfect reflection direction */
	Rdir = normalize (Rfldir);
	if (blur > 0) {
	    /* Construct orthogonal components to Rdir */
	    uoffset = blur * normalize (vector (zcomp(Rdir) - ycomp(Rdir),
						xcomp(Rdir) - zcomp(Rdir),
						ycomp(Rdir) - xcomp(Rdir)));
	    voffset = Rdir ^ uoffset;
	    for (i = 0;  i < samples;  i += 1) {
		for (j = 0;  j < samples;  j += 1) {
		    /* Add a random offset to the smooth reflection vector */
		    R = Rdir +
			((i + float random())/samples - 0.5) * uoffset +
			((j + float random())/samples - 0.5) * voffset;
		    ev += trace (P, normalize(R));
		}
	    }
	    ev *= kr / (samples*samples);
	} else {
	    /* No blur, just do a simple trace */
	    ev = kr * trace (P, Rdir);
	}
    }

    /* Calculate the refraction color */
    if (kt > 0.001) {
	/* Rdir gets the perfect refraction direction */
	Rdir = normalize (Rfrdir);
	if (blur > 0) {
	    /* Construct orthogonal components to Rdir */
	    uoffset = blur * normalize (vector(zcomp(Rfrdir) - ycomp(Rfrdir),
					       xcomp(Rfrdir) - zcomp(Rfrdir),
					       ycomp(Rfrdir) - xcomp(Rfrdir)));
	    voffset = Rfrdir ^ uoffset;
	    for (i = 0;  i < samples;  i += 1) {
		for (j = 0;  j < samples;  j += 1) {
		    /* Add a random offset to the smooth reflection vector */
		    R = Rdir +
			((i + float random())/samples - 0.5) * uoffset +
			((j + float random())/samples - 0.5) * voffset;
		    cr += trace (P, R);
		}
	    }
	    cr *= kt / (samples*samples);
	} else {
	    /* No blur, just do a simple trace */
	    cr = kt * trace (P, Rdir);
	}
    }

    Oi = 1;
    Ci = ( Cs * (Ka*ambient() + Kd*diffuse(Nf)) +
	   specularcolor * (ev + Ks*specular(Nf,-IN,roughness)) +
	   transmitcolor * cr );
}
