73.查看法线纹理

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

主要步骤

  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

新建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#代码

主要步骤

  1. 新建C#脚本,命名和Shader相同
  2. 继承PostEffectBase
  3. 在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

×

喜欢就点赞,疼爱就打赏