OpenGL: how to determine whether a 3D (rendered) point will be closed by other 3D (rendered) primitives in front of it?

In my OpenGL program, I do the following:

// Drawing filled polyhedrons // Drawing points using GL_POINTS // Displaying information for each above point beside it 

To display point information (for example, a point / number identifier), I convert the 3D coordinates of the point to the coordinates of the 2D window using gluProject (). I am writing a point identifier in this 2D window using glRasterPos () and a 2D character rendering code.

When the rendered point is closed by another primitive, it is not automatically displayed due to the test for automatic occlusion and depth testing that occurs in the OpenGL pipeline. However, my point identifier text is displayed next to the point, even when it is closed, as I am not getting this occlusion information.

How to determine whether a 3D (rendered) point will be closed by other 3D (rendered) primitives in front of it? Or is there a better way to display text information about a point next to it only when it is not closed?

Note. I know methods that require additional rendering. I feel it is expensive for my purpose.

+4
source share
3 answers

If you do not want to use a second occlusion request session, you can try sampling the Z buffer to compare with your test point.

Since you are adding text next to a point, take the normalized value of the Z-buffer (say, using gluProject) of the point, and then compare this value with the selected Z-buffer (using the value of glReadPixels) at that point. If your point is beyond the (large) depth value that you have selected, your point should be closed, and you may not draw text.

This, of course, requires that you display all your geometry in front of the text, but that should not be a problem.

Code example:

 // Assumed to already hold 3D coordinates of point GLdouble point3DX, point3DY, point3DZ; // Project 3D point coordinates to 2D GLdouble point2DX, point2DY, point2DZ; // 2D coordinates of point gluProject( point3DX, point3DY, point3DZ, mMatrix, pMatrix, vMatrix, // MVP matrices &point2DX, &point2DY, &point2DZ); // Read depth buffer at 2D coordinates obtained from above GLfloat bufDepth = 0.0; glReadPixels( static_cast<GLint>( point2DX ), static_cast<GLint>( point2DY ), // Cast 2D coordinates to GLint 1, 1, // Reading one pixel GL_DEPTH_COMPONENT, GL_FLOAT, &bufDepth); // Compare depth from buffer to 2D coordinate "depth" GLdouble EPSILON = 0.0001; // Define your own epsilon if (fabs(bufDepth - point2DZ) < EPSILON) // 3D point is not occluded else // 3D point is occluded by something 
+3
source

Reading from the z-buffer can be very slow on modern hardware. This is why the occlusion request was invented. See the extension of ARQ-occlusion-request. It has a couple of delay frames before you can get the results, but that will not affect your performance.

If the occlusion request does not work for any reason, the next backup option is to perform the ray-intersect-world software operation using the BSP tree (which does not use GL at all).

+2
source

In addition to Alan’s answer, you can mathematically test occlusion by projecting the beam from the camera’s position to your point and determining if it intersects any geometry. There are many links on the Internet for conducting ray intersection testing (see, for example, Object / Object Intersection Page ). If you have a lot of geometry, you can speed things up using bounding volumes or a BSP tree.

As a bonus, your occlusion code should be much simpler unit test, because it does not rely on extracting values ​​from OpenGL.

+2
source

All Articles