일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 유니티 그래픽스 최적화 스타트업
- 리깅
- 오류
- 파이널 IK
- github
- 유니티
- tutorial
- NavMesh
- 튜토리얼
- 익명 타입
- 리팩토링
- Effective C#
- 프로퍼티
- 유니티 그래픽 최적화
- 에러
- 속성
- 애니메이션
- shader
- Final IK
- 쉐이더
- 깃허브
- 애님
- c#
- error
- unity
- 2판
- 메모리
- 최적화
- 사용법
- 쓰는 법
- Today
- Total
참치김밥은 최고의 한식이다
[유니티] Stencil 본문
스텐실 ?
스텐실 버퍼는 오브젝트의 픽셀을 화면에 그리거나, 그리지 않도록 판단하기 위한 마스크로 사용된다.
스텐실 버퍼의 모든 값은 8비트(0~255)를 가지며, 기본적으로 모든 픽셀에 0으로 초기화되어 있다.
이 값은 Ref 로 지정할 수 있다.
스텐실 테스트 과정 ?
스텐실 테스트는 먼저 그려진 오브젝트에 대해 먼저 수행된다.
테스트 과정은 다음과 같다고 한다.
1. Stencil Test (Comp) : 스텐실 버퍼의 값과 자신의 Ref 값을 비교. 이때, Comp Always이면 무조건 통과, Comp Equal 이면 스텐실 버퍼의 값과 자신의 Ref값이 같을 때에만 통과
2. 스텐실 테스트 실패 시, Fail 동작 수행
3. 스텐실 테스트 성공 시, 깊이 테스트 (ZTest)
4. 깊이 테스트 성공 시 Pass 동작 수행 후 종료
5. 깊이 테스트 실패 시 ZFail 동작 수행 후 종료
구현 방법 :
<포털(Quad)에 적용할 쉐이더>
Shader "Custom/StencilPractice"
{
Properties
{
[IntRange] _StencilID("Stencil ID", Range(0, 255)) = 0
}
SubShader
{
Tags {
//"RenderType"="Opaque"
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Geometry-1"
//Originally the render queue of stencil shader should be set after Geometry(2001~)
//But with URP's function, we can cover the results of geometry rendering.
}
Pass
{
//Blend Zero One
//Use existing pixel color and ignore this shader's result
ZWrite Off
ColorMask 0
Cull back
Stencil{
Ref [_StencilID]
//비교 결과에 따라 이 픽셀의 스텐실 값을 다양하게 변경할 수 있다.
//실제로 마스크 셰이더는 항상 스텐실값을 재정의하기를 원하므로,
//Comp Always 라고 지정해서, 스텐실 테스트가 항상 통과하도록 할 수 있다.
//그 반대는 Comp Never 이다.
Comp Always
//스텐실 및 깊이 테스트를 모두 통과하면,
//픽셀에 연결된 스텐실 값을 이 셰이더에서 정의한 새 값으로 바꿀 수 있다.
//이 기능을 Pass Replace 라고 한다.
Pass Replace
//스텐실 or 깊이 테스트 둘 중 하나라도 실패할 경우를 대비해, Fail Keep 을 지정할 수 있다.
//이는 유니티가 이 픽셀의 스텐실 버퍼에 이미 있는 모든 값을 유지한다는 의미이다.
//Fail Keep
}
}
}
}
<큐브(쿼드를 통해 보일 오브젝트)에 적용할 쉐이더>
Shader "Unlit/StencilBackground"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Stencil{
Ref 0
//만약 Stencil Ref 값이 버퍼의 값과 다르면, 버퍼의 현재 콘텐츠를 유지해라.
//즉, 만약 Stencil Ref 값이 버퍼의 값과 같으면, 버퍼의 내용을 수정해라.
Comp NotEqual
Pass keep
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
위 쉐이더를 만들고, 머터리얼을 만들어서, 각각의 오브젝트에 적용해 준 다음,
레이어를 새로 생성한 후, 큐브 2개의 레이어에 하나씩 할당해줌.
쿼드의 머터리얼ㅇ의 Stencil ID는 각각 1과 2로 정해줌.
Stencil ID가 1인 쿼드는 StencilLayer1인 큐브만 보이도록 만들 것이고, ID가 2인 쿼드는 StencilLayer2인 큐브만 보이도록 만들 것임 (여기까진 아직 스텐실 적용 안 됨 밑에가 찐임)
본인이 현재 사용중인 Renderer Asset을 찾아 클릭한 후, 인스펙터에서 Add Renderer Feature - Render Objects 선택하여 새로운 Feature 추가.
Name은 걍 보기 좋게 짓고, Layer Mask는 Stencil Layer1로 설정, Overrides 토글 펼쳐 Stencil 체크, Value는 Stencil Layer1인 오브젝트가 어떤 Ref 값을 가졌으면 좋겠는지 (여기선 1) 설정, Compare Function은 포탈(Stencil ID가 1또는 2인 걔네들)을 통해서만 큐브를 볼 수 있어야 하므로, 즉 포탈의 Stencil ID(Ref) == Stencil Layer1 레이어를 가진 오브젝트들의 Stencil Value(Ref) 일 때에만 오브젝트를 볼 수 있어야 하므로, Equal로 설정.
이렇게 하면 Stencil ID가 1인 쿼드로는 (Render Objects로 인해 Value가 1로 설정된 Stencil Layer1 레이어)를 가진 오브젝트만 볼 수 있게 됨.
같은 방식으로 Render Objects를 하나 추가하여 Stencil ID가 2인 경우에 대해서도 지정해주면 됨
'Unity' 카테고리의 다른 글
[유니티] WebRTC WebRTC.Context null 오류 해결 (0) | 2023.12.14 |
---|---|
[유니티] TMP_Text와 TextMeshProUGUI의 차이? (2) | 2023.12.11 |
[유니티] Z-Buffer & Color Buffer (0) | 2023.11.20 |
[Unity] 처음으로 직접 만들어 본 HLSL 쉐이더 - 눈 쌓인 쉐이더 (0) | 2023.10.11 |
[Unity] Particle 회전 시키는 방법 (0) | 2023.09.08 |