작업환경 : Unity 2022.3.49, URP
목적 : 특정 오브젝트를 통과했을 때만 보이는 오브젝트 제작
wall 레이어를 할당한 Transparent 벽 오브젝트 뒤에 one 레이어를 할당한 Transparent 큐브 오브젝트가 있다.
Render Objects 렌더러 피쳐를 이용해 투명 벽 오브젝트로 스텐실을 먼저 그리고,
추가로 Render Objects 피쳐를 이용해 스텐실과 값이 같다면 Opaque 머테리얼을 오버라이드하는 식으로 진행하려 했다.
하지만 원하는 대로 작동하지 않고, 오브젝트는 투명한 그대로 유지되었다.
어째서인지 원인을 분석하고, 해결책을 제시하라.

- ColorMask 0 등으로 컬러 버퍼에 아무것도 쓰지 않는다.
- Stencil 설정을 통해 원하는 레퍼런스(Ref) 값, 비교(Comp), 패스(Pass) 동작을 설정하여 스텐실 버퍼에 기록한다.
- 필요하다면 깊이 버퍼(ZWrite)를 켤지 끌지를 결정한다.
- 스텐실만 찍고 싶으면 보통 ZWrite On으로 설정하되, “눈에 보이는 색상은 0”으로 하는 Pass를 만들어 “기하(Geometry)가 스텐실/깊이 버퍼에 존재함”을 인식시키는 식이다.
- 혹은 ZWrite Off로 설정할 수도 있지만, 그 경우 “카메라에서 보는 물체가 뒤에 있는지” 등에 따라 적절히 스텐실이 찍히지 않을 수 있으므로 상황에 따라 선택한다.
- 표준 Shader Graph만으로는 ColorMask 0을 직접 켜기 어려우므로, 커스텀 쉐이더(혹은 Shader Graph에 HLSL 주입) 필요
Shader "Custom/MagicMirror"
{
Properties
{
// 두 번째 Pass(화면 표시용)에서 사용할 색상/알파
_Color("Color (For Transparent Pass)", Color) = (1, 1, 1, 0.5)
}
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
// 스텐실 작성 예: 항상 통과, 통과 시 Ref=1로 교체
Stencil
{
Ref 1
Comp Always
Pass Replace
}
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
}
//----------------------------------------------------------------------
// 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;
};
// 선언한 Properties 참조
float4 _Color;
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
// _Color 알파값으로 반투명/불투명 조절
// 예) _Color = RGBA(1,1,1,0.5)이면 반투명
// _Color = RGBA(1,1,1,0)이면 완전 투명 (화면에 안 보임)
return half4(_Color);
}
ENDHLSL
}
}
}

Shader "Custom/MagicMirrorTest"
{
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
}
}
}
(o1이 짜준 코드에서 불필요한 부분들 제거)

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이 작성되지 않음.
꾸준히 개발자의 길을 걷고 계시는 군요. 잊지 않고 응원하고 있습니다.