/* Copyrighted Pixar 1989 */
/* From the RenderMan Companion p.357 */
/* Listing 16.20  Surface shader providing a paned-window highlight*/

/*
 *  windowhighlight(): Give a surface a window-shaped specular highlight.
 */
surface 
windowhighlight(	
	point	center	= point "world" (0, 0, -4), /* center of the window */
		in	= point "world" (0, 0, 1),  /* normal to the wall */
		up	= point "world" (0, 1, 0);  /* 'up' on the wall */
	color	specularcolor = 1; 
	float	Ka	= .3,
		Kd	= .5,
		xorder	   = 2,	/* number of panes horizontally */
		yorder	   = 3,	/* number of panes vertically   */
		panewidth  = 6,	/* horizontal size of a pane    */
		paneheight = 6,	/* vertical size of a pane      */
		framewidth = 1,	/* sash width between panes     */
		fuzz	   = .2;) /* transition region between pane and sash */
{
    uniform
      point	in2,	/* normalized in */
		right, 	/* unit vector perpendicular to	 in2 and up2 */
		up2,	/* normalized up perpendicular to in	     */
		corner;	/* location of lower left corner of window   */
      point 	path,	/* incident vector I reflected about normal N */
		PtoC, 	/* vector from surface point to window corner */
		PtoF;	/* vector from surface point to wall along path */
      float 	offset, modulus, yfract, xfract;
      point 	Nf = faceforward( normalize(N), I );

    /* Set up uniform variables as described above */
    in2 	= normalize(in);				
    right 	= up ^ in2;				
    up2 	= normalize(in2^right);
    right	= up2 ^ in2;
    corner = center - right*xorder*panewidth/2 - 
			    up2*yorder*paneheight/2;

    path = reflect(I, normalize(Nf));	/* trace source of highlight */
    PtoC = corner - Ps;

    if (path.PtoC <= 0) {	/* outside the room */
	xfract = yfract = 0;
    } else {

	/*
	 * Make PtoF be a vector from the surface point to the wall 
	 *	by adjusting the length of the reflected vector path.
	 */
	PtoF = path * (PtoC.in2)/(path.in2);						
	/* 
	 * Calculate the vector from the corner to the intersection point, and
	 *	project it onto up2. This length is the vertical offset of the
	 *	 intersection point within the window.
	 */
	offset = (PtoF - PtoC).up2;
	modulus = mod(offset, paneheight);
	if( offset > 0 && offset/paneheight < yorder ) { /* inside the window */
	    if( modulus > (paneheight/2))						/* symmetry about pane center  */
		modulus = paneheight - modulus;
	    yfract = smoothstep(	/* fuzz at the edge of a pane    */
		(framewidth/2) - (fuzz/2),
		(framewidth/2) + (fuzz/2),
		modulus);
	} else {
	    yfract = 0;
	}

	/* Repeat the process for horizontal offset */
	offset = (PtoF - PtoC).right;
	modulus = mod(offset, panewidth);
	if( offset > 0 && offset/panewidth < xorder ) {
	    if( modulus > (panewidth/2))
		modulus = panewidth - modulus;
	    xfract = smoothstep( 
		(framewidth/2) - (fuzz/2),
		(framewidth/2) + (fuzz/2),
		modulus);
	} else {
	    xfract = 0;
	}
    }
    /* specular calculation using the highlight */
    Ci = Cs * (Kd*diffuse(Nf) + Ka*ambient())
	  + yfract*xfract*specularcolor ;
}
