在我的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(渲染)基元遮挡?或者,当它没有被遮挡时,是否有更好的方法在 旁边显示点信息文本?
注意:我知道需要额外渲染通道的方法。我认为那些对我来说很贵。
答案 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 );