[DirectX 11] Order Independent Transparency

2022. 1. 7. 08:53·Graphics

CPU Sorting Transparency

 

- DirectX 11의 Blend State를 이용해 Output Merge에 바인딩을 하여 Blending을 일반적인 Alpha Blending 할 경우를

  생각해보면 가려지는 부분은 그릴 필요가 없기 때문에 Pixel에 그리기 전 깊이에 따른 정렬을 해주어야 한다.

 

Order Independent Transparency

 

- 오브젝트 단위로 투명도 렌더링을 할 경우 정확한 투명도의 선후관계를 처리하기 힘들다.

- 결국 정확한 선후관계를 판별하기엔 픽셀 단위로 해야하는데 위의 문제를 보안하기 위해 쉐이더 내부에서 처리하는

OIT 기술을 적용하게 되었다.

- 반투명 오브젝트는 렌더링 하기전 미리 분류한 후 다른 방식의 렌더링 방식으로 처리한다.

- 오브젝트를 해당 RenderTarget에 그리는 것이 아닌 RWStructBuffer와 RWByteAddressBuffer을 통해 저장해둔 후 마지막

  불투명 오브젝트를 그린 RenderTarget과 Blending 하는 방식이다.

 

- 반투명 오브젝트 데이터

  1) RWStructBuffer (Piece / Link Buffer )

       : 화면 크기의 레이어와 정렬과 혼합을 위해 필요한 Color, Depth, Next Index에 대한 Data를 담을 구조적 버퍼를 이용하여

         저장해 둡니다.

  2) RWByteAddressBuffer ( First Node Offset Buffer )

       : Link Buffer 대상 픽셀에 해당하는 정적 링커에 해당하는 첫 번째 노드 오프셋입니다.

 

Blending Pass 및 Transparency Layer Data
Link Buffer Update 과정

struct FragmentData
{
    uint Color;
    float Depth;
};

struct FLStaticNode
{
    FragmentData Data;
    uint Next;
};

[earlydepthstencil]
void OIT_Particle_PS(VertexIn pIn)
{
    ...
    
    uint pixelCount = gPieceLinkBuffer.IncrementCounter();
    
    uint2 vPos = (uint2) pIn.PosH.xy;
    uint startOffsetAddress = 4 * (gFrameWidth * vPos.y + vPos.x);
    uint oldStartOffset;
    gFirstOffsetBuffer.InterlockedExchange(
        startOffsetAddress, pixelCount, oldStartOffset);
    
    FLStaticNode node;
    node.Data.Color = PackColorFromFloat4(texColor);
    node.Data.Depth = pIn.PosH.z;
    node.Next = oldStartOffset;
    
    gPieceLinkBuffer[pixelCount] = node;
}

- 위의 Shader Code는 반투명 오브젝트를 해당 Link Buffer에 Color, Depth, Next Index Data를 삽입하는 과정이다.

- 이전에 불투명 오브젝트를 그린 DepthStencilView를 기반으로 Depth 체크를하여 Data를 삽입한다.

- 원래 Pixel Shader 이후에 깊이 테스트를 하지만 [earlydepthstencil] 속성을 사용함으로써 강제로 깊이 테스트를 먼저

  실행하여 성능 오버헤드를 줄어들게 할 수 있다.

void SortPixelInPlace(int numPixels)
{
    FragmentData temp;
    for (int i = 1; i < numPixels; ++i)
    {
        for (int j = i - 1; j >= 0; --j)
        {
            if (gSortedPixels[j].Depth < gSortedPixels[j + 1].Depth)
            {
                temp = gSortedPixels[j];
                gSortedPixels[j] = gSortedPixels[j + 1];
                gSortedPixels[j + 1] = temp;
            }
            else
            {
                break;
            }
        }
    }
}

float4 OIT_PS(float4 posH : SV_Position) : SV_Target
{
    uint2 vPos = (uint2) posH.xy;
    int startOffsetAddress = 4 * (gFrameWidth * vPos.y + vPos.x);
    int numPixels = 0;
    uint offset = gFirstOffsetBuffer.Load(startOffsetAddress);
    
    FLStaticNode element;
    
    while (offset != 0xFFFFFFFF)
    {
        element = gPieceLinkBuffer[offset];
        gSortedPixels[numPixels++] = element.Data;
        offset = (numPixels >= MAX_SORTED_PIXELS) ?
            0xFFFFFFFF : element.Next;
    }
    
    SortPixelInPlace(numPixels);
    
    float4 currColor = gBackGround.Load(int3(posH.xy, 0));
    
    for (int i = 0; i < numPixels; ++i)
    {
        float4 pixelColor = UnpackColorFromUInt(gSortedPixels[i].Color);
        currColor.xyz = lerp(currColor.xyz, pixelColor.xyz, pixelColor.w);
    }
    
    return currColor;
}

- 위의 Shader Code는 불투명 오브젝트를 그리고 반투명 오브젝트의 Layer Data를 쌓아둔 후 최종 혼합을 하는 과정이다.

- 미리 쌓아둔 Pixel별 Layer Data를 기반으로 Sorting과 Blending을 한번에 하여 최종 Pixel Color을 출력한다.

 

Order Independent Transparency 장점

  1) Pixel별 Layer Data를 이용하여 정밀한 Blending이 가능하다.

  2) 그리기전 오브젝트별 Sorting 작업을 할 필요가 없어진다.

 

Order Independent Transparency 단점

  1) Pixel별 Layer Data는 GPU 메모리에 올라가기에 미리 정해두고 한정적으로 사용해야 한다.

  2) 속도 측면에서 매 Pixel마다 Sorting이 요구되므로 속도면에서 차이가 있다.

 

- 위의 단점들을 보안할 방법은 추후 개선하도록 해야겠다.

 

적용 영상

Order Independent Transparency 적용 영상

'Graphics' 카테고리의 다른 글

[DirectX 11] PBR (Physically Based Rendering)  (0) 2022.01.21
[DirectX 11] Deferred Rendering FXAA  (0) 2022.01.16
[DirectX 11] Particle System  (0) 2021.12.26
[DirectX 11] Terrain Mesh Blending  (0) 2021.12.20
[DirectX 11] Map / UnMap vs UpdataSubresource  (0) 2021.12.19
'Graphics' 카테고리의 다른 글
  • [DirectX 11] PBR (Physically Based Rendering)
  • [DirectX 11] Deferred Rendering FXAA
  • [DirectX 11] Particle System
  • [DirectX 11] Terrain Mesh Blending
KyuHwang
KyuHwang
  • KyuHwang
    DirectX Engine
    KyuHwang
  • 전체
    오늘
    어제
    • 분류 전체보기 (50)
      • C++ (4)
      • CS (0)
      • Graphics (32)
      • DLL (2)
      • Shader (7)
      • Project (4)
      • ETC (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • YouTube
  • 공지사항

  • 인기 글

  • 태그

    dll
    mobile format
    Directx11
    bc format
    texture block compression
    Implicit Linking
    std::is_base_of
    Shader Macro
    animation retargeting
    shader
    RunTime Compile Shader
    Explicit Linking
    Project
    Define Function
    Win API
    nvtt
    DLL Interface
    Order Independent Transparency
    DirectX 2D
    std::enable_if
    Shader Resource 관리
    C ++
    Define Macro
    Hash Code
    rigging chain
    Alpha Blending
    Shader Reflection
    animation constraint
    Return Type Operator
    hlsl
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
KyuHwang
[DirectX 11] Order Independent Transparency
상단으로

티스토리툴바