Unity 深度 depth (URP)

本文基于Unity URP,对深度相关知识进行整理。介绍了Eye Depth,即物体相对摄像机平面的距离,还提及ComputeScreenPos的作用;阐述深度图,包括其存储及采样方法;最后讲述根据深度重建世界坐标的多种方法,如逆推、射线法等。

本文只是对深度的一些整理和个人理解,如果有不对的地方,请一定要告诉我。演示基于Unity URP, shader用shader graph 或者HLSL,build-in自行根据对照表更改

1. Eye Depth(观察空间)

Eye Depth是物体相对于摄像机所在平面的距离,因为是相对,所以Z是相反的,Eye Depth的0就是摄像机,1就是一个单位,10就是10个单位,所以有的人会把他称为“World” space Depth,这个depth在所有平台上都是一样的,而且不区分正交透视,因为他在投影之前。在shader graph 中如何得到片段的Eye Depth呢

正交或者投影

 只适用于透视

HLSL

第一种

// 顶点
float3 positionWS = TransformObjectToWorld(IN.positionOS.xyz);
float3 positionVS = TransformWorldToView(positionWS);
OUT.positionVS = positionVS;
// 片段
float fragmentEyeDepth = -IN.positionVS.z;

 第二种

//裁剪空间坐标
float4 positionCS 	= TransformWorldToHClip(input.positionOS.xyz);
OUT.positionCS 		= positionCS;
//求屏幕坐标
//一种方法是
float4 positionScr	= positionCS * 0.5f;
positionScr.xy 		= float2(positionScr.x, positionScr.y * _ProjectionParams.x) + positionScr.w;
positionScr.zw 		= positionCS.zw;
OUT.scrPos= positionScr;
//或者直接用URP封装的
OUT.scrPos= ComputeScreenPos(positionCS);//[-w,w]->[0,w]
//片段
float fragmentEyeDepth = IN.scrPos.w;

这边扯开了,先讲下ComputeScreenPos,他的作用是把裁剪空间齐次坐标转换到屏幕空间的齐次坐标 ,或者换句话说就是把xy取值范围从[-w,w] 转到 [0,w],然后再做透视除法(齐次除法),取值范围变成[0,1],就可以用来提取屏幕纹理了

注意 透视除法应该放在片段着色器里执行,不然会造成UV扭曲,因为片段着色器之前的光栅化会对几何数据做差值,而做差值前做除法会导致结果不准确

这个方法得到了屏幕齐次坐标,那么再经过透视除法,可以的到NDC,再走一步可以直接得到Z Buffer Depth,也就是深度纹理中的像素值

float3 ndcPos 		= IN.scrPos.xyz / IN.scrPos.w;//[0-1] D3D
float2 screenUV 	= ndcPos.xy;
float zdepth 		= ndcPos.z; 

对于D3D,NDC z取值范围已经是[0,1],所以可以直接相等,而openGL z在[-1,1],需要

z* 0.5 + 0.5

所以我常用的是第二种方法,因为可以顺便得到更多的信息

 PS:

NDC=

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值