PDA

View Full Version : Carmack's reversed Problem



jeppa
02-04-2002, 05:56 AM
I have a problem with "Carmack's reverse"
Stencil Shadow.Is It correct way???

code:

//Set Stencil buffer //
glDepthMask(GL_FALSE);
glEnable(GL_STENCIL_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilFunc(GL_ALWAYS,0,0xFFFFFFFFL);

//**********************//
glStencilOp(GL_KEEP,GL_INCR,GL_KEEP);
glCullFace(GL_FRONT);
drawShadowVolume();

//**********************//
glStencilOp(GL_KEEP,GL_DECR,GL_KEEP);
glCullFace(GL_BACK);
drawShadowVolume();


//***********Draw panel*************//

glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glColor4f(0.0f,0.0f,0.0f,0.5f);
glEnable( GL_BLEND );
glDisable(GL_CULL_FACE);
glBlendFunc( GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA );
glStencilFunc( GL_NOTEQUAL, 0, 0xFFFFFFFFL);
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

Thanks in Advance;

Spartacus
02-04-2002, 06:45 AM
I believe that in reverse method you should render shadow volumes using GL_GREATER depth function. The idea is to render shadow volume only on parts where it is "behind" other scene geometry.
Code would look something like this:

glColorMask(0,0,0,0);
glDepthMask(0);
glStencilFunc(GL_ALWAYS, 0,0xffffffff);
glDepthFunc(GL_GREATER); //render behind scenery
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glCullFace(GL_FRONT); //Render back faces
RenderVolume();

glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
glCullFace(GL_BACK); // render front faces
RenderVolume();

vincoof
02-04-2002, 06:53 AM
jeppa: that's the right algorithm.
What's wrong with this implementation ?

spartacus: your algorithm works fine, but that's exactly what jeppa's algorithm does http://www.opengl.org/discussion_boards/ubb/smile.gif there's just a slight different philosophy, but results are simply the same.

jeppa
02-04-2002, 06:54 AM
I' have tried this method,it does not work.

Thanks

Sandro

jeppa
02-04-2002, 07:00 AM
I have seen,some artifact in my demo.the shadow volumes does not work correctly with
Carmack's reversed.

jeppa
02-04-2002, 07:04 AM
this is my projective matrix,is it correct?
gluPerspective(45.0f,width/height,0.1,100.0);

Thanks

Sandro

vincoof
02-04-2002, 07:16 AM
I don't think the projection matrix have to do with shadow problems.
But heh, anyway this is correct.

If reversed do not work, try the "standard" unreversed algorithm.
It might work.

jeppa
02-04-2002, 07:20 AM
The standard algorithm work correctly,but
I have a problem when the shadow volumes
intersects the near clip plane.

Thanks

Sandro

PH
02-04-2002, 07:34 AM
jeppa,

Try this thread,
http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/003593.html

vincoof
02-04-2002, 08:31 AM
hey, that's a very interesting thread. thanx.

but most of the links are broken, and I still can't get understanding how to go through Carmack's far plane problem. http://www.opengl.org/discussion_boards/ubb/frown.gif

PH
02-04-2002, 08:59 AM
...but most of the links are broken

Yes, all the NVIDIA links are broken. All the papers are still there though.


...and I still can't get understanding how to go through Carmack's far plane problem. http://www.opengl.org/discussion_boards/ubb/frown.gif

You'll have to compute a MaxZ value that will completely enclose all your shadow volumes and use that when you specify your frustum far plane.

jeppa
02-04-2002, 09:17 AM
thanks for your reply,but I have use the Carmack's Reversed with md2shader (demo from
Nvida):it does not work,artifact on screen

Thanks.

PH
02-04-2002, 09:24 AM
If you just change the stencil ops then it wont work. md2shader uses open ended shadow volumes - Carmack's reverse requires closed volumes.

jeppa
02-04-2002, 09:42 AM
I change order of the vertexs of polygons???
es:0,1,2,3 ->3,2,1,0??

