popping artifacts with shadow volumes and smooth shading

If you’ve ever been irritated with shadow volumes when you see polygons “pop” into
and out of shadow, and the ugly interaction it has with smooth shaded surfaces, here’s an approach you may want to take a look at.
http://www.r3.nu/~cass/shadow_volumes/

It includes some images, an email thread discussing the solution, and updated source code for the infinite_shadow_volumes demo.

I’d be interested to hear if others have success with this approach.

                           Thanks -
                           Cass

I can’t seem to find the timer.h file, is it in one of the SDK’s ? Can you provide a binary ( or the timer.h file ) ?
I did some tricks with the silhouette in the past but it didn’t work when a model cast a shadow onto its silhouette boundary. That will be the first thing I check with your demo .

You can get it from
http://cvs1.nvidia.com/OpenGL/src/demos/infinite_shadow_volumes/

I’ll be interested to hear your results.

Thanks,
Cass

Originally posted by cass:
[b]
If you’ve ever been irritated with shadow volumes when you see polygons “pop” into
and out of shadow, and the ugly interaction it has with smooth shaded surfaces, here’s an approach you may want to take a look at.
http://www.r3.nu/~cass/shadow_volumes/

It includes some images, an email thread discussing the solution, and updated source code for the infinite_shadow_volumes demo.

I’d be interested to hear if others have success with this approach.

                           Thanks -
                           Cass[/b]

Unfortuantly I haven’t had any success with the infinite_shadow_volumes code at all. Maybe it’s just my 3D model data (just 3DS models), but I haven’t been able to get the winged edge, or anything else to work.

Oh well.

I thought about your algorithm, but discarded to use it (atleast at the moment).
The problem is u need to check each polygon if it is facing the light each time u render the mesh (atleast everytime the relation betweeen mesh and light changes which is each frame for me).

I will just think a bit more about it, but i don’t see a fast solution for that.

At the moment i am not selfshadowing objects that have problems with that (like planets) on other objects, i can just hope that it isn’t that recognizable.

By the way is that also noticeable with shadowmaps ?
I only have a geforce2go and 2mx at home so no chance to check this now…

Lars

Cass, one word…absolutely brilliant ( ok, two words ). I hacked it into my engine ( using glVertex/attrib calls ) and it works. I’ll have to think about why it works ( I just looked at the comments in the code ).
From initial tests, I see absolutely no problems with this method. It works on completely general scenes.

Originally posted by Lars:
[b]I thought about your algorithm, but discarded to use it (atleast at the moment).
The problem is u need to check each polygon if it is facing the light each time u render the mesh (atleast everytime the relation betweeen mesh and light changes which is each frame for me).

I will just think a bit more about it, but i don’t see a fast solution for that.
Lars[/b]

this is just a simple dotproduct per triangle, very quick, most engines done this before hardware t+l came in + doing your own backface culling wasnt such a plus.

btw very nice cass, as i wrote on these forums before the ‘popping’ effect was disgusting glad to see its been solved (havent looked at the paper though)

Yay! Just when I get my inf shadow volume prog working correctly a solution to the ‘popping’ comes out. Cool!

Now all I need to do is make shadows cast from something more complex than a cube.

-SirKnight

I dont say that this is useless, it is an extrem cool extension to the standard algorithm. But it slows things down a bit.

I need to build two new indexlists for each instance of an object i draw [edit]and that for each light that affects the object[/edit].

But i am still thinking about it…
And maybe i can put it into the calculations that do the bumpmapping. If i do them outside a vertex program i could sort out the polygons where we have vertices that point away and towards the light. And after that rendering just those polygons with the changed stencil function. This would involve a second render call, but their would only be some polygons to draw…
Maybe i will do this, but i have to go away from the vertex programs…poor >gf2 users.

Lars

[This message has been edited by Lars (edited 09-21-2002).]

Cass,

We emailed back and forth when this was posted on the gdalgorithms list a few weeks ago. At the time you didn’t believe me when I told you this produced artifacts. Now I can show you what I’m talking about. The problem comes from concave areas. The shadow ends up getting cut off at the beginning so it looks like it’s coming from nowhere. For instance turn the model a little and look at his helmet. You can see there’s a shadowed triangle on his right side of his helmet. This seems to pop in when you turn him. In my tests with a model that was tessellated more than this one I had more than a just a few occurrences. It might not be as jarring as the popping but imho if it produces errors its worse. I just went back to the inset method because it ended up really causing problems.

Brian

