QT+OpenGL深度测试
本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主
深度缓冲
在前面的文章中,我们渲染了一个3D箱子,并且运用了深度缓冲来防止阻挡的面渲染到其他面的前面。
现在大部分的GPU都提供一个叫做提前深度测试(Early Depth Testing)的硬件特性。提前深度测试允许深度测试在片段着色器之前运行。只要我们清楚一个片段永远不会是可见的(它在其他物体之后),我们就能提前丢弃这个片段。
-
深度缓冲是由窗口系统自动创建的,他会以16、24或者32位float的形式存储它的深度值。
-
当深度测试被启用的时候,OpenGL会将一个片段的深度值与深度缓冲内容对比。如果测试通过,深度缓冲将会更新为新的深度值。如果深度测试失败,片段将会被丢弃。
-
深度缓冲是在片段着色器,以及模板测试运行之后在屏幕空间中运行的
-
GLSL内建变量gl_FragCoord, x和y分量代表了片段的屏幕空间坐标(其中(0, 0)位于左下角), z分量他包含了片段真正的深度值
// 开启深度测试
glEnable(GL_DEPTH_TEST);
// 深度函数
glDepthFunc(GL_LESS);
// 禁用深度缓冲
glDepthMask(GL_FALSE);
// 清除深度缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthFunc:
函数 | 描述 |
---|---|
GL_ALWAYS | 永远通过深度测试 |
GL_NEVER | 永远不通过深度测试 |
GL_LESS | 在片段深度值小于缓冲的深度值时通过测试 |
GL_EQUAL | 在片段深度值等于缓冲区的深度值时通过测试 |
GL_LEQUAL | 在片段深度值小于等于缓冲区的深度值时通过测试 |
GL_GREATER | 在片段深度值大于缓冲区的深度值时通过测试 |
GL_NOTEQUAL | 在片段深度值不等于缓冲区的深度值时通过测试 |
GL_GEQUAL | 在片段深度值大于等于缓冲区的深度值时通过测试 |
深度值精度
深度缓冲包含了一个介于0.0到1.0之间的深度值:
- 片段着色器中,gl_FragCoord向量的z值
F d e p t h = z − n e a r f a r − n e a r \begin{equation} F_{depth} = \frac{z - near}{far - near} \end{equation} Fdepth=far−nearz−near
这里的near和far值是我们之前提供给投影矩阵设置可视平截头体的那个 near 和 far 值。这个方程需要平截头体中的一个z值,并将它变换到了[0, 1]的范围中
然而,在实践中是几乎永远不会使用这样的线性深度缓冲(Linear Depth Buffer)的。要想有正确的投影性质,需要使用一个非线性的深度方程,它是与 1/z 成正比的。
F
d
e
p
t
h
=
1
/
z
−
1
/
n
e
a
r
1
/
f
a
r
−
1
/
n
e
a
r
\begin{equation} F_{depth} = \frac{1/z - 1/near}{1/far - 1/near} \end{equation}
Fdepth=1/far−1/near1/z−1/near
#version 330 core
out vec4 FragColor;
float near = 0.1;
float far = 100.0;
float LinearizeDepth(float depth)
{
float z = depth * 2.0 - 1.0;
return (2.0 * near * far) / (far + near - z * (far - near));
}
void main()
{
float depth = (LinearizeDepth(gl_FragCoord.z)-near) / (far-near);
FragColor = vec4(vec3(depth), 1.0);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x0vDyX3x-1676882895765)(C:\Users\89869\Desktop\桌面文件\LearnC++\learn-c\QT+OpenGL\深度测试.png)]