gluProject & glReadPixels

Hi,

Here is my problem: I would like to know if the center of a specific object is occluded or not by another object in the scene.

I know about several method how to do it, I chose projecting and reading depth buffer.

Here is a part of a code I use for tests:

glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1, 0 .1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( 0,0,0, 0,0,-1, 0,1,0);

glColor3f(1,0,0);
glPushMatrix();
glTranslatef(0,0,-400);
glutSolidSphere(50,60,60); //First sphere
glPopMatrix();

glColor3f(1,1,0);
glPushMatrix();
glTranslatef(0,0,-300);
glutSolidSphere(10,60,60); //Second sphere
glPopMatrix();

glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
glGetIntegerv(GL_VIEWPORT,viewPort);

gluProject(0,0,-400,modelMatrix,projMatrix,viewPort,&wx,&wy,&wz);
glReadBuffer(GL_BACK_LEFT);
glReadPixels((GLint) wx, (GLint) wy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &zd);

glutSwapBuffers();

in this case wz = 0.9998499916 and zd = 0.997406006 seams to be ok as second sphere occludes the first one (zd < wz)

now when I translate before second sphere to 100,0,-300 the results are
wz = 0.9998499916 and zd = 0.9998016357

as you see still zd < wz, BUT the first sphere is NOT occluded by the second one.

The main question is WHY I always get zd < wz? Maybe I dont anderstand how glProject works? Please explain me.

Thnak you in advance.

  1. You are assuming a point (0, 0, -400) will be transformed to the same position as the front center of a #1 sphere. That is wrong. I suggest you use a something flat (GL_QUAD instead of gluSphere)

  2. You may be experiencing z fighting when you move the second sphere. I dont really know.

  3. The depth of your z buffer effects the results you read in undesirable ways.

V-man

It doesn’t matter I use a sphere or other object. The results are the same for quads too.

I need it for knowing when to draw flares for lights, suns, engines and other bright objects.

Maybe you know other method (but not raytracing) to find if a point is ocluded by something.

Regards

You could test if the segment from the eye point to the object you want to test for occlusion intersects any objects in your scene.

[This message has been edited by Asgard (edited 11-02-2002).]

That’s an option. But it is the same fing as in raytracing method and it is too epensive for high populated scenes.

Method with reading depth buffer should work perfectly, I just dont anderstand why it returns such values…

That’s an option. But it is the same fing as in raytracing method and it is too epensive for high populated scenes.

You could use a bounding volume hierarchy to reduce the complexity.

Method with reading depth buffer should work perfectly, I just dont anderstand why it returns such values…

Well, I’m not really sure if I understand your example correctly. But looking at those two last values for zd and wz it seems that they are basically the same within the limits of tolerance for floating-point values. You’re probably using a 16-bit z-buffer which is not as precise as the double calculations done by gluProject. Due to the conversion from fixed-point to floating-point that happens in glReadPixels, you’re probably even losing a bit more precision. Even if you’re using a 24-bit z-buffer, you’re still far away from double precision.

Edit: Fixed quote tags.

[This message has been edited by Asgard (edited 11-02-2002).]

On NV2x hardware you could use the nv_occlusion_query extension which counts the pixels that have passed the depth test.

Thanks for ideas, I’ll have to try them all.

But, I would still like to know what is wrong with my example. I did a search on “lens flares” in this forum and found an article where reading depth buffer worked fine for some people, but they have no e-mail addres in their user info, so I couldnt ask them directly.

If anyone of you did implement in your engine lens flares by reading depth buffer, please let me know how and post some lines from your code if possible.

Regards.

PS: Just found that my card doesent support nv_occlusion_query extension, so it is not an option for me

[This message has been edited by Maverick_75 (edited 11-04-2002).]

Hi again,

For the time being I’ve solved my problem with occlusion test. Apparently (at least on my card) with 24 bits depth buffer only first 5 digits after comma are significant.

I use this test:

if ((long) (zdepth100000) >= (long) (winz100000))
{
DrawFlare;
}

and it worked fine for me. Sure it might not be the ideal solution. Hope it will help people out there

Regards,
PS: Thank you for helping. (especially for your comment Asgard )

[This message has been edited by Maverick_75 (edited 11-04-2002).]