z buffer fight and decals

Hi,
I am writing a space trading simulation ( www.dodgyposse.com ).

I am drawing my meshes using display lists, and after I have done this, I have a series of quads which I wish to draw just above the surface of the meshes.

e.g pirate logo, players preferred logo,
I believe this is called decalling(???)

This is the sequence of commands
glDisable( GL_BLEND) ;
glDepthMask( GL_TRUE );
drawTheShip();
glEnable( GL_DEPTH_TEST);
glDepthMask( GL_FALSE );
glEnable( GL_LIGHTING );
glEnable( GL_TEXTURE_2D );
glDisable(GL_CULL_FACE);
drawQuad();

Sadly, as I move the camera, the mesh occludes the decal quad. Sometimes it looks ok, and other times I lose the decal.

Is this because it is too close to the surface of the mesh?

What can i do to countermand this?

dd

Extra info:
http://www.dodgyposse.com/maverick/Image1.jpg
illustrates the problem.

At the top of the mesh, can see what should be a quad…

At the bottom of the mesh, you can see another quad which has drawn ok…

You can try polygon offsetting your decal. You tell OpenGL to pull your decal away from the side of the ship such that you minimize your z fighting. Your loop should look like this:

glDisable( GL_BLEND) ;
glDepthMask( GL_TRUE );
drawTheShip();
glEnable( GL_DEPTH_TEST);
glDepthMask( GL_FALSE );
glEnable( GL_LIGHTING );
glEnable( GL_TEXTURE_2D );
glDisable(GL_CULL_FACE);

// Enable polygon offset
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( -4.5f, -4.5f );

drawQuad();

glDisable( GL_POLYGON_OFFSET_FILL );

The negative values passed tell it to bring that geometry closer to the viewer in Z space. Try playing with those numbers a little bit until your happy.

–Marcos

Try using glPolygonOffset. It was made for this though can be difficult to understand.
Another thing you might consider is changing the the model by removing or modifying the surface that is fighting with the logo. That is, split up the model geometry to include the quad that gets the logo texture. I would only use decals for stuff like burn and damage marks that can appear in many different positions at random times. I’m assuming the logo is fixed in position, so no real need to decal it.

[This message has been edited by DFrey (edited 04-15-2002).]

I am using display lists to draw the models.
The reason the decal is not part of the main mesh, is because I want to change its texture on the fly.

I want to use this technique to put animated forcefields over the docking entrances of the ship, and also to have animated adverts like in bladerunner…

Ok…tried that and it works…

until I move the camera away from the ship.
Then I can see the decal through the mesh again.

Check out: http://www.dodgyposse.com/maverick/Image2.jpg

Look at the end of the red lines.
The decal is on the face of the mesh facing away from the camera, and yet it is visible
through the mesh.

As the camera approaches the mesh, things sort themselves out… and the decal is no longer visible.

any ideas?

You don’t have to make it part of the mesh literally - just cut a hole out of the mesh, and have your logo fit into that hole, matching up the vertices - that way you can change the material/texture as much as you like.

What about using render_to_texture to render the decal thingy to the texture that is on the geometry? I havnt gotten around to using render_to_texture yet so im not really sure if this will help any. To me it sounds nice.

-SirKnight

Well, for one thing, you are disabling culling. Thats why you can see it even though its facing away from you.

Second, when objects get closer to the far clip plane, you begin to lose some z precision and objects that are at different distances end up with the same z values. glPolygonOffset modifies the the z value to move it a certain number of z-units closer to the camera. The problem is that if your mesh z values all fall within 4 z-units of each other, but you have glPolygonOffset setup to pull the object 5 z-unit closer to the camera, an object drawn just on the back side of your mesh will end up in front of your mesh. In other words, glPolygonOffset works in z-buffer space, not cartesian space, hence its effects are greater near the far clip plane. If you set the offset too small, you have problems at the near clip plane. To large, and you get problems at the far clip plane.

Its for this reason mainly that glPolygonOffset is considered a hack and is often avoided if at all possible. A while back I was having some problems with z-fighting and a few people on this board told me to use polygon offset to solve it. I refused to do so for just this reason. Its better to find a proper way to deal with it if you can, but that isnt always possible.

You can use the stencil buffer for adding decals without artifacts. The stencil buffer marks the pixels on the surface you want to add the decal to. You’ll want to use a depth test of always in conjunction with the stencil test ( to make sure you’re drawing on the surface ). To mark the surface, redraw the surface writing to stencil only and set stencil to 1 if depth test passes ( so the surface is depth sorted wrt. the other surfaces ).

Thanks for all the feedback…I realised the error of my ways straight after postings ( i.e depth buffering was off ).

I’ll try a few more things…this glPolygonOffset thing works to a degree, but I’m not happy with the effect I am getting.

One idea I had,was to manually determine whether the decal was facing away from me…and then don’t bother drawing it…
i.e draw it using glPolygonOffset, but only if I am likely to see it…

Originally posted by dodgyposse:
One idea I had,was to manually determine whether the decal was facing away from me…and then don’t bother drawing it…

Why go to that trouble? Thats what culling is for. Leave backface culling on and just draw it.

Perhaps drawing the decals with depth test GL_LEQUAL and depth writing off will also help

HTH

Jean-Marc

Another thing, you have made sure that the decals are actually a little offset from the actual meshes (not using polygon offset, but real-world offset)?
This should ensure that they will always draw in front or on top of the mesh when drawing them after the mesh and using depth test GL_LEQUAL.
You have to make sure the offset is tiny enough to not show up when the camera is very close to the decal (YMMV).

Jean-Marc.

Yes,The decals are offset a small amount
but I was testing with GL_LESS…

good point!!

dodgyposse,

What about the stencil approach I mentioned ? It’s nice and simple ( and you can avoid using polygon offset ).

I’ve not used the stencil buffer for anything so far, so I’m not too familiar with it. Doesn’t it incur additional processing overhead?

Your approach sounds interesting though, so I’ll give it a try.

Thanks for posting!

derrick

It should be possible to mark the surface while drawing it ( to avoid doing two passes ). Using stencil can be considered free if you’re already doing depth testing ( according to NVIDIA ).

Mark Kilgard talked about a similar technique where you could use the stencil buffer to avoid double blending of projected shadows and for reflections. That’s pretty much the same method.

But since you want to add logos to surfaces, you could just use projected textures ( this even allows you to add the logos to curved surfaces and you can use multitexture for single pass ).

Anyway, have a look at this presentation - that may give you some more ideas,
http://developer.nvidia.com/view.asp?IO=shadows_transparency_fog

–a bit of useless info–
in my new game im drawing the decals straight into the base texture, according to my fps counter (my eyes) this doesnt occur a frame hit. + is much cleaner than having to worry about lotsa decals floating around.
of course the surface will have to be uniquely textured