深入URP之Shader篇10: 深度值专题(1)

news2024/11/20 8:38:06

之前研究Unlit shader的时候就遇到一些Z值相关的问题,一笔带过了,比如ComputeFogFactor中的UNITY_Z_0_FAR_FROM_CLIPSPACE。今天就把URP Shader中出现的Z相关的问题做一个专题一起研究下。

深度缓冲的方向和UNITY_REVERSED_Z

先说这个关于z的宏,因为这是平台级别的,比较底层,其他深度相关的宏也会用它。在不同的平台,比如DX11/12,Metal,OpenGL等深度缓冲的方向是不一样的,分为两种:

DX11/DX12, Metal, Vulkan 等新一代图形API以及一些较新的主机平台如NS使用翻转的方向

  • 深度缓冲中,1.0表示的是近裁剪面的深度值,0.0表示的是远裁剪面的深度值。
  • clip space的Z值范围为[near,0],即从near plane的深度值递减到far plane的0.0

其他平台,如DX9, OpenGL,OpenGL ES 2.0/3.0使用传统的方向

  • 深度缓冲中,0.0表示的是近裁剪面的深度值,1.0表示的是远裁剪面的深度值。
  • clip space的Z值范围根据不同平台有两类
    • D3D-Like的平台,clip space的Z值范围为[0,far],即从near plane的0.0递增到far plane的深度值
    • OpenGL-Like的平台,clip space的Z值范围为[-near, far], near plane的深度值为负值,递增到far plane。

使用翻转深度值方向的优势

如果深度缓冲是浮点缓冲,此时使用翻转的深度值方向,可以显著的提升深度缓冲的精度。这可以减轻z值的冲突以及提高阴影质量,特别是当使用很小的near plane和很大的far plane时。

UNITY_REVERSED_Z的定义

当平台使用翻转深度值方向时,Unity就会定义UNITY_REVERSED_Z为1:

image.png

在这些平台上,由于深度缓冲是翻转的,那么_CameraDepthTexture的范围也是1(near)到0(far)。同时clip space的z值范围是[near,0]。在shader中就要使用UNITY_REVERSED_Z区分出这种情况做相应的处理。例如,当我们要从_CameraDepthTexture中采样深度值时,需要这么写:

float z = tex2D(_CameraDepthTexture, uv); 
#if defined(UNITY_REVERSED_Z) 
    z = 1.0f - z; 
#endif

而如果我们要手动操作clip space Z值时,也要多加注意了,比如下面这个情况。

UNITY_Z_0_FAR_FROM_CLIPSPACE

这个宏是URP封装好了,方便我们手动处理clip space的z值的,传入的参数是clip space的z,返回的也是clip space的z,但是根据不同的情况做了处理,保证返回的z值范围是0到far。我搜索了一下,这个宏目前只有ComputeFogFactor用了:

real ComputeFogFactor(float z)
{
    float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z);
    
}

看一下定义:

#if UNITY_REVERSED_Z
    #if SHADER_API_OPENGL || SHADER_API_GLES || SHADER_API_GLES3
        //GL with reversed z => z clip range is [near, -far] -> should remap in theory but dont do it in practice to save some perf (range is close enough)
        #define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) max(-(coord), 0)
    #else
        //D3d with reversed Z => z clip range is [near, 0] -> remapping to [0, far]
        //max is required to protect ourselves from near plane not being correct/meaningfull in case of oblique matrices.
        #define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) max(((1.0-(coord)/_ProjectionParams.y)*_ProjectionParams.z),0)
    #endif
#elif UNITY_UV_STARTS_AT_TOP
    //D3d without reversed z => z clip range is [0, far] -> nothing to do
    #define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) (coord)
#else
    //Opengl => z clip range is [-near, far] -> should remap in theory but dont do it in practice to save some perf (range is close enough)
    #define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) (coord)
#endif

这里面还有个很重要的unity内置的uniform_ProjectionParams:

   // x = 1 or -1 (-1 if projection is flipped)
    // y = near plane
    // z = far plane
    // w = 1/far plane
    float4 _ProjectionParams;

这儿有四种情况:

  • 平台定义了翻转Z,但API是OpenGL。GL原本的clip z范围是[-near,far],平台翻转了就是[near,-far]。这儿直接取了个负,其实是变成[-near,far]了,然后使用max(0)来直接截断-near到0。这个其实是性能的折中,按道理应该映射到[0,far]的。
  • 平台定义了翻转Z,且API是D3D,这是主要需要处理的情况,核心计算就是这个:
