depth testing, rendering, and fake shadows

MarkJ
Unregistered
 
Post: #1
Basically, I have a system where every in-game entity has a Shadow object that gets checked against all my level geometry, and then the each Shadow object renders itself (just a textured polygon) if it needs to.

[Image: shadow1.png]

Here's the problem. In order for these fake shadows to render on top my curved level geometry, I have to turn off GL_DEPTH_TEST before I draw them, otherwise they would draw tangentially to the circular surface (and therefore underneath the ground).

The problem is, if the shadow gets rendered after other entities that are in front of it, it'll draw on top of them. I'm not sure how to work around this problem since the way my rendering currently works is that I step through each entity and render it. An entity can be anything from level geometry (which is chunked into display lists), the player, or other items.

[Image: shadow2.png]

Any suggestions on how to tacklle a problem like this? I'm thinking I might have to reorganize rendering so that everything is rendered in order of it's distance from the camera, but that'd be a huge undertaking, as right now everything rendered in the order they're loaded into the entity hierarchy.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
you could do stencil shadows or shadow mapping, either of which would solve this problem...

other than that, you could try using polygon offset (or just an offset along the shadowed surface's normal) to allow you to keep depth testing on.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #3
If all your objects have relatively high polygon counts, I can give you some code for a shader. Basically, what it does is it extends back-facing vertices away from the light for the stencil volume. For a better solution, if you know how to access the vertex data in the model, I could also give you an algorithm I used to create 0-width quads to make the shadows even better when extending the polygons. However, it might need some adapting for your case, and you need to know how to access the vertices and normals of the models. (I use it with a simple, hard-coded model using all triangles, but I'm planning on expanding it when I start my next project)
Quote this message in a reply
Member
Posts: 184
Joined: 2004.07
Post: #4
OneSadCookie Wrote:other than that, you could try using polygon offset (or just an offset along the shadowed surface's normal) to allow you to keep depth testing on.

Last time I had this problem I used this solution and it worked out all right- turn depth testing on and just move the shadow up the normal a little bit. If you have surfaces that curve a lot with respect to the size of the shadow, you could potentially make your shadow a small curved mesh itself.

Another thing you can do that is kind of wasteful but accurate is just redraw the object the shadow is on top of once per each shadow, and textured only with a single projected shadow texture. This is also a fairly common, and relatively cheap (if you can only redraw the triangles the shadow is on.)

I wouldn't recommend using shadow maps or stencil buffers- both take up an entire extra buffer that can take up a lot of memory and implementation time.
Quote this message in a reply
MarkJ
Unregistered
 
Post: #5
Thanks for the ideas, guys.

Using glPolygonOffset() almost works perfectly. I have to use a big offset for the whole quad to draw above the curved geometry, but then there's weird problems where the shadow texture's transparent parts will sometimes blend with wrong objects "underneath" it. It looks like a trade-off of bad visual artifacts for different bad visual artifacts Smile.

I guess I'll look into using stencil shadows. All I want are simple projections that extend directly below the models.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #6
Stencil shadows definitely look a lot better. The main reason I ended up doing stencil shadows, other than the looks, is the fact that I didn't want to deal with different slopes of terrain or going over buildings etc.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #7
Stencil shadows are the way to go. I've not done anything like akb825's shader-based projection, but I get pretty good performance with vanilla vertex arrays and tight code. The main issue, as I see it, is smart culling of shadows which shouldn't be visible. In my case I make an AABB encapsulating the shadow by projecting the occluder's AABB and clipping against the ground plane ( which is below the terrain ). I can then test this in the scene graph and it's good.

Also, be certain to cache the projections of objects which don't move. That alone brought me from situations where I got 5 fps to 30 or more.
Quote this message in a reply
Member
Posts: 70
Joined: 2004.06
Post: #8
MarkJ Wrote:there's weird problems where the shadow texture's transparent parts will sometimes blend with wrong objects "underneath" it.
This can be fixed by rendering all "solid" objects, and then disabling depth-writes and rendering all transparent objects from front to back.

Imagine that you render a triangle five metres from the camera with an alpha of 0.2. The OGL will blend it with whatever is currently in the colour buffer, which in this case is black.

You then render a quad ten metres from the camera that appears partially behind the triangle. When the OGL goes to render it, it will see that some of the pixels trying to be drawn (those covered by the triangle) are actually obscured by another object closer to the camera, and so it will ignore them.

For it to look correct, however, those pixels should actually be the solid colour of the quad blended with the partially transparent colour of the triangle, but the OGL has no way of knowing this. Thus you end up with a "hole" in your image, rather than a mostly-invisible triangle over a quad.

EDIT: I don't know how stencil shadows work, but I assume that they are solid-colour polygons, and so depth sorting would be unnecessary (unless there are other areas in your game where you render transparent objects)
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #9
For stencil shadows, at least how I implement them, you draw all solid objects, then turn the depth mask to false and the color mask to false for all values, draw the shadow volumes with front faces and increment the stencil buffer when it zfails, then draw the shadow volumes with back faces and decrement the depth buffer when it zfails, then set the projection matrix to ortho 0 to 1 in x and y and have one tranlucent black polygon fill the entire screen. In order to make the shadow volumes, I use the model with extra 0-length quads (which have different normals for the different polygons on its edges) and feed it into the shader. I then draw all transparent objects with z-writing off. So no, no depth sorting is necessary for the shadows themselves, but if you have transparency effects, you really should draw those after the opaque objects.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Window drop shadows NelsonMandella 9 4,998 Mar 21, 2010 02:34 PM
Last Post: NelsonMandella
  Making 2D Stencil Shadows Soft metacollin 16 14,056 Jul 22, 2009 01:59 PM
Last Post: NelsonMandella
  softening 2d shadows NelsonMandella 5 4,351 May 19, 2009 04:19 AM
Last Post: Najdorf
  Real-Time Soft Shadows MarkJ 6 4,896 Feb 17, 2007 03:10 PM
Last Post: MarkJ
  Rendering 2D Shadows for Convex Shapes Nick 16 9,313 Nov 28, 2006 11:50 AM
Last Post: memon