/*-----------------------------------------------------------------------
 * cmarble - a surface shader producing white marble with colored veins
 *		whose color is determined from C.
 *
 * Ks, Ks, Ka, roughness, specularcolor - the usual meaning
 * veining - frequency of veins
 *-----------------------------------------------------------------------*/
surface
cmarble(
	float Ks=.4,float Kd=.6, float Ka=.1, float roughness=.1,
	float veining = 1,
	color specularcolor=1)
{
	point PP;
	float cmi;
	normal Nf;
	vector V;
	color diffusecolor ;
	float pixelsize, twice, scale, weight, turbulence;
	/* variables for rgb to hsv conversion ... */
	string spoke;	/* part of color wheel it's in */
	float x;	/* smallest RGB component */
	float hue, sat, val;
	float red, grn, blu;


	Nf = faceforward( normalize(N), I);
	V = -normalize(I);

	PP = transform("shader",P) * veining;
	PP = PP/2;	/* frequency adjustment (S-shaped curve) */
	pixelsize = sqrt(area(PP)); twice = 2 * pixelsize;

	/* compute turbulence */
	turbulence = 0;
	for (scale = 1; scale > twice; scale /= 2) {
		turbulence += scale * abs(noise(PP/scale)-0.5);
	}
	/* gradual fade out of highest freq component near visibility limit */
	if (scale > pixelsize) {
		weight = (scale / pixelsize) - 1;
		weight = clamp(weight, 0, 1);
		turbulence += weight * scale * abs(noise(PP/scale)-0.5);
	}
	/*
	 * turbulence now has a range of 0:2, but its values actually
	 * tend strongly to lie around 0.75 to 1.
	 */

	cmi = clamp(turbulence, 0, 1);

	/*
	 * Assuming that C is in RGB space, convert to HSV space so
	 * that we can modulate saturation and value without changing hue.
	 */
	C = transformc ("hsv", C);

	/*
	 * Now we have C in hue,sat,val (HSV) form.  Proceed to modulate
	 * saturation and value based on the turbulence computed earlier.
	 * Value is blended between the value of C and white (value = 1).
	 * So a "black" marble has black veins and a "white" marble has
	 * white veins outlined in dark gray.
	 */

	float satramp[9] = {0.999, 0.999, 0.200, 0.060, 0.030, 0.020,
		0.010, 0.010, 0.000};
		
	C[1] *= spline("catmull-rom",turbulence, satramp);
	float blackramp[11] = {0.999, 0.999, 0.400, 0.000,
		0.000, 0.000, 0.000,
		0.000, 0.000, 0.000, 0.000};
	float whiteramp[11] = {0.000, 0.000, 0.000, 0.800,
		0.800, 0.800, 0.800,
		0.999, 0.999, 0.999, 0.999};
	C[2] = C[2] * spline("catmull-rom",turbulence, blackramp) + spline("catmull-rom",turbulence, whiteramp);

	/*
	 * Now reconstruct an RGB color from the hue,sat,val and use
	 * that as the diffuse surface color in a "plastic" shading formula.
	 */

	diffusecolor = transformc ("hsv", "rgb", C);

	C = diffusecolor * (Ka*ambient() + Kd*diffuse(Nf));
	/* add in specular component */
	C = opacity * (C + specularcolor * Ks * specular(Nf,V,roughness));
}


