OpenGL:如何确定3D(渲染)点是否被其前面的其他3D(渲染)基元遮挡?

时间:2009-08-21 13:14:20

标签: opengl occlusion

在我的OpenGL程序中,我按顺序执行以下操作:

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

为了显示点信息(例如点标识符/数字),我使用gluProject()将点的3D坐标转换为2D窗口坐标。我使用glRasterPos()和2D角色渲染代码在该2D窗口位置写入点标识符。

当渲染点被另一个图元遮挡时,由于OpenGL管道中发生的自动遮挡测试和深度测试,它会自动显示。但是,我的点标识符文本显示在该点旁边,即使它被遮挡,因为我没有得到这个遮挡信息。

如何确定3D(渲染)点是否被其前面的其他3D(渲染)基元遮挡?或者,当它没有被遮挡时,是否有更好的方法在 旁边显示点信息文本?

注意:我知道需要额外渲染通道的方法。我认为那些对我来说很贵。

4 个答案:

答案 0 :(得分:3)

如果您不愿意使用遮挡查询第二遍,您可以尝试对Z缓冲区进行采样以与您的测试点进行比较。

由于您要在点旁边添加文本,请抓取该点的标准化Z缓冲区值(例如使用gluProject),然后将该值与该点处的采样Z缓冲区(使用glReadPixels)值进行比较。如果您的点落后(大于)您采样的深度值,您的点应该被遮挡,您可以选择不绘制文本。

这当然要求您在文本之前渲染所有几何体,但这不应成为问题。

示例代码:

// 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

答案 1 :(得分:2)

在现代硬件上从z缓冲区读取可能非常慢。这就是发明遮挡查询的原因。查找ARB-occlusion-query扩展。在获得结果之前,它有几帧延迟,但它不会达到你的表现。

如果遮挡查询因任何原因无效,则下一个后备选项是使用BSP树(根本不使用GL)进行软件光线交叉世界操作。

答案 2 :(得分:2)

根据Alan的回答,您可以通过将光线从相机位置投射到您的点,并确定它是否与您的任何几何相交来以数学方式测试遮挡。互联网上有很多用于进行射线 - 物体相交测试的参考文献(例如,参见Object/Object Intersection Page)。如果你有很多几何体,那么你可能想要使用边界体积或BSP树加快速度。

作为奖励,您的遮挡代码应该更容易进行单元测试,因为它不依赖于从OpenGL中提取值。

答案 3 :(得分:0)

Ashwin Nanjappa的回复非常有帮助。我不是OpenGL专家,所以我花了一些时间来了解如何获得MVP矩阵。我在这里分享代码以补充他的帖子:

    GLint viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
    glGetDoublev( GL_PROJECTION_MATRIX, projection );
    glGetIntegerv( GL_VIEWPORT, viewport );