You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2022.2.19 URP下如何渲染DepthNormals深度图?

在Unity 2022.2.19中渲染并应用DepthNormals深度图(Shader/Shader Graph实现)

一、手写Shader实现DepthNormals渲染

创建一个Unlit Shader,替换为以下代码,该Shader会将场景的深度与法线信息编码输出到纹理中:

Shader "Custom/DepthNormals"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float depth : TEXCOORD1;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                // 将深度转换为[0,1]范围
                o.depth = -UnityObjectToViewPos(v.vertex).z * _ProjectionParams.w;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 归一化法线并编码到[0,1]区间
                float3 normal = normalize(i.worldNormal);
                float2 encNormal = EncodeNormal(normal);
                // 深度值饱和处理
                float depth = saturate(i.depth);
                
                // RG通道存编码后的法线,BA通道存深度(可按需调整通道分配)
                return fixed4(encNormal, depth, 1.0);
            }
            ENDCG
        }
    }
    FallBack "VertexLit"
}

二、Shader Graph可视化实现

  1. 创建Unlit Shader Graph,按以下步骤连接节点:
    • 拖入Position节点,选择World Space,连接到Normal Vector节点的Position输入(Normal Vector节点选择World Space),得到世界空间法线。
    • 添加Encode Normal节点,输入上述法线,将法线编码至[0,1]范围。
    • 添加Scene Depth节点,选择Eye Depth,再连接到Linear 0 to 1节点,将深度值转换为[0,1]区间。
    • 将编码后的法线R、G通道连到Master节点的R、G输入;转换后的深度值连到B或A通道。
    • 保存Shader Graph,命名为DepthNormalsGraph。

三、应用到整个相机/场景

通过相机后处理让效果覆盖整个场景:

  1. 创建C#脚本DepthNormalsCapture,代码如下:
using UnityEngine;

[RequireComponent(typeof(Camera))]
public class DepthNormalsCapture : MonoBehaviour
{
    public Shader depthNormalsShader;
    private Material _depthNormalsMat;

    void Awake()
    {
        _depthNormalsMat = new Material(depthNormalsShader);
        // 确保相机能获取深度法线纹理
        GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
    }

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        Graphics.Blit(src, dest, _depthNormalsMat);
    }
}
  1. 将脚本挂载到主相机,把你创建的DepthNormals Shader(手写或Shader Graph生成的)拖入脚本的depthNormalsShader字段。
  2. 运行游戏,相机将直接输出整个场景的DepthNormals图。

补充提示

如果只是为了Moebius风格的轮廓检测,无需单独渲染可视化的DepthNormals图——只需开启相机的DepthTextureMode.DepthNormals,在后续的轮廓后处理Shader中直接采样内置纹理_CameraDepthNormalsTexture即可。Moebius风格的描边核心是对比相邻像素的深度与法线差值,超过阈值时绘制边缘。

内容的提问来源于stack exchange,提问作者bob0815

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:53:21