PDA

View Full Version : Shadows and popping artifact : new fix



tfpsly
04-09-2003, 09:30 PM
Hi,
I've been thinking yesterday about how stencil shadows show "popping" of polygons going in or out of shadow. I've come up with a simple way to fix it.

In short, we disable self-shadowing at the face level (not at the mesh leve): a face cannot shadow itself!

Commonly, shadow volumes are created using the faces that are facing the light. But then the faces that are not facing the light are shadowed, even on the mesh casting shadows.

So let's build the shadow volume using the face from the "back" of the mesh (back according to the light point of view). For the "infinitly projected" vertices of the volume, compute their position as you usually do. But do not use the vertices of the mesh themselves on the other end of the volume. Instead, add to them a small displacement on the light to vertex axis.

This way a face of the back of the occluding mesh will not be in its own shadow volume. Self-shadowing will still works (as long as the displacement is small). Other meshes will be shadowed properly (it won't change anything for them).

a screenshot of the algo: http://tfpsly.planet-d.net/Files/Antipopping.jpg

tfpsly
04-09-2003, 09:33 PM
I forgot another point:
using the faces that are not facing the light can also speed up a bit the shadow volume construction.

Just think about an indoor scene. Lots of wall do not shadow anything, right? Well it happens that in this case these walls do not have faces closing a volume behind them, so these parts of the building will not cast shadow =)

JustHanging
04-09-2003, 11:13 PM
That's nice. I don't see why it wouldn't work. And it's so simple... Thank god I haven't spent too much time on stencil shadows so I don't have to feel stupid now.

-Ilkka

cbwan
04-10-2003, 01:04 AM
there is still a slight problem for concave objects.

for example, when closing a hand, fingers would shadow the palm, but also the back of the hand (which should only be shadowed by regular lighting computation), thus causing popping there.

but this should be quite marginal http://www.opengl.org/discussion_boards/ubb/smile.gif
anyway this is a good idea, I'll try this http://www.opengl.org/discussion_boards/ubb/wink.gif

(thanx to philippe for pointing this out)

Sébastien Kuntz
SNCF VR Lab

AdrianD
04-10-2003, 01:54 AM
Originally posted by cbwan:
there is still a slight problem for concave objects.

for example, when closing a hand, fingers would shadow the palm, but also the back of the hand (which should only be shadowed by regular lighting computation), thus causing popping there.



i using also this method for my shadows. usually there are no(visible) shadow-artifacts, when you do correct lighting computations, because the artifacs appear only in areas which should be black anyway...

AdrianD
04-10-2003, 02:00 AM
btw, this fix isn't really new:
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=02-20-2003&forum=iotd&id=-1

skynet
04-10-2003, 03:57 AM
"I forgot another point:
using the faces that are not facing the light can also speed up a bit the shadow volume construction."


I implemented this "new idea" about four days ago :-) But in fact, backface extrusion raises the triangle count in most cases, because (at least for point lights) there are usually more faces facing away from the light then facing towards it. Just think of a cube, lit by a pointlight. Take the ideal case where there is exactly one face of it lit by the light. Frontface extrusion would take that one face as front and backcap, backface extrusion would use the other 5(!) faces.

rgpc
04-10-2003, 04:18 AM
So if I understand correctly you are extruding the rear facing (WRT the light) rather than (a) determining the silhouette or (b) extruding the front facing faces?

