URP, HDRP, ShaderGraph, 표면 셰이더, 빌트인 셰이더는 이미 싱글 패스 스테레오 인스턴스화 렌더링을 지원합니다.하지만 에셋 스토어의 셰이더, 타사의 셰이더, 사용자가 직접 작성한 셰이더는 업데이트해야 할 수 있습니다.
셰이더에서의 인스턴스화 렌더링 지원에 대한 자세한 내용은 GPU 인스턴싱을 참조하십시오.이 섹션에서는 특히 스테레오 렌더링에 대한 내용을 설명하며 일반적으로 인스턴스화 렌더링을 지원하기 위해 수행해야 하는 모든 변경 사항을 포함하지 않을 수 있습니다.
UNITY_VERTEX_INPUT_INSTANCE_ID
매크로를 appdata
구조체에 추가합니다.
예:
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};
UNITY_VERTEX_OUTPUT_STEREO
매크로를 v2f
출력 구조체에 추가합니다.
예:
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO //Insert
};
다음 매크로를 메인 vert
메서드의 처음에 추가합니다(순서대로).
UNITY_SETUP_INSTANCE_ID()
UNITY_INITIALIZE_OUTPUT(v2f, o)
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO()
UNITY_SETUP_INSTANCE_ID()
는 GPU가 어느 쪽 눈을 렌더링하느냐에 따라 빌트인 unity_StereoEyeIndex
및 unity_InstanceID
셰이더 변수를 계산하여 올바른 값으로 설정합니다.
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO
는 unity_StereoEyeIndex
값을 기반으로 텍스처 배열에서 어느 쪽 눈에 렌더링되어야 하는지 GPU에 알립니다. 또한 이 매크로는 버텍스 셰이더의 unity_StereoEyeIndex
값을 전송하여 프래그먼트 셰이더 frag
메서드에서 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX
가 호출된 경우에만 프래그먼트 셰이더에서 액세스할 수 있도록 만듭니다.
UNITY_INITALIZE_OUTPUT(v2f,o)
는 모든 v2f
값을 0으로 초기화합니다.
예:
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v); //Insert
UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
포스트 프로세싱 셰이더가 싱글 패스 스테레오 인스턴싱을 지원하도록 하려면 커스텀 셰이더의 단계와 아래 단계를 따르십시오.
참고:Unity 웹사이트에서 모든 Unity 기본 셰이더 스크립트를 다운로드할 수 있습니다.
싱글 패스 인스턴싱을 지원하려는 각 포스트 프로세싱 셰이더에 대해 다음을 수행하십시오.
특정 스테레오 렌더링 메서드 사용 시 GPU가 그에 적합한 텍스처 샘플러를 사용할 수 있도록 frag 메서드 외부의 UNITY_DECLARE_SCREENSPACE_TEXTURE(tex) 매크로를 셰이더 스크립트에 추가합니다(아래의 배치 예시 참조).예를 들어 멀티 패스 렌더링을 사용하는 경우 GPU가 텍스처 2D 샘플러를 사용합니다.싱글 패스 인스턴싱이나 멀티 뷰 렌더링의 경우 텍스처 샘플러는 텍스처 배열입니다.
프래그먼트 셰이더 frag 메서드 시작 시 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i)
를 추가합니다(아래의 배치 예시 참조).이 매크로만 추가하면 unity_StereoEyeIndex
빌트인 셰이더 변수를 사용하여 GPU가 어느 쪽 눈에 대해 렌더링하고 있는지 확인할 수 있습니다.이 기능은 포스트 프로세싱 효과를 테스트할 때 유용합니다.
UNITY_SAMPLE_SCREENSPACE_TEXTURE()
매크로를 사용하여 2D 텍스처를 샘플링합니다(아래의 배치 예시 참조).스탠다드 셰이더는 2D 텍스처 기반 백 버퍼를 사용하여 텍스처를 샘플링합니다.싱글 패스 스테레오 인스턴싱은 이 타입의 백 버퍼를 사용하지 않습니다. 따라서 2D 텍스처 샘플링에 다른 메서드를 지정하지 않으면 셰이더가 제대로 렌더링하지 못합니다.이러한 렌더링 문제를 방지하기 위해 UNITY_SAMPLE_SCREENSPACE_TEXTURE()
매크로는 사용 중인 스테레오 렌더링 경로를 감지한 후 올바른 방식으로 텍스처를 자동 샘플링합니다.뎁스 텍스처 및 스크린 공간 섀도우 맵에 사용되는 유사한 매크로에 대한 자세한 내용은 HLSLSupport.cginc에 대한 Unity 기술 자료를 확인하십시오.
예:
UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //Insert
fixed4 frag (v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //Insert
fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //Insert
// just invert the colors
col = 1 - col;
return col;
}
아래는 템플릿 이미지 효과 셰이더의 간단한 예시이며 이전에 언급한 모든 변경 사항을 적용하여 싱글 패스 인스턴싱을 지원하도록 만들었습니다.셰이더 코드에 대해 추가한 줄은 코멘트//Insert
로 표시되어 있습니다.
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};
//v2f output struct
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO //Insert
};
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v); //Insert
UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //Insert
fixed4 frag (v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //Insert
fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //Insert
// invert the colors
col = 1 - col;
return col;
}
Graphics.DrawProceduralIndirect() 및 CommandBuffer.DrawProceduralIndirect() 메서드를 사용하여 GPU의 절차적 지오메트리를 완전히 드로우할 때는 두 메서드 모두 컴퓨트 버퍼에서 인자를 받는다는 점에 유의하십시오.따라서 런타임 시점에 인스턴스 수를 늘리기 어렵습니다.인스턴스 수를 늘리려면 컴퓨트 버퍼에 포함된 인스턴스 수를 수동으로 두 배로 만들어야 합니다.
다음 셰이더 코드는 사용자의 왼쪽 눈에는 녹색으로, 사용자의 오른쪽 눈에는 적색으로 게임 오브젝트를 렌더링합니다. 이 셰이더를 사용하면 모든 스테레오 그래픽스가 제대로 동작 및 기능하는지 확인할 수 있기 때문에 스테레오 렌더링을 디버그할 때 특히 유용합니다.
Shader "XR/StereoEyeIndexColor"
{
Properties
{
_LeftEyeColor("Left Eye Color", COLOR) = (0,1,0,1)
_RightEyeColor("Right Eye Color", COLOR) = (1,0,0,1)
}
SubShader
{
Tags { "RenderType" = "Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 _LeftEyeColor;
float4 _RightEyeColor;
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
return lerp(_LeftEyeColor, _RightEyeColor, unity_StereoEyeIndex);
}
ENDCG
}
}
}
ShaderGraph는 싱글 패스 스테레오 렌더링을 지원하는 데 필요한 매크로를 자동으로 추가합니다.ShaderGraph에서 디버그 셰이더를 구현하려면 눈 인덱스에 따라 기본 컬러를 설정하는 커스텀 함수 노드를 사용하면 됩니다.
unity_StereoEyeIndex
셰이더 속성을 사용하여 렌더링되는 눈 인스턴스에 따라 기본 컬러를 결정할 수 있습니다.위 예시의 커스텀 함수 노드에는 다음 코드가 포함되어 있습니다.
Out = lerp(LeftColor, RightColor, unity_StereoEyeIndex);