Rml4o
03-25-2003, 12:04 PM
Here is an idea that should enable to render multiple lights with shadow volume without clearing the stencil buffer for every light (at least in some cases).
The point is to use some bits in the stencil buffer to identify the effects of various lights.
We assume:
-Zpass method
-viewer outside the shadow volumes
-s is the number of stencil bits
-n the number of "light bits": we will see that we can treat 2^n lights without clearing the stencil buffer. The light bits are those on the left.
-m the number of "normal bits": they will be used like in normal Zpass (of course s=n+m):2^mis the effective range of the buffer
-for light number i (i in [1,2^n]) we define A(i)=(i-1)*2^m
Now, you have probably found the idea: for each light, the relevant range of stencil buffer will be in [A(i),A(i+1)-1]. The following just describes the stencil settings to make things work.
Let's consider a particular pixel, S is its stencil value.
Fill Zbuffer (and ambiant)
for light i:
draw shadow volumes with:
*front pass: if(S<A(i)+1)
S=A(i)+1
else
S++
*back pass: S--
draw normal geometry, with stencil test:
S<=A(i) (not the usual ==)
next light...
A few comments:
The trick is in the front pass: every pixel covered by a shadow volume directly jumps in the range of the current light and gets incremented if it is not already in this range. If it is, we just increment as usual.
Note that given the assumptions, the back pass can't make the stencil value decrease outside of the range of the light.
I hope I've made it clear (I didn't mention a few subtleties), tell me what you think about this (especially if I'm wrong).
Armel.
The point is to use some bits in the stencil buffer to identify the effects of various lights.
We assume:
-Zpass method
-viewer outside the shadow volumes
-s is the number of stencil bits
-n the number of "light bits": we will see that we can treat 2^n lights without clearing the stencil buffer. The light bits are those on the left.
-m the number of "normal bits": they will be used like in normal Zpass (of course s=n+m):2^mis the effective range of the buffer
-for light number i (i in [1,2^n]) we define A(i)=(i-1)*2^m
Now, you have probably found the idea: for each light, the relevant range of stencil buffer will be in [A(i),A(i+1)-1]. The following just describes the stencil settings to make things work.
Let's consider a particular pixel, S is its stencil value.
Fill Zbuffer (and ambiant)
for light i:
draw shadow volumes with:
*front pass: if(S<A(i)+1)
S=A(i)+1
else
S++
*back pass: S--
draw normal geometry, with stencil test:
S<=A(i) (not the usual ==)
next light...
A few comments:
The trick is in the front pass: every pixel covered by a shadow volume directly jumps in the range of the current light and gets incremented if it is not already in this range. If it is, we just increment as usual.
Note that given the assumptions, the back pass can't make the stencil value decrease outside of the range of the light.
I hope I've made it clear (I didn't mention a few subtleties), tell me what you think about this (especially if I'm wrong).
Armel.