OpenGL3.3深度测试


这一篇主要是讲解深度测试时怎么工作的
一般深度缓冲的精度值都是24位float存储
深度缓冲是由窗口系统自动创建的

具体原理:

如果深度测试开启了,则OpenGL会将一个片段的深度值和深度缓冲中的内容做对比 OpenGL会执行一个深度测试,如测试通过,深度缓冲会更新为新的深度值。如果深度测试失败,片段会被丢弃
所以这个深度测试是会以一个视角为准(一般是选择摄像机) 存储离这个摄像机最近的深度值
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);中的GL_DEPTH_BUFFER_BIT就是为了清除上一帧的深度缓冲,防止被影响
如果一个片段通过了深度测试的话,OpenGL会在深度缓冲中储存该片段的z值;如果没有通过深度缓冲,则会丢弃该片段

深度缓冲是在片段着色器运行之后以及模板测试运行之后在屏幕空间中运行
(但是目前大部分GPU都提供提前深度测试,就是为了有些片段没有必要被渲染,但是提前深度测试的前提就是不要在片段着色器中取更改深度值)
屏幕空间坐标可以直接使用GLSL内建变量gl_FragCoord从片段着色器中直接访问。gl_FragCoord的x和y分量代表了片段的屏幕空间坐标(其中(0, 0)位于左下角) 而z值包含了片段真正的深度值。z值就是需要与深度缓冲内容所对比的那个值
深度缓冲中包含的深度值是在0-1之间 但是物体自己的深度值并不一定 物体包含的深度值是在平截头的远近平面里 就是near和far 但是深度缓冲中的深度值就要和物体自己的深度值进行比较 所以需要将物体自己的深度值转换为0-1 方法就是 ((1/物体自己的深度值)减去(1/近平面的z))/((1/远平面的z)-(1/近平面的z)) 1/xxx的目的是让他变成非线性的

深度缓冲存在冲突 一般是两离的非常近的平面会争夺谁出现 解决办法一般是让他们俩不要离那么近 具体看网站

glDepthMask(GL_FALSE);禁止使用深度缓冲的写入功能 这样只能读取深度缓冲不能更新
在某些情况下你会需要对所有片段都执行深度测试并丢弃相应的片段,但不希望更新深度缓冲
深度掩码(Depth Mask)

glDepthFunc(GL_LESS);设置比较运算符

可接受参数
GL_ALWAYS 永远通过深度测试
GL_NEVER 永远不通过深度测试
GL_LESS 在片段深度值小于缓冲的深度值时通过测试
GL_EQUAL 在片段深度值等于缓冲区的深度值时通过测试
GL_LEQUAL 在片段深度值小于等于缓冲区的深度值时通过测试
GL_GREATER 在片段深度值大于缓冲区的深度值时通过测试
GL_NOTEQUAL 在片段深度值不等于缓冲区的深度值时通过测试
GL_GEQUAL 在片段深度值大于等于缓冲区的深度值时通过测试
默认情况是GL_LESS 它将会丢弃深度值大于等于当前深度缓冲值的所有片段

我们目前使用的深度值是非线性的 所以他在z值很小的时候有很高的精度,而z值很大的时候有较低的精度。片段的深度值会随着距离迅速增加,所以几乎所有的顶点的深度值都是接近于1.0的
这也就能理解 当时我在用鼠标直接获取鼠标所点位置的像素深度值的时候为什么都基本是0.99+以上的了

(很重要)如果想将深度值转换为线性的 就如下做!!!!!!
首先depth是我们通过gl_FragCoord.z获取到的 也就是非线性 远处的时候非出解决1.0的片段深度值
将深度值变换为NDC:
float z = depth * 2.0 - 1.0;
接下来使用获取到的z值,应用逆变换来获取线性的深度值:()near和far是近平面和远平面
float linearDepth = (2.0 * near * far) / (far + near - z * (far - near));
最终这个值会在near和far之间线性分布

多边形偏移

什么是多边形偏移

如果我们想给一个多边形加一个不同颜色的边框 让他更明显 我们可以先画一个多边形 再在他边界位置用line画一个多边形的边框 但是由于线和填充多边形的光栅化过程并不是完全一致的 线和多边形边长的深度值通常是不一样的 加亮的线可能隐没在于多边形重叠的区域 出现“斑驳”现象
在这里插入图片描述

如何解决

这种情况可以通过多边形偏移解决 添加一个恰当的偏移值 让重叠的z值强行分离
通过glEnable() 参数:GL_POLYGON_OFFSET_FILL,GL_POLYGON_OFFSET_LINE,GL_POLYGON_OFFSET_POINT开启

glPolygonOffset(GLfloat,GLfloat units)

开启之后每个片元的深度值都会被修改 在执行深度测试之前添加一个计算偏移的值:
offset = m × factor + r × units
其中:
m是多边形的最大深度斜率(在光栅化过程中计算得到)
r是两个不同深度值之间的 可识别的最小差值 参数factor和units可以是负数

offset偏移值如何计算

在这里插入图片描述
不仅和深度斜率有关 还和线宽度大小,深度值得变换也不是线性的等

early-z

early-z(在光栅化之后 片元着色器之前)
early-z会采用类似于mipmap的算法
在这里插入图片描述
可以把这个类比为一个屏幕的深度缓冲 会生成三级Mipmap
我们每次光栅化结束后都会得到一堆的片元 然后我们逐区域的进行判断 我们先拿这个9和所有的片元深度做对比 如果所有片元都比9大 说明输入进来的这一堆片元都被遮挡了 直接剔除掉 如果没有就进入下一级 进行类似判断 但是这个比直接和第一级比较更快吗? 是因为屏幕像素分辨率和深度缓冲的分辨率并不能一一对应是吗 如果直接对比可能会每一个像素都需要计算他对应哪个深度缓冲的值
大佬的原话:
如果发现落在某片区域的所有像素深度都比这个最大值大,那么直接丢弃不参与下一阶段的渲染
如果不是,再取下一级mipmap进行比较,直到发现这些像素再也无法被剔除,证明这个像素深度值比深度缓冲区低,需要用它的深度覆盖这个深度缓冲区已有的值。

在光栅化之前进行遮挡剔除?

对于TBDR渲染架构而言,可以使用Hidden Surface Removal技术来做几何阶段的遮挡剔除 具体看大佬的文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值