(1.0-(coord)/_ProjectionParams.y)*_ProjectionParams.z

这个函数是将[near,0]映射到[0,far]。我换一种形式可能更好懂:

Z1 = far - Z*far/near

当z为near时,返回0;z为0时,返回far; z取中间的某个值,如 near/k 时,返回 far/k。

  • 如果平台没定义翻转Z,但是定义了UNITY_UV_STARTS_AT_TOP,这个宏一般用来判断API是D3D。此时D3D没有使用翻转Z,那么它的clip z范围就是[0,far]因此什么都不做。
  • 如果平台没定义翻转Z,也不是D3D,那么就是OpenGL,由于OpenGL的clip z范围是[-near, far],理论上应该重新映射,但实际上为了节约性能消耗什么都不做。这儿也没用max。
    关于这儿的平台和API的区别,我只能猜测一下,比如NS这种主机,是定义了翻转Z的,但是它又能用OpenGL,是不是这时候就会出现第一种情况?

本篇小结

关于Z的话题果然一篇讲不完,这才只是研究了一下Reversed Z。下篇继续。

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

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

相关文章

nacos:服务注册与发现

导入SpringCloudAlibaba相关的依赖&#xff0c;并在父工程将依赖进行管理 <dependencyManagement> <dependencies> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-s…

Java EE|多线程代码实例之定时器与线程池

文章目录&#x1f534;定时器什么是定时器以及开发中的作用标准库中的定时器定时器的实现&#x1f534;线程池什么是线程池标准库中的线程池创建一个线程池ThreadPoolExecutor构造方法解析线程池的实现&#x1f534;定时器 什么是定时器以及开发中的作用 程序中的定时器功能与…

【互联网大厂机试真题 - 华为】九宫格

题目描述 九宫格是一款广为流传的游戏,起源于河图洛书。游戏规则是:1到9九个数字放在3x3的格子中,要求每行、每列以及两个对角线上的三数之和都等于15. 在金麻名著《射雕英雄传》中黃蓉曾给九宫格的一种解法,口诀:戴九恩一,左三右七,二四有肩,八六为足,五居中央。解法…

【云原生进阶之容器】第四章Operator原理4.3节--Operator模式

1 Operator概述 1.1 诞生背景 Kubernetes实际是期望状态管理器。先在Kubernetes中指定应用程序期望状态(实例数,磁盘空间,镜像等),然后它会尝试把应用维持在这种状态。Kubernetes的控制平面运行在Master节点上,它包含数个controller以调和应用达到期望状态: 检查当前的…

【阶段三】Python机器学习30篇:机器学习项目实战:智能推荐系统的基本原理与计算相似度的常用方法

本篇的思维导图: 智能推荐系统模型 智能推荐系统属于非监督式学习,是机器学习一个非常重要的应用领域,它能带来的经济价值往往是直接且非常可观的。 智能推荐系统的基本原理 智能推荐系统的应用场景 互联网每天都在产生海量信息,用户行为数据呈现爆发式增长…

PyTorch - 常见神经网络

文章目录LeNetAlexNetDropoutAlexNet 网络结构torchvision中的AlexNet的实现ZFNetVGG-NetsVGG 各网络VGG-16 网络结构GoogLeNet代码实现ResNetDenseNetRNNLSTMGRULeNet 1998年&#xff0c;由 LeCun 提出用于手写数字识别任务只有5层结构&#xff1b;目前看来不输入深度学习网络…

智能售货机系统帝可得

智能售货机 概述项目使用springcloudalibaba中提供的短信服务图形验证码生成多端登录/网关统一鉴权对象存储服务代码的自动填充微服务集成emq&#xff0c;发送emq工单业务流 接收工单 拒绝工单 运维工单补货工单使用xxl-job进行任务调度lkd集成xxl-job自动创建维修工单自动…

设计模式_结构型模式 -《代理模式》

设计模式_结构型模式 -《代理模式》 笔记整理自 黑马程序员Java设计模式详解&#xff0c; 23种Java设计模式&#xff08;图解框架源码分析实战&#xff09; 结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式&#xff0c;前者采用继承…

Docker 架构和安装

