비타Cpp

렌더링 파이프 라인 - IA(Input Assembler) Stage -Vertex & Primitive Topology 본문

DirectX12/메모

렌더링 파이프 라인 - IA(Input Assembler) Stage -Vertex & Primitive Topology

멍C 2021. 7. 30. 19:40

IA(Input Assembler) 단계에서는 메모리에서 기하 자료(정점과 색인)를 읽어 기하학적 기본 도형(primitive)을 조립한다.(색인은 정점들을 모아서 기본 도형을 형성하는 방식을 결정한다.)

 

정점(vertex)은 하나의 점을 의미한다. 하지만 Direct3D에서의 정점은 공간적 위치 이외의 정보를 담을 수 있다. 예를 들어 법선 벡터를 추가하거나, 텍스처 좌표를 추가할 수도 있다. 이를 통해 Direct3D에서는 좀 더 복잡한 효과를 유연하게 적용시킬 수 있다.

 

정점들은 정점 버퍼(vertex buffer)라고 하는 Direct3D 자료구조 안에 담겨서 렌더링 파이프 라인에 묶인다. 정점 버퍼는 그냥 정점들을 연속적인 메모리에 저장하는 자료구조이다. 정점 버퍼에서 기본도형들을 위한 정점의 조합에 대한 방법은 들어있지 않다. 정점 자료를 이용해서 기하학적 기본 도형을 형성하는 방법을 Direct3D에 알려주려면 기본 도형 위상 구조(Primitive Topology)라는 것을 설정해야 한다.

 

Primitive Topology를 설정하는데 쓰이는 메서드와 관련 열거형은 다음과 같다.

//https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12graphicscommandlist
void IASetPrimitiveTopology(
  D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology
);

//https://docs.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_primitive_topology
typedef enum D3D_PRIMITIVE_TOPOLOGY {
  D3D_PRIMITIVE_TOPOLOGY_UNDEFINED,
  D3D_PRIMITIVE_TOPOLOGY_POINTLIST,
  D3D_PRIMITIVE_TOPOLOGY_LINELIST,
  D3D_PRIMITIVE_TOPOLOGY_LINESTRIP,
  D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
  D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
  D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ,
  D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ,
  D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ,
  D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ,
  D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST,
  D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST,
  .
  .
  .
  D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST
} ;

 

(a)Point List, (b)Line Strip, (c)Line List, (d)Triangle Strip

 

1. POINTLIST

D3D_PRIMITIVE_TOPOLOGY_POINTLIST를 지정해서 IASetPrimitiveTopology를 호출하면 점 목록(Point List)이 현재 위상구조로 설정된다. 해당 상태는 Draw호출의 모든 정점은 개별적인 점으로 그려진다.

 

2.LINESTRIP

D3D_PRIMITIVE_TOPOLOGY_LINESTRIP를 지정하면 선 띠(Line Strip; 또는 선분 띠)가 설정된다. 해당 상태에서는 Draw호출의 정점들은 차례로 연결되는 선분들을 형성한다. 위 그림의 (b)처럼 n+1개의 정점으로 n개의 선분이 만들어진다.

 

3.LINELIST

D3D_PRIMITIVE_TOPOLOGY_LINELIST를 지정하면 선 목록(Line List; 또는 선분 목록)이 설정된다. 해당 상태에서 Draw호출의 매 정점 두 개가 하나의 선분을 형성한다. 따라서 위 그림의 (c)처럼 정점 2n개로 n개의 선분을 만든다.

 

4.TRIANGLESTRIP

D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP을 지정하면 삼각형 띠(Triangle Strip)가 설정된다. 해당 상태에서 Draw호출의 정점은 위의 그림 (d)에 나온 방식으로 연결되어서 삼각형들을 형성한다. n개의 정점으로 n-2개의 삼각형이 만들어진다. Triangle Strip에서 짝수번째 삼각형과 홀수 번째 삼각형의 정점들의 감기는 순서(Winding Order)가 다르다는 점을 주목해야 한다. 이 때문에 후에 배울 후면 선별 시 문제가 발생한다. 이를 바로잡기 위해, GPU는 내부적으로 짝수 번째 삼각형의 처음 두정점의 순서를 맞바꾸어서 홀수 번째 삼각형과 같은 순서가 되게 만든다.

 

(a)Triangle List, (b)Adjacent Triangle

5.TRIANGLELIST

D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST를 지정하면 삼각형 목록(Triangle List)이 설정된다. 삼각형 목록이 설정된 상태에서 Draw호출의 매 정점 세 개마다 삼각형을 하나 형성한다. 위의 그림 (a)처럼 3n개의 정점으로 n개의 삼각형이 만들어진다.

 

6.TRIANGLELIST_ADJ

삼각형 목록을 만들 때, 각 삼각형에 인접한 이웃 삼각형 세 개에 관한 정보를 포함할 수 있다. 그렇게 만든 삼각형 목록을 "인접성(Adjacency)을 가진 삼각형 목록"이라고 부르고, 주어진 삼각형에 접한 삼각형들을 인접 삼각형(Adjacent Triangle)이라고 부른다. 위의 그림 (b)에 인접 삼각형들을 지정하는 방식이 나와 있다. 이러한 방식은 인접 삼각형들에 접근해야 하는 특정한 기하 셰이딩 알고리즘을 기하 셰이더에서 구현할 때 쓰인다.

기하 셰이더가 인접 삼각형들에 접근하려면 삼각형 자체와 함께 인접 삼각형들의 정보도 정점 버퍼와 색인 버퍼에 담아서 파이프라인에 제출해야 한다. 그리고 D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ로 위상 구조를 지정해야 한다.

인접 기본 도형의 정점들은 오직 기하 셰이더의 입력으로만 쓰일 뿐, 실제로 그려지는 것이 아니다.

 

7.CONTROL_POINT_PATCHLIST

D3D_PRIMITIVE_TOPOLOGY_N_CONTROL_POINT_PATCHLIST Topology는 정점 자료를 N개의 제어점(Control Point)들로 이루어진 패치 목록으로 해석해야 함을 뜻한다. 이 제어점 패치는 렌더링 파이프라인의 테셀레이션 단계(생략 가능)에 쓰인다.

Comments