Shadow Caster Volumes For The Culling Of Potential Shadow Casters

If you find this article contains errors or problems rendering it unreadable (missing images or files, mangled code, improper text formatting, etc) please contact the editor so corrections can be made. Thank you for helping us improve this resource

1.0 Introduction

To efficiently render a scene, the minimal possible amount of geometry must be passed to the GPU. Objects that do not intersect the view frustum can be ignored. When rendering using an additiveshadow algorithm (stencil shadow volumes or shadow mapping), the scene is rendered in multiple passes, one pass for each light source. In this case objects can be ignored when they do not intersectboth the view frustum and the light source's bounding volume.

For shadow casters though, checking only against the view frustum is not sufficient. Objects that lie outside the view frustum (herein “the frustum”) can still cast shadows into thevisible area. Diagram 1 shows a simple case.

Diagram 1: B lies outside of the frustum, yet it casts a shadow into the frustum

If instead, the light source's bounding volume is used to determine potential shadow casters, then all correct shadow casters will be returned. But this approach is too conservative. It will alsoreturn true for objects that cannot cast a shadow into the frustum. The final results on the screen will look the same, but it will take longer to render as all the vertex calculations must beperformed. Diagram 2 shows such a case.

To solve this problem, we instead check against a shadow caster volume. The shadow caster volume is the convex polyhedron that intersects any objects that can cast a shadow into the view frustum.It is calculated by extending the view frustum to include the light source. Diagram 3 shows the shadow caster volume for the scene in Diagram 2.

Diagram 3: The shadow caster volume for the light source includes B, but not C

Note that as well as checking potential shadow casters against the shadow caster volume, they should also be tested against the light source's bounding volume. This is particularly important forsmall point light sources.

For a description of how a convex polyhedron (frustum or shadow caster volume) is used with scene management data structures like an octree or a BSP tree, see [LENG02a].

This article will cover the calculation of shadow caster volumes, and in the process of doing this, will also cover LUP decomposition of matrices. LUP decomposition turns out to be necessary forthe numerical stability of this algorithm, even when using double precision IEEE 754 calculations.

The way the shadow caster volume is generated depends on the type of the light source. To start with we will cover point lights, then later directional lights. Finally, the special case of shadowcaster volumes for semi-transparent objects is discussed.

2.0 Point Light Sources

For the purpose of this article, we will assume that the frustum is stored as a set of planes. Where the frustum volume is the intersection of the plane's positive half spaces. This means thateach plane's normal points inwards as shown below.

Diagram 4: View frustum plane normals point inwards

For a point light source, when the light lies within the frustum, the shadow caster volume is the same as the frustum.

When the light lies outside of the frustum, the frustum must be extended to include the light. We create a new polyhedron, using all the frustum planes that the light source lies on the positiveside of, and creating new planes for each edge that is shared by one plane that points towards the light and one that points away.

But the devil is in the details. Firstly we need to be able to calculate the edges of the frustum, then we need to ensure the normals of the new planes point inwards, not outwards.

If we know that the view frustum is always a simple six plane pyramidal frustum, then we can use the known view space edges, and transform them into world space. But to handle more general cases(such as the frustums formed by portal clipping, or the bounding volumes of semi-transparent objects discussed below) we treat the frustum as a convex polyhedron.

To find the edges of a convex polyhedron, we first need to find the vertices of the polyhedron. Finding the vertices involves checking all three plane combinations to see if they intersect at apoint, then checking that the point is on the polyhedron's surface. We define a plane P as a unit length normal vector N and a scalar distanceD to the origin.

D is the signed distance from the plane to the origin in the direction of N .

The signed distance from a plane P to a point Q in the direction of N is,

A point Q lies on a plane if Q · N + D = 0. So to find the intersection of three planes, we need tosolve a system of three linear equations,

In matrix form,

There is not necessarily a solution to this system of equations, and neither is there necessarily only one solution if they are solvable. But we are only interested in the case of three planesintersecting at a single point, and this corresponds to the case where there is a single solution to the system of equations.

The method that most people are probably familiar with for solving such a system of equations, is to multiply both sides by the matrix inverse like so,

