/* -------------------------------------------------------------------------- 
 *  'stippled' shades objects as though they were made out of plastic with
 *  lots of little bumps.
 *  This shader makes a fairly good attempt at automatic anti-aliasing.
 *
 *  Ks, Ka, Kd, roughness, specularcolor - the usual meaning
 *  grainsize - the size in shader space of the granules
 *  stippling - magnitude of speckling intensity variation
 * -------------------------------------------------------------------------- */
surface 
grass( float Ks=.3, Kd=.8, Ka=.1, roughness=.3,
	grainsize=1000, stippling=1000; color specularcolor=1 )
{
    point V, Nf, Nfake, Ndiddle,PP;
    float disp, pixelsize, Kflat;
    color Cstippled,Cflat;

    /* N and I are not automatically normalized in this implementation. */
    Nf = faceforward( normalize(N), I);
    V = -normalize(I) ;

    PP = transform("shader",P);
    /* get a vector pointing in some random direction and add it to normal */
    Ndiddle =  stippling * (point noise(PP / grainsize) - .5);
    Nfake =  normalize(Nf + Ndiddle);
    Cstippled = Os * (Cs * (Ka*ambient() + Kd*diffuse(Nfake)) +
	    specularcolor * Ks * specular(Nfake,V,roughness) );

    /* anti-alias by mixing between flat color and stippled color as pixels */
    /*  get small */
    pixelsize = sqrt(area(PP));
    Oi = Os;
    if (grainsize >= pixelsize) {
	if (pixelsize >= 0) {
	Ci = Cstippled;
	} 
	Cflat = Os * (Cs * (Ka*ambient() + Kd*diffuse(Nf)) +
	specularcolor * Ks * specular(Nf,V,roughness) );
	Ci = mix(Cflat,Cstippled,smoothstep(0,1,grainsize/pixelsize));
    } else {
        /* calculate flat color to shade toward for anti-aliasing */
	    Cflat = Os * (Cs * (Ka*ambient() + Kd*diffuse(Nf)) +
		    specularcolor * Ks * specular(Nf,V,roughness) );
	    Ci = mix(Cflat,Cstippled,smoothstep(0,1,grainsize/pixelsize));
    }
}