WinCNT

Toggle과 KeywordEnum로 셰이더의 키워드 간단하게 선언하기! 본문

Unity/Graphics 관련

Toggle과 KeywordEnum로 셰이더의 키워드 간단하게 선언하기!

WinCNT_SSS 2025. 6. 28. 15:32

서론

셰이더에서 키워드는 뗄래야 뗄 수 없는 존재

셰이더 코드 부분에서의 사용은 둘째 치고, Inspector에서 컨트롤할 수 없으면 그림의 떡이기 때문에 ShaderGUI의 구현도 잘 생각해햐 한다

 

하지만! 유니티에서는 그 부분을 쉽게 구현할 수 있는 기능을 제공한다!

또한 일반적으로 사용되거나 단순 레벨의 키워드는 ShaderGUI 없이도 구현할 수 있게 해준다

그냥 커스텀 패키지 도입하겠다는 나쁜 말은 ㄴㄴ~


Properties에서의 사용 예시

우선은 Properties에서 어떤 식으로 사용되는지 살펴보자

Properties
{
    // Toggle
    [Toggle] _LIGHTING("Lighting On/Off", Float) = 0

    // KeywordEnum
    [KeywordEnum(NML,POS)] _OUTLINE("Outline Mode", Float) = 0

    // CompareFunction
    [Enum(UnityEngine.Rendering.CompareFunction)] _OutlineZTest("ZTest", Float) = 4 // LEqual

    // Custom
    [Enum(CustomShaderGUI.PaletteSwapMode)] _PaletteSwapMask3ColorMode ("Palette Swap Mask 3 Color Mode", Float) = 0
}

Toggle

토글은 제일 간단하게 셰이더 키워드를 구현할 수 있는 방법으로, Inspector에는 체크 박스가 표시된다(아래의 이미지는 좀 더 개량한 형태)

참고로 [Toggle]만 앞에 붙였을 경우는 프로퍼티명 + “_ON”라는 셰이더 키워드가 생성된다(예시의 경우에는 _LIGHTING_ON)

한편 [Toggle(LIT)]와 같이 괄호로 따로 선언했을 경우에는 괄호에 선언한 그대로의 셰이더 키워드가 생성된다(이 경우에는 LIT)

그리고 ToggleOff와 같은 속성도 있지만…이건 생략하도록 한다

자세한 건 아래의 사이트를 참고!

Unity - Scripting API: MaterialPropertyDrawer

 

KeywordEnum

KeywordEnum은 괄호 안에 선언한 키워드들이 Inspector에서 콤보 박스의 형태로 표시된다

(이미지는 Built-in과 같이 때문에 생략)

생성되는 셰이더 키워드는 프로퍼티명 + “_괄호에 선언한 값”이 된다

예시의 경우에는 _OUTLINE_NML와 _OUTLINE_POS라는 셰이더 키워드가 생성된다

참고로 괄호의 키워드는 최대 9까지 선언할 수 있다

 

이미 있는 것들은 가져다 쓰자!

일반적으로 사용되는 건 이미 구현되어 있기 때문에 가져다 쓰는 게 편하다

Z Test에 [Enum(UnityEngine.Rendering.CompareFunction)]를 붙이면 Inspector에서 아래와 같이 표시된다

 

사족) Custom

ShaderGUI에서 Enum이 있으면, 그걸 그대로 Inspector에 표시할 수도 있다

하지만 이 경우는 정말로 Inspector에 표시만 할 뿐이라…키워드와는 직접적인 연관이 없다…

키워드가 필요하다면 ShaderGUI에서 If-else와 case 등으로 열심히 구현해주자! 하하하!


셰이더 부분에서의 사용 예시

Properties에서 Toggle과 KeywordEnum을 선언했다면 자동으로 셰이더 키워드가 생성되니 셰이더 파트에서는 똑같은 감각으로 사용하면 된다

주의해야 할 것은 (Document에 따르면)Properties에서 소문자로 선언했어도 셰이더에서는 대문자인 키워드가 생성된다는 점이다

또한 Built-in은 섣불리 응용하기 보다 그대로 따라서 사용하기를 권장한다

아래는 예시이다

자동으로 생성될 셰이더 키워드에 맞춰 #pragma multi_compile도 선언해주고, #ifdef으로 사용하고 있다

Pass
{
    Name "Sample"
    Tags
    {
        "LightMode" = "UniversalForward"
    }
    ZTest [_OutlineZTest]

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

    #pragma vertex vert
    #pragma fragment frag
    
    #pragma multi_compile _OUTLINE_NML _OUTLINE_POS
    #pragma multi_compile __ _LIGHTING_ON
    
    Varyings vert(Attributes IN)
    {
        Varyings OUT;
        ZERO_INITIALIZE(Varyings, OUT);
        
        // ...생략...
        
        float3 normalOS = 0;
    #ifdef _OUTLINE_NML
        normalOS = IN.normal;
    #elif _OUTLINE_POS
        normalOS = normalize(IN.pos.xyz);
    #endif
        
        // ...생략...
        
    #ifdef _LIGHTING_ON
        // ...생략...
    #endif

        return OUT;
    }
    
    // ...생략...
    
    ENDHLSL
}

마무리

이번 기능은 간단한 테스트용 셰이더를 구현할 때 매우 도움이 될 것 같다

반대로 응용하려고 하면 MaterialPropertyDrawer도 제대로 알아야 하고 상당히 힘들어지겠지만…

코딩에서 무엇인가가 자동으로 그렇게 된다는 것은 반대로 말하자면 무엇인가가 자동으로 보이도록 해주고 있다와 같은 것이므로 당연하다면 당연하다고 할 수 있겠지

아무튼 응용하게 될 지도 모르는 미래의 나, 힘내라!


참고 사이트

Unity - Manual: Add shader keywords to the Inspector window

 

Unity - Scripting API: MaterialPropertyDrawer

 

【Unity】【シェーダ】【エディタ拡張】KeywordEnumがスクリプトから扱いづらい問題とその解決案 - LIGHT11

 

【Unity】【シェーダ】【エディタ拡張】KeywordEnumがスクリプトから扱いづらい問題とその解決案

KeywordEnumがスクリプトから扱いづらい問題とその解決案です。

light11.hatenadiary.com