UnityShader学习——深度和法线纹理(原理)

本文介绍了Unity中深度和法线纹理的用途,如提升边缘检测的准确性。详细讲解了深度纹理的获取方法,包括从G-buffer、通过Shader Replacement技术以及摄像机设置。同时,阐述了如何采样和线性化深度纹理,以及如何从深度法线纹理中解码深度和法线信息。
摘要由CSDN通过智能技术生成

为什么要用深度和法线纹理?

之前的屏幕后处理效果都只是在屏幕颜色图像上进行各种操作来实现的。然而,很多时候我们不仅需要当前屏幕的颜色信息,还希望得到深度和法线信息。例如,在进行边缘检测时,直接利用颜色信息会使检测到的边缘信息受物体纹理和光照等外部因素的影响,得到很多我们不需要的边缘点。一种更好的方法是,我们可以在深度纹理和法线纹理上进行边缘检测,这些图像不会受纹理和光照的影响,而仅仅保存了当前渲染物体的模型信息,通过这样的方式检测出来的边缘更加可靠。

如何获取深度和法线纹理?

一、深度纹理实际就是一张存储高精度的深度值的渲染纹理

由于被存储在一张纹理中,深度纹理里的深度值范围是[0, 1],而且通常是非线性分布的。这些深度值来自于顶点变换后得到的归一化的设备坐标(Normalized Device Coordinates , NDC)。一个模型要想最终被绘制在屏幕上,需要把它的顶点从模型空间变换到齐次裁剪坐标系下,这是通过在顶点着色器中乘以MVP变换矩阵得到的。在变换的最后一步,我们需要使用一个投影矩阵来变换顶点,当我们使用的是透视投影类型的摄像机时,这个投影矩阵就是非线性的。

透视摄像机

透视摄像机

正交摄像机

正交摄像机

在得到NDC后,深度纹理中的像素值就可以很方便地计算得到了,这些深度值就对应了NDC中顶点坐标的z分量的值。由于NDC中z分量的范围在[-1, 1],为了让这些值能够存储在一张图像中,需要将其映射到[0,1]。

二、在Unity中不同渲染路径获得深度纹理的方法
  • 通常来讲,使用延迟渲染路径时,深度纹理可以从G-buffer访问到。
  • 无法直接获取深度缓存时,深度和法线纹理是通过一个单独的Pass渲染而得的。具体实现是,Unity会使用Shader Replacement技术,选择那些RenderType标签为Opaque的物体,判断它们使用的渲染队列是否小于等于2500(内置的Background、Geometry和AlphaTest渲染队列均在此范围内),如果满足条件,就把它渲染到深度和法线纹理中。
三、在Unity中通过摄像机得到【深度或深度法线纹理】的方法
  • 单独的深度纹理:Unity会直接获取深度缓存。或是用着色器替换技术,选取需要的不透明物体,并使用LightMode被设置为ShadowCaster的Pass来得到深度纹理。如果Shader中不包含这样一个Pass,那么这个物体就不会出现在深度纹理中。深度纹理的精度通常是24位或16位,这取决于使用的深度缓存的精度。
  • 深度+法线纹理:Unity会创建一张和屏幕分辨率相同、精度为32位(每个通道为8位)的纹理,其中观察空间下的法线信息会被编码进纹理的R和G通道,而深度信息会被编码进B和A通道。法线信息的获取在延迟渲染中是可以非常容易就得到的,Unity只需要合并深度和法线缓存即可。而在前向渲染中,默认情况下是不会创建法线缓存的,因此Unity底层使用了一个单独的Pass把整个场景再次渲染一遍来完成。这个Pass被包含在Unity内置的一个Unity Shader中,我们可以在内置的builtin_shaders-xxx/DefaultResources/Camera-DepthNormalTexture.shader文件中找到这个用于渲染深度和法线信息的Pass。
四、获取【深度或深度法线纹理】的具体代码

在脚本中设置摄像机的depthTextureMode然后在Shader中访问对应变量即可。

//【1】深度纹理
camera.depthTextureMode = DepthTextureMode.Depth;//在Shader中声明 _ CameraDepthTexture
//【2】深度+法线纹理
camera.depthTextureMode = DepthTextureMode.DepthNormals;//在Shader中声明_CameraDepthNormalsTexture
//【3】深度 和 深度+法线纹理
camera.depthTextureMode |= DepthTextureMode.Depth;
camera.<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值