vincoof
02-04-2002, 10:02 AM
> You'll have to compute a MaxZ value that will completely
> enclose all your shadow volumes and use that when
> you specify your frustum far plane.

That's what I understood when I read the "other" thread, but I ended up in applying a 10000.0 far plane and I still get ugly effects. I computed vertex coordinates from OpenGL modelview matrix and the farthest vertex is at Z=1000.0f (approximatively).

Edit: Aw, I think I need to display the cap... If so, that's a _bad_ thing since it needs to draw more polygons... http://www.opengl.org/discussion_boards/ubb/frown.gif

[This message has been edited by vincoof (edited 02-04-2002).]

Spartacus
02-04-2002, 10:36 AM
Originally posted by jeppa:
I change order of the vertexs of polygons???
es:0,1,2,3 ->3,2,1,0??


Well, if you declare shadow volume verts in wrong order, it will generate wrong results. So you could try to change shadow volume vert order. By the way what kind of artifacts you get on the screen? (screenshot maybe?)

Vincoof: There is a great difference between rendering with depth func GL_GREATER and GL_LESS. With GL_GREATER you can eliminate problems when shadow volume intersects with near clipping plane. Or am I completely wrong? These things can get quite confusing http://www.opengl.org/discussion_boards/ubb/smile.gif

vincoof
02-04-2002, 10:53 AM
Yes, quite confusing somehow ^^

well, let's take a look at jeppa's code and your (spartacus) code :

Jeppa wrote :
glStencilOp(GL_KEEP,GL_INCR,GL_KEEP);

Assuming he didn't change the depth function, so it is something like GL_LEQUAL

Spartacus wrote :
glDepthFunc(GL_GREATER); //render behind scenery
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);

The stencil operations become :

Jeppa's stencil :
- if stencil fail, KEEP stencil value
- if stencil ok, and zfail (eg z is NOT LEQUAL), then INCRement stencil value,
- if stencil ok, and zpass (eg z is LEQUAL), then KEEP stencil value.

Spartacus' stencil :
- if stencil fail, KEEP stencil value
- if stencil ok, and zfail (eg z is NOT GREATER), then KEEP stencil value,
- if stencil ok, and zpass (eg z is GREATER), then INCRement stencil value.

Huh, please explain me where's the diff http://www.opengl.org/discussion_boards/ubb/wink.gif

jeppa
02-04-2002, 11:03 AM
yes my scene it is render with :
glDepthFunc(GL_LEQUAL);

vincoof
02-04-2002, 11:40 AM
okay, I give up http://www.opengl.org/discussion_boards/ubb/frown.gif
I can force my application not to project shadows on the near plane, so I will do with it and stick to the "unreversed" style.

Thanx for the nice discussion anyway. It is really interesting.

Spartacus
02-04-2002, 12:45 PM
Well this is how I do it:
1. Render scene lighting enabled
2. Render back faces of shadow volume using depth func GL_GREATER and increment stencil. Basically this simply renders only parts of volume that are behind rendered scene geometry.
3. Render front faces using GL_GREATER and decrement stencil.
4. Render scene unlit whre stencil other than 0.

This way shadow volume can intersect with near clipping plane, and still create correct shadow. Offcourse shadow volume caps should also be rendered to create the right effect. This makes life lot easier because you don't have to project shadow volume cap to near plane.

Vincoof: Check out this thread http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/003712.html
There seems to be quite good explanations about the technique.

[This message has been edited by Spartacus (edited 02-04-2002).]

[This message has been edited by Spartacus (edited 02-04-2002).]

ToolTech
02-04-2002, 01:20 PM
I thought I could share a new technique with you for automatic capping in almost 100% of the cases. No need to calculate geometry capping or to extend far plane to fit shadows.

The algo is named MAC and is based on carmacks reverse with some extensions. The algo can be found at http://www.tooltech-software.com

/Anders

Spartacus
02-04-2002, 01:35 PM
That's pretty intersting method. This method requires shadow volume to be rendered two times (if I understood correctly), doesen't this consume fillrate too much? However no capping ruired makes that method pretty intriguing. Must lookinto this.

