OpenGL:深度缓冲向后工作,是不是按缠绕顺序?

Posted

技术标签:

【中文标题】OpenGL:深度缓冲向后工作,是不是按缠绕顺序?【英文标题】:OpenGL: Depth buffering working backwards, is it in the winding order?OpenGL:深度缓冲向后工作,是否按缠绕顺序? 【发布时间】:2015-01-12 01:10:30 【问题描述】:

我一直在使用我的 opengl 模型查看器,但遇到了问题。当我渲染我的场景时,模型似乎被看穿了。我调查了一下,想也许我的深度缓冲区没有工作,但我已经为它准备好了代码:

glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

以及深度缓冲区的测试

glGetIntegerv(GL_DEPTH_BITS)

返回一个非 0 值(它返回 24)。于是我更深入地测试了一下,发现并不是深度缓冲不起作用,而是它反向起作用了。它显示了前面的背面。如果我调用 glCullFace(GL_FRONT),模型的渲染正常。这很好,但它提出了为什么会发生这种情况的问题,我可能应该找到问题的根源。环顾四周,似乎我的缠绕顺序可能是问题所在,我为 modelviewprojectionmatrix 构建了自己的矩阵堆栈,我认为这可能是问题所在。如果我在相机向后移动 20 个单位的情况下渲染场景,水平 fov 为 0.785 rad,纵横比为 1.333,clipplaneNear 为 1.000,clipplaneFar 为 30.000,我的矩阵如下所示:

model: 
[ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]
view: 
[ 1   0   0   0 ]
[ 0   1   0   0 ]
[ 0   0   1   0 ]
[ 0   0   -20 1 ]
proj:  
[ 2.414214  0         0         0  ]
[ 0         -3.218951 0         0  ]
[ 0         0         -1.068966 -1 ]
[ 0         0         -2.068966 0  ]

当我在前面有 cullface 时,它​​会完全按照我想要的方式进行渲染,并且对象会在距离相机 20 个单位的地方正确渲染。我可以随意旋转和移动它,一切正常。但是如果没有 cullface,深度是相反的,我的 z 值是不是在某个地方搞砸了?一切看起来都与我迄今为止使用的资源相似。如果不是这样,那么这个倒退问题是从哪里来的?

【问题讨论】:

如果您遇到问题,您是否启用了GL_CULL_FACEglCullFace(GL_BACK)?或者您是否禁用了GL_CULL_FACE 如果我将其保留为 GL_BACK,问题就存在,如果我禁用它,问题仍然存在。但是我最初遇到问题的时候以及我在没有 GL_FRONT 的情况下运行它的方式是使用它作为 GL_BACK 【参考方案1】:

我花了大约 12 个小时梳理我的所有代码,并尝试各种可能性来找出哪里出错了。我将其缩小到我的投影矩阵,然后缩小到第二列第二行。我使用this source 阅读投影矩阵并手动计算它以找出我的值应该是什么,然后注意到一个差异。 3.21 的值应该是正数而不是负数,这改变了我的深度值。我设法发现我正在使用端口的库被移植时出现错误。该库有一个用于 make_projection_fov 的函数,该函数将视野转换为顶部/底部/右侧/左侧值,并称为函数 make_projection。但是 make_projection 的参数是 right left top bottom near far 并且 make_projection_fov 调用它时 right left bottom top near far 。负面消息来自那里。

这告诉我我真的需要检查我的图书馆。从那以后,我对我所有的库函数进行了测试,并在一些当前未使用的函数中发现了另一个错误。

【讨论】:

我注意到矩阵元素 [1][1] 是负数。不过,这应该对深度没有影响。它只是将 y 值倒置,并在此过程中反转缠绕顺序。这就是为什么我问如果禁用GL_CULL_FACE 会发生什么。如果您在禁用剔除时遇到问题,我认为仅此一项并不能说明问题。【参考方案2】:

我在使用正交投影作为透视矩阵时遇到了这个问题。我通过确保在定义 leftrightbottomtopnearfar - near 时应该是正数而 far 应该是负数来修复它。或者至少near 应该大于far

这似乎是因为 OpenGL 将“向前”解释为 -Z,所以屏幕空间中更远的东西应该有越来越小的 Z 分量。

【讨论】:

以上是关于OpenGL:深度缓冲向后工作,是不是按缠绕顺序?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL深度缓冲区不工作

在 OpenGL 中将深度渲染到纹理时出现奇怪的结果

3.OpenGL渲染技巧

获取网格的边界边缘 - 按缠绕顺序

OpenGL 中的反射和深度

Opengl渲染到深度纹理 - 红色?