While mathematically correct for real numbers, this unfortunately gives inaccurate results when using floating point numbers. If we do not solve this system of equations accurately, then for avalid polyhedron vertex, we are liable to discard it as may end up on the negative side of a plane. A much better way to solve the equations is LUP decomposition (also known as LU decomposition)[CLRS01] , [PTVF88].

2.1 LUP Decomposition

The basic idea of LUP decomposition, is that given a non-singular (invertible) square matrix M , we want to find matrices L ,U and P such that,

Where L is unit lower triangular, U is upper triangular and P is a permutation matrix. A lower triangular matrix hasall entries above the main diagonal 0, and an upper triangular matrix has all entries below the main diagonal 0. A unit lower or upper triangular matrix is lower or upper triangular with all entrieson the main diagonal equal to 1. For example, a unit lower triangular matrix,

and an upper triangular matrix,

A permutation matrix has one entry per row that is equal to 1, and the rest equal to 0. When pre-multiplying a matrix M with a permutation matrixP , the rows of M are swapped. For example,

We want to find L and U to allow us to solve the system by using backwards, then forwards substitution. Given a system of equations in uppertriangular form, we can solve using backwards substitution as follows,

And forwards substitution with a lower triangular works the same way, only we start from the first row of the matrix, not the last. With a unit lower triangular matrix, we know the entries maindiagonal are 1, so it's even simpler,

Once L , U and P are found (and they always exist for non-singular square matrices, though they may not be unique), itbecomes very simple to solve MV = C .

So now we need to find L , U and P . This is done using Crout's method .

First we'll look at the simpler case of LU decomposition (no permutation matrix).

Let M be an invertible n×n matrix.

Where

and

is called the Schur complement of M with respect to m11. If M is invertible, then so is the Schur complement (see[CLRS01] for proof). This then gives us a recursive way to find the LU decomposition. Let L' U ' equal the Schur complement, whereL' is unit lower triangular and U' is upper triangular. Then we have,

To implement this algorithm, the tail recursion of decomposing the Schur complement into L' U ' can be converted into iteration.

The LU decomposition will fail if there exists i in {1,..., n } such that mii = 0. Even if no such i exists, the LU decomposition will still havenumerical stability problems if any mii is a very small value.

LUP decomposition permutes the matrix so that at every step we are dividing by the largest possible value. This additional step of finding the best (largest) value and swapping rows appropriately,is known as pivoting. If no non-zero value is found in the first column of any Schur complement, then the matrix M is not invertible.

Listing 3 implements LUP decomposition, and using the decomposition to solve systems of linear equations. The permutation matrix P is stored as a permutation array, sincethis is a more compact representation for exactly the same information.

2.2 Calculating the New Shadow Caster Volume Planes

Now that we have the points of intersection of the planes, we need to test if they are near the polyhedron, and are therefore vertices of the polyhedron. To check if a point lies in or on thepolyhedron, we find the distance from each plane to the point. We say the point lies in or on the polyhedron if every distance is greater than some very small negative value. Note that in Listing 2,this “small negative value” is not a constant, but proportional to the plane's distance from the origin. This is because of the cancellation that occurs when subtracting two floatingpoint numbers that are similar in value [GOLD91] .

From the vertices, we need to determine the edges of the polyhedron, where an edge is simply a pair of vertices. To do this, we loop through each pair of vertices, and if the vertices share twocommon planes, then we output an edge. Notice that this requires us to store the plane indices with each calculated vertex.

Now that we have a method for finding the edges of a polyhedron, we return to the problem of constructing the new planes needed for the shadow caster volume.

Given three distinct points we can construct a plane as follows. First we need to calculate the plane's normal. For this we use a cross product, but to get the direction correct, we need to imposea winding order on the points. For a clockwise winding order of points P1, P2 and P3,the normal can be calculated as follows,

Now we have reduced the problem to calculating the plane given the normal N and a point P on the plane. So we need to calculate D, the distanceto the origin.

Let Q be the point on the plane closest to the origin, so

And since Q lies on the plane,