vincoof
02-04-2002, 11:59 PM
tooltech:
Your method eliminates some problems, but I'm still experiencing problems with self-intersecting geometry with its shadow.

Anyhow, it odesn't seem to exist a 100% reliable method, so I'll stick with the standard unreversed algorithm, which works quite good. I experience more than lots of problems with the reverse algorithm...

ToolTech
02-05-2002, 12:15 AM
Our algorithm is just an extension to the carmacks reversed which solves the issues about the far plane capping. However we have sen in our code that it works in almost 100 % of the cases without the need for capping. The only situation it doesn't solve si when you are standing in a shadow that extends from the near plane to the far plane and the inside of the shadow overlap in both the far and near plane. We have added a test for this which makes the shadow work in 100 %.

one thing worth to mention is that you only need to do the first additional rendering (the pseudo back capping) when the volume pos + extent reaches beyond back plane which makes it easy to accellerate. This means that we can do shadows with an average of one extra pass for shadow volume but without the need for geom capping...

This method in combination with shadow map extrusion is quite powerfull.... (and could be implemented in future HW ;-) )

/Anders

Julien Cayzac
02-05-2002, 01:11 AM
1. Render Shadow volume front geometry with disabled depth buffer, increment stencil on Z pass, No color, No Z update
2. Render Shadow volume back geom with disabled depth buffer, decrement stencil on Z pass, No color, No Z update

I don't understand these 2 first passes. What's the purpose of a Z test if depth buffer is disabled anyway ? I just understand this as a NO_OP...

Or is it a way of getting rid of shadow volumes intersections by filling the stencil buffer with a kind of "intersection maks" ?

Julien


[This message has been edited by deepmind (edited 02-05-2002).]

[This message has been edited by deepmind (edited 02-05-2002).]

ToolTech
02-05-2002, 01:18 AM
It refers to the last operator in glStencilOp. It will always pass as there are no geometry drawn yet. The only thing this does is to create a stencil value where the volume intersects the back plane. Only do this when the volume extens beyond the back plane...

PH
02-05-2002, 06:19 AM
Why would anyone render their shadow volumes twice, when all it takes is moving the far plane and using Carmack's reverse ? Computing a new (approximate) far plane is a lot cheaper than drawing the volumes twice.

Paul J. Diefenbach is the researcher who came up with using a second shadow volume rendering to build a cap in the stencil buffer.

Mark Kilgard's (NVIDIA) has an extremely elegant algorithm though certainly not an obvious one.

ToolTech
02-05-2002, 06:38 AM
You can not use the same depth precision then. If you render geometry with different lighting (no specular etc) you will end up with a render pass with much lower z buffer resolution if your shadows are deep.

PH
02-05-2002, 06:57 AM
Originally posted by ToolTech:
You can not use the same depth precision then. If you render geometry with different lighting (no specular etc) you will end up with a render pass with much lower z buffer resolution if your shadows are deep.

Yes, that's true. In practice it doesn't really seem to be a problem - I clip the shadows to solve some other problems, so the shadows don't extend a lot farther than the other geometry. I think getting a balance between CPU work and fill rate consumed is the key to getting the best performance.

vincoof
02-05-2002, 07:42 AM
Hey, I finally got it working. Thanx a lot guys !!!

About the frustum, I don't like changing the far plane for the shadow algorithm.
First of all (as noticed) it changes the depth precision.
And secondly, in my applications I sometimes use the viewing frustum for miscellaneous geometrical computations. If the frustum varies randomly (which would be the case if the far plane was guided by shadows) then it would mess up all the algorithms that use the frustum.

IMO, a good solution is to compute limited volumes, eg extend edges with a smart scale so that the extended vertices always lie in front of the far clipping plane.

cass
02-05-2002, 07:44 AM
If n << f, then pushing the far plane out to very_far doesn't hurt the depth precision in the [n,f] range much at all.

The precision in the [f,very_far] range is bad, but who cares?

Cass

ToolTech
02-05-2002, 01:17 PM
Just wanted to comment on PH comment on Paul J Diefenbachs method to cap. As far as I know he caps the front plane always when the viewer is inside volume.

