73.深度和法线纹理-查看法线纹理
73.1 知识点
知识回顾:法线纹理的使用
在 C# 中设置摄像机的深度纹理模式
- 生成深度 + 法线纹理:
Camera.main.depthTextureMode = DepthTextureMode.DepthNormals;
在 Shader 中声明法线纹理采样器属性
- 声明法线纹理采样器:
sampler2D _CameraDepthNormalsTexture;
法线纹理的具体操作
用于存储深度值的变量:
float depth;
用于存储法线的变量:
float3 normals;
对深度 + 法线纹理进行采样(其中 xy 是法线信息,zw 是深度信息):
float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv);
使用 UnityCG.cginc 内置文件中的方法 用于得到深度值(0~1)和法线信息(观察空间下):
同时解码深度和法线:
DecodeDepthNormal(depthNormal, depth, normals);
单独解码深度:
depth = DecodeFloatRG(depthNormal.zw);
单独解码法线:
normals = DecodeViewNormalStereo(depthNormal);
如何查看法线纹理信息
可以在屏幕后期处理中用我们学习过的获取法线信息的知识点,将法线作为颜色显示在屏幕上,感受法线纹理中存储的内容
实现 查看法线纹理屏幕后期处理效果 对应 Shader
主要步骤
新建 Shader,删除无用代码。
声明变量
- 在 Shader 中通过声明
_CameraDepthNormalsTexture
获取深度 + 法线纹理。
- 在 Shader 中通过声明
顶点着色器
- 只需要修改传入结构体类型。
片元着色器
- 对深度 + 法线纹理进行采样(其中
xy
是法线信息,zw
是深度信息):float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv);
- 使用
UnityCG.cginc
内置文件的方法,得到深度值(0~1)和法线信息(观察空间下)。- 用于存储深度值的变量:
float depth;
- 用于存储法线的变量:
float3 normals;
- 同时解码深度和法线:
DecodeDepthNormal(depthNormal, depth, normals);
- 单独解码深度:
depth = DecodeFloatRG(depthNormal.zw);
- 单独解码法线:
normals = DecodeViewNormalStereo(depthNormal);
- 用于存储深度值的变量:
- 对深度 + 法线纹理进行采样(其中
关闭回退Fallback Off
新建Shader,删除无用代码。声明主纹理,并且声明法线纹理采样器_CameraDepthNormalsTexture获取深度法线纹理,顶点函数和结构体保持常规即可
Shader "Unlit/Lesson73_DepthNormalTexture"
{
Properties
{
// 主纹理属性,默认白色
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// 主纹理采样器
sampler2D _MainTex;
// 主纹理缩放平移属性
float4 _MainTex_ST;
// 深度 + 法线纹理采样器
sampler2D _CameraDepthNormalsTexture;
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;
}
ENDCG
}
}
}
片元函数, 以 tex2D 对深度 + 法线纹理采样(其 xy 含法线信息,zw 含深度信息),结果存于 depthNormal 。借助 UnityCG.cginc 里的 DecodeDepthNormal 方法,能同时处理深度与法线,得到 0~1 深度值及观察空间下法线,分别用 depth (float 型)存深度、normals (float3 型)存法线并完成解码赋值。
fixed4 frag(v2f v2f) : SV_Target
{
//直接采样 获取到的是裁剪空间下的法线和深度信息
float4 depthNormal = tex2D(_CameraDepthNormalsTexture, v2f.uv);
fixed depth;//不使用深度值
fixed3 normals;// 使用法线值
DecodeDepthNormal(depthNormal, depth, normals);//调用了这个函数 会自动赋值给depth normals
//法线的-1到1之间的区间 变换到 0~1之间
return fixed4(normals * 0.5 + 0.5, 1);
}
禁用回退 Shader
// 不使用回退Shader
Fallback Off
实现 查看法线纹理屏幕后期处理效果 对应 C#代码
主要步骤
- 新建C#脚本,命名和Shader相同
- 继承PostEffectBase
- 在Start函数中设置深度纹理模式
新建C#脚本,命名和Shader相同,继承PostEffectBase,在Start函数中设置深度纹理模式
public class Lesson73_DepthNormalTexture : PostEffectBase
{
void Start()
{
Camera.main.depthTextureMode = DepthTextureMode.DepthNormals;
}
}
挂载到摄像机,可以看到每个像素在观察空间的法线纹理图。三个轴对应的法线是对应其rgb的
73.2 知识点代码
Lesson73_深度和法线纹理_查看法线纹理.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson73_深度和法线纹理_查看法线纹理 : MonoBehaviour
{
void Start()
{
#region 知识回顾 法线纹理的使用
//第一步:在C#中设置摄像机的深度纹理模式
//生成深度+法线纹理
//Camera.main.depthTextureMode = DepthTextureMode.DepthNormals;
//第二步:在Shader代码中按规则声明属性
//sampler2D _CameraDepthNormalsTexture;
//法线纹理使用
//用于存储深度值的变量
//float depth;
//用于存储法线的变量
//float3 normals;
//对深度+法线纹理进行采样(其中xy是法线信息,zw是深度信息)
//float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv);
//UnityCG.cginc 内置文件中的方法 用于得到深度值(0~1)和法线信息(观察空间下)
//相当于一次性处理深度和法线
// DecodeDepthNormal(depthNormal, depth, normals);
//单独得到深度
// depth = DecodeFloatRG(depthNormal.zw);
//单独得到法线
// normals = DecodeViewNormalStereo(depthNormal);
#endregion
#region 知识点一 如何查看法线纹理信息
//我们可以在屏幕后期处理中用我们学习过的获取法线信息的知识点
//将法线作为颜色显示在屏幕上
//感受法线纹理中存储的内容
#endregion
#region 知识点二 实现 查看法线纹理屏幕后期处理效果 对应 Shader
//1.新建Shader,删除无用代码
//2.声明变量
// 在Shader中通过声明_CameraDepthNormalsTexture获取深度+法线纹理
//3.顶点着色器
// 只需要修改传入结构体类型
//4.片元着色器
// 对深度+法线纹理进行采样(其中xy是法线信息,zw是深度信息)
// float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv);
// UnityCG.cginc 内置文件中的方法 用于得到深度值(0~1)和法线信息(观察空间下)
// 相当于一次性处理深度和法线
// 用于存储深度值的变量
// float depth;
// 用于存储法线的变量
// float3 normals;
// DecodeDepthNormal(depthNormal, depth, normals);
// 单独得到深度
// depth = DecodeFloatRG(depthNormal.zw);
// 单独得到法线
// normals = DecodeViewNormalStereo(depthNormal);
//5.Fallback Off
#endregion
#region 知识点三 实现 查看法线纹理屏幕后期处理效果 对应 C#代码
//1.新建C#脚本,命名和Shader相同
//2.继承PostEffectBase
//3.在Start函数中设置深度纹理模式
#endregion
}
}
Lesson73_DepthNormalTexture.shader
Shader "Unlit/Lesson73_DepthNormalTexture"
{
Properties
{
// 主纹理属性,默认白色
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// 主纹理采样器
sampler2D _MainTex;
// 主纹理缩放平移属性
float4 _MainTex_ST;
// 深度 + 法线纹理采样器
sampler2D _CameraDepthNormalsTexture;
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
{
//直接采样 获取到的是裁剪空间下的法线和深度信息
float4 depthNormal = tex2D(_CameraDepthNormalsTexture, v2f.uv);
fixed depth;//不使用深度值
fixed3 normals;// 使用法线值
DecodeDepthNormal(depthNormal, depth, normals);//调用了这个函数 会自动赋值给depth normals
//法线的-1到1之间的区间 变换到 0~1之间
return fixed4(normals * 0.5 + 0.5, 1);
}
ENDCG
}
}
// 不使用回退Shader
Fallback Off
}
Lesson73_DepthNormalTexture.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson73_DepthNormalTexture : PostEffectBase
{
void Start()
{
Camera.main.depthTextureMode = DepthTextureMode.DepthNormals;
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com