在 CPU 上执行您自己的交集计算当然是一种选择。但根据我对您的要求的理解,我认为您也可以让 OpenGL 来完成这项工作,这应该更容易、更高效。
方法概述
想到的机制是遮挡查询。它们允许您计算已渲染的像素。如果将此与使用剪刀测试相结合,则可以计算在选择矩形内呈现的像素。
应用到用例
用例 2 是这种方法更简单的一个。您将选择矩形设置为剪刀矩形,并为每个表面使用遮挡查询渲染所有表面。然后检查查询的结果,查询结果大于 0 的所有表面在选择矩形内都有像素。
用例 1 稍微复杂一些。要知道曲面是否完全包含在矩形内,您需要通过两次。在启用剪刀测试的情况下,您可以像上面那样使用遮挡查询进行一次渲染。然后你第二次做同样的事情,禁用剪刀测试。如果一个表面在两次传递中具有相同的查询结果,则它完全在矩形内。
执行
我不会为此提供完整的代码。这一切都应该很简单。但这里有一些指针和代码片段。调用显示为 C 绑定。我希望它在 Python 绑定中看起来很明显。
首先,由于您想在选择中包含隐藏的表面,您需要禁用深度测试:
glDisable(GL_DEPTH_TEST);
由于您实际上并不需要产生输出,并且可能不想干扰视觉渲染输出,因此您可能还想禁用颜色输出:
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
如果您启用了背面剔除,您可能还想禁用它:
glDisable(GL_CULL_FACE);
然后,对于上面提到的只想计算选择矩形内的像素的通道,设置剪刀矩形,并启用剪刀测试:
glScissor(selectionLeft, selectionBottom, selectionWidth, selectionHeight);
glEnable(GL_SCISSOR_TEST);
对于使用遮挡查询的渲染,您需要每个表面的查询对象:
GLuint queryIds[surfaceCount];
glGenQueries(surfaceCount, queryIds);
然后对于每个表面,k
用作循环索引:
glBeginQuery(GL_SAMPLES_PASSED, queryIds[k]);
// render surface k
glEndQuery(GL_SAMPLES_PASSED);
渲染完所有表面后,可以得到查询结果:
GLint pixelCounts[surfaceCount];
// for all surfaces k
glGetQueryObjectiv(queryIds[k], GL_QUERY_RESULT, &pixelCounts[k]);
然后评估像素数以决定应该为每个用例选择哪些表面,如上一节所述。
完成后不要忘记重置所有状态以准备再次渲染。深度测试、彩色蒙版、剪刀测试等