Carmack's reverse method handle this but leaves the back plane unguarded. My algo (MAC) caps the back plane when nessecary (The combination of a reversed cap + a far plane z biased clear of the stencil buffer)

The similarity between Diefenbach and MAC is that is uses an conditional extra pass but the calculation effort to decide whether to use the extra pass is very different in complexity.

A final comment on this is that the MAC algo enables the carmack's reversed to be used without changing the view frustrum. You do not need to iterate over all possible shadow depths to get the extent. The extra passes is only needed for shadows which extends beyond far plane and this can be decided at render time. Most shadows in a scene do not need the extra passes....

In my point of view.. The carmack's reversed + the MAC (extra conditional pass) gives a very good shadow imp without rescaling of view frustrums or pre knowledge about the extent of the shadows to be drawn...

/Anders

vincoof
02-06-2002, 04:43 AM
Just an idea...

Wouldn't it be possible to render the scene normally (eg with a "standard" far plane), then change the projection matrix for rendering the shadow volumes so that the far plane is very far ? Because the far plane only causes to alterate the shadow volumes' depth precision, it would not be a great loss.

But the problem is to configure the depth buffer in order to match the two different projection matrices (because depth is always in the range [0,1], and then when projection matrix changes the depth min and max *world* values changes).

I thought about using either glDepthRange or glPolygonOffset to trick the depth buffer, but I can't see a good one working...

PH
02-06-2002, 06:33 AM
vincoof,

It will most likely introduce more problems than it solves. If you look at Cass' post, you'll see that precision really is not a problem in practice. I use the frustum for all kinds of calculations too but nobody is stopping you from using the original ( with the far plane of your choice ) for your other calculations. Moving the far plane is only for making sure the shadows are drawn correctly - all your geometry ( that is shadowed ) will still lie in the range [n,f] ( which is why nobody should care about the precision in the [f,very_far] range ).

vincoof
02-06-2002, 06:38 AM
Cass is right, but if we could use a simple solution that does not hurt the depth precision *at all*, that you would be great. wouldn't it ?

PH
02-06-2002, 07:12 AM
Sure, but that would be like solving a problem that isn't there... try setting your far plane at 50000 ( or even 100000 ) and see if it makes a _noticable_ difference to what's rendered in the [4,4000] range - it doesn't, which is the point I'm trying to make.

vincoof
02-06-2002, 07:43 AM
Obviously you're right, but the thing on which I was thinking is polygon offseting.
Because polygon offset units depends on the depth precision, it becomes even more difficult to use it correctly with a very far plane.
Anyway, because depth buffer uses a logarithmic scale, it doen't hurt that much even in this particular case.

ToolTech
02-06-2002, 07:48 AM
If you got a near plane at 0.1 and far plane at 500. Would this not be different rendered than having a far plane at 10000 ???? Or am I getting this wrong. I certainly get effects when changing the depth buffer like z fighting for close surfaces etc...

cass
02-06-2002, 08:02 AM
Right - you can't change your frustum without introducing invariance issues.

It's probably a lot less trouble just to push your far plane out, but continue to do frustum culling with the old far plane.

Cass

PH
02-06-2002, 08:06 AM
ToolTech,

I always set znear to 4 but even using [0.1,100000] doesn't cause any problems for close surfaces in my own work.

EDIT: I only made a quick test using those values but of cause I wouldn't recommend it..

[This message has been edited by PH (edited 02-06-2002).]

ToolTech
02-06-2002, 09:20 AM
Ok. It looks like some people like to extend the view frustrum and do not get any anomalies like I do. I will not argue any more.

In my case where I do soft shadows, rendering objects with disabled specular components, mixing output from severla light sources etc. it is vital NOT to change the view frustrum.

The are many other cases like usage of impostors at far plane. Terrain occluders. Decals and polygon offset. Shadow maps in combination with shadow volumes etc...

In applications like this the MAC extension to the Carmack's reversed is a VERY easy way to manage shadows in such situations. Ok I have got no more to say...

/Anders