views:

160

answers:

1

I'm not entirely sure if I can do what I want here, but I have a bunch of objects being rendered in OpenGL (using JOGL). For one group of objects, I want to ensure that certain objects in that group are rendered in front of other objects in that group. I've tried clearing the depth buffer bit and rendering the "front" objects last, and that works, except it messes up other depth buffering on screen.

What it comes down to is I have a list of objects being rendered and I want to ensure that certain objects in that list are rendered in front of other objects (they are all at the same Z coordinate though). Is there a way to do that?

thanks, Jeff

+1  A: 

This is a very common technique to draw transparent objects (objects that have parts with alpha!=1).

The most common approach is to first build a tree of objects to be drawn that you can then sort along to the "depth" after being passed through the projection*camera matrices. Basically instead of just blindly throwing triangles at the GPU, you send your objects one by one as you're processing them in the world to a temporary buffer. These objects have full knowledge of every triangle and every vertex color/vertex shader/texture name+id etc. Then you can sort your buffer (either naively, object by object, or a full blown sort based on similar patches across objects).

The glDepthMask trick, if i recall correctly, goes something like this:

glDepthMask(true);
drawOpaqueObjects();
glDepthMask(false);
drawTransparentObjects();

For best results the transparent objects are sorted back-to-front, but in most (simple) applications this doesn't matter.

edit: note that for the 2nd technique, while you enable and then disable depth buffer WRITING, you still use depth buffer TESTING, so transparent objects behind your normal objects (a helmet pointing "into" the screen for example) won't get drawn.

Blindy
Thanks. In this case though, I'm not trying to draw components with alpha. I have a bunch of objects very close to each other on screen and when the user clicks one, I want to bubble it up to the top.
Jeff Storey
In this case I'd use the real Z axis to order them. Anything else, especially multiple-parses rendering, will just slow your application down for no reason.
Blindy
The problem there is that this is a mapping application and the Z axis will affect the item's elevation (which I don't want to do). So if I have two overlapping items next to each other at the same elevation, I want to be able to specify which gets rendered "on top".
Jeff Storey
OK how about this then? you draw everything not-selected first normally, writing and testing against the depth buffer. After that, you disable depth buffer testing (and writing, but that doesn't matter anymore) and draw the object that's supposed to be on top. This only works if the object you're drawing on top is convex (a rectangle of sorts would be best).
Blindy
I've tried to do something like that, if I'm understanding you correctly. Where I think I'm struggling is that do I need to draw all the objects in the scene that are not selected (there are other types of objects in the background that cannot be selected)? Or just draw the non-selected objects in this one group of objects (meaning this group that has objects that can be selected)?
Jeff Storey
You draw everything in the scene except the "selected" item first. Now that I think about it, don't disable depth testing/writing between the 2 phases, just call `glClear(GL_DEPTH_BUFFER_BIT)` before you draw the selected object, this way you maintain full depth testing without obscuring your object with background/unselected objects.
Blindy
Hmm...sounds like that would work. Unfortunately I'm using a 3rd party application that does most of the rendering and I don't have the hooks to control the overall rendering...but I think you've given me a bit of good guidance. Thanks.
Jeff Storey