GameTech/URP 渲染实战
源码 / Ch06/DepthNormalsPass.hlsl
Ch06/DepthNormalsPass.hlsl
// DepthNormals Pass:同时写深度和世界空间法线到 _CameraNormalsTexture。
// SSAO(Depth Normals 模式)、贴花、部分自定义屏幕空间效果都依赖它。
#ifndef COOKBOOK_CH06_DEPTH_NORMALS_PASS_INCLUDED
#define COOKBOOK_CH06_DEPTH_NORMALS_PASS_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

struct DepthNormalsAttributes
{
    float4 positionOS : POSITION;
    float3 normalOS   : NORMAL;
    float2 texcoord   : TEXCOORD0;
    UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct DepthNormalsVaryings
{
    float4 positionCS : SV_POSITION;
    float2 uv         : TEXCOORD0;
    float3 normalWS   : TEXCOORD1;
    UNITY_VERTEX_INPUT_INSTANCE_ID
    UNITY_VERTEX_OUTPUT_STEREO
};

DepthNormalsVaryings DepthNormalsVertex(DepthNormalsAttributes input)
{
    DepthNormalsVaryings output = (DepthNormalsVaryings)0;
    UNITY_SETUP_INSTANCE_ID(input);
    UNITY_TRANSFER_INSTANCE_ID(input, output);
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
    output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
    output.normalWS = TransformObjectToWorldNormal(input.normalOS);
    output.uv = input.texcoord;
#if defined(_ALPHATEST_ON)
    output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
#endif
    return output;
}

void DepthNormalsFragment(DepthNormalsVaryings input
    , out half4 outNormalWS : SV_Target0
#ifdef _WRITE_RENDERING_LAYERS
    , out float4 outRenderingLayers : SV_Target1
#endif
)
{
    UNITY_SETUP_INSTANCE_ID(input);
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
#if defined(_ALPHATEST_ON)
    clip(SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a - _Cutoff);
#endif
    // URP 14 的 _CameraNormalsTexture 直接存归一化的世界空间法线(不做 0.5 偏移)
    outNormalWS = half4(NormalizeNormalPerPixel(input.normalWS), 0.0);
#ifdef _WRITE_RENDERING_LAYERS
    // 开启“渲染层”且有贴花等需求时,URP 会让这个 Pass 顺便写出网格的渲染层
    outRenderingLayers = float4(EncodeMeshRenderingLayer(GetMeshRenderingLayer()), 0, 0, 0);
#endif
}

#endif