80.深度法线纹理实现边缘检测具体实现

  1. 80.深度和法线纹理-效果实现-深度法线纹理实现边缘检测-具体实现
    1. 80.1 知识点
      1. 知识回顾:深度+法线纹理实现边缘检测的基本原理
      2. 实现 利用深度+法线纹理实现边缘检测屏幕后期处理效果 对应 Shader
        1. 主要步骤
        2. 新建Shader,取名EdgeDetectionWithDepthNormalsTexture,删除无用代码
        3. 声明属性,并进行属性映射,包括主纹理、边缘检测强度(0显示场景 1只显示边缘 用于控制自定义背景色程度—)、描边颜色、背景颜色、采样偏移距离、深度敏感度、法线敏感度、纹素、深度+法线纹理 _CameraDepthNormalsTexture(定死的名称)
        4. 声明屏幕后处理标配指令
        5. 声明结构体,包括顶点坐标和uv数组(5个空间,存储中心点、对角线4个点)
        6. 顶点函数进行顶点坐标转换和5个uv坐标赋值
        7. 实现一个用于比较两点深度、法线信息的函数,返回0或1,方便进行插值计算
        8. 片元函数直接采样得到对角线四个点的深度法线信息,调用比较函数得到是否是边缘,考虑背景色进行三次插值
        9. 不使用回退 Shader
      3. 实现 利用深度+法线纹理实现边缘检测屏幕后期处理效果 对应 C#
        1. 主要步骤
        2. 新建C#脚本,取名和Shader相同,继承PostEffectBase。Start函数中 开启深度+法线纹理,注意不要直接=,使用|=,避免关闭深度纹理.声明Shader中的可变变量,重写UpdateProperty函数,在其中设置属性
        3. 挂载到摄像机关联shader,修改参数可以查看边缘效果
    2. 80.2 知识点代码
      1. Lesson80_深度和法线纹理_效果实现_深度法线纹理实现边缘检测_具体实现.cs
      2. Lesson80_EdgeDetectionWithDepthNormalsTexture.shader
      3. Lesson80_EdgeDetectionWithDepthNormalsTexture.cs

80.深度和法线纹理-效果实现-深度法线纹理实现边缘检测-具体实现


80.1 知识点

知识回顾:深度+法线纹理实现边缘检测的基本原理

  • 基于 Roberts (罗伯茨) 交叉算子,通过比较对角线上的像素的深度和法线值,判断是否处于边缘上。
  • 步骤1:获取对角线像素
    利用纹素变量进行 UV 坐标偏移,得到对角线的像素位置。可以通过采样偏移距离变量控制描边的粗细。
  • 步骤2:进行深度和法线值的比较
    获取对角线像素的深度和法线信息,通过减法得到差值,用差值和阈值进行比较,判断两点是否在同一平面上。
  • 步骤3:判断是否在边缘
    根据比较结果,决定中心像素使用的是原本的颜色还是描边的颜色。

实现 利用深度+法线纹理实现边缘检测屏幕后期处理效果 对应 Shader

主要步骤

  1. 新建Shader

    • 取名 EdgeDetectionWithDepthNormalsTexture
    • 删除无用代码。
  2. 声明属性,属性映射

    • 主纹理:_MainTex
    • 边缘检测强度:_EdgeOnly(0 显示场景,1 只显示边缘,用于控制自定义背景色的程度)
    • 描边颜色:_EdgeColor
    • 背景颜色:_BackgroundColor
    • 采样偏移距离:_SampleDistance
    • 深度敏感度:_SensitivityDepth
    • 法线敏感度:_SensitivityNormal
    • 注意:映射属性时需要加入:
      • 纹素:_MainTex_TexelSize
      • 深度 + 法线纹理:_CameraDepthNormalsTexture
  3. 屏幕后处理标配

  4. 结构体

    • 顶点坐标
    • uv数组,包含5个空间(存储中心点、对角线四个点)
  5. 顶点着色器

    1. 顶点坐标转换
    2. 5个uv坐标赋值,按以下顺序:
      • 中心点、左上角、右下角、右上角、左下角
  6. 片元着色器

    1. 直接采样得到对角线四个点的深度法线信息
    2. 实现一个用于比较两点深度、法线信息的函数,返回0或1,方便进行插值计算
    3. 声明一个插值变量,0代表使用边缘色,1代表使用源颜色
    4. 考虑背景色差值
  7. FallBack Off

