Version: Unity 6.0 (6000.0)
언어 : 한국어
스테레오 렌더링
포비티드 렌더링

싱글 패스 인스턴스화 렌더링과 커스텀 셰이더

URP, HDRP, ShaderGraph, 표면 셰이더 및 빌트인 셰이더는 이미 싱글 패스 스테레오 인스턴스화 렌더링을 지원합니다. 하지만 에셋 스토어나 타사의 셰이더, 직접 작성한 셰이더를 업데이트해야 할 수 있습니다.

셰이더에서 인스턴스화된 렌더링을 지원하는 방법에 대한 자세한 내용은 GPU 인스턴싱을 참조하십시오. 이 섹션에서는 특히 스테레오 렌더링에 대한 내용을 설명하며, 일반적으로 인스턴스화 렌더링을 지원하기 위해 수행해야 하는 모든 변경 사항을 포함하지 않을 수 있습니다.

버텍스 입력 속성 구조체 업데이트

UNITY_VERTEX_INPUT_INSTANCE_ID 매크로를 appdata 구조체에 추가합니다.

예:

struct appdata
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;

    UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};

버텍스 출력 속성 구조체 업데이트

v2f 출력 구조체에 UNITY_VERTEX_OUTPUT_STEREO 매크로를 추가합니다.

예:

struct v2f
{
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;

    UNITY_VERTEX_OUTPUT_STEREO //Insert
};

메인 버텍스 셰이더 함수 업데이트

다음 매크로를 메인 vert 메서드의 시작 부분에 추가합니다(순서대로).

  1. UNITY_SETUP_INSTANCE_ID()
  2. UNITY_INITIALIZE_OUTPUT(v2f, o)
  3. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO()

UNITY_SETUP_INSTANCE_ID()는 GPU가 어느 쪽 눈을 렌더링하느냐에 따라 빌트인 unity_StereoEyeIndexunity_InstanceID 셰이더 변수를 계산하여 올바른 값으로 설정합니다.

UNITY_INITIALIZE_VERTEX_OUTPUT_STEREOunity_StereoEyeIndex 값을 기반으로 렌더링해야 하는 텍스처 배열의 눈을 GPU에 알립니다. 또한 이 매크로는 버텍스 셰이더에서 unity_StereoEyeIndex 값을 전송하므로 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX가 프래그먼트 셰이더 frag 메서드에서 호출된 경우에만 프래그먼트 셰이더에서 액세스할 수 있습니다.

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 웹사이트에서 다운로드할 수 있습니다.

싱글 패스 인스턴싱을 지원하려는 각 포스트 프로세싱 셰이더에 대해 다음을 수행하십시오.

  1. 셰이더 스크립트에서 frag 메서드 외부의 UNITY_DECLARE_SCREENSPACE_TEXTURE(tex) 매크로(배치에 대한 아래 예시 참조)를 추가하여 특정 스테레오 렌더링 메서드를 사용할 때 GPU가 적절한 텍스처 샘플러를 사용하도록 합니다. 예를 들어 멀티 패스 렌더링을 사용하는 경우 GPU는 텍스처 2D 샘플러를 사용합니다. 싱글 패스 인스턴싱 또는 멀티뷰 렌더링의 경우 텍스처 샘플러는 텍스처 배열입니다.

  2. 프래그먼트 셰이더 frag 메서드의 시작 부분에 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i)를 추가합니다(배치에 대한 아래 예시 참조). unity_StereoEyeIndex 빌트인 셰이더 변수를 사용하여 GPU가 렌더링하는 눈을 확인하려면 이 매크로만 추가해야 합니다. 이는 포스트 프로세싱 효과를 테스트할 때 유용합니다.

  3. 2D 텍스처를 샘플링할 때 UNITY_SAMPLE_SCREENSPACE_TEXTURE() 매크로를 사용합니다(아래 예시 참조). 스탠다드 셰이더는 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;
}

절차적 지오메트리

GPU에서 완전히 절차적 지오메트리를 그리기 위해 Graphics.DrawProceduralIndirect()CommandBuffer.DrawProceduralIndirect() 메서드를 사용하는 경우 두 메서드 모두 컴퓨트 버퍼에서 인자를 수신합니다. 따라서 런타임 시 인스턴스 수를 늘리는 것은 어렵습니다. 인스턴스 수를 늘리려면 컴퓨트 버퍼에 포함된 인스턴스 수를 직접 두 배로 늘려야 합니다.

셰이더 디버깅

다음 셰이더 코드는 게임 오브젝트를 사용자의 왼쪽 눈에 녹색으로, 오른쪽 눈에 빨간색으로 렌더링합니다. 모든 스테레오 그래픽스가 제대로 작동하는지 확인할 수 있으므로 이 셰이더는 스테레오 렌더링을 디버깅하는 데 유용합니다.

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는 싱글 패스 스테레오 렌더링을 지원하는 데 필요한 매크로를 자동으로 추가합니다. ShaderGraph에서 디버그 셰이더를 구현하려면 눈 인덱스에 따라 기본 컬러를 설정하는 Custom Function 노드를 사용할 수 있습니다.

렌더링되는 눈 인스턴스에 따라 unity_StereoEyeIndex 셰이더 속성을 사용하여 기본 컬러를 결정합니다. 위 예제의 Custom Function 노드에는 다음 코드가 포함되어 있습니다.

Out = lerp(LeftColor, RightColor, unity_StereoEyeIndex);
스테레오 렌더링
포비티드 렌더링