Version: 2018.2
싱글 패스 스테레오 렌더링(더블 와이드 렌더링)
HoloLens용 싱글 패스 스테레오 렌더링

싱글 패스 인스턴스화 렌더링

Single Pass Instanced 렌더링(’스테레오 인스턴싱’이라고도 불림)을 사용하면 GPU가 단일 렌더 패스를 수행하여 각 드로우 콜을 인스턴스화된 드로우 콜로 교체합니다. 이렇게 하면 두 드로우 콜 간의 캐시 일관성으로 인해 CPU 사용이 대폭 감소하고, GPU 사용은 소폭 감소합니다. 또한 애플리케이션의 전력 소비도 크게 절감됩니다.

지원 플랫폼

  • PlayStation VR
  • Oculus Rift(DirectX 11)
  • HoloLens
  • Magic Leap
  • Multiview 확장자를 지원하는 Android 기기
  • 데스크톱에서 DirextX를 사용하는 경우 GPU가 Direct3D 11과 VPAndRTArrayIndexFromAnyShaderFeedingRasterizer 확장자를 지원해야 합니다.
  • 데스크톱에서 OpenGL을 사용하는 경우 GPU가 다음 확장자 중 하나를 지원해야 합니다.
    • GL_NV_viewport_array2
    • GL_AMD_vertex_shader_layer
    • GL_ARB_shader_viewport_layer_array

이 기능을 활성화하려면 Player Settings (Edit > Project Settings > Player 로 이동)를 엽니다. Player Settings 에서 하단의 XR Settings 로 이동하고 Virtual Reality Supported 체크박스를 선택한 후 드롭다운 메뉴의 Stereo Rendering Method 에서 Single Pass Instanced (Preview) 를 선택합니다.

XR Settings 에서 Stereo Rendering Method 를 Single Pass Instanced (Preview) 로 설정
XR Settings 에서 Stereo Rendering MethodSingle Pass Instanced (Preview) 로 설정

기본 Stereo Rendering MethodMulti Pass 입니다. 이 설정은 느리지만, 대개 커스텀 셰이더와 사용하면 효과적입니다. 커스텀 셰이더가 있는 경우 Single Pass Instanced 렌더링과 호환되도록 변경해야 할 수 있습니다.

커스텀 셰이더

아래의 지침을 따르기 전에 인스턴싱을 사용할 수 있도록 커스텀 셰이더를 업데이트하십시오(GPU 인스턴싱 참조).

그런 다음, 커스텀 셰이더의 프래그먼트 셰이더(Vertex/Hull/Domain/Geometry) 전에 사용된 마지막 셰이더 단계에서 두 가지를 추가로 변경해야 합니다.

각 커스텀 셰이더에 대해 싱글 패스 인스턴스화를 지원하고 싶다면 다음 단계를 따르십시오.

1단계: UNITY_VERTEX_INPUT_INSTANCE_IDappdata struct에 추가합니다.

예:

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

    UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};

2단계: UNITY_VERTEX_OUTPUT_STEREOv2f output struct에 추가합니다.

예:

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

    UNITY_VERTEX_OUTPUT_STEREO //Insert
};

3단계: 메인 vert 메서드 시작 시 UNITY_SETUP_INSTANCE_ID() 매크로를 추가한 후 UNITY_INITIALIZE_OUTPUT(v2f, o)UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO()를 호출합니다.

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

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

싱글 패스 인스턴스화를 지원하도록 만들 각 포스트 프로세싱 셰이더에 대해 다음을 수행하십시오.

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

2단계: 프래그먼트 셰이더 frag 메서드 시작 시 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i)를 추가합니다(아래의 배치 예시 참조). 이 매크로만 추가하면 unity_StereoEyeIndex 빌트인 셰이더 변수를 사용하여 GPU가 어느 쪽 눈에 대해 렌더링하고 있는지 확인할 수 있습니다. 이 기능은 포스트 프로세싱 효과를 테스트할 때 유용합니다.

3단계: 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
      }
   }
}

2018–09–07 일부 편집 리뷰를 거쳐 페이지 게시됨

  • 2017.3 2017.3에서 싱글 패스 인스턴스화 추가됨 NewIn20173
싱글 패스 스테레오 렌더링(더블 와이드 렌더링)
HoloLens용 싱글 패스 스테레오 렌더링