Docker 包括三个基本概念: 镜像&#xff08;Image&#xff09;&#xff1a;Docker 镜像&#xff08;Image&#xff09;&#xff0c;就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。 容器&#xff08;Con…

<Linux> Linux项目自动化构建工具—makemakefile的使用

< Linux> Linux 项目自动化构建工具—make/makefile的使用 文章目录< Linux> Linux 项目自动化构建工具—make/makefile的使用一、make/makefile的背景二、如何编写 makefile1.依赖关系和依赖方法2.makefile的使用3.clean的使用4.多文件编译5.伪目标 .PHONY6.三个时…

无约束优化——线性搜索法

无约束优化——线性搜索法&#xff08;line search&#xff09;前言概述构建关于步长的函数Wolfe条件Strong Wolfe条件Zoutendijk条件后记前言 该系列为学习笔记系列&#xff0c;所有内容可以在 Numerical Optimization (2nd Edition) 中找到&#xff0c;该书十分有用经典建议…

组件封装 - Tabs组件

首先我们先来看一下 Element UI 里面的 Tabs 是怎么样的 <template><el-tabs v-model"activeName" class"demo-tabs" tab-click"handleClick"><el-tab-pane label"User" name"first">User</el-tab-pa…

基于matlab的汽车牌照识别程序详细教程

设计一个基于matlab的汽车牌照识别程序&#xff0c;能够实现车牌图像预处理&#xff0c;车牌定位&#xff0c;字符分割&#xff0c;然后通过神经网络对车牌进行字符识别&#xff0c;最终从一幅图像中提取车牌中的字母和数字&#xff0c;给出文本形式的车牌号码。关键词&#xf…

C语言 一个特殊的数组【柔性数组】

文章目录前言柔性数组的特点柔性数组的使用柔性数组的优势写在最后前言 也许你从来就没有听过柔性数组&#xff08;flexible array&#xff09;这个概念&#xff0c;但他是真的存在&#xff1b;柔性数组的概念存在于C99标准当中&#xff0c;C99标准表示&#xff1a;结构体的最后…

Linux-进程概念

目录 进程状态&#xff1a; 操作系统简图 调用进程bin.exe的详细过程 cpu运行队列的结构 R进程和阻塞进程 进程状态&#xff1a;挂起&#xff1a; Linux操作&#xff1a; ​编辑 R运行状态 S休眠状态 T暂停状态&#xff1a; kill kill -18 表示继续 kill -9 杀死进程…

肿瘤内微生物群在癌症转移中的新作用

谷禾健康 癌症是一种复杂的疾病&#xff0c;归因于多因素变化&#xff0c;导致治疗策略困难。 90%的癌症患者死于复发或转移。癌症转移是恶性肿瘤进展的关键步骤&#xff0c;由癌细胞内在特性和外在环境因素决定。 一些微生物组通过诱导癌性上皮细胞和慢性炎症促进癌发生、癌症…

光耦合器:类型及其应用

光耦合器&#xff1a;类型及其应用 介绍 光耦合器&#xff08;也称为光隔离器&#xff09;是一种在两个隔离电路之间传输电信号的半导体器件。光耦合器由两部分组成&#xff1a;发射红外光的LED和检测LED光的光敏器件。这两个部件都装在一个带有连接销的黑匣子中。输入电路接收…

数据可视化笔记记录(二)pandas

笔记内容是根据B站上面的一位老师的视频而记录了&#xff0c;因为我也还在学习&#xff0c;所以个人理解可能会出现错误&#xff0c;若有错误请指出。另外这篇文章会很长 B站视频连接、 numpy,matplotlib的学习记录 pandas 学习记录 SerIes结构&#xff0c;一图胜千言 Seri…

实用工具:FastDoc 文档提取工具

实用工具&#xff1a;FastDoc 文档提取工具 简单、实用的 HTTP API 文档生成工具&#xff0c;支持 Spring MVC/Spring Boot 下的控制器信息提取&#xff0c;类似 Swagger 但稍有不同的机制。 在线演示地址在 https://framework.ajaxjs.com/demo/fast-doc/。 关于研发者这工具…

二三层转发原理

二层转发原理 数据帧 二层即数据链路层的转发是以数据帧的格式进行转发&#xff0c;数据帧的格式如下&#xff1a; 目的地址(Destination Address,DA) &#xff1a;可以是单独的地址,或者是广播或组播MAC地址。 源地址(Source Address,SA) &#xff1a;用来识别发送没备,在S…