新建Shader,取名EdgeDetectionWithDepthNormalsTexture,删除无用代码

Shader "Unlit/Lesson80_EdgeDetectionWithDepthNormalsTexture"
{
    Properties
    {
    
    }
    SubShader
    {

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

        
            ENDCG
        }
    }
}

声明属性,并进行属性映射,包括主纹理、边缘检测强度(0显示场景 1只显示边缘 用于控制自定义背景色程度—)、描边颜色、背景颜色、采样偏移距离、深度敏感度、法线敏感度、纹素、深度+法线纹理 _CameraDepthNormalsTexture(定死的名称)

Properties
{
    //主纹理
    _MainTex ("Texture", 2D) = "white" {}
    //用于控制自定义背景颜色程度的 0要显示原始背景色 1只显示边缘 完全显示自定义背景色
    _EdgeOnly("EdgeOnly", Float) = 0
    //边缘的描边颜色
    _EdgeColor("EdgeColor", Color) = (0,0,0,0)
    //自定义背景颜色
    _BackgroundColor("BackgroundColor", Color) = (1,1,1,1)
    //采样偏移程度 主要用来控制描边的粗细 值越大越粗 反之越细
    _SampleDistance("SampleDistance", Float) = 1
    //深度和法线的敏感度 用来进行这个差值判断时 起作用
    _SensitivityDepth("SensitivityDepth", Float) = 1
    _SensitivityNormal("SensitivityNormal", Float) = 1
}
//主纹理
sampler2D _MainTex;
//纹素 用于进行uv坐标偏移 取得周围像素的uv坐标的
half4 _MainTex_TexelSize;
//深度+法线纹理
sampler2D _CameraDepthNormalsTexture;\
//用于控制自定义背景颜色程度的 0要显示原始背景色 1只显示边缘 完全显示自定义背景色
fixed _EdgeOnly;
//边缘的描边颜色
fixed4 _EdgeColor;
//自定义背景颜色
fixed4 _BackgroundColor;
//采样偏移程度 主要用来控制描边的粗细 值越大越粗 反之越细
float _SampleDistance;
//深度和法线的敏感度 用来进行这个差值判断时 起作用
float _SensitivityDepth;
float _SensitivityNormal;

声明屏幕后处理标配指令

//屏幕后处理标配
ZTest Always // 始终通过深度测试
Cull Off // 关闭背面剔除
ZWrite Off // 禁止写入深度缓冲

声明结构体,包括顶点坐标和uv数组(5个空间,存储中心点、对角线4个点)

struct v2f
{
    //用于存储5个像素的uv坐标
    half2 uv[5] : TEXCOORD0;
    float4 vertex : SV_POSITION;
};

顶点函数进行顶点坐标转换和5个uv坐标赋值

//顶点着色器
v2f vert(appdata_base appdata_base)
{
    v2f v2f;
    //转换到裁剪空间
    v2f.vertex = UnityObjectToClipPos(appdata_base.vertex);
    //uv相关坐标赋值
    half2 uv = appdata_base.texcoord;
    //中心点
    v2f.uv[0] = uv;
    //对角线相关像素uv坐标赋值
    //左上角
    v2f.uv[1] = uv + _MainTex_TexelSize.xy * half2(-1, 1) * _SampleDistance;
    //右下角
    v2f.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1) * _SampleDistance;
    //右上角
    v2f.uv[3] = uv + _MainTex_TexelSize.xy * half2(1, 1) * _SampleDistance;
    //左下角
    v2f.uv[4] = uv + _MainTex_TexelSize.xy * half2(-1, -1) * _SampleDistance;

    return v2f;
}

实现一个用于比较两点深度、法线信息的函数,返回0或1,方便进行插值计算

