72.深度和法线纹理-查看深度纹理
72.1 知识点
知识回顾:深度纹理的使用
第一步:在 C# 中设置摄像机的深度纹理模式
生成深度纹理:
Camera.main.depthTextureMode = DepthTextureMode.Depth;
第二步:在 Shader 代码中声明深度纹理属性
按规则声明深度纹理变量:
sampler2D _CameraDepthTexture;
第三步:深度纹理的使用
使用深度纹理采样宏
获取非线性的深度值:float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
转换为线性深度值(观察空间下的距离)
将非线性深度值转换为像素点到摄像机的距离:float viewDepth = LinearEyeDepth(depth);
映射深度值到
[0,1]
区间
将像素点到摄像机的距离映射到[0,1]
区间内,得到线性深度值:float linearDepth = Linear01Depth(depth);
如何查看深度纹理信息
我们可以在 屏幕后期处理 中,运用获取深度信息的知识点,将深度值作为颜色的 RGB 值显示在屏幕上,从而直观地感受深度纹理中存储的内容。
- 实现效果:
理论上,如果深度值使用的是0~1
范围的线性值:- 越接近近裁剪面,越靠近黑色。
- 越接近远裁剪面,越靠近白色。
实现 查看深度纹理屏幕后期处理效果 对应 Shader
主要步骤
新建 Shader,删除无用代码
开始构建一个新的 Shader 文件,保留必要的核心结构。声明变量
在 Shader 中通过声明_CameraDepthTexture
属性以获取深度纹理。顶点着色器
在顶点着色器中,只需修改传入的结构体类型,以支持纹理坐标和顶点位置的处理。片元着色器
在片元着色器中完成深度纹理的采样和处理:- 使用深度纹理采样宏
SAMPLE_DEPTH_TEXTURE
对_CameraDepthTexture
进行采样,获取非线性深度值。 - 使用
Linear01Depth
函数,将非线性深度值转换到观察空间下,并将像素点到摄像机的距离映射到[0,1]
区间内,得到线性深度值。 - 最后,将深度值作为返回颜色的 RGB 值,用于渲染效果展示。
- 使用深度纹理采样宏
禁用回退 Shader
使用Fallback Off
以禁用不需要的 Shader 回退行为。
新建Shader,删除无用代码
Shader "Unlit/Lesson72_DepthTexture"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
ENDCG
}
}
}
声明属性,包括主纹理,并且在Shader中通过声明深度纹理变量_CameraDepthTexture获取深度纹理
声明主纹理属性和深度纹理变量:
Properties
{
// 主纹理属性,默认白色
_MainTex ("Texture", 2D) = "white" {}
}
// 主纹理采样器
sampler2D _MainTex;
float4 _MainTex_ST;
//按规则命名的 深度纹理变量
sampler2D _CameraDepthTexture;
结构体和顶点函数按常规的纹理坐标和裁剪坐标进行定义和转换
struct v2f
{
// 纹理坐标
float2 uv : TEXCOORD0;
// 顶点在裁剪空间中的位置
float4 vertex : SV_POSITION;
};
// 顶点着色器函数
v2f vert(appdata_base appdata_base)
{
v2f v2f;
// 转换顶点到裁剪空间
v2f.vertex = UnityObjectToClipPos(appdata_base.vertex);
// 变换纹理坐标
v2f.uv = TRANSFORM_TEX(appdata_base.texcoord, _MainTex);
return v2f;
}
片元函数中,通过深度纹理采样宏 SAMPLE_DEPTH_TEXTURE 对 _CameraDepthTexture 依据传入的纹理坐标 进行采样操作,得到非线性的深度值。运用 Linear01Depth 函数将之前获取到的非线性深度值转换至观察空间下,并且把像素点到摄像机的距离映射到 [0, 1] 这个区间内,从而得到线性深度值。把所得到的深度值作为要返回颜色的 RGB 三个通道的值,以此来实现基于深度信息的特定视觉效果
fixed4 frag(v2f v2f) : SV_Target
{
//非线性的 裁剪空间下的深度值
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, v2f.uv);
//得到一个线性的 0~1 区间的深度值
fixed linearDepth = Linear01Depth(depth);
//把深度值作为RGB颜色输入 越接近摄像 就呈现出黑色 越远离摄像机 就呈现出白色 中间就是灰色 具体就会呈现出深浅灰
return fixed4(linearDepth, linearDepth, linearDepth, 1);
}
关闭 Shader 回退
// 不使用回退Shader
Fallback Off
实现 查看深度纹理屏幕后期处理效果 对应 C#代码
主要步骤
1.新建C#脚本,命名和Shader相同
2.继承PostEffectBase
3.在Start函数中设置深度纹理模式
新建C#脚本继承PostEffectBase在Start函数中设置深度纹理模式,得到对应的深度纹理信息了
using UnityEngine;
public class Lesson72_DepthTexture : PostEffectBase
{
void Start()
{
//可以在Shader中得到对应的深度纹理信息了
Camera.main.depthTextureMode = DepthTextureMode.Depth;
}
}
C#脚本关联shader挂载到摄像机,可以看到Game窗口渲染的深度值。缩小远裁剪面数值可以看到更明显。离摄像机越远越接近白色,把立方体靠近摄像机越接近黑色
72.2 知识点代码
Lesson72_深度和法线纹理_查看深度纹理.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson72_深度和法线纹理_查看深度纹理 : MonoBehaviour
{
void Start()
{
#region 知识回顾 深度纹理的使用
//第一步:在C#中设置摄像机的深度纹理模式
//生成深度纹理
//Camera.main.depthTextureMode = DepthTextureMode.Depth;
//第二步:在Shader代码中按规则声明属性
//sampler2D _CameraDepthTexture;
//深度纹理使用
//使用深度纹理采样宏 得到的结果是非线性的
// float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
//将非线性的深度值 转换到观察空间下 得到的值是像素点到摄像机的距离(线性深度值)
// float viewDepth = LinearEyeDepth(depth);
//将非线性的深度值 转换到观察空间下 并将像素点到摄像机的距离转换到[0,1]区间内 (线性深度值)
// float linearDepth = Linear01Depth(depth);
#endregion
#region 知识点一 如何查看深度纹理信息
//我们可以在屏幕后期处理中用我们学习过的获取深度信息的知识点
//将深度值作为颜色的RGB值显示在屏幕上
//感受深度纹理中存储的内容
//理论上来说,如果深度值使用0~1范围的线性值
//越接近近裁剪面越靠近黑色
//越接近远裁剪面越靠近白色
#endregion
#region 知识点二 实现 查看深度纹理屏幕后期处理效果 对应 Shader
//1.新建Shader,删除无用代码
//2.声明变量
// 在Shader中通过声明_CameraDepthTexture获取深度纹理
//3.顶点着色器
// 只需要修改传入结构体类型
//4.片元着色器
// 使用深度纹理采样宏 得到的结果是非线性的
// float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
// 将非线性的深度值 转换到观察空间下 并将像素点到摄像机的距离转换到[0,1]区间内 (线性深度值)
// float linearDepth = Linear01Depth(depth);
// 将深度值作为返回颜色的RGB值
//5.Fallback Off
#endregion
#region 知识点三 实现 查看深度纹理屏幕后期处理效果 对应 C#代码
//1.新建C#脚本,命名和Shader相同
//2.继承PostEffectBase
//3.在Start函数中设置深度纹理模式
#endregion
}
}
Lesson72_DepthTexture.shader
Shader "Unlit/Lesson72_DepthTexture"
{
Properties
{
// 主纹理属性,默认白色
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// 主纹理采样器
sampler2D _MainTex;
float4 _MainTex_ST;
//按规则命名的 深度纹理变量
sampler2D _CameraDepthTexture;
struct v2f
{
// 纹理坐标
float2 uv : TEXCOORD0;
// 顶点在裁剪空间中的位置
float4 vertex : SV_POSITION;
};
// 顶点着色器函数
v2f vert(appdata_base appdata_base)
{
v2f v2f;
// 转换顶点到裁剪空间
v2f.vertex = UnityObjectToClipPos(appdata_base.vertex);
// 变换纹理坐标
v2f.uv = TRANSFORM_TEX(appdata_base.texcoord, _MainTex);
return v2f;
}
// 片元着色器函数
fixed4 frag(v2f v2f) : SV_Target
{
//非线性的 裁剪空间下的深度值
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, v2f.uv);
//得到一个线性的 0~1 区间的深度值
fixed linearDepth = Linear01Depth(depth);
//把深度值作为RGB颜色输入 越接近摄像 就呈现出黑色 越远离摄像机 就呈现出白色 中间就是灰色 具体就会呈现出深浅灰
return fixed4(linearDepth, linearDepth, linearDepth, 1);
}
ENDCG
}
}
// 不使用回退Shader
Fallback Off
}
Lesson72_DepthTexture.cs
using UnityEngine;
public class Lesson72_DepthTexture : PostEffectBase
{
void Start()
{
//可以在Shader中得到对应的深度纹理信息了
Camera.main.depthTextureMode = DepthTextureMode.Depth;
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com