Z-Fighting问题解决(二) - Reverse-z

news2025/1/12 1:10:46

Z值相关技术概论理清

开始之前先简单理清科普一下涉及的跟三维图形学相关的深度Z相关的概念:

  1. Z-Buffer:上个世纪八十年代的图形学飞跃节点算法之一; Z缓冲是一种解决深度排序问题的方法,主要用于确定哪些物体在其他物体的前面。每个物体的每一个像素点被赋予一个深度值(Z值),并且会被储存在Z-buffer中。渲染时,系统会检查新的像素的Z值是否小于已储存在Z-buffer中的Z值,如果小于,则更新Z-buffer的值,并且在屏幕上绘制该像素,否则不进行绘制(与Z-Test与Z-Write紧密联合使用)。这种技术基本上是为了避免进行不必要的像素绘制,从而优化性能。
  2. Early-Z,需要GPU底层支持的,其可以在进行像素着色之前就对像素进行深度测试。通过这种方式,如果有一个像素在早期就被判定为被遮挡,则可以跳过对这个像素的昂贵的着色计算,因此可以大大提升图形渲染的性能。
  3. Z-Cull,:Z-Culling也是一种3D场景优化技术,它在渲染管线阶段(应用程序阶段)尽早剔除那些肯定不可见的多边形,以避免无效的图形计算。GPU利用Z-buffer以确定哪些图元对最终图像不可见,然后丢弃它们以节省资源。
  4. Z-Test与Z-Write在图形管线(一)后处理阶段 alpha测试 模版测试 深度测试 混合
    也就详细介绍,这里就不在赘余。
  5. Hierarchical Z-Buffer(分层Z缓冲区):硬件的场景优化技术,基本思想是先快速地清除视图中被完全遮挡的区域,这可以大幅度减少因不可见的像素而浪费的渲染时间。虽然存在Z-Test,但在许多情况下,有很大一部分的像素是完全被其他像素所遮挡的,理论上,这些被遮挡的像素是无需进行渲染的。Hierarchical Z-Buffer使用一种叫做四叉树(Quadtree)或者八叉树的数据结构,将屏幕分割为不同的区域。在四叉树中,每一个节点代表了一个屏幕区域,其子节点则代表了这个区域的四个子区域。当开始渲染时,首先对树的顶层节点进行深度测试。如果一个节点失败了深度测试,那么就可以保证这个节点所代表的整个屏幕区域都在其他物体的后面,因此无需再去处理这个节点下的任何子节点。这就跳过了大量的深度测试,大幅度提高了渲染性能。Hierarchical Z-Buffer是一种非常有效的硬件加速技术,很多现代的GPU都会内建支持这种技术。
  6. Z-Sort(Z排序):解决OIT的一种方法,顾名思义,这种方法是根据距离观察者的远近,对所有物体或者透明物体进行排序。尤其是在绘制透明对象时,Z排序尤其重要!因为你通常需要从后向前的顺序来正确地融合颜色。
  7. W-Buffering(W缓冲):这是一种类似于Z-buffer的技术,但是用摄像机空间中的w坐标(经过透视变换之后的z坐标)来代替z值。这种方法可以提供更精确的深度测试,特别是当你处理远离摄像机的几何体时。
  8. Depth Peeling: 这种技术用于渲染半透明物体,它通过多次渲染场景并逐渐“剥离”最前面的透明层,从而为每个像素生成一个由前到后的透明层列表(之前我写的博客中提到 透明的渲染
    )。
  9. Stencil Buffer(模板缓冲):虽然不直接基于深度值,但模板缓冲经常与深度缓冲共同使用,用于为每个像素创建一个额外的信息层,这可以用来控制渲染操作的应用程度 图形管线(一)后处理阶段 alpha测试 模版测试 深度测试 混合

Z值在管线空间转换中的变化:

不同的空间变换对Z值(深度值)的处理方式有所不同,其中一部分是线性变化,另外一部分则是非线性变化。

  1. 模型空间、世界空间和视图空间:在这些空间里,Z值(深度)是线性变化的。这主要是因为这些空间的变换通常包含平移、旋转、缩放等线性运算。
  2. 裁剪空间和屏幕空间:在裁剪空间进行透视除法(除以齐次坐标W)后,深度Z值变成了非线性的。透视除法是将三维空间投影到二维屏幕上,同时保持透视感(远处对象小,近处对象大)。然而,这导致了Z值(深度)的非线性变化,即距离相机越近,Z值变化越大;距离相机越远,Z值变化越小。

