/* This is a varient of the slide-projector light shader 
   From the RenderMan Companion p.373
*/

/*
 * TLblocker1spotlight -- texture-map used as a light blocker for a spot
 * light (1 channel version)
 *
 * DESCRIPTION:
 * This is basically the slideprojector from the RC.  The twist is that the
 * 1 Channel texture map is treated as a either a positive or negative blocker.
 * ie. the image is use to block the light based on the pattern of the black &
 * white image.
 *
 * This version has the properties of a spotlight, too.
 *
 * HINTS:
 * If the "negative" is false, then the white region will let light pass though
 * and block the rest.  If "negative" is true, then it will do the opposite.
 *
 * AUTHOR: Tal Lancaster
 *	tal AT renderman DOT org
 *
 * History:
 *	Created: 8/10/97
 * 
 */


light
TLblocker1spotlight(	
    float intensity = 1.0;
	color lightcolor = 1;
	float	fieldofview=PI/32;
	point	from		= (8, -4, 10),
		to		= (0,0,0),
		up		= point "eye"  (0,1,0);
	float coneangle = radians (30);
	float conedeltaangle = radians (5);
	float beamdistribution = 2;
	float negative = 0;
	string	blockername 	= "",
		shadowname      = "" )
{
	uniform point	relT, 	/* normalized direction vector */
			relU, 	/* "vertical" perspective of surface point */
			relV;	/* "horizontal" perspective of surface point */
	uniform point A;
	uniform float spread = 1/tan(fieldofview/2); /* spread of "beam" */
	float	Pt, 		/* projection of Ps on relT (distance of 
				   surface point along light direction)	*/
		Pu, 		/* projection of Ps on relU */
 		Pv, 		/* projection of Ps on relU */
 		sloc, tloc;	/* perspected surface point */
	float cosoutside = cos (coneangle);
	float cosinside = cos (coneangle-conedeltaangle);
	float atten;
	float cosangle;
	float blockerVal;   /* value from texture map */

	/* Initialize uniform variables for perspective */
	relT = normalize(to - from);
	relU = relT ^ up;
	relV = normalize(relT ^ relU);
	relU = relV^relT;
	
	A = relT;

	Cl = lightcolor * intensity;
	
	illuminate(from, relT, /*atan(sqrt(2)/spread)*/coneangle) {
		L =  Ps - from;	/* direction of light source from surf. point */
		Pt = L.relT;	/* coordinates of Ps along relT, relU, relV */
		Pu = L.relU;
		Pv = L.relV;
		sloc = spread*Pu/Pt;	/* perspective divide	*/
		tloc = spread*Pv/Pt;
		sloc = sloc*.5 + .5;	/* correction from [-1,1] to [0,1] */
		tloc  = tloc*.5 + .5;
		
		cosangle = L.A / length (L);
		atten = pow (cosangle, beamdistribution)/ (L.L);
		atten *= smoothstep (cosoutside, cosinside, cosangle);
		
		Cl *= atten;
		
		if (blockername != "") {
			blockerVal = float texture(blockername, sloc,tloc);
			if (negative == 1)
				blockerVal = 1 - blockerVal;
			Cl *= blockerVal;
		}
		
		if( shadowname != "" )
			Cl *= 1-shadow(shadowname, Ps);
	}
}
