分为三个地方讲解。

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

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

何为线性何为非线性

正交投影得到的深度是线性的,而透视投影得到深度是非线性的。

所谓线性,就是指变化曲线的一阶导数为常量,也就是说变化量是恒定的。既然变换是恒定的,即深度z的采样点在[-1,]1之间均匀分布。

正交投影的裁剪空间变换矩阵并没有变化w的值,而是对xyz进行等量缩放,变化之后z还是均匀变化的,所以为线性。

而透视投影经过裁剪空间变换矩阵后w的值等于-z的值,所以最终归一化是和1/z成变化关系,变化量必然不恒定,所以为非线性。

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

我们可以调用camera.depthTextureMode |= DepthTextureMode.Depth;

camera.depthTextureMode |= DepthTextureMode.DepthNormals;来得到深度纹理/深度和法线纹理,深度纹理记录的深度对应的是NDC坐标中的z分量。

因为深度纹理的d分量为[0,1]而NDC的分量为[-1, 1],所以两者的关系为

d = Zndc * 0.5 + 0.5

而前面说到NDC的深度不是线性的,而Unity给我们提供了相关的api来解析深度纹理为线性深度。

  • LinearEyeDepth :还原成视角空间的深度。**这里说得视角就是透视投影/正交投影在缩放成裁剪
  • Linear01Depth:在上一个的基础上缩放为[0, 1]之间。

深度纹理获取深度

//在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);

深度和法线纹理获取深度

camera.depthTextureMode |= DepthTextureMode.DepthNormals;
//在Subshader中声明
sampler2D __CameraDepthNormalsTexture; //获取[0,1]范围内的线性深度
float depth = DecodeFloatRG(tex2D(_CameraDepthNormalsTexture, i.uv));
//获取法线
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坐标下取得深度纹理的B分量之后,只需要 d * 2 - 1就是Zndc。

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

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

最新文章

  1. sdk开发时,对外暴露的接口封装
  2. Android 数据库管理— — —更新数据
  3. yum install mysql
  4. mysql,sql server,oracle 唯一索引字段是否允许出现多个 null 值?
  5. 继承(引用~析构~virtual)
  6. [转]反向代理过程与Nginx特点详解
  7. virtualbox怎么装系统OVA虚拟包大全一键安装
  8. ueditor编辑器图片自定义存放目录及路径修改
  9. selenium webdriver python 操作浏览器
  10. iOS字体 UIFont 字体名字大全
  11. 蓝牙UUID——Android各种蓝牙设备的UUID
  12. Android判断当前系统语言
  13. 泛微关于js设计的一些小技巧
  14. Python框架学习之Flask中的数据库操作
  15. MySQL随记(二)
  16. Baidu地图Map api直接加https不起作用
  17. scrapy 命令行创建 启动 跟踪
  18. android SDK SDK Manager.exe 无法打开,一闪而过最终解决办法
  19. JavaScript概述-第1章
  20. Luogu3163 [CQOI2014]危桥 ---- 网络流 及 一个细节的解释

热门文章

  1. transition过渡2D、3D效果
  2. #pragma mark指令
  3. Java GUI 简单台球游戏模型
  4. NoSQL之Redis配置与优化
  5. 3.HTTP协议详解
  6. netstat 竟然还能这么玩儿?
  7. suse 12 二进制部署 Kubernetets 1.19.7 - 番外篇 - 增加node节点
  8. pypi服务器搭建
  9. 小程序入门心得(不谈api)
  10. Hyperledger Fabric 2.x 动态更新智能合约