openGL深度冲突z-fighting

openGL系列文章目录

前言

针对z-fighting从问题的描述,到为什么会产生z-fighting现象,在继而从投影矩阵的的角度来解释这个问题的发生以及解决,最后稍微介绍一下深度值的非线性与线性的转换所能应用的渲染场景。如有不妥欢迎留言,如果读者觉得我的文章对自己有益,还望推荐给自己的朋友,感激不尽。
开启深度测试后OpenGL就不会再去绘制模型被遮挡的部分,这样实现的显示画面更为真实,但是由于深度缓冲区精度的限制,对于深度相差非常小的情况(例如在同一平面上进行两次绘制),OpenGL就不能正确判定两者的深度值,会导致深度测试的结果不可预测,显示出来的现象时交错闪烁的前后两个画面,这种情况称为z-fighting。

下面我将从这几个方向进行阐述z-fighting的前世今生

1.z-fighting问题的描述
2.为什么会产生z-fighting现象?
3.从透视投影矩阵的角度解释以及如何避免
4.深度值的非线性与线性的转化

一、为什么会产生z-fighting

z-fighting问题的描述
首先来讲一下,我们在进行三维渲染物体的时候,一般都是采用透视投影矩阵这样会产生近大远小的效果,很符合现实中人眼观看世界的情况。但是渲染中经常会遇到场景中离视点较远的物体会有闪烁的现象,而场景中离视点比较近的地方反而很少会长生物体闪烁的现象。

这是为什么那?

而如果我们换用了正交投影矩阵后,闪烁的问题会极大的解决,这又是为什么那?

为什么会产生z-fighting现象?
第一点原因

场景中渲染多个三维物体的时候,几个三维物体的摆放位置有点接近,导致在深度缓冲测试的时候,会产生精度的误差,然后会导致几个物体之间的片段值有的时候a通过,有的时候b通过,导致交替显示这几个物体的颜色值,然后那就会产生闪烁的现象。

第二点原因

采用透视投影矩阵渲染的场景,其深度缓冲区存储的深度值,ndc空间中的深度值。而ndc空间的深度值是经由透视空间转换过来的,ndc空间的深度值与透视空间的深度值转换并非是线性的,而是非线性。大家都知到,透视空间转换到ndc空间会有一步透视除法,是处以z值。这样就会导致,离视点越近的物体的片段深度值是越精确的,离视点距离约远的物体的片段的深度值是约不精确的。这样就会导致z-fighting问题。

而采用正交透视矩阵渲染场景,其变换是线性的,为什么,因为其透视空间转换为ndc空间的时候采用的透视除法是处以1,所以其片段距离视点的深度值是线性的,这样除非你把两个物体设置的位置非常接近,否则是产生不了z-fighting这种现象的。

那么为什么透视投影矩阵渲染场景的时候,在透视空间转换到ndc空间时,透视除法会除以z值那?下面笔者从透视投影矩阵的数学推导层面来回到这个问题。

从透视投影矩阵计算的角度解释以及如何避免
三维空间的物体在经历的图元装配以后,会经历剪裁与淘汰这两步操作。其中在剪裁中经历坐标系的转换的。

坐标系的转换如下所示:

模型坐标系–>世界坐标系—>相机坐标系—>投影坐标系—>标准设备化空间–>视口变换—>光栅化阶段。

在其投影坐标系转换到标准设备化空间的时,需要将xyz坐标转换为-1到1之间,也可以说标准设备化空间(NDC)是一个立方体空间。那么该怎么达到这样的操作那?答案是借助于矩阵,矩阵的一个几何意义就是将一个物体从一个坐标系转换到另外一个坐标系。那么笔者下面将去介绍这个透视投影矩阵是长的什么样子。

在这里插入图片描述
在这里插入图片描述
注意到蓝色线框里面.有花屏现象
在这里插入图片描述
这张图片就没有深度冲突

二、防止深度冲突

1.第一种方法

第一个也是最重要的技巧是永远不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠。通过在两个物体之间设置一个用户无法注意到的偏移值,你可以完全避免这两个物体之间的深度冲突。在箱子和地板的例子中,我们可以将箱子沿着正y轴稍微移动一点。箱子位置的这点微小改变将不太可能被注意到,但它能够完全减少深度冲突的发生。然而,这需要对每个物体都手动调整,并且需要进行彻底的测试来保证场景中没有物体会产生深度冲突。

2.第二种方法

第二个技巧是尽可能将近平面设置远一些。在前面我们提到了精度在靠近近平面时是非常高的,所以如果我们将近平面远离观察者,我们将会对整个平截头体有着更大的精度。然而,将近平面设置太远将会导致近处的物体被裁剪掉,所以这通常需要实验和微调来决定最适合你的场景的近平面距离。

3.第三种方法

另外一个很好的技巧是牺牲一些性能,使用更高精度的深度缓冲。大部分深度缓冲的精度都是24位的,但现在大部分的显卡都支持32位的深度缓冲,这将会极大地提高精度。所以,牺牲掉一些性能,你就能获得更高精度的深度测试,减少深度冲突。

我们上面讨论的三个技术是最普遍也是很容易实现的抗深度冲突技术了。还有一些更复杂的技术,但它们依然不能完全消除深度冲突。深度冲突是一个常见的问题,但如果你组合使用了上面列举出来的技术,你可能不会再需要处理深度冲突了。

参考

牧野
SkySnow

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
opengles是一种用于在移动设备和嵌入式系统上实现2D和3D图形渲染的图形库。而gl-transitions是一个开源的OpenGL库,用于创建平滑过渡效果,可以应用于图像、视频等多种媒体内容。 要将gl-transitions移植到opengles上,需要进行以下步骤: 1. 确定opengles版本:gl-transitions可能使用的是OpenGL的较新版本,而opengles可能只支持较旧的版本。因此,首先需要确定opengles版本,并了解其与OpenGL之间的差异。 2. 了解gl-transitions的实现:深入了解gl-transitions的实现方式和代码结构,理解其对OpenGL的使用方式和功能。 3. 理解opengles的API:熟悉opengles的API,包括顶点/片段着色器、缓冲区对象、纹理对象等。理解opengles的渲染管线和数据传递方式,以便能够正确地将gl-transitions移植到opengles上。 4. 逐步移植:根据gl-transitions的实现和opengles的API,逐步将gl-transitions的代码移植为opengles可用的代码。这可能涉及到对着色器代码的修改、纹理对象的创建和绑定、缓冲区对象的使用等。 5. 调试和测试:移植完成后,进行调试和测试以确保移植后的代码在opengles上正常工作,并且能够正确地渲染出所需的过渡效果。 需要注意的是,由于较新版本的OpenGL可能具有一些opengles不支持的功能,因此在移植过程中可能需要做一些功能的调整或替代。此外,移植过程中可能还需要考虑设备的性能和兼容性问题,确保移植后的代码能够在目标设备上流畅地运行。 总结起来,将gl-transitions移植到opengles上需要对opengles的API有很好的了解,并根据它的渲染方式和数据传递方式对gl-transitions的代码进行适当的修改和调整。这样才能确保移植后的代码能够在opengles上正常运行并呈现出所需的过渡效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值