Hi Brian,

I still contend that this approach behaves properly for situations where smooth shading behaves properly. That is, if your shading normals are “bad” and produce a fully lit triangle that is backfacing the light, then it’s going to look wrong – but that’s bad shading anyway.

The point is that smooth shading with shadow can produce shading errors either way. There is no “correct” here, as far as I can tell because one method is using interpolated vertex shading and shadowing is done at polygon edges.

I really would like to see an example where this approach fails on a well-tessellated piece of geometry with good smooth normals.

The knight is so geometrically undersampled, that it’s hardly a good case. That’s what you get with programmer art, though. Lucky it wasn’t a teapot, though at least the tessellation would have been better. :stuck_out_tongue:

Thanks -
Cass

I tried to recreate the problem that Brian mentioned.

Here’s a shot ( yes, same old textures and lousy map ), http://www.geocities.com/SiliconValley/Pines/8553/ShadowTest.html )

The green lines are the normals. The problems occurs in the V-shaped area. It’s basically a deformed patch.

Edit:
It doesn’t occur in all concave areas, only something exaggerated like the V-shape.

[This message has been edited by PH (edited 09-21-2002).]

Hi cass, i came up with this method with brian and we tried this approach a while ago. if i understand what you did right you cause poly’s to not shadow themselves. if another poly casts a shadow it will show up, but polys simply facing away from the light dont shadow.

this should work in theory, but when you have and s curve like the one shown in the post above you run into problems. the polys are rotating tward the light enough so that some of the bumps are lit, but the actuall poly is still not facing the light. this would be fixed with the normals of the bumpmap being close to what the poly normal is, but that sorta ruins the whole concept of bumpmaps.

I do think Cass is right, the problem is due to bad shading ( the normals in the V-shape are really wrong ). Creating a sharp edge in that case would solve the problem ( since it is in fact not a smooth area ). Whether it’s easy to fix these issues automatically, is something else.

[This message has been edited by PH (edited 09-21-2002).]

in that case a sharp edge would fix it, but think about a curved surface with the same v type shape, for example clevage. There will always be the problem of non light-facing polys getting a little light because of their bump maps or smooth shading.

these aren’t a problem when the surface is going from shade to light, where popping usually occurs, but with this method you get this between a bunch of fully shaded objects so it really sticks out and pops in that place instead. just moving the popping to a new position, not really a fix

it is very important that our clevage looks good, we need to find a better fix.

[This message has been edited by Mazer (edited 09-21-2002).]

Here’s my best attempt to explain it. Any back facing triangles shadow gets canceled out. The problem comes when you have the triangle back facing the light yet its edge further from the light has normals facing the light. This doesn’t only happen in exaggerated V shapes or even only in S curves. Its not all concave areas but those are where the problem happens. It has to be concave to have a non-silhouette edge of a back facing poly to have normals facing the light.

Its really a geometric problem not a problem with tessellation. More polys will help but it can still happen. Its just less likely. it should really be on all concave areas I think just you see it when its enough to come past enough of the self shadowing.

I think to fully get rid of it you’d need more tris than you’d really want to use. I think robustness is more important than fixing most cases.

That’s my best attempt. I really can’t do better without drawing it. I could also post a shot but I have no web page.

Brian

Brian, I think you might be right ( unfortunately ).

Brian,

I’d be happy to post a shot or drawing on my web site illustrating the problem if you want to email it to me.

Thanks -
Cass

it should be possible to preprocess meshes to identify trouble spots like that and just duplicate the vertex normals (like you would to avoid tangent-space basis degeneracy).

anyone see a problem with that? in the picture posted you would just change that edge to separate verts with different normals to make a crease. the bump-maps can still make the lighting look smooth when it’s not in shadow, because the tangent-space basis does not have to be oriented the same as the vertex normals use for self-shadowing. or if you use object-space bumpmaps - no problems.

and the shadows will be correct as long as you use the unperturbed normal self-shadowing trick. (modulate bump map result by interpolated vertex normal dot light) it would avoid the problem posted in the picture, wouldn’t it?

[This message has been edited by vshader (edited 09-21-2002).]

Ok, I see at least one of the issues now.

It occurs at the edge between triangles in a concave region where there is a back facing triangle with a shading normal that faces toward the light.

I agree this does complicate things. Good call, Brian. Thanks for hanging in there with me. I’m pretty sure you can identify these cases too (at some extra cost), and keep them from being lit, but let me think about it a bit more.

Thanks!
Cass