A while ago when I was implementing shadow volumes in my rendering engine I came up with an algorithm to compute a given light’s bounding screen-rectangle. According to my tests, it works pretty darn well, however, having said that I’m still wondering if there are cases out there that could break it.

Anyway here it is, I would appreciate any commments:

```
Tuple4i Renderer::getScissorRect(const Tuple3f &lightPosition,
float lightRange)
{
Tuple4i scissor;
//Retrieve the current view port to extract the screen width and height
glGetIntegerv(GL_VIEWPORT,viewport);
//Get the camera world position
Tuple3f cameraPosition = getCameraPosition(),
lightPos = lightPosition,
diagonal;
//If the camera distance to the light source is lesser than
//the light range, return the description of the whole screen
if(cameraPosition.getDistance(lightPos) - lightRange <= EPSILON)
return viewport;
//Retrieve the projection matrix, we will use it later to project
//our corners points onto the screen
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
//Retrieve the modelview matrix, we will extract the up and right
//vectors from it
glGetFloatv(GL_MODELVIEW_MATRIX , modelviewMatrix);
/**************************************/
/* + Upper corner */
/* / */
/* / */
/* / */
/* / */
/* / */
/* / */
/* ( ) Light position */
/* / */
/* / */
/* / */
/* / */
/* / */
/* / */
/* + Lower corner */
/**************************************/
//Multiply the light range by square root of two since we will compute
//the corners of square
lightRange *= 1.42f;
diagonal.set(modelviewMatrix[0] + modelviewMatrix[1],
modelviewMatrix[4] + modelviewMatrix[5],
modelviewMatrix[8] + modelviewMatrix[9]);
diagonal *= lightRange;
//Compute the lower corner
corners[0].set(lightPosition.x - diagonal.x,
lightPosition.y - diagonal.y,
lightPosition.z - diagonal.z,
1.0f);
//Compute the upper corner
corners[1].set(lightPosition.x + diagonal.x,
lightPosition.y + diagonal.y,
lightPosition.z + diagonal.z,
1.0f);
//Project both onto the screen surface
for(int i = 0; i < 2; i++)
{
corners[i] *= modelviewMatrix;
corners[i] *= projectionMatrix;
corners[i] /= corners[i].w;
corners[i].x = viewport[0] + float(viewport[2])*(corners[i].x + 1.0f)/2.0f;
corners[i].y = viewport[1] + float(viewport[3])*(corners[i].y + 1.0f)/2.0f;
corners[i].z = 0.5f*corners[i].z + 0.5f;
}
//Set up the scissor info
scissor[0] = int(corners[0].x);
scissor[1] = int(corners[0].y);
scissor[2] = int(corners[1].x);
scissor[3] = int(corners[1].y);
scissor[0] = scissor[0] < 0 ? 0 : scissor[0];
scissor[1] = scissor[1] < 0 ? 0 : scissor[1];
return scissor;
}
```