《Unity shader入门精要》复习<第13章 关于NDC坐标和深度/法线纹理>

2023-11-09 16:59

本文主要是介绍《Unity shader入门精要》复习<第13章 关于NDC坐标和深度/法线纹理>,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

NDC(Normalize Device Coordinates)归一化的设备坐标

NDC坐标是模型空间下的坐标通过MVP变换之后再进行归一化得到的归一化的设备坐标。只需要再一步变换就能得到屏幕空间坐标。顺便提一下因为已经归一化了,如果需要从NDC坐标乘以VP的逆矩阵还原成世界坐标,还原后w分量不一定为1,需要注意最后除w分量。

何为线性何为非线性

正交投影得到的深度是线性的,而透视投影得到深度是非线性的。
所谓线性,就是指变化曲线的一阶导数为常量,也就是说变化量是恒定的。既然变换是恒定的,即深度z的采样点在[-1,1]之间均匀分布。
正交投影的裁剪空间变换矩阵并没有变化w的值,而是对xyz进行等量缩放,变化之后z还是均匀变化的,所以为线性。
而透视投影经过裁剪空间变换矩阵后w的值等于-z的值,由于最终归一化z需要除w,所以是和1/z成变化关系,变化量必然不恒定,所以为非线性。

得到相机记录的深度/法线信息

深度纹理和NDC的深度的关系

我们可以调用camera.depthTextureMode |= DepthTextureMode.Depth;
camera.depthTextureMode |= DepthTextureMode.DepthNormals;来得到深度纹理/深度和法线纹理,深度纹理记录的深度对应的是NDC坐标中的z分量。
因为深度纹理的分量取值范围为[0,1],而NDC的分量的取值范围为[-1, 1],两者的关系为
d = Zndc * 0.5 + 0.5

如何得到线性深度

我们前面说到透视投影后得到的深度不是线性的,而Unity给我们提供了相关的api来解析深度为线性深度。

  • LinearEyeDepth(float depth) :还原成视角空间的深度。经过MV还未进行P变化时的空间 ,取值为[near, far],near为近平面的深度,far为远平面的深度。
  • Linear01Depth(float depth):在上一个的基础除以相机远平面far从而缩放为[0, 1]之间。

这里贴一下入门精要里面还原成线性深度的过程
在这里插入图片描述
但是入门精要对于Projection变换矩阵并没有很详细的推理,需要知道矩阵怎么得到应该去看Game101

  • 通过深度纹理获取深度
//在C#代码声明
camera = GetComponent<Camera>();
camera.depthTextureMode |= DepthTextureMode.Depth;//在shader中
//直接在Subshader里面声明
sampler2D _CameraDepthTexture;//获取
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
//视角空间下的深度
LinearEyeDepth(Depth);
//返回范围在[0,1]的线性深度值,也就是上面那个除以Far,因为裁剪空间的Z轴取值为[Near, Far]
Linear01Depth(Depth);
  • 深度和法线纹理获取线性深度和法线方向
    Unity提供了函数DecodeDepthNormal来帮助我们获取深度和法线,这个深度值是范围在[0, 1]的线性深度值(这与单独的深度纹理中存储的深度值不同〉,而得到的法线则是视角空间下的法线方向。
inline void DecodeDepthNormal( float4 enc, out float depth, out float3 normal){depth = DecodeFloatRG (enc.zw);normal= DecodeViewNormalStereo(enc);}
camera.depthTextureMode |= DepthTextureMode.DepthNormals;
//在Subshader中声明
sampler2D __CameraDepthNormalsTexture;//获取[0,1]范围内的线性深度
float depth = DecodeFloatRG(tex2D(_CameraDepthNormalsTexture, i.uv).zw);
//获取法线
fixed3 normal = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, i.uv).xy);
return fixed4(normal *0.5 + 0.5 ,1.0);

深度纹理和NDC坐标的关系

//取得深度纹理在对应uv下的深度
float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);
float NDC = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);

在对应的uv坐标下取得深度纹理的z分量之后,只需要 * 2 - 1就是Zndc。

所以NDC坐标为(i.uv , d * 2 - 1, 1)

而如果需要 还原成线性深度,则d带入LinearEyeDepth / Linear01Depth得到结果

这篇关于《Unity shader入门精要》复习<第13章 关于NDC坐标和深度/法线纹理>的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/377408

相关文章

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

Open3D 基于法线的双边滤波

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 输入参数: 输出参数: 参数影响: 2.2完整代码 三、实现效果 3.1原始点云 3.2滤波后点云 Open3D点云算法汇总及实战案例汇总的目录地址: Open3D点云算法与点云深度学习案例汇总(长期更新)-CSDN博客 一、概述         基于法线的双边

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al