单精度float精度问题:

除此之外我们还需要考虑其他的,单精度! 在现代的GPU架构内我们都是单精度float的至少在目前为止没有双精度double的。根据 IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985) 的规定:一个float 四字节共32位,其中1个符号位,8个指数位,剩余的23 位有效位,这就导致了精度只能达到7 到8 位,甚至8到9位就无法表示了,在计算机中就是随机给。在这里插入图片描述

相对应的flaot精度的分布图如下:在这里插入图片描述

这说明浮点数的分布与深度值的分布一样是不均与的,越靠*0的浮点数分布越密集,越远离0的浮点数分布越稀疏浮点数的范围和精度问题(从原理到结论)

Reverse-z的简介

通常在三维场景中的深度值Z是如图 在这里插入图片描述
越靠近近平面深度值的精度越高,反正则越稀疏,当远场景中两个靠的较近的面由于精度等问题导致的深度值的比较相近,Z-test上一帧A大于B下一帧B大于A的深度就会导致Z-Fighting的产生。
对于"Reverse-Z"是它也是一种距离(深度)缓冲策略。 它的工作原理是将Z缓冲区的表示颠倒过来,使得0表示最远处,1表示最近处。使用反向Z缓冲,近处的值被设置为1,而远处的值被设置为0。这使得3D场景的远景中获得更高的精度,并有效地解决了Z-fighting等问题,同时还能更好地利用z-buffer精度,这在大型开放世界游戏和其他需要大规模深度范围的应用中尤其重要。另外,Reverse-z策略通常需要配合无穷远遮挡剔除(Infinite Far Plane Clipping)技术使用,以处理极远处的物体。

Reverse-z的本质一句话就是,在View Space下对应的平面尽量均匀分布,移动视野等过度相对平滑,使得不管近处或是远处的物体都极低概率出现z-fighting现象为佳。 传统的近平面映射至0,远平面至1的方法,因为Z值在NDC空间内与View Space 并非线性映射,再加上浮点数的精度在靠近0的范围聚集两点原因,导致高精度范围完全堆积在了靠近近平面的位置。

如下图虽然我们使用反向Z缓冲+正常的精度来表示深度的精度,近处的值被设置为1,而远处的值被设置为0但是跟之前Z的分布没有太大的区别!在这里插入图片描述
但当我们将Reversed-Z([n,f]映射到[1,0])与浮点数结合起来,情况就变成了: 距离相机近和远的物体分得的深度值就比较均匀了,实现了改善深度值分布状况,从而也达到了降低Z-Fighting出现的概率(是的,虽然Reversed-Z这么神奇,但Z-Fighting还是不能完全避免的,虽然概率已经降到很低)。在这里插入图片描述
为什么说Near与far 颠倒过来与float精度结合会有如此效果:这种颠倒是有原因的。主要的优势在如上单精度的表述在于浮点数的精度分布。浮点数在接近0的区间拥有更高的精度,允许更精细的深度分辨率。就是这样Near与far取反结合1、浮点数在接近0的区间拥有更高的精度,而且2、正常的通常深度值是近的深度精度越高,远的深度越远,两者结合互补的效果。当然这样做是要求修改投影矩阵的,所以要在一开始的时候就做好~~

opengl实现Reverse-z:

Reversed-Z 设计用于 [0,1] 范围内的剪辑空间 Z 值,而不是 [-1,+1] 范围内。 OpenGL 的默认约定是 [-1,+1],但您可以使用 glClipControl 覆盖它:但是可以通过修改剪裁范围为[0.0, 1.0],从而同样可以使用反向z。 底下有一篇文章有详细的做法:Reverse-z在OPENGL的实现
特别注意:
Reversed-Z除了将([n,f]映射到[1,0])修改投影矩阵以将深度值反向映射外,并且你还需要修改你的Z-Test函数。例如,如果你之前是用GL_LESS作为深度测试函数,则需要改为GL_GREATER。同时,确保清除深度缓冲时使用的值是0,而不再是1,因为理论上,最远的物体应该拥有最小的深度值。

