如何在OpenGL中检查对象是否位于裁剪区域之外?

8

我对OpenGL的模型视图变换感到非常困惑。我理解所有的变换过程,但是当涉及到投影矩阵时,我就迷失了:(

如果我有一个点P(x, y, z),我如何检查这个点是否会被绘制在由平行裁剪体或透视裁剪体定义的裁剪体上?这个过程背后的数学原理是什么?


你想学习其中涉及的数学知识,还是只想知道如何得到答案? - Jerry Coffin
@Jerry Coffin:我也想学习数学背景。我谷歌了一下,发现可以使用反馈模式进行检查,但代价是性能,所以我认为数学解释会更有用。谢谢。 - roxrook
1
一个起点可以是OpenGL规范。例如,OpenGL 2.0的第2.11节,位于:http://www.opengl.org/documentation/specs/version2.0/glspec20.pdf。尽管这部分是规范的一部分,但它大部分是教程,包括相当不错的图表、所使用的矩阵乘法等。 - Jerry Coffin
@Jerry Coffin:很棒的文档;)。我现在就会阅读它。非常感谢。 - roxrook
我知道这很老了,但是看看这个:http://www.crownandcutlass.com/features/technicaldetails/frustum.html - dr4cul4
3个回答

13

应用模型视图投影矩阵到对象,然后检查它是否在由以下平面定义的剪裁坐标截锥体之外:

    -w < x < w
    -w < y < w
     0 < z < w

如果您有一个点p,它是一个vec3,并且有一个模型视图投影矩阵M,那么在GLSL中它将如下所示:

    bool in_frustum(mat4 M, vec3 p) {
        vec4 Pclip = M * vec4(p, 1.);
        return abs(Pclip.x) < Pclip.w && 
               abs(Pclip.y) < Pclip.w && 
               0 < Pclip.z && 
               Pclip.z < Pclip.w;
    }

我猜你是使用每个角落的8个检查来测试边界框? - TheJosh
@TheJosh 因为边界框只有6个面,所以只需要进行6次检查。角落的作用很小,因为一个平面由三个点定义。大致上,这将被检查的点的坐标插入到平面方程中,根据结果的符号和平面的定义方式来验证它落在平面的哪一侧。请注意,abs()技巧同时检查顶部/底部平面(以及左/右平面),因此只需检查4个条件。 - NicoBerrogorry
这个绝妙的答案很遗憾已经过时了。 - Paul Childs

3

对于依赖于已接受答案的任何人来说,它是不正确的(至少在当前实现中)。OpenGL在z平面上的剪辑与x和y相同,即-w < z < w (https://www.khronos.org/opengl/wiki/Vertex_Post-Processing)。

因此,z的两个测试应该是:std::abs(Pclip.z) < Pclip.w

检查零将排除所有绘制的点,这些点比远裁剪平面更靠近近裁剪平面。


2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接