Non-Euclidean Space : 면에 따라 다르게 보이기


Shader "Custom/MagicMirror"
{
    SubShader
    {
        // 전체적으로 투명 Queue로 설정 (필요에 따라 변경 가능)
        Tags
        {
            "RenderType"="Transparent"
            "Queue"="Transparent"
            "UniversalMaterialType"="Unlit"  // 혹은 "Lit" 등
        }

        //----------------------------------------------------------------------
        // 1) 스텐실만 찍는 Pass (ColorMask 0)
        //----------------------------------------------------------------------
        Pass
        {
            Name "StencilOnly"
            // URP가 Forward 렌더링 시 이 Pass를 인식하도록
            Tags { "LightMode"="UniversalForward" }

            // 화면 컬러는 전혀 쓰지 않음
            ColorMask 0

            // 깊이 버퍼에 쓰지 않음(= 뒤쪽 물체가 가려지지 않도록)
            ZWrite Off
            ZTest LEqual

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            // URP 코어 함수 include
            #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(Varyings IN) : SV_Target
            {
                // ColorMask 0이므로 실제 화면에는 아무것도 안 찍힘
                return half4(1,1,1,1);
            }
            ENDHLSL
        }
    }
}
  • 레이어 wall_1, wall_2, wall_3 생성. 각각의 레이어를 가진 벽을 생성.
    • 오브젝트들에 위에 있는 셰이더를 사용한 머테리얼 적용
  • 레이어 one, two, three 생성. 각각의 레이어를 가진 오브젝트를 벽들 뒤에 배치.
    • 오브젝트들에 Unlit Transparent 머테리얼 적용
  • 렌더러 애셋을 새로 만들고 ‘Stencil Renderer’라 명명한 후 렌더 파이프 라인 애셋에서 Set Default
  • 렌더러 애셋의 Opaque Layer Mask, Transparent Layer Mask에서 wall_1,2,3와 one,two,three 레이어 체크 해제
  • Render Objects 렌더러 피쳐를 생성하고 ‘WallStencil1’으로 명명.
    • Event : AfterRenderingOpaques
    • Filters
      • Queue : Transparent
      • Layer Mask : wall_1
    • Overrides
      • Stencil : 체크
        • Value : 1
        • Copmpare Function : Always
        • Pass : Replace
        • Fail : Keep
  • Render Objects 렌더러 피쳐를 추가로 생성하고 ‘Render1’으로 명명.
    • Event : BeforeRenderingSkybox
    • Filters
      • Queue : Transparent
      • Layer Mask : one
    • Overrides
      • Override Mode : Material
        • Material : 눈에 띄는 색깔을 넣은 Lit 머테리얼
      • Stencil : 체크
        • Value : 1
        • Coompare Function : Equal
          • Pass : Keep
          • Fail : Keep
  • wall_2와 two, wall_3와 three에 대해서도 렌더러 피쳐를 추가해주고, stencil 값만 변경.

alt text

개선 및 추가 연구할 것들

  • 레이어를 따로 나누지 않고 렌더러 피쳐 2개 만으로 여러 스텐실 (여러 면) 에 해당하는 오브젝트들을 보여줄 수 있는지
  • 성능에 얼마나 영향이 가는지
Shader "Custom/MagicMirror_StencilParam"
{
    Properties
    {
        _Color("Color (For Transparent Pass)", Color) = (1, 1, 1, 0.5)

        // 추가: 스텐실 Ref를 머티리얼 Inspector에서 조절할 수 있게 만듦
        _StencilRef("Stencil Reference", Range(0,255)) = 1
    }

    SubShader
    {
        Tags
        {
            "RenderType"="Transparent"
            "Queue"="Transparent"
            "UniversalMaterialType"="Unlit"
        }

        //----------------------------------------------------------------------
        // 1) 스텐실만 찍는 Pass (ColorMask 0)
        //----------------------------------------------------------------------
        Pass
        {
            Name "StencilOnly"
            Tags { "LightMode"="UniversalForward" }

            ColorMask 0

            ZWrite Off
            ZTest LEqual

            Stencil
            {
                // 머티리얼 프로퍼티 값을 Ref로 사용
                // 즉, Inspector에서 _StencilRef 변경 시 실제 기록값도 변경됨
                Ref [_StencilRef]

                Comp Always
                Pass Replace
            }

            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(Varyings IN) : SV_Target
            {
                return half4(1,1,1,1); // ColorMask 0 이라 화면에는 안 찍힘
            }
            ENDHLSL
        }

        //----------------------------------------------------------------------
        // 2) 화면에 렌더되는 투명 Pass
        //----------------------------------------------------------------------
        Pass
        {
            Name "TransparentVisual"
            Tags { "LightMode"="UniversalForward" }

            ZWrite Off
            ZTest LEqual
            Blend SrcAlpha OneMinusSrcAlpha

            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;
            };

            float4 _Color;

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

            half4 frag(Varyings IN) : SV_Target
            {
                return half4(_Color);
            }
            ENDHLSL
        }
    }
}

머테리얼 프로퍼티로 스텐실을 조절할 수 있는 코드도 받긴 했었다. 하지만 o1의 말과는 다르게 stencil이 작성되지 않음.