4

在我的 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

4 回答 4

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
于 2009-08-21T13:39:15.797 回答
2

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

如果遮挡查询由于某种原因无法工作,下一个备用选项是使用 BSP 树(根本不使用 GL)进行软件光线相交世界操作。

于 2009-08-23T23:01:12.763 回答
2

除了 Alan 的回答,您可以通过将光线从相机位置投影到您的点,并确定它是否与您的任何几何体相交,以数学方式测试遮挡。Internet 上有很多关于进行光线-对象相交测试的参考资料(例如,请参阅对象/对象相交页面)。如果您有很多几何图形,那么您可能希望使用包围体或 BSP 树来加快速度。

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

于 2009-08-25T04:05:18.487 回答
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 );
于 2018-05-10T16:56:46.893 回答