Wednesday, November 6, 2013

Encapsulating a spot light with a approximated cone mesh for Deferred Lights

 I've been improving on my deferred renderer by using basic primitives for rendering each of the lights during the lighting for optimizations. Following is the link I am using as reference for my optimizations:

Keith Judge's blog on Stencil Buffer Optimizations for Deferred Lights

 For point lights, I use a sphere and for spot lights I use a cone. I wanted to use an approximated mesh for rendering the light.

The problem of using an approximated mesh without any adjustments is that the edges get cut off.


To illustrate the issue, here's what happens:
 


Let's asume the following:
  • 's' = size of the cone
  • 'b' = angle of the cone
  • 'r' = base radius of cone = s * cos(b)
  • 'h' = height of cone = s * sin(b)
If we consider the original angle and size of cone, we notice that the mesh ends up inside the spot light. On looking at the base of the cone mesh, we see the regular polygon (represents the cone mesh) surrounding by the circle (represents the actual spot light). Only the vertices of the polygon fall on the circle. The area color in red shows what areas get cut off.

We can adjust the mesh slightly to encapsulate the spot light. We need to figure out what modifications should be made. One option is to increase the radius of the light, and increase the angle of the cone mesh by some amount. If we use a constant amount, it would be a large value to cover for all the cases. So we need to calculate a new angle and radius for each mesh, and use that for the cone mesh. Here is the math to figure out those values. Let's assume that we use a mesh that has 'n' sides on the cone. Our aim is to get the base of the cone mesh to encapsulate the base of the spotlight circle. For that we should do the following:

From the diagram, I've marked the following:
  • r = original base radius of cone
  • nr = new radius which is the line between the center to the vertex of the polygon
  • a = angle between r and nr
We can use the following formula to get nr:
nr = r / cos(a)

Next, we calculate the new angle and new radius of the cone mesh.
From the above diagram, we can calculate the following:
  • b = original angle of cone
  • h = height of cone = s * cos(b)
  • c = new angle of cone = atan(nr / h)
  • t = new size of cone = nr / cos(c)
Once you calculate 'b' and 't', you can use that as the angle and the size to render the cone mesh. The end result you get is this:

Hooray, no more cuts in the light source.

No comments: