Say we have a water surface at y=0 and we place a model in it, where parts are below and parts are above the water. Now I would like a partly reflective and transparent water surface and I would like the water surface to be modulated with a bluish-water-texture. The problem is when rendering the mirrored object where I would want the parts y>0 to be cut off. The right way would be to use a user clipping plane but nvidia does only support this when saccrificing a texture unit. Any suggestions?

LordKronos

05-31-2002, 10:31 AM

I suggest sacrificing the texture unit. The other option is that you could manually clip the object, but I would strong suggest you should NOT do that. Or you could try stenciling out areas, but that may not be as good either (I certainly dont think it would get you any better off than the clipping plane)

mfugl

05-31-2002, 10:41 AM

Originally posted by LordKronos:
I suggest sacrificing the texture unit. The other option is that you could manually clip the object, but I would strong suggest you should NOT do that. Or you could try stenciling out areas, but that may not be as good either (I certainly dont think it would get you any better off than the clipping plane)

Thank you for your comment. As I see it stencilling cant do the work here. And yes manually would be too slow. The clipping plane is the right way. It is really unacceptable that nvidia doesn't support such an simple feature. Even quake3 uses a user clipping plane for the portals.

Other suggestions to this problem are welcome?

dorbie

05-31-2002, 08:31 PM

Hmm.... can you afford 2 passes on the clipped reflection? Are you already using stencil?

A first pass with a stencil write on the clipped reflection would improve things. Then you stencil test on the second pass leaving you with all textures.

It's not perfect, if the clipped reflection get's occluded by the unclipped reflected geometry above the water it will pass the stencil test.

You could supplement this with primitive level culling to reduce the likelyhood of the above problem.

[This message has been edited by dorbie (edited 05-31-2002).]

dorbie

05-31-2002, 08:44 PM

Trying to solve the occlusion problem raised by my solution I realized that a depth equal test on the second pass would solve the occlusion problem if you're on a decent NVIDIA card (this isn't guaranteed on all OpenGL implementations but probably is OK on most decent new cards).

Now for the bonus. Depth equal testing the second reflection pass also eliminates the need to use a stencil test.

So you draw the reflection with glColorMask to stop color writes, and a clip plane to clip to the water surface. Then you draw the reflection with a glDepthFunc of GL_EQUAL without the clipping letting you include all your shader stuff, and any stencil you might want for other purposes.

You basically use the depth buffer to store the invisible fragment clip test result to the framebuffer.

[This message has been edited by dorbie (edited 05-31-2002).]

zed

05-31-2002, 10:38 PM

i assume an extra pass is worse than 'sacrificing a texture unit' (said with a big grin) the best way to do it is sacrifice a texture unit using uum i dont know projected textures or something (with alpha test) sorry guys http://www.opengl.org/discussion_boards/ubb/smile.gif

dorbie

05-31-2002, 11:59 PM

The extra pass is a bummer but it might save having to implement a multipass shader or compromise on the appearance of the object being reflected. It's getting drawn twice anyway, so it's 3 vs 2.

If you're prepared to sacrafice the texture unit you'd probably want to use glClipPlane, why reinvent the wheel?

I find it frustrating there's no way to work around this in a single pass, (at least nobody has come up with it yet).

dorbie

06-01-2002, 12:15 AM

How about this; assign fragment alpha using vertex values to be linearly interpolated? No texture unit required.

You map the alpha from 0-1 linearly on the object in the plane of the water such that .5 alpha fragment interpolation lands exactly on the water surface. If height changes you must reassign vertex alpha, if you want to you could easily implement a vertex shader to make vertex alpha generation by height automatic. Then you perform fragment alpha test with a reference value at 0.5. You end up with the alpha clipping at the waterline (precision permitting).

knackered

06-01-2002, 02:34 AM

Or use the fog coordinate extension, with a fog alpha range, the use the alpha test.
Essentially the same thing as using a vertex program (but more widely supported), but you lose the use of fog!

mfugl

06-02-2002, 12:25 AM

Thank you for your comments.

Stencil: As you wrote, with stencilling some of the guys 'feet' would be included.

z-buffer: it could be used, but then the model would have to be drawn z-sorted (too slow).

alpha pixel test: It may work, but I fear that precision could be a problem.

alpha-fog pixel test: I dont think alpha is a part of the opengl fogging.

user clip plane: this is the right way if the hardware supports it.

How about some of you made a small demo program which illustrated your idea? I actually think this problem is much more relevant than many other strange new hardware features. Nvidia should have implemented this long ago. Doesn't the radeon support this?

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

dorbie

06-02-2002, 06:35 PM

The model is not drawn zsorted for the zbuffer approach. It certainly needs to be drawn without the water plane in the zbuffer but that's true with any approach.

With the vertex alpha pixel test you clamp at 0 and 1, the real precision must be spent between where you know the largest polygon will be on either side of the plane while intersecting the plane.

i.e. the precision issues are mitigated by the triangle size rather than the primitive or object size. This should only be a problem if you have very large triangles.

Good luck.

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

Coop

06-04-2002, 04:08 AM

mfugl
About user clipping planes: don't forget they don't work with nVidia's vertex programs. If you have something that is drawn using vertex program and must be clipped to the water then you have to use texture shader and sacrifice TMU by yourself http://www.opengl.org/discussion_boards/ubb/smile.gif

Coop

mfugl

06-04-2002, 01:05 PM

Originally posted by coop:
mfugl
About user clipping planes: don't forget they don't work with nVidia's vertex programs. If you have something that is drawn using vertex program and must be clipped to the water then you have to use texture shader and sacrifice TMU by yourself http://www.opengl.org/discussion_boards/ubb/smile.gif

Coop

Where did you get this idea? They clip on a per pixel basis using a tmu always and probably switch to software mode if not enough tmu's are unused.

mfugl

06-04-2002, 01:06 PM

Originally posted by dorbie:
The model is not drawn zsorted for the zbuffer approach. It certainly needs to be drawn without the water plane in the zbuffer but that's true with any approach.

With the vertex alpha pixel test you clamp at 0 and 1, the real precision must be spent between where you know the largest polygon will be on either side of the plane while intersecting the plane.

i.e. the precision issues are mitigated by the triangle size rather than the primitive or object size. This should only be a problem if you have very large triangles.

Good luck.

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

This is black talk to me!

Coop

06-04-2002, 11:15 PM

It's in the GL_NV_vertex_program specification. Look at the issue section, here is the fragment:

Ok thanks http://www.opengl.org/discussion_boards/ubb/smile.gif I can't see the logic though. Perhaps it is something against a possible future implementation with clipping which modifies geometry...

LordKronos

06-05-2002, 02:46 AM

I think the reason is more simple than that. Nvidia does clipping planes using a texture unit with texgen. Texgen is part of the T&L processes. Vertex programs bypass the standard T&L and allow you to specify a custom T&L process, thus it would probably be difficult for nvidia to mix clipping planes into your user defined vertex programs (ex: what do they do if your vertex program is too big for them to add in extra instructions for the clip plane tex-gen?).

dorbie

06-05-2002, 03:40 AM

What is black talk?

PH

06-05-2002, 04:12 AM

Originally posted by dorbie:
What is black talk?

It's a Danish expression translated literally into English http://www.opengl.org/discussion_boards/ubb/smile.gif - it means you might aswell have been speaking Chinese ( I think that is the English version ) - that is, he didn't understand what you wrote.

mfugl

06-05-2002, 04:47 AM

Originally posted by PH:
It's a Danish expression translated literally into English http://www.opengl.org/discussion_boards/ubb/smile.gif - it means you might aswell have been speaking Chinese ( I think that is the English version ) - that is, he didn't understand what you wrote.

Damn http://www.opengl.org/discussion_boards/ubb/wink.gif that was bad english

dorbie

06-05-2002, 05:06 AM

For future reference the appropriate English translation is "double Dutch" :-)

LordKronos

06-05-2002, 09:33 AM

"black talk" means "you might aswell have been speaking Chinese"? Are there many black Chinese in Denmark? http://www.opengl.org/discussion_boards/ubb/smile.gif

Jeffry J Brickley

06-06-2002, 10:51 AM

I've got a friend there, maybe I should have him count next time he rides his bike to work. http://www.opengl.org/discussion_boards/ubb/wink.gif

naw, sounds like a good research project, think I could get a sponser to send me there to count? http://www.opengl.org/discussion_boards/ubb/biggrin.gif

dorbie

06-06-2002, 07:48 PM

OK back to the subject. You said you didn't understand, but I've presented 2 solutions to your problem, I'll try one more time.

The zbuffer approach I mentioned initially WILL solve your problem without z sorting, but it requires you draw the object twice. I don't think that is too difficult to understand, it has no more need for sorting than any other multipass implementation.

The single pass approach with vertex alpha and glAlphaTest is the better solution. What I was saying is that the precision will be OK if your alpha interpolation between 0 and 1 is confined to a small region either side of the water plane. This means that you want to specify the alpha ramp in as narrow a region around the water plane as possible. You cannot do this for big triangles which extent either side of the water because you cannot specify alpha >1 or <0. So you are forced to apply alpha on triangles where 1 >= alpha >=0. That should be clear enough, but what are the consequences? It means you should be able to specify alpha in a region either side of your water based on the size of triangles likely to intersect the water. In otherwords interpolation precision need only be spent across a region determined by your triangle size. This in turn means that you very probably have enough precision to do what you need, and for any geometry you have where this doesn't help some geometry division will correct the problem. The remaining triangles which don't intersect the water will either have vertex alpha all < .5 or all > .5 clamping at 0 and 1.

I can't do any better without pictures. I can assure you both approaches can work if you take time to think about their implementation.