VR을 개발하다 보면 한 쪽 눈에만 오브젝트 혹은 UI가 렌더링되는 경우가 종종 발생하시죠?
이러한 문제들을 해결하기 위해서는 싱글 패스 인스턴스(Single Pass Instanced)라는 개념을 아셔야 합니다.
싱글 패스 인스턴스(Single Pass Instanced) 개념이 어디에 사용되냐고요?
아래 사진을 보시면 VR 세팅을 하실 때 보실 수 있습니다.
이번 포스팅에서는 싱글 패스 인스턴스(Single Pass Instanced)에 대해 배우진 않고, 어떻게 두 눈에 렌더링 되게 하는지 해결방법에 대해 알아보고자 합니다.
싱글 패스 인스턴스(Single Pass Instanced)는 이전 포스팅을 참고해주세요.
유니티 Multi Pass와 Single Pass Instanced/Multi View에 대해
VR작업을 하다보면 초반 세팅하는 부분에 한 번씩쯤 다들 봤을 것입니다. Rendering Mode에 보면 Multi Pass와 Single Pass Instanced , 모바일의 경우 Multi View가 존재합니다. 이 3개의 차이는 아래 표와 같습니
wlsdn629.tistory.com
VR에서 객체가 한 쪽눈만 렌더링되는 경우 해결하기
급할 때 가장가장가장 쉽게 해결하는 방법은 아래와 같습니다.
스테레오 렌더링 모드를 싱글 패스 인스턴스(Single Pass Instanced)에서 Multi Pass로 바꾸는 겁니다.
이렇게 하면 VR 기기는 왼쪽 눈을 그리고 다시 오른쪽 눈을 그립니다. 즉, 2번 렌더링하기에 드로우콜도 그만큼 커지지만, 급하게 테스트할 때 해결할 수 있는 방법입니다.
권장하지는 않습니다! 근본적인 해결방법이 아니기 때문입니다.
다른 방법으로는 싱글 패스 인스턴스(Single Pass Instanced)에 맞게 쉐이더를 수정하는 방법등을 고려하셔야 합니다.
쉐이더를 기준으로 말씀을 드리자면 쉐이더 코드에 아래 매크로들을 쉐이더 코드에 삽입하시면 됩니다.
매크로 | 설명 |
UNITY_VERTEX_INPUT_INSTANCE_ID | struct appdata에 인스턴스 ID를 추가하여 다중 인스턴싱을 지원할 수 있습니다. 인스턴스화된 객체를 렌더링할 때 각 객체에 고유한 ID를 할당할 수 있습니다. |
UNITY_VERTEX_OUTPUT_STEREO | 스테레오 렌더링을 위한 struct v2f에 추가하는 매크로입니다. 이 매크로는 왼쪽 및 오른쪽 눈에 대한 카메라 정보를 처리하는 데 사용됩니다. |
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o) | 스테레오 렌더링을 위한 v2f vert를 초기화하는 매크로입니다. 이 매크로는 UNITY_VERTEX_OUTPUT_STEREO를 사용한 후, 각 눈의 좌표를 설정하는 데 필요합니다. |
UNITY_SETUP_INSTANCE_ID(v) | 인스턴싱을 지원하기 위해 v2f vert에서 인스턴스 ID를 초기화하는 매크로입니다. 이 매크로는 인스턴스화된 객체들에 대해 인스턴스 ID를 설정합니다. |
Shader "Custom/UnlitTransparentAlwaysOnTop"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Color ("Tint Color", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
ZWrite Off
ZTest Off
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
fixed4 _Color;
v2f vert(appdata v)
{
UNITY_SETUP_INSTANCE_ID(v);
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv) * _Color;
col.a = _Color.a; // 알파값 유지
return col;
}
ENDCG
}
}
}
VR에서 UI가 한 쪽 눈에만 렌더링 되는 경우
이게 정답인지는 모르겠지만... 일단 해결방법을 찾아서 공유를 드립니다.
이렇게 하는게 정말 잘못된 접근 방식이라면 가르쳐 주세요!
이때의 상황은 싱글 패스 인스턴스(Single Pass Instanced)를 사용하는 경우입니다.
TextMeshPro의 쉐이더를 Mobile -> Distance Field Overlay로 바꿔줍니다.
기존에는 오버레이가 아닌 그냥 Distance Field로 되어 있을겁니다. 오버레이로 바꿔주면 폰트가 최상위에 항상 노출되기에 해결되는거 같긴 하지만, 정확한 이유는 잘 모르겠습니다.