Substituting for Q ,

So given three distinct points with clockwise winding order, the plane they form is

To form a new shadow caster volume plane, we have three points, the two silhouette edge endpoints, and the point light source's location, but we do not have a defined winding order. So tocalculate the plane, we use the above method for three points, then flip the direction of the normal if necessary. We use a point known to be within the frustum to test if the normal needs to beflipped. If the signed distance from the plane to the point is negative, then the normal is pointing in the wrong direction. A simple way to get a point known to be inside the frustum, is to take theaverage of all the frustum's vertices.

3.0 Directional Light Sources

Calculating the shadow caster volume for a directional light source is very similar to the calculations for point light sources. Diagram 6 shows the shadow caster volume for a directional lightsource.

Diagram 6: Shadow volume for an infinite directional light source

Notice that the shadow volume is not a true polyhedron, as it has an infinite volume. Depending on your needs, you may wish to add an additional plane to make the volume finite.

When generating the shadow volume for a directional light, we keep view frustum planes if their normal points towards the light source (plane normal dotted with the light's direction is negative),and discard them otherwise. Silhouette edges are again the edges between kept and discarded planes.

New planes are generated using the two silhouette edge endpoints, and a third point obtained by adding the light source direction vector to one of the end points. Again the direction of theplane's normal should be checked to determine if it needs to be flipped.

4.0 Semi-Transparent Objects

Rendering semi-transparent objects that can receive shadows is very expensive. First the scene must be rendered as normal using all opaque objects. The main steps for an additive stencil shadowalgorithm [LENG02b] are given below,

Render to the stencil buffer, shadow volumes for all shadow casters, that intersect the shadow caster volume and the light source's bounding volume.

Render semi-transparent object using current light source.

While more light sources, goto 2.

An important improvement is that the shadow caster volume calculated for each light source, semi-transparent object pair, can be greatly reduced from the general shadow caster volume for the lightsource. Instead of calculating the shadow caster volume from the view frustum, we instead calculate it from the semi-transparent object's bounding box.

Diagram 7: The shadow caster volume for a light source and a semi-transparent object.

Once we convert the semi-transparent object's bounding box to a polyhedron, the calculation of the shadow caster volume is the same as for a view frustum.

We assume that the bounding box is stored as four vectors, R , S , T and C .R , S and T are the orthogonal axes of the bounding box, with the each vector's magnitude being the size of the box alongthe axis. C is the center of the bounding box.

For each axis, we want to calculate the two planes for the box's end points. Let A be the axis we are currently dealing with.

Diagram 8: End point planes for axis A of bounding box.

As derived above, we can define a plane given its normal, and a point on the plane. So the two planes for an axis A are,

Given a normal convex polyhedron – bounding volume intersection test implementation, polyhedron planes that meet at an acute angle are likely to give false positives. This occurs because itis possible for an object's bounding volume to intersect the positive half space of each plane, yet still not intersect the polyhedron. Diagram 9 illustrates an example of this.

Diagram 9: Polyhedra with planes that meet at an acute angle increase occurrence of false positives.

Acute angles are much more likely to occur when generating shadow caster volumes for semi-transparent objects than for view frustums. A solution to this problem is to add an additional plane tothe shadow caster volume polyhedron [LENG02a].

Diagram 10: Adding an extra plane to the polyhedron prevents the false positive.

5.0 Summary

To cull shadow casters that do not affect the visible scene, we have introduced a shadow caster volume. Only objects that intersect both the shadow caster volume and the light source's boundingvolume can cast a visible shadow.

For rendering shadow receiving semi-transparent objects, we can calculate a smaller shadow caster volume that only intersects objects that can cast a shadow onto the semi-transparent object, notthe entire visible scene.

Once the shadow casters have been determined by using a shadow caster volume, scissor tests and depth tests can be used to reduce the amount of work done per shadow caster [LENG02b] [LENG05] .

Listing 1 is the implementation of the shadow caster volume calculation for a point light source. Listing 2 is a Polyhedron class that includes the calculations for polyhedron vertices and edges,and listing 3 is the LUP decomposition implementation.