72.查看深度纹理

  1. 72.深度和法线纹理-查看深度纹理
    1. 72.1 知识点
      1. 知识回顾:深度纹理的使用
        1. 第一步:在 C# 中设置摄像机的深度纹理模式
        2. 第二步:在 Shader 代码中声明深度纹理属性
        3. 第三步:深度纹理的使用
      2. 如何查看深度纹理信息
      3. 实现 查看深度纹理屏幕后期处理效果 对应 Shader
        1. 主要步骤
        2. 新建Shader,删除无用代码
        3. 声明属性,包括主纹理,并且在Shader中通过声明深度纹理变量_CameraDepthTexture获取深度纹理
        4. 结构体和顶点函数按常规的纹理坐标和裁剪坐标进行定义和转换
        5. 片元函数中,通过深度纹理采样宏 SAMPLE_DEPTH_TEXTURE 对 _CameraDepthTexture 依据传入的纹理坐标 进行采样操作,得到非线性的深度值。运用 Linear01Depth 函数将之前获取到的非线性深度值转换至观察空间下,并且把像素点到摄像机的距离映射到 [0, 1] 这个区间内,从而得到线性深度值。把所得到的深度值作为要返回颜色的 RGB 三个通道的值,以此来实现基于深度信息的特定视觉效果
        6. 关闭 Shader 回退
      4. 实现 查看深度纹理屏幕后期处理效果 对应 C#代码
        1. 主要步骤
        2. 新建C#脚本继承PostEffectBase在Start函数中设置深度纹理模式,得到对应的深度纹理信息了
        3. C#脚本关联shader挂载到摄像机,可以看到Game窗口渲染的深度值。缩小远裁剪面数值可以看到更明显。离摄像机越远越接近白色,把立方体靠近摄像机越接近黑色
    2. 72.2 知识点代码
      1. Lesson72_深度和法线纹理_查看深度纹理.cs
      2. Lesson72_DepthTexture.shader
      3. Lesson72_DepthTexture.cs

72.深度和法线纹理-查看深度纹理


72.1 知识点

知识回顾:深度纹理的使用

第一步:在 C# 中设置摄像机的深度纹理模式

生成深度纹理:

Camera.main.depthTextureMode = DepthTextureMode.Depth;

第二步:在 Shader 代码中声明深度纹理属性

按规则声明深度纹理变量:

sampler2D _CameraDepthTexture;

第三步:深度纹理的使用

  1. 使用深度纹理采样宏
    获取非线性的深度值:

    float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
    
  2. 转换为线性深度值(观察空间下的距离)
    将非线性深度值转换为像素点到摄像机的距离:

    float viewDepth = LinearEyeDepth(depth);
    
  3. 映射深度值到 [0,1] 区间
    将像素点到摄像机的距离映射到 [0,1] 区间内,得到线性深度值:

    float linearDepth = Linear01Depth(depth);
    

如何查看深度纹理信息

我们可以在 屏幕后期处理 中,运用获取深度信息的知识点,将深度值作为颜色的 RGB 值显示在屏幕上,从而直观地感受深度纹理中存储的内容。

  • 实现效果:
    理论上,如果深度值使用的是 0~1 范围的线性值:
    • 越接近近裁剪面,越靠近黑色
    • 越接近远裁剪面,越靠近白色

实现 查看深度纹理屏幕后期处理效果 对应 Shader

主要步骤

  1. 新建 Shader,删除无用代码
    开始构建一个新的 Shader 文件,保留必要的核心结构。

  2. 声明变量
    在 Shader 中通过声明 _CameraDepthTexture 属性以获取深度纹理。

  3. 顶点着色器
    在顶点着色器中,只需修改传入的结构体类型,以支持纹理坐标和顶点位置的处理。

  4. 片元着色器
    在片元着色器中完成深度纹理的采样和处理:

    • 使用深度纹理采样宏 SAMPLE_DEPTH_TEXTURE_CameraDepthTexture 进行采样,获取非线性深度值。
    • 使用 Linear01Depth 函数,将非线性深度值转换到观察空间下,并将像素点到摄像机的距离映射到 [0,1] 区间内,得到线性深度值。
    • 最后,将深度值作为返回颜色的 RGB 值,用于渲染效果展示。
  5. 禁用回退 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

×

喜欢就点赞,疼爱就打赏