(BTW - AdrianD's link states "My colleague came up with an idea for shadow volume extrusion - if you want to use simplified mesh for the volume and have self-shadowing - extrude the frontfaces, not the backfaces!" which is the opposite of what tfpsly appears to be suggesting.)

My stencil shadows are done by determining the silhouette, extruding it and then rendering the end caps as being the front faces (near to light) and the back faces ("infinity"). When I first did it, however, I thought that the self shadowing of the back faces didn't look as nice as the normal shading you get in OpenGL.

To fix this I rendered the near cap as the back faces (with reverse winding) to get rid of the self shadowing. (See here) (http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008531.html)

However I later found that you can get artifacts when you get touching geometry. You end up with a ring of lit pixels around the areas where the geometry touches (ie. the artifacts mark where your back faces intersect the geometry that the shadow is touching). This might not be a problem for you but it may help to know that this could happen.

tfpsly
04-10-2003, 06:24 AM
Originally posted by rgpc:
So if I understand correctly you are extruding the rear facing (WRT the light) rather than (a) determining the silhouette or (b) extruding the front facing faces?

Well, I use the "rear" of the mesh to create a silhouette. The rear faces (here displaced a bit) are also used to create both caps of my closed shadow volume.

tfpsly
04-10-2003, 06:27 AM
Originally posted by skynet:
Just think of a cube, lit by a pointlight. Take the ideal case where there is exactly one face of it lit by the light. Frontface extrusion would take that one face as front and backcap, backface extrusion would use the other 5(!) faces.

That's oviously true for a cube. That's not that obvious for an indoor level: the "back faces" of your cube would be part of another area, which could be discarded thanks to portazls/pvs/whatever.

Gonna check that...

SirKnight
04-10-2003, 07:06 AM
This is an interesing topic. I think for cases where you are talking about world geometry that most of the time I beleive you won't have more triangles that are backfacing w.r.t the light as there are front facing. On the otherhand, for some object, like an entity, beit a character or something, this may be the case some of the time. Depends on the model really. Just think of..let's say a backpack in your world sitting on a desk. Now the back side of the backpack will probably not be tesselated very much since it's pretty much flat. But the other side since it sticks out and curves, it will have more polygons. If there was a light shining on the back side of this backpack, then yes there will be more back facing triangles than front. Most of the time this wont be the case for world geometry except for things like pillars or something. Right now I'm in the library of the University I go to and there are 4 sided pillars over to my left. Also there are a few cylinder ones. These would be part of the world geometry if this library were in a 3d engine and if a light was shining on one face then there would be more triangles backfacing in this case. Even for the cylinder shaped pillars, this would also happen. For walls, stairs, and other things like that, I don't see this really happening. Even if it did, it wouldn't matter since like a wall is connected to other walls, the floor, ceiling, etc.


-SirKnight

rgpc
04-10-2003, 05:05 PM
Originally posted by tfpsly:
Well, I use the "rear" of the mesh to create a silhouette. The rear faces (here displaced a bit) are also used to create both caps of my closed shadow volume.



I am curious as to how you create the silhouette just from the back faces? The "normal" way to do it (I believe) is to just find the front facing triangles that share an edge with a back facing triangle and use that edge as part of the silhouette. You extrude that edge to make your volume.

Just using the back faces seems to imply that you just extrude all of the back facing edges, without actually creating a silhouette.

Irrespective of how you do it you may still experience the problem I mentioned in my original post regarding intersecting (or touching) geometry.

DopeFish
04-10-2003, 06:22 PM
Using the backfaces for the shadow caps isnt such a good idea if you plan on having ANY 'open' meshes at all.

If you use front-faces, then these are automatically taken care of as part of the algorithm with no extra work required.

rgpc
04-10-2003, 08:28 PM
I would think that if you have open meshes then using the front or back faces will cause you problems. (ie. the faces that cause you problems as back faces will cause you problems as front faces when rotated 180degs) IMO it's best to just avoid open meshes.

tfpsly
04-10-2003, 09:31 PM
Originally posted by rgpc:
I am curious as to how you create the silhouette just from the back faces? The "normal" way to do it (I believe) is to just find the front facing triangles that share an edge with a back facing triangle and use that edge as part of the silhouette.

As long as your mesh is closed, inversing the words "front" and "back" in what you said does not change anything on the result =)

rgpc
04-11-2003, 03:22 AM
Originally posted by tfpsly:
As long as your mesh is closed, inversing the words "front" and "back" in what you said does not change anything on the result =)

You know I was going to put in "or back faces that share an edge with a front face" but I figured most people would realise that they mean the same thing. I also thought you'd understand that "just using the back faces" and "determining a silhouette with the front & back (or back & front) faces" are two seemingly different statements.

But I guess I'm not going to get an answer to my question of how you create the silhouette from just the back faces.

JustHanging
04-11-2003, 04:10 AM
If an edge is connected to only one backface, it's a silhouette.

tfpsly
04-11-2003, 07:24 AM
Originally posted by rgpc:
But I guess I'm not going to get an answer to my question of how you create the silhouette from just the back faces.

Ok, I might not have been very clear, sorry for that.
I use the classical front & back test to generate the silhouette (that is the sides of the shadow volume), and the back face to close the volume (using the back faces at one end, using the back face projected to "infinity" - that is, far enough).
The trick here being that I also move a bit the "back faces not projected to infinity"'s vertices along their light to vertex ray.