Today I implemented additive lighting & shadows, ie a more realistic (and more expensive) technique where multiple lights and their shadows can be combined more realistically. You can see my initial results in this screenshot. Basically we have to split or categorise every pass into an ambient, per-light or decal pass, and build up the lighting in the scene by rendering the ambient passes, then rendering per light whilst masking out shadowed areas, then render the textures over the top.
Heh, I guess that’ll teach me to speak too soon. I was so sure my new shadow culling system was working last Tuesday, but in fact there was a bug which caused shadows to be prematurely culled. I spent ages tracking it down, thinking it was in the cull volume building, so I added debug volumes and tried lots of things - in the end it was a simple error in Frustum::getWorldCorners which I hadn’t noticed before because it had no discernable effect on previous usages of it.
Wow, something actually went quicker than I expected for a change! 😀Tonight I polished off the shadow caster elimination code I’ve had in my head for a while - previously the location of shadow casters was pretty basic - since obviously objects which are not in the camera’s frustum can still cast shadows into the view there is an issue of how you efficiently locate all objects which can be casting visible shadows.
I finally nailed some of the more annoying problems I’ve had on my TODO list - it turns out the lack of shadows when hardware skinning (which actually caused GL to crash in the driver - yuck), were due to a feature I put in, but forgot about. :/ I wanted to suppress the update of a shadow buffer to the hardware version when only doing the software vertex blend because of the shadow, because otherwise you would unnecessarily upload the buffer twice.
Manual meshes were not prepping for volume constructions properly, and there were some issues with prepping meshes which used shared vertex buffers for multiple components. These are now fixed. I still have a number of issues with animated meshes which I’m sure are related - that is the hardware skinning disappearing shadow problem, and the D3D9-fullscreen-software-blend glitch, neither of which I’ve been ableto explain despite detailed tracing through the code. I have also found that if I prepare an animated mesh for volume construction more than once, I get random crashes a few frames later, which suggests there is a buffer overrun somewhere.
I fixed another shadow visual glitch, where zpass and zfail volumes overlapped and caused artefacts, and squashed all the release mode-only crashes (I hate those). I’m now very happy with the stability and performance of my stencil shadows, although I have a number of optimisations yet to do which should primarily help with larger scenes. I’ve put my todo list up on the site so people can see what I have on my plate - as you can see I have a few more things on there left to do before I feel 0.
Well, after ruthlessly crushing the light cap problem underfoot, I now have what appear to be pretty darn stable shadows. I’ve had a couple of small problems, but I think they’re due to dodgy meshes rather than bad code - with volumes it’s very important that the mesh is completely closed. I’ve knocked off a few more items, namely 2-sided stencil support (which allows you to render ½ as many shadow volumes, which is nice), more config options, multiple light combinations and being able to turn off the shadows for each light.
They say the dark side of the Force is easier and more seductive; well, it turns out the same applies for shadow volume caps. 😀They’re needed whenever you enter the projection of the shadow volume (towards or away from the light), at the time when you need to use the ‘zfail’ volume rendering method (otherwise known as the Carmack method), because otherwise you can see out the ‘tube’ which is formed by the extrusion of the silhouette edges.
I’ve been slowly chipping away at the issues with shadows; I’ve resolved the majority of the issues with degenerate edges (those for which a second triangle cannot be found), and squashed lots of issues with animated meshes. I’m using modulative shadows as my test bed, here’s a screenshot I still have some issues to resolve, such as the use of 2-sided stencil operations (which allow you render the shadow volumes once instead of twice), zfail volume rendering, and GL which seems to be getting worse performance wise on nVidia right now.
Well, I’m finally back looking at shadows again, I got seriously distracted sorting out hardware skinning, because it turns out that there are several things that can throw it off kilter, like the fact that the GeForce4 does not support the UBTYE4 vertex element type (used for matrix indices), which is a bit naff if you ask me. Even my little Radeon Mobility supports that. I toyed with the idea of trying to deal with it, and tried a few options but they were all very hacky, or required much more vertex buffer memory than I was happy with, so in the end I decided not to support hardware skinning on cards which can’t handle UBYTE4 but can handle vertex programs, meaning that the prerequisite for hardware skinning is vertex program and UBYTE4 support.