如何在植被Shader中实现半透明阴影接收

解读

国内项目里植被(草、树叶、蕨类)普遍使用Alpha Test + Alpha Blend混合渲染,但Unity内置ShadowCaster只认Alpha Test(clip/discard),导致半透明区域无法接收阴影;面试官想确认你能否在URP/HDRP下把阴影收集(Shadow Collector) 阶段也做半透明采样,并兼顾移动端带宽Overdraw压力。

知识点

  1. 阴影映射管线:Unity在Shadow Pass里只渲染深度,默认Alpha Test;半透明物体不参与,因此阴影贴图里没有半透明信息
  2. 阴影收集(Shadow Collector)/屏幕空间阴影:URP在Additional LightsMain Light分别走Screen Space ShadowCascade Shadowmap;需要把阴影衰减乘进半透明片元
  3. 自定义Shadow Receiver:在ForwardBaseForwardTransparent里手动采样_MainLightShadowmapTexture_AdditionalLightsShadowmapTexture,用植被世界坐标计算shadowCoord,再与Alphalerp(1, shadowAttenuation, alpha)
  4. 半透明排序与ZWrite冲突:植被需关闭ZWrite队列=Transparent+250ShadowCaster单独写Alpha Test版本,防止阴影断裂
  5. 移动端优化
    • 4-tap PCF代替7×7 PCF
    • Shader Variant里**#pragma skip_variants DIRLIGHTMAP_COMBINED**减少变体;
    • 级联混合lerp而非branch防止warp divergence

答案

分四步落地:

  1. ShadowCaster Pass仍用Alpha Test保证深度写入:

    Pass {
        Name "ShadowCaster"
        ZWrite On Cull Off
        HLSLPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
        half4 frag (Varyings i) : SV_TARGET {
            half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv).a;
            clip(alpha - _Cutoff);
            return 0;
        }
        ENDHLSL
    }
    
  2. Transparent Pass里手动采样阴影:

    half4 frag (Varyings i) : SV_TARGET {
        half4 col = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
        float4 shadowCoord = TransformWorldToShadowCoord(i.worldPos);
        half shadowAtt = MainLightRealtimeShadow(shadowCoord);   // 内置URP函数
        col.rgb *= lerp(1, shadowAtt, col.a);                    // 半透明越淡,阴影越弱
        return col;
    }
    
  3. 队列与混合设置

    Tags { "Queue"="Transparent+250" "RenderType"="TransparentCutout" }
    Blend SrcAlpha OneMinusSrcAlpha
    ZWrite Off
    
  4. 美术规范

    • Alpha通道渐变而非硬边,防止阴影跳变
    • 植被面片不超过300三角Overdraw控制在**2×**以内;
    • 关闭级联阴影Soft Shadow选项,iOS A14以下机型用2级联

拓展思考

  1. HDRP下可用Micro Shadow+Contact Shadow次表面散射阴影,但需Custom Passshadow mask写入VT(Virtual Texture),带宽翻倍中高端机才开。
  2. WebGLNative Shadowmap,可预烘焙植被Shadow MaskLightmapAlpha8通道,运行时采样代替实时阴影包体+0.8 MB帧率+15%
  3. GPU Driven场景可用Clustered Shadow植被实例化ID写入StructuredBuffer,在Compute Shader一次PCF完成256草的阴影接收,DrawCall=1骁龙888实测0.4 ms