I'm facing a somewhat obvious problem with shadow volumes that I somehow failed to anticipate. I just wanted a few tips and suggestions on how to deal with it.
We love shadow-volumes because they provide perfect resolution shadows with none of the aliasing artifacts that are characteristic of shadow maps. But the only case where this fails is on the occluder itself. Since the silhouette edge is calculated on a per-polygon basis, the self shadowing can appear jagged.
I couldn't get a clear screenshot so I just drew up a pic.
What are some common ways to deal with this?
So far my ideas are:
1. Blur the shadow a lot.
2. Use very high polygon models with stencil shadows
3. Use gpu tesselation to make polygons finer
4. Use a hybrid system with a shadow-map to handle self shadowing.
1 works a bit but still creates noticable artifacts.
2 is very limiting
3 is maybe a good idea but complicated as it involves not only subdividing the mesh, but also keeping track of adjacent vertices for silhouette edge calculation
4 seems like a good idea except the main reason i'm using stencil shadows is that shadow maps are not greatly suited for point lights.
Since I am not working with an artist I get my my models from sites like turbosquid. This being the case I can't really place constraints on my models so I need to use fairly robust techniques.
In my last thread, someone suggested an algorithm proposed in this paper for how to create stencil shadow volumes with no constraints placed on the model.
The algorithm essentially comes down to first, creating a unique set of triangle-edges, where each edge has a signed counter variable initialized to 0. You create the shadow volume in two steps. First you render the front facing triangles, and while doing so, you either increment or decrement the counter value of its edges based on a certain condition (specifically, based on whether the edge is directed the same as the rendered triangle).
After all triangles have been processed, the silohuette edges are rendered based on the value of the counter in each edge object.
The exact details are not so important, my concern is a good GPU implementation. The shader would need to keep a list of counters for each edge and update them per-triangle render. Then process only those edges who's final counter value is non-zero. Since they potentially update the same value counter variable, there could be some bottleneck I think.
Is this technique just not practical for GPU optimization?
I, like you, studied OpenGL about ten years ago and recently was looking for good materials to update me, without starting from scratch. I had surprisingly little luck locating a textbook that had the topics I was looking for. This book got my attention, but I felt like it covered too much of what I already knew. I have read other books in the Morgan-Kauffman series, though, and they were pretty great!
I know its not a textbook, but since you are in the same boat I was in, I would very highly recommend these tutorials. Even if you arent using Linux, there is actually nothing Linux Specific about any of the tutorials other than the fact that there are no Visual Studio project files. Moreover I recently spoke with the author, who told me they are working on creating Visual Studio Project files so the tutorials won't be linux specific anymore.
These tutorials are extremely good and very concise. I would even suggest starting at tutorial 1. The author never uses any immediate mode rendering. He uses vertex buffer objects and shaders from the start. So even in tutorial 1 you should be learning new stuff. The first few tutorials are very brief, and they get longer as the topics get more complex.
The author also constructs a lot of wrapper classes and essentially builds a graphics engine during the course of the tutorials. I am up to Tutorial 33 and I couldn't be happier with how much I've learned. Needless to say, I'm all about these tutorials!
The only criticism I could make other than the Visual Studio Project files not being available (yet) is that the tutorials use a left-handed coordinate system, while OpenGL tutorials (from my experience) are traditionally right handed. Can be confusing if you choose to combine techniques from other online tutorials or textbooks.
Thanks for all the input guys! I just got shadow-mapping workingwith a single light, for a single model. So now I am moving towards multiple lights, and multiple models.
To avoid excessive extra-rendering, I am planning on enclosing each lamp in a bounding volume (i.e. an Axis Aligned Bounding Box) and checking for intersections with each models bounding volume. I admit I haven't read up much on this just yet, there's something called 'Cascaded Shadows' that I need to look into, but I wanted to get your input on the algorithm I came up with today.
Here's the psuedo-code. Should be pretty self explanatory:
// SHADOW PASS //
for light in AllLights
// determine which models are hit by the light
for model in AllModels:
if (collision(light.volume, model.volume)
// give model access to light data, including its shadow map
// if any models were hit by the light
if (light.modelsInView.Count > 0)
// render all models in this light's view to the light's shadowmap
for model in light.modelsInView
// FINAL RENDER //
for model in models:
for light in model.shadowCasters:
Obviously the relevant lists need to be cleared after each rendered. Further optimizations can obviously be made, such as caching shadows for stable objects. But I think the general structure is captured here, wouldn't you say?
I started out with the ASSIMP library and was pretty fond of it! But unfortunately, many models I exported from maya/3dsmax came out scrambled, skewed, and otherwise distorted. Autodesk maintains the FBX SDK and this ensures compatibility with maya/3dsmax, and FBX seems to be a pretty standard file format, so I thought it might be better choice and less hassle than ASSIMP.
However! I have to say I find the FBX SDK documentation pretty poor. Its very brief, vague, and mostly tries to teach through example code, but leaves way too many questions open (at least to a beginner). I looked around and there seem to be no textbooks available, or more detailed, comprehensive tutorials. The autodesk fbx sdk discussion boards are a bit of a ghost town and the answers I've gotten are not very helpful.
I'm pretty frustrated because I really want to learn this well, but I can't seem to find the right resources or get my questions answered. Does anyone have any advice? Would it be worth asking my FBX related questions on these boards perhaps?