//用于比较两个点的深度和法线纹理中采样得到的信息 用来判断是否是边缘
//返回值的含义 
//1 - 法线和深度值基本相同 处于同一个平面上
//0 - 差异大 不在一个平面上
half CheckSame(half4 depthNormal1, half4 depthNormal2)
{
    //分别得到两个点信息的深度和法线
    
    //第一个点的
    //得到深度值
    float depth1 = DecodeFloatRG(depthNormal1.zw);
    
    //得到法线的xy
    float2 normal1 = depthNormal1.xy;

    //第二个点的
    //得到深度值
    float depth2 = DecodeFloatRG(depthNormal2.zw);
    
    //得到法线的xy
    float2 normal2 = depthNormal2.xy;

    //法线的差异计算
    //计算两条法线的xy的差值 并且乘以 自定义的敏感度
    float2 normalDiff = abs(normal1 - normal2) * _SensitivityNormal;
    
    //判断两个法线是否在一个平面
    //如果差异不大 证明基本上在一个平面上 返回 1;否则返回0
    int isSameNormal = (normalDiff.x + normalDiff.y) < 0.1;

    //深度的差异计算
    float depthDiff = abs(depth1 - depth2) * _SensitivityDepth;
    
    //判断深度是不是很接近 是不是相当于在一个平面上
    //如果满足条件 证明深度值差异非常小 基本趋近于在一个平面上 返回1;否则 返回0
    int isSameDepth = depthDiff < 0.1 * depth1;
    
    //返回值的含义 
    //1 - 法线和深度值基本相同 处于同一个平面上
    //0 - 差异大 不在一个平面上
    return isSameDepth * isSameNormal ? 1 : 0;
}

片元函数直接采样得到对角线四个点的深度法线信息,调用比较函数得到是否是边缘,考虑背景色进行三次插值

//片元着色器
fixed4 frag(v2f v2f) : SV_Target
{
    // 从深度+法线纹理中采样四个邻近点的深度和法线信息
    // 左上角像素的深度和法线信息
    half4 TL = tex2D(_CameraDepthNormalsTexture, v2f.uv[1]);
    // 右下角像素的深度和法线信息
    half4 BR = tex2D(_CameraDepthNormalsTexture, v2f.uv[2]);
    // 右上角像素的深度和法线信息
    half4 TR = tex2D(_CameraDepthNormalsTexture, v2f.uv[3]);
    // 左下角像素的深度和法线信息
    half4 BL = tex2D(_CameraDepthNormalsTexture, v2f.uv[4]);

    // 初始化边缘插值值,默认设为 1(表示未检测到边缘)
    half edgeLerpValue = 1;

    // 比较对角线上两个点的深度和法线信息
    // 如果两个点深度和法线的差异较大(即不在同一平面),edgeLerpValue 会被置为 0
    edgeLerpValue *= CheckSame(TL, BR); // 左上和右下
    edgeLerpValue *= CheckSame(TR, BL); // 右上和左下

    // 根据检测到的边缘信息对颜色进行插值
    
    // 根据是否是边缘,混合边缘颜色 (_EdgeColor) 和场景原始颜色 (tex2D(_MainTex, v2f.uv[0]))
    // 如果 edgeLerpValue 为 1,显示场景颜色;如果为 0,显示边缘颜色
    fixed4 withEdgeColor = lerp(_EdgeColor, tex2D(_MainTex, v2f.uv[0]), edgeLerpValue);

    // 根据是否是边缘,边缘颜色与自定义背景颜色 (_BackgroundColor) 进行插值
    // edgeLerpValue 为 1 时显示背景颜色;为 0 时显示边缘颜色
    fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edgeLerpValue);

    // 将计算后的混合原纹理颜色和混合自定义背景颜色插值
    return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
}

不使用回退 Shader

Fallback Off// 不使用回退Shader

实现 利用深度+法线纹理实现边缘检测屏幕后期处理效果 对应 C#

主要步骤

  1. 新建C#脚本

    • 取名与Shader相同。
  2. 继承 PostEffectBase

  3. 声明可控变量

  4. Start函数

    • 开启深度 + 法线纹理
    • 注意:使用 |= 操作符,而不是 =,避免关闭深度纹理。
  5. 重写 UpdateProperty 函数

    • 在其中设置属性即可。

新建C#脚本,取名和Shader相同,继承PostEffectBase。Start函数中 开启深度+法线纹理,注意不要直接=,使用|=,避免关闭深度纹理.声明Shader中的可变变量,重写UpdateProperty函数,在其中设置属性

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 自定义的屏幕后处理效果,用于基于深度和法线纹理的边缘检测
public class Lesson80_EdgeDetectionWithDepthNormalsTexture : PostEffectBase
{
    // 边缘显示程度,范围 [0, 1]
    // 0 表示显示完整的原始场景,1 表示只显示边缘
    [Range(0, 1)] public float edgeOnly = 0;

    // 边缘的描边颜色
    public Color edgeColor = Color.black;

    // 背景的自定义颜色
    public Color backgroundColor = Color.white;

    // 采样偏移量,用于控制边缘粗细
    public float sampleDistance = 1;

    // 对深度敏感程度,用于判断是否是边缘
    public float sensitivityDepth = 1;

    // 对法线敏感程度,用于判断是否是边缘
    public float sensitivityNormal = 1;

    void Start()
    {
        // 确保摄像机启用深度+法线纹理模式,以便采样深度和法线信息
        // 使用按位或操作防止覆盖其他后处理需求
        Camera.main.depthTextureMode |= DepthTextureMode.DepthNormals;
    }

    // 更新材质属性的方法,由基类调用
    protected override void UpdateProperty()
    {
        // 如果材质存在,更新其对应的参数值
        if (material != null)
        {
            // 设置边缘显示程度
            material.SetFloat("_EdgeOnly", edgeOnly);
            // 设置边缘颜色
            material.SetColor("_EdgeColor", edgeColor);
            // 设置背景颜色
            material.SetColor("_BackgroundColor", backgroundColor);
            // 设置采样偏移量(边缘粗细)
            material.SetFloat("_SampleDistance", sampleDistance);
            // 设置深度敏感度
            material.SetFloat("_SensitivityDepth", sensitivityDepth);
            // 设置法线敏感度
            material.SetFloat("_SensitivityNormal", sensitivityNormal);
        }
    }
}

挂载到摄像机关联shader,修改参数可以查看边缘效果



80.2 知识点代码

Lesson80_深度和法线纹理_效果实现_深度法线纹理实现边缘检测_具体实现.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson80_深度和法线纹理_效果实现_深度法线纹理实现边缘检测_具体实现 : MonoBehaviour
{
    void Start()
    {
        #region 知识回顾 深度+法线纹理实现边缘检测 基本原理

        //基于Roberts(罗伯茨)交叉算子,通过比较对角线上的的像素的深度和法线值,判断是否在边缘上。
        //1.得到对角线上的像素
        //  利用纹素变量进行uv坐标偏移,得到对角线像素位置(可以加入一个采样偏移距离变量控制描边粗细)
        //2.进行深度和法线值的比较
        //  获取对角线像素的深度+法线信息,通过减法得到差值,用差值和阈值进行比较,判断两点是否在同一平面上
        //3.决定是否在边缘
        //  根据比较结果,决定中心像素使用的颜色是原本的颜色还是描边的颜色

        #endregion

        #region 知识点一 实现 利用深度+法线纹理实现边缘检测屏幕后期处理效果 对应 Shader

        //1.新建Shader,取名EdgeDetectionWithDepthNormalsTexture
        //  删除无用代码
        
        //2.声明属性,属性映射
        //  主纹理 _MainTex
        //  边缘检测强度 _EdgeOnly 0显示场景 1只显示边缘 用于控制自定义背景色程度
        //  描边颜色 _EdgeColor
        //  背景颜色 _BackgroundColor
        //  采样偏移距离 _SampleDistance
        //  深度敏感度 _SensitivityDepth
        //  法线敏感度 _SensitivityNormal
        //  注意:映射属性时需要加入
        //  纹素 _MainTex_TexelSize
        //  深度+法线纹理 _CameraDepthNormalsTexture
        
        //3.屏幕后处理标配
        
        //4.结构体
        //  顶点坐标
        //  uv数组,5个空间(存储中心点、对角线4个点)
        
        //5.顶点着色器
        //  5-1.顶点坐标转换
        //  5-2.5个uv坐标赋值,按这样的顺序
        //      中心点、左上角、右下角、右上角、左下角
        
        //6.片元着色器
        //  6-1.直接采样得到对角线四个点的深度法线信息
        //  6-2.实现一个用于比较两点深度、法线信息的函数,返回0或1,方便进行插值计算
        //  6-3.声明一个插值变量 0代表使用边缘色 1代表使用源颜色
        //  6-4.考虑背景色差值
        
        //7.FallBack Off

        #endregion

        #region 知识点二 实现 利用深度+法线纹理实现边缘检测屏幕后期处理效果 对应 C#

        //1.新建C#脚本,取名和Shader相同
        
        //2.继承PostEffectBase
        
        //3.声明可控变量
        
        //4.Start函数中 开启深度+法线纹理
        //  注意:不要直接=,要|=,避免关闭深度纹理
        
        //5.重写UpdateProperty函数
        //  在其中设置属性即可

        #endregion
    }
}

Lesson80_EdgeDetectionWithDepthNormalsTexture.shader

Shader "Unlit/Lesson80_EdgeDetectionWithDepthNormalsTexture"
{
    Properties
    {
        //主纹理
        _MainTex ("Texture", 2D) = "white" {}
        //用于控制自定义背景颜色程度的 0要显示原始背景色 1只显示边缘 完全显示自定义背景色
        _EdgeOnly("EdgeOnly", Float) = 0
        //边缘的描边颜色
        _EdgeColor("EdgeColor", Color) = (0,0,0,0)
        //自定义背景颜色
        _BackgroundColor("BackgroundColor", Color) = (1,1,1,1)
        //采样偏移程度 主要用来控制描边的粗细 值越大越粗 反之越细
        _SampleDistance("SampleDistance", Float) = 1
        //深度和法线的敏感度 用来进行这个差值判断时 起作用
        _SensitivityDepth("SensitivityDepth", Float) = 1
        _SensitivityNormal("SensitivityNormal", Float) = 1
    }
    SubShader
    {
        //屏幕后处理标配
        ZTest Always // 始终通过深度测试
        Cull Off // 关闭背面剔除
        ZWrite Off // 禁止写入深度缓冲

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            //主纹理
            sampler2D _MainTex;
            //纹素 用于进行uv坐标偏移 取得周围像素的uv坐标的
            half4 _MainTex_TexelSize;
            //深度+法线纹理
            sampler2D _CameraDepthNormalsTexture;\
            //用于控制自定义背景颜色程度的 0要显示原始背景色 1只显示边缘 完全显示自定义背景色
            fixed _EdgeOnly;
            //边缘的描边颜色
            fixed4 _EdgeColor;
            //自定义背景颜色
            fixed4 _BackgroundColor;
            //采样偏移程度 主要用来控制描边的粗细 值越大越粗 反之越细
            float _SampleDistance;
            //深度和法线的敏感度 用来进行这个差值判断时 起作用
            float _SensitivityDepth;
            float _SensitivityNormal;

            struct v2f
            {
                //用于存储5个像素的uv坐标
                half2 uv[5] : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            //用于比较两个点的深度和法线纹理中采样得到的信息 用来判断是否是边缘
            //返回值的含义 
            //1 - 法线和深度值基本相同 处于同一个平面上
            //0 - 差异大 不在一个平面上
            half CheckSame(half4 depthNormal1, half4 depthNormal2)
            {
                //分别得到两个点信息的深度和法线

                //第一个点的
                //得到深度值
                float depth1 = DecodeFloatRG(depthNormal1.zw);

                //得到法线的xy
                float2 normal1 = depthNormal1.xy;

                //第二个点的
                //得到深度值
                float depth2 = DecodeFloatRG(depthNormal2.zw);

                //得到法线的xy
                float2 normal2 = depthNormal2.xy;

                //法线的差异计算
                //计算两条法线的xy的差值 并且乘以 自定义的敏感度
                float2 normalDiff = abs(normal1 - normal2) * _SensitivityNormal;

                //判断两个法线是否在一个平面
                //如果差异不大 证明基本上在一个平面上 返回 1;否则返回0
                int isSameNormal = (normalDiff.x + normalDiff.y) < 0.1;

                //深度的差异计算
                float depthDiff = abs(depth1 - depth2) * _SensitivityDepth;

                //判断深度是不是很接近 是不是相当于在一个平面上
                //如果满足条件 证明深度值差异非常小 基本趋近于在一个平面上 返回1;否则 返回0
                int isSameDepth = depthDiff < 0.1 * depth1;

                //返回值的含义 
                //1 - 法线和深度值基本相同 处于同一个平面上
                //0 - 差异大 不在一个平面上
                return isSameDepth * isSameNormal ? 1 : 0;
            }

            //顶点着色器
            v2f vert(appdata_base appdata_base)
            {
                v2f v2f;
                //转换到裁剪空间
                v2f.vertex = UnityObjectToClipPos(appdata_base.vertex);
                //uv相关坐标赋值
                half2 uv = appdata_base.texcoord;
                //中心点
                v2f.uv[0] = uv;
                //对角线相关像素uv坐标赋值
                //左上角
                v2f.uv[1] = uv + _MainTex_TexelSize.xy * half2(-1, 1) * _SampleDistance;
                //右下角
                v2f.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1) * _SampleDistance;
                //右上角
                v2f.uv[3] = uv + _MainTex_TexelSize.xy * half2(1, 1) * _SampleDistance;
                //左下角
                v2f.uv[4] = uv + _MainTex_TexelSize.xy * half2(-1, -1) * _SampleDistance;

                return v2f;
            }

            //片元着色器
            fixed4 frag(v2f v2f) : SV_Target
            {
                // 从深度+法线纹理中采样四个邻近点的深度和法线信息
                // 左上角像素的深度和法线信息
                half4 TL = tex2D(_CameraDepthNormalsTexture, v2f.uv[1]);
                // 右下角像素的深度和法线信息
                half4 BR = tex2D(_CameraDepthNormalsTexture, v2f.uv[2]);
                // 右上角像素的深度和法线信息
                half4 TR = tex2D(_CameraDepthNormalsTexture, v2f.uv[3]);
                // 左下角像素的深度和法线信息
                half4 BL = tex2D(_CameraDepthNormalsTexture, v2f.uv[4]);

                // 初始化边缘插值值,默认设为 1(表示未检测到边缘)
                half edgeLerpValue = 1;

                // 比较对角线上两个点的深度和法线信息
                // 如果两个点深度和法线的差异较大(即不在同一平面),edgeLerpValue 会被置为 0
                edgeLerpValue *= CheckSame(TL, BR); // 左上和右下
                edgeLerpValue *= CheckSame(TR, BL); // 右上和左下

                // 根据检测到的边缘信息对颜色进行插值

                // 根据是否是边缘,混合边缘颜色 (_EdgeColor) 和场景原始颜色 (tex2D(_MainTex, v2f.uv[0]))
                // 如果 edgeLerpValue 为 1,显示场景颜色;如果为 0,显示边缘颜色
                fixed4 withEdgeColor = lerp(_EdgeColor, tex2D(_MainTex, v2f.uv[0]), edgeLerpValue);

                // 根据是否是边缘,边缘颜色与自定义背景颜色 (_BackgroundColor) 进行插值
                // edgeLerpValue 为 1 时显示背景颜色;为 0 时显示边缘颜色
                fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edgeLerpValue);

                // 将计算后的混合原纹理颜色和混合自定义背景颜色插值
                return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
            }
            ENDCG
        }
    }
    Fallback Off// 不使用回退Shader
}

Lesson80_EdgeDetectionWithDepthNormalsTexture.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 自定义的屏幕后处理效果,用于基于深度和法线纹理的边缘检测
public class Lesson80_EdgeDetectionWithDepthNormalsTexture : PostEffectBase
{
    // 边缘显示程度,范围 [0, 1]
    // 0 表示显示完整的原始场景,1 表示只显示边缘
    [Range(0, 1)] public float edgeOnly = 0;

    // 边缘的描边颜色
    public Color edgeColor = Color.black;

    // 背景的自定义颜色
    public Color backgroundColor = Color.white;

    // 采样偏移量,用于控制边缘粗细
    public float sampleDistance = 1;

    // 对深度敏感程度,用于判断是否是边缘
    public float sensitivityDepth = 1;

    // 对法线敏感程度,用于判断是否是边缘
    public float sensitivityNormal = 1;

    void Start()
    {
        // 确保摄像机启用深度+法线纹理模式,以便采样深度和法线信息
        // 使用按位或操作防止覆盖其他后处理需求
        Camera.main.depthTextureMode |= DepthTextureMode.DepthNormals;
    }

    // 更新材质属性的方法,由基类调用
    protected override void UpdateProperty()
    {
        // 如果材质存在,更新其对应的参数值
        if (material != null)
        {
            // 设置边缘显示程度
            material.SetFloat("_EdgeOnly", edgeOnly);
            // 设置边缘颜色
            material.SetColor("_EdgeColor", edgeColor);
            // 设置背景颜色
            material.SetColor("_BackgroundColor", backgroundColor);
            // 设置采样偏移量(边缘粗细)
            material.SetFloat("_SampleDistance", sampleDistance);
            // 设置深度敏感度
            material.SetFloat("_SensitivityDepth", sensitivityDepth);
            // 设置法线敏感度
            material.SetFloat("_SensitivityNormal", sensitivityNormal);
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