WinCNT

URP의 디폴트 ShadowCaster와 SRP Batcher 본문

Unity/Unity 개발 중 발생한 이슈 정리

URP의 디폴트 ShadowCaster와 SRP Batcher

WinCNT_SSS 2023. 1. 27. 11:44

URP의 디폴트 ShadowCaster와 SRP Batcher

발생한 이슈

UsePass로 Universal Render Pipeline에서 제공하는 Shadow Cater를 사용하려고 하니 SRP Batcher가 not compatible이 되었다

UsePass "Universal Render Pipeline/Lit/ShadowCaster"

not compatible


이슈 상세

처음 확인한 것은 툰 렌더러용 쉐이더를 쓰고 있을 때였다

그림자도 있으면 좋겠네~라는 가벼운 마음으로 Use Pass를 써서 ShadowCaster를 추가하니 SRP Batcher가 무효가 되었다

그 때 발생한 알림은 다음과 같다

UnityPerMaterial CBuffer inconsistent size inside a SubShader(ShadowCaster)

싫은 느낌(그림자도 직접 구현 필요)이 든다…

대충 번역하자면 UnityPerMaterial CBuffer의 사이즈랑 SubShader(ShadowCaster)의 UnityPerMaterial CBuffer의 사이즈가 일치하지 않는다는 뜻인 것 같다

 

그래서 호기심에 기본 UnLit 템플릿에서는 어떻게 되나 확인해보았다

Shader "Example/URPUnlitShaderBasic"
{
    Properties
    {
    }

    SubShader
    {
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

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

            struct Attributes
            {
                float4 positionOS   : POSITION;
            };

            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
            };

            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                return OUT;
            }

            half4 frag() : SV_Target
            {
                half4 customColor = half4(0.5, 0, 0, 1);
                return customColor;
            }
            ENDHLSL
        }
        UsePass "Universal Render Pipeline/Lit/ShadowCaster"
    }
}

그러자 똑같이 SPR Batcher가 무효이긴 했지만 다른 알람이 나왔다

UnityPerMaterial var is not declared in shader property setion(_BaseMap_ST)


발생 원인

SRP Batcher로 렌더링하기 위해서는 SRP Batcher와 호환 가능한 쉐이더를 만들어야 한다

그 조건 중 하나가 모든 머티리얼 프로퍼티를 “UnityPerMaterial”로 명명된 하나의 CBuffer에서 선언해야 한다는 것이다

 

커스텀 툰 렌더링용 쉐이더는 따로 CBuffer를 만들었기 때문에 SubShader로 추가한 ShadowCaster와 CBuffer와의 사이즈가 일치하지 않아 호환성이 깨졌던 것으로 추정된다

 

CBuffer를 따로 만들지 않았던 기본 UnLit 템플릿의 경우는 명확한 이유는 모르겠으나, 알림대로 특정 변수가 프로퍼티 쪽에 없어서 호환성이 깨졌던 것으로 보인다


해결법

기본 UnLit 템플릿의 경우는 프로퍼티를 추가하니 해결되었다

(_BaseMap_ST는 _BaseMap의 타일링 & 오프셋를 위한 것이므로 맵만 추가함)

Properties
    {
        _BaseMap("Albedo", 2D) = "white" {}
    }

 

커스텀 툰 렌더링용 쉐이더의 경우는……커스텀 Shadow를 만들 수 밖에 없을 듯 하다

참고로 필요 없는 변수를 선언해서 억지로 CBuffer의 사이즈를 맞추니 호환이 되기는 하였다

 

하지만 변수 추가, 삭제에 자유롭지 못 하므로 실질적으로 채용하긴 어려울 것 같다

그리고 사이즈가 완전히 일치하지 하지 않아도 괜찮은 경우가 있었다

데이터 정렬 때문인가? 아닌 거 같은데… 아무튼 커스텀으로 만드는 게 나을 것 같다

CBUFFER_START(UnityPerMaterial)
    float4 _BaseMap_ST;
    float4 _SpecularColor;
    half4 _ShadowColor1;
    half4 _BaseColor;
    half4 _ShadowColor2;
    half _ShadowPower1;
    half _ShadowPower2;
    half _SpecularPower;
    //TEST
    half _BumpScale;
    half _Parallax;
    half _OcclusionStrength;
    half _ClearCoatMask;
    half _ClearCoatSmoothness;
    half _DetailAlbedoMapScale;
    half _DetailNormalMapScale;
    half _Surface;
CBUFFER_END
CBUFFER_START(UnityPerMaterial)
    float4 _BaseMap_ST;
    float4 _SpecularColor;
    half4 _ShadowColor1;
    half4 _BaseColor;
    half4 _ShadowColor2;
    half _ShadowPower1;
    half _ShadowPower2;
    half _SpecularPower;
    //TEST
    half4 _SpecularPower3;
    half _ClearCoatSmoothness;
    half _DetailAlbedoMapScale;
    half _DetailNormalMapScale;
    half _Surface;
CBUFFER_END

참고 자료

참고로 ShadowCaster의 CBuffer는 다음과 같다

(정확히는 Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl의 CBuffer)

CBUFFER_START(UnityPerMaterial)
	float4 _BaseMap_ST;
	float4 _DetailAlbedoMap_ST;
	half4 _BaseColor;
	half4 _SpecColor;
	half4 _EmissionColor;
	half _Cutoff;
	half _Smoothness;
	half _Metallic;
	half _BumpScale;
	half _Parallax;
	half _OcclusionStrength;
	half _ClearCoatMask;
	half _ClearCoatSmoothness;
	half _DetailAlbedoMapScale;
	half _DetailNormalMapScale;
	half _Surface;
CBUFFER_END