/* --------------------------------------------------------------------------
 *  '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
stippled( float Ks=.3, float Kd=.8, float Ka=.1, float roughness=.3,
	float grainsize=.01, float stippling=.2, color specularcolor=1 )
{
    normal Nf, Nfake, Ndiddle;
    vector V;
    point PP;
    float pixelsize;
    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 * (noise(PP / grainsize) - .5);
    Nfake =  normalize(Nf + Ndiddle);
    Cstippled = opacity * (C * (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));
    if (grainsize >= pixelsize) {
	C = Cstippled;
    } else {
        /* calculate flat color to shade toward for anti-aliasing */
	    Cflat = opacity * (C * (Ka*ambient() + Kd*diffuse(Nf)) +
		    specularcolor * Ks * specular(Nf,V,roughness) );
	    C = mix(Cflat,Cstippled,smoothstep(0,1,grainsize/pixelsize));
    }
}