参考资料:

  1. Reversed-Z详解
  2. Reversed-Z in OpenGL
  3. 精度优化–ReversedZ提高zbuffer精度
  4. 反向Z(Reversed-Z)的深度缓冲原理
  5. Depth Precision Visualized | NVIDIA Developer — 深度精度可视化 |英伟达开发者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1099892.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Oracle】分析函数partition by,解决了使用group by后select语句中只能是分组的字段或者是一个聚合函数的问题

首先我们看一下group by的用法,比如根据省份分组。 select province, sum(persons) from t_person group by province;使用了group by后,select语句中只能是分组的字段(比如上面的province)或者是一个聚合函数(比如co…

【特纳斯电子】基于单片机的火灾监测报警系统-仿真设计

视频及资料链接:基于单片机的火灾监测报警系统-仿真设计 - 电子校园网 (mcude.com) 编号: T0152203M-FZ 设计简介: 本设计是基于单片机的火灾监测报警系统,主要实现以下功能: 1.通过OLED显示温度、烟雾、是否有火…

jenkins pipeline使用

1、jenkins全局配置 1.1、maven配置 1.2、jdk配置 1.3、git配置 2、构建环境配置 2.1、安装时间插件 Date Parameter 2.2、Git Parameter 插件安装 3、pipeline如下 pipeline {agent anyenvironment {image_name "192.168.122.150/ken-test/price-service:${date}&…

jmeter监控服务器的资源使用

一. 下载安装包SeverAgent-x.x.x.zip并安装到被监控服务器 下载地址:https://github.com/undera/perfmon-agent 下载完解压后执行运行,windows运行startAgent.bat, linux运行startAgent.sh 二. 在jmeter上添加插件jpgc-PerfMon Metrics Collector监听器…

电商API接口的发展,电商API接口主要应用场景:

随着互联网技术的不断进步和电商行业的迅猛发展,电商API接口在商品交易、物流配送、客户服务等方面发挥着越来越重要的作用。本文将深入探讨电商API接口的技术原理、应用场景、开发方法以及优缺点。 一、技术原理 电商API接口是基于HTTP、TCP、IP等网络协议实现的…

代码随想录二刷 Day41

509. 斐波那契数 这个题简单入门&#xff0c;注意下N小于等于1的情况就可以 class Solution { public:int fib(int n) {if (n < 1) return n; //这句不写的话test能过但是另外的过不了vector<int> result(n 1); //定义存放dp结果的数组&#xff0c;还要定义大小r…

基于复合优化加速算法研究实际问题

import optimtool as oo from optimtool.base import np, sp, pltpip install optimtool>2.5.0加载hybird.nesterov.accer方法 import optimtool.hybrid as oh nes_acc oh.nesterov.accer初始化输入数据 f ( x ) ∑ i 1 n ( ( n − ∑ j 1 n cos ⁡ x j ) i ( 1 − co…

jenkins出错与恢复

如果你的jenkins出现了如下图所示问题&#xff08;比如不能下载插件&#xff0c;无法保存任务等&#xff09;&#xff0c;这个时候就需要重新安装了。 一、卸载干净jenknis 要彻底卸载 Jenkins&#xff0c;您可以按照以下步骤进行操作&#xff1a; 1、停止 Jenkins 服务&…

学信息系统项目管理师第4版系列29_信息系统治理

1. IT治理 1.1. 描述组织采用有效的机制对信息技术和数据资源开发利用&#xff0c;平衡信息化发展和数字化转型过程中的风险&#xff0c;确保实现组织的战略目标的过程 1.2. 驱动因素 1.2.1. 信息孤岛 1.2.2. 信息资源整合目标空泛 1.3. 高质量IT治理因素 1.3.1. 良好的I…

flask基础开发知识学习

之前做了一些LLM的demo&#xff0c;接口用flask写的&#xff0c;但是涉及到后端的一些业务就感觉逻辑写的很乱&#xff0c;代码变成屎山&#xff0c;于是借助官方文档和GPT迅速补了一些知识&#xff0c;总结一下一个很小的模板 于是决定边学边重构之前的代码… 文章目录 代码结…

吃鸡达人必备神器,提升战斗力享受顶级游戏干货!

大家好&#xff01;今天我为大家介绍一款专为吃鸡玩家打造的神器——吃鸡盒子。无论您是新手还是老玩家&#xff0c;吃鸡盒子都能帮助您提升游戏的战斗力&#xff0c;分享顶级游戏作战干货&#xff0c;并且还能方便吃鸡作图、查询库存和保护账号安全。 让我们先来说说提升战斗力…

使用Premiere、PhotoShop和Audition做视频特效

今天接到一个做视频的任务&#xff0c;给一个精忠报国的视频&#xff0c;要求&#xff1a;   ①去掉人声&#xff0c;就是将唱歌的人声去掉&#xff0c;只留下伴奏&#xff1b;   ②截图视频中的横幅&#xff0c;做一个展开的效果&#xff0c;类似卷纸慢慢展开&#xff1b;…

Golang学习:基础知识篇(二)—— 数组及切片

Golang学习&#xff1a;基础知识篇&#xff08;二&#xff09;—— 数组及切片 前言什么是Golang&#xff1f;Go语言的基础语法数组声明数组初始化数组访问数组知识点补充 切片定义切片切片初始化len() 和 cap() 函数空(nil)切片切片截取append() 和 copy() 函数知识点补充 前言…

【版本控制】Git(学习笔记)

一、Git工作流程图 clone&#xff08;克隆&#xff09;: 从远程仓库中克隆代码到本地仓库checkout &#xff08;检出&#xff09;&#xff1a;从本地仓库中检出一个仓库分支然后进行修订add&#xff08;添加&#xff09;: 在提交前先将代码提交到暂存区commit&#xff08;提交&…

Python--逻辑运算符(与或非) and or not

逻辑运算符&#xff08;与或非&#xff09; not就是取反&#xff0c;只有一个表达式not 表达式&#xff0c;如果表达式为True&#xff0c;则not以后就返回False。反之&#xff0c;则返回True。 案例&#xff1a;讲个非诚勿扰的小故事&#xff1a; ① 女孩子要求比较高&#…

【SpringBoot篇】基于SpringBoot进行Web开发

&#x1f38a;专栏【SpringBoot】 &#xfeff;> &#x1f354;喜欢的诗句&#xff1a;天行健&#xff0c;君子以自强不息。 &#xfeff;> &#x1f386;音乐分享【如愿】 &#xfeff;> &#x1f384;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x…

【Java学习之道】TCPIP套接字编程实例

引言 网络编程是Java学习中不可或缺的一部分&#xff0c;而TCP/IP套接字编程又是网络编程的基础。那么&#xff0c;初学者如何才能快速掌握TCP/IP套接字编程呢&#xff1f;今天我们就来通过一个简单的实例&#xff0c;为你揭示TCP/IP套接字编程的奥秘&#xff01; 一、什么是…

互联网Java工程师面试题·Java 总结篇·第三弹

20、重载&#xff08;Overload&#xff09;和重写&#xff08;Override&#xff09;的区别。重载的方法能否根据返回类型进行区分&#xff1f; 方法的重载和重写都是实现多态的方式&#xff0c;区别在于前者实现的是编译时的多态性&#xff0c;而后者实现的是运行时的多态性。重…

【UBOOT】1-使用与烧写

​一、uboot简介 1&#xff09;uboot是一个裸机程序&#xff0c;比较复杂 2&#xff09;最主要的作用是引导Linux内核启动&#xff1b; 初始化DDR&#xff1b; 因为Linux是运行在DDR里面的&#xff1b;而Linux镜像&#xff08;zImage或uImagedtb&#xff09;一般存放在SD EMM…

基础课3——自然语言处理的应用

自然语言处理是一种将人类语言转换为机器语言&#xff0c;以实现人机交互的技术。应用非常广泛&#xff0c;例如&#xff1a; 人机交互&#xff1a;自然语言处理技术可以应用于人机交互&#xff0c;让机器能够理解和运用人类语言&#xff0c;从而实现更加智能化的交互体验。 机…