DirectX12의 Rendering Pipeline (출처: https://docs.microsoft.com/ko-kr/windows/win32/direct3d12/pipelines-and-shaders-with-directx-12)

Input Assembler

  • Input Assembler 단계는 메모리에서 기하 자료를 읽어 기하학적 기본 도형을 조립한다.

Vertex

  • 원래 Vertex는 두 변이 만나는 점이다. 때문에 "기하학적 기본 도형의 꼭짓점"이라는 인상을 받을 것이다.
    • 그러나 Direct3D의 정점은 그보다 훨씬 일반적이다.
  • Direct3D의 Vertex는 본질적으로 공간적 위치 이외의 정보도 담을 수 있다.
    • 그리고 이를 이용해 더 복잡한 Redering 효과를 낼 수 있다.
      • 예를 들어 조명을 구현하기 위해 Vertex에 Normal Vector를 추가할 수 있다.
      • 또는 Texture를 적용하기 위해 Vertex에 Texture 좌표를 추가할 수도 있다.
  • Direct3D에서는 Application이 자신만의 Vertex type을 정의할 수 있는 유연성을 제공한다.

기본도형 위상구조(Primitive Topology)

  • Vertex들은 Vertex Buffer라는 특별한 Direct3D Data Structure 안에 담겨서 Rendering Pipeline에 묶인다.
    • 이는 그저 Vertex들을 연속적인 Memory에 저장하는 Data Structure일 뿐이다.
  • Vertex Buffer 그 자체는 Vertex들이 어떤 식으로 조합해서 기본도형을 형성할 것인지 알려주지 않는다.
    • 이를 알려주는 것은 Primitive Topology가 맡는다.
  • 다음은 Primitive Topology를 지정하는 Method와 이를 정의한 Enumeration이다.
virtual void STDMETHODCALLTYPE IASetPrimitiveTopology( 
            _In_  D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology) = 0;
            
typedef 
enum D3D12_PRIMITIVE_TOPOLOGY_TYPE
    {
        D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED	= 0,
        D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT	= 1,
        D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE	= 2,
        D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE	= 3,
        D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH	= 4
    } 	D3D12_PRIMITIVE_TOPOLOGY_TYPE;
  • 한번 Method를 호출해서 Primitive Topology를 설정하면, 다음 호출이 있기 전까지 모든 그리기 호출에서 이 Primitive Topology가 적용된다.
  • 각 Primitive Topology의 방식은 아래 링크로 대체한다.

https://docs.microsoft.com/ko-kr/windows/uwp/graphics-concepts/primitive-topologies

 

기본 토폴로지 - UWP applications

Direct3D는 여러 개의 기본 토폴로지를 지원하는데, 이 토폴로지는 점 목록, 선 목록, 삼각형 스트립 등 파이프라인이 꼭짓점을 해석 및 렌더링하는 방식을 정의합니다.

docs.microsoft.com

색인(Index)

  • 앞서 이야기 했듯이, 3차원 Solid Object의 기본 구축 요소는 삼각형이다.
  • 다른 다각형을 표현할 때에도 여러 개의 삼각형으로 나누어서 표현을 한다.
    • 때문에 다각형을 여러 개의 삼각형으로 표현하기 위해서는 다음과 같이 Vertex Array를 사용한다.
Vertex quad[6] = {
	v0, v1, v2, 	// 삼각형 0
    	v0, v2, v3	// 삼각형 1
};

Vertex octagon[24] = {
	v0, v1, v2, 	// 삼각형 0
	v0, v2, v3, 	// 삼각형 1
	v0, v3, v4, 	// 삼각형 2
	v0, v4, v5, 	// 삼각형 3
	v0, v5, v6, 	// 삼각형 4
	v0, v6, v7, 	// 삼각형 5
	v0, v7, v8, 	// 삼각형 6
	v0, v8, v1 	// 삼각형 7
};
  • 예시에서 보이듯이, 각 삼각형들은 다 수의 Vertex들을 공유한다.
    • 한 두개라면 상관이 없지만, 팔각형처럼 공유하는 Vertex가 많아지면 문제가 심각해진다.
      • 같은 Vertex를 여러번 저장하면서 Memory 요구량이 증가한다.
      • 마찬가지로 같은 Vertex를 여러번 처리하면서 Graphic Hardware의 처리량이 증가한다.
  • 물론 다른 방식의 Primitive Topology를 사용하는 방법도 있지만, 삼각형 방식만큼 유연성이 높은 방식이 없다.
  • 때문에 우리는 삼각형 목록에서 중복 Vertex를 제거하기 위해 Index를 사용한다.
    • 예를 들어 사각형의 Vertex Array는 다음과 같이 표현한다.
Vertex v[4] = { v0, v1, v2, v3 };
UING indexList[6] = { 0, 1, 2, 	// 삼각형 0
		      0, 2, 3};	// 삼각형 1
  • Graphic Hardware는 Vertex Array의 고유한 Vertex들을 처리한 후, Index를 이용해 Vertex들을 조합한다.
  • Vertex의 중복이 없어지는 대신 Index의 중복이 발생하지만, 이는 큰 문제가 없다.
    • Index는 그냥 정수이므로 Vertex Structure보다 메모리 점유양이 적다.
    • Vertex Cache 순서가 좋은 경우 Graphic Hardware가 중복된 Vertex를 처리하지 않아도 된다.

Vertex Shader

  • Input Assembler에서 기본 도형들을 조립 한 후, Vertex들이 Vertex Shader(VS)로 입력된다.
    • 이는 Vertex 하나를 입력 받아 Vertex 출력하는 함수로 간주해도 될 것이다.
    • 화면에 그려질 모든 Vertex는 이 Vertex Shader를 거쳐간다.
  • Vertex Shader Function의 구체적인 내용은 Programmer가 구현해서 GPU에 제출한다.
    • 이 Function은 각 Vertex에 대해 GPU에서 실행되기 때문에 아주 빠르다.
  • Transform, Illuminate, Conversion Mapping 등 수 많은 특수효과를 GS에서 수행할 수 있다.
    • Vertex Shader에서 Vertex data는 물론 Texture, Transform Matrix등 GPU Memory에 담긴 다른 자료에도 접근할 수 있기 때문이다.

Local Space와 World Space

  • 3D 물체를 만들 때에는 장면 전역의 좌표계가 아니라 물체 자신의 국소 좌표계를 기준으로 구축한다.
    • 전자의 좌표계를 World Space라고 부른다.
    • 후자의 좌표게는 Local Space라고 부른다.
  • Local Space에서 3차원 물체의 Vetex들을 정의 했다면, 이를 World Space에 적절히 배치해야 한다.
  • 이를 위해서는 Local Space와 World Space의 관계를 정의할 수 있어야한다.
    • 정확히는 World Coordinate를 기준으로 한 Local Coordinate의 원점과 Axis의 위치, 방향을 지정.
    • 그리고 이에 해당하는 Coordinate Transformation을 수행해야 한다.
  • 이 Coordinate Transformation을 세계 변환(World Transform)이라 부른다.
    • 이때 Transform 되는 Matrix를 세계 행렬(World Matrix)라고 부른다.
  • World Matrix를 만들기 위해서는 World Space를 기준으로 한 Local Space의 원점과 Axis의 좌표가 필요하다.
  • 더 흔한 접근 방식은 World Transform W를 SRT 형태로 정의하는 것이다.
    • S는 Scaling Matrix
    • R은 Rotation Matrix
    • T는 Translate Matrix
  • 이와 같이 Local Space에서 물체를 정의하는 방식을 사용하는 이유는 다음과 같다.
    • 더 쉽다. 
      • 보통 Local Space에서 원점과 물체의 중심이 일치하고, Axis 중 하나와 대칭한다.
    • 더 합리적이다.
      • World Space에서 모양은 같으니 크기나 방향이 다른 물체를 여러번 만드는 것은 비합리적이다.
      • 이를 Local Space에서 생성하여 다양한 크기와 방향에 맞춰 배치하는 것이 더 합리적이다.
    • 같은 물체를 반복적으로 배치해야 할 경우, Vertex나 Index으로 인한 낭비를 막아준다.
  • 이런 방식을 Instancing이라고 부른다.

시야 공간(View Space)

  • 최종적으로 화면에 표시 될 2차원 이미지를 만들기 위해서는 가상의 카메라를 배치해야 한다.
    • 이느 World에 2차원 이미지를 생성해야 하는 영역을 결정하는 것이다.
  • 이 때 카메라에 Local Coordinate를 부여했을 때, 이 Coordinate를 View Space라 한다.
    • View Space는 시점 공간(Eye Space) 또는 카메라 공간(Camera Space)라고 부르기도 한다.
  • 카메라는 View Space에서 +Z축을 바라보고, 카메라의 오른쪽이 +X축, 위쪽이 +y축이다.
    • 이 때 World Space에서 Local Space로의 Transform 하는 것을 시야 변환(View Transform)라 한다.
    • Transform 되는 Matrix는 시야 행렬(View Matrix)라고 부른다.
  • 이는 World Space에서 카메라의 좌표에 대한 World Matrix W의 반대되는 역할을 한다.
    • 즉 W의 역행렬이 View Matrix이다.
  • 이에 대해 DirectXMath.h는 다음과 같은 함수들을 제공하고 있다.
XMMATRIX    XM_CALLCONV     XMMatrixLookAtLH(FXMVECTOR EyePosition, FXMVECTOR FocusPosition, FXMVECTOR UpDirection);
XMMATRIX    XM_CALLCONV     XMMatrixLookAtRH(FXMVECTOR EyePosition, FXMVECTOR FocusPosition, FXMVECTOR UpDirection);
XMMATRIX    XM_CALLCONV     XMMatrixLookToLH(FXMVECTOR EyePosition, FXMVECTOR EyeDirection, FXMVECTOR UpDirection);
XMMATRIX    XM_CALLCONV     XMMatrixLookToRH(FXMVECTOR EyePosition, FXMVECTOR EyeDirection, FXMVECTOR UpDirection);

투영과 동차 절단 공간

  • 카메라를 서술하는 요소가 하나 더 있다.
    • 카메라가 바라보는 절두체(Frustum)의 공간 영역이다.
  • 이제 할 일은 이 절두체 안의 3차원 기하 구조를 2차원 투영 창으로 Projection하는 것이다.
    • 이를 위해서는 반드시 평행선들이 하나의 소실점으로 수렴하는 방식으로 이루어져야 한다.
    • 그래야 3차원 Dpeth가 증가함에 따라 Project 된 결과가 줄어드는 현상이 나타나다.
    • 즉 이는 원근투영(Perspective Projection)을 따른다는 것이다.
    • 정점에서 시점으로의 직선을 정점의 투영선(line of projection)이라 부른다.
  • 원근투영 변환(Perspective Projection Transform)은 하나의 3차원 Vertex v를 Line of Projection이 2차원 투영 평면과 만나는 점 v'로 변환하는 Transform이다.
    • 이 v'를 v의 Projection이라 부른다.

Frustum의 정의

  • View Space에서 Center of Projection을 원점에 두고 +Z축을 바라보는 Frustum을 4가지 수량으로 정의할 수 있다.
    • 원점과 가까운 평면 사이의 거리 n
    • 원점과 먼 평면 사이의 거리 f
    • 수직 시야각 a
    • 종횡비(Aspect Ratio) r
  • 여기서 평면이 XY 평면과 평행임을 주목하자.
    • 이로 인해 평면과 원점사이의 거리는 Z축 상의 거리가 된다.
  • Aspect Ratio r = w / h로 정의 된다.
    • w: Projection 창의 너비
    • h: Projection 창의 높이
  • Projection 창은 본질적으로 View Space 안 장면의 2차원 이미지이고, 이는 결국 Back Buffer에 사상된다.
    • 때문에 Projection Window의 Aspect Ratio는 Back Buffer의 Aspect Ratio와 같게 만드는 것이 바람직하다.
  • 그래서 일반적으로 Back Buffer에 맞춰서 설정한다.

정규화된 장치 좌표(Normalized Device Coordinates)

  • Vertex를 Aspect Ratio을 이용해 Projection하면 Aspect Ratio에 의존한다는 문제가 발생한다.
    • 이는 Hardware가 Projection 창의 크기가 관여하는 연산을 수행할 수 있으려면
      Hardware에 Asprect Ratio를 알려줘야 한다는 것이다.
  • 이 문제를 해결하기 위해 우리는 X 좌표 성분을 [-r, r]에서 [-1, 1]로 비례시킨다.
    • 이러한 작업이 수행된 후의 좌표를 Normalized Device Coordinates(NDC)라 부른다.
  • Space Area에서 NDC Space로의 변환은 일종의 단위 변환(unit conversion)으로 볼 수 있다.
  • x 축에서 NDC의 한 단위는 View Area의 r 단위와 같다.
    • 1 ndc = r vs
    • 즉, NDC 좌표에서는 Projection 창의 너비도, 높이도 2이다.
  • 위와 같이 Projection 창의 크기가 조정되었으므로, Hardware는 Aspect Ratio를 몰라도 된다.
    • 뒤집어 말하면, Graphic Hardware는 Project된 Coordinate들이 NDC Space라고 가정하므로,
      프로그래머는 항상 실제로 NDC Space를 기준으로 한 Projection Coordinate를 공급하는 것에
      신경을 써야 한다.

Projection Transform을 Matrix로 표현

  • 일관성을 위해서는 Projection Trnasform을 하나의 Matrix로 표현하는 것이 좋다.
    • 그러나 식이 비선형적이라 Matrix Expression이 존재하지 않는다.
  • 그래서 우리는 한가지 요령으로 이 문제를 피해간다.
    • 바로 선형 부분과 비선형 부분을 분리하는 것이다.
  • Projection Transform에서 비선형적인 연산은 z로 나누는 연산이다.
    • 임의의 Vertex V = ( x, y, z, w )에 대한 Transform 연산을 하면 w = z가 되기 때문이다.
  • 그렇기에 Transform 연산을 한 후에 z로 나누어 w = 1로 만들어준다.
    • z = 0인 경우를 걱정 할 수 있으나, 아무리 평면과 가까워도 z는 0보다 크다.
  • 이와 같이 w로 나누는 것을 원근 나누기(Perspective Divide), 또는 동차 나누기(Homogeneous Divide)라 부른다.

Normalized Depth

  • Projection이 끝났다면 3차원의 z 성분은 이제 버려도 되지 않을까 하는 생각이 들 수 있다.
    • 하지만 Depth Buffering을 위해 여전히 Depth 정보가 필요하다.
  • 앞서 보았듯이, Direct3D는 투영된 x, y 좌표가 Normalized 되어 있기를 요구한다.
    • Depth 역시 마찬가지로 [0, 1] 구간으로 Normalized 되기를 요구한다.
  • 이를 위해 구간 [n, f]를 [0, 1]로 사상하는 순서 보존 함수 g(z)를 구축할 필요가 있다.
    • 이는 Depth 값들이 Transform 되어도 상대적 관계는 유지 시키는 함수이다.
  • Depth Buffering에는 Dpth의 값이 아니라 상대적 관계가 필요한 것임을 기억하자.
  • Depth를 Normalize 하기 위해서는 한번의 Scaling과 한번의 Translate 연산이 필요하다.
    • 하지만 실제로 적용을 해본다면, 잘 먹히지 않을 것이다.

  • 이제 여기서 두 가지 구속조건을 만족하는 A와 B를 선택해야 한다.
    • 조건 1) g(n) = A + B/n = 0 (가까운 평면이 0으로 사상됨)
    • 조건 2) g(f) = A + B/f = 1 (먼 평면이 1로 사상됨)
  • 여기서 조건 1을 풀고, 조건 2를 푼다면 함수 g의 그래프가 순증가(strictly increasing)이고, 비선형임을 알 수 있다.
    • 또한 치역의 대부분을 가까운 평면에 가까운 Depth이 차지하고 있음도 알 수 있다.
      • Depth들이 치역의 작은 부분에 몰려 있는 것이다.
    • 때문에 Depth Buffer에서 정밀도 문제가 발생 할 수 있다.
  • 이를 해결하기 위한 일반적인 조언은, "가까운 평면과 먼 평면을 최대한 가깝게 하라"는 것이다.
    • 값이 작으면 작을수록 기울기가 늘어나면서 치역이 분포가 더 퍼지게 된다.
  • 이 Proejction Matrix를 곱하고, Perspective Divide를 하기 전의 기하 구조를
    동차 절단 공간(Homogeneous Clip Space) 또는 투영 공간(Projection Area)에 있다고 한다.
  • Perspective Divide를 수행한 후의 기하 구조를 가리켜 Normalized Device Coordinate Area에 있다고 말한다.

XMMatrixPerspectiveFovLH

  • DirectXMath.h에는 이에 대해 다음 함수를 제공한다.
XMMATRIX    XM_CALLCONV     XMMatrixPerspectiveFovLH(float FovAngleY, float AspectRatio, float NearZ, float FarZ);
XMMATRIX    XM_CALLCONV     XMMatrixPerspectiveFovRH(float FovAngleY, float AspectRatio, float NearZ, float FarZ);

 

Hull Shader

  • Hull Shader에 대한 자세한 설명은 따로 찾을 수 없었다. 우선은 관련 링크로 대체를 한다.

https://docs.microsoft.com/ko-kr/windows/uwp/graphics-concepts/hull-shader-stage--hs-

 

HS(헐 셰이더) 단계 - UWP applications

HS(헐 셰이더) 단계는 공간 분할 단계 중 하나로, 모델의 한 표면을 효율적으로 많은 삼각형으로 나눕니다.

docs.microsoft.com

Tessellator

  • Tessellation은 한 mesh의 삼각형들을 더 잘게 쪼개서 새로운 삼각형들을 만드는 과정을 나타낸다.
    • 이렇게 생성된 새로운 삼각형들을 새로운 위치로 이동함으로써 좀 더 세밀한 메시를 만들어낼 수 있다.
  • Tessellation의 장점은 다음과 같다.
    • 계산 리소스를 더 중요한 곳에 투자할 수 있다.
      • 카메라에 가까운 삼각형들에는 세부도를 높이고,
        먼 삼각형들에는 Tessellation을 적용하지 않으면서 세부도를 낮춘다.
      • 이러한 방식의 세부수준(LOD) 메커니즘은 눈에 띄는 부분에 삼각형을 더 투자할 수 있게 한다.
    • 메모리 소모를 줄일 수 있다.
      • 메모리에는 삼각형이 적은 Mesh를 담아두고 즉석에서 삼각형을 추가함으로써 메모리를 적용할 수 있다.
    • 계산량을 줄일 수 있다.
      • Animation이나 물리 처리 같은 연산들을 저다각형 Mesh로 수행하고,
        Tessellation된 고다각형 Mesh는 Rendering에만 사용한다.
  • Direct3D 11에서 추가된 Tessellation Step은 GPU에서 기하구조를 그 수단을 제공한다.
    • 이전에는 CPU에서 새로운 기하구조를 만들고, 이를 GPU에 올려 Rendering해야 했다.
      • 하지만 CPU 메모리에서 GPU 메모리로 올리는 것은 매우 느린 연산이다.
      • 게다가 CPU에서 Tessellation 하는 것도 큰 부담이 된다.
  • 그래서 Direct3D 11 이전에는 실시간 그래픽에서 Tessellation이 별로 인기가 없었다.
  • 하지만 Direct3D 11에서는 이를 전적으로 Hardware에서 수행하는 API를 제공한다.
    • 이 덕분에 Tessellation은 매우 매력적인 기법이 되었다.
  • Tessellation 단계는 생략이 가능한 단계이다.
  • Tessellation에 대한 자세한 이론은 나중에 뒤에서 좀 더 자세히 다루겠다.

Domain Shader

  • 역시 자세한 설명을 찾지 못해 링크로 대체한다.

https://docs.microsoft.com/ko-kr/windows/uwp/graphics-concepts/domain-shader-stage--ds-

 

DS(도메인 셰이더) 단계 - UWP applications

DS(도메인 셰이더) 단계는 출력 패치에서 세분화된 지점의 꼭짓점 위치를 계산합니다. 이 단계에서 각 도메인 샘플에 해당하는 꼭짓점 위치도 계산합니다.

docs.microsoft.com

Geometry Shader

  • Geometry Shader(GS) 단계는 생략 가능한 단계이며, 한참 뒤에 사용할 것이기에 간단히 설명만 하겠다.
  • Geometry Shader는 하나의 온전한 기본도형을 입력받아 임의로 변경한다.
    • 예를 들어 삼각형 목록을 그리는 경우, Geometry Shader에는 삼각형을 정의하는 Vertex 3개가 입력된다.
      • 이 Vertex들은 이미 Vertex Shader 처리를 거친 것들이다.
  • Geometry Shader가장 큰 장점은 기하구조를 생성하거나 파괴 할 수 있다는 것이다.
    • 예를 들어 Geometry Shader는 입력 기본도형을 다른 여러 기본 도형으로 확장할 수 있다.
    • 또 특정 조건에 따라서는 출력하지 않고 폐기할 수도 있다.
  • 이는 Vertex Shader와 대조되는 특징이다.
    • Vertex Shader는 항상 Vertex 하나를 받아 Vertex 하나를 출력한다.
    • 하지만 Geometry Shader의 흔한 용도는 하나의 점이나 선분을 하나의 사각형으로 확장하는 것이다.
  • Rendering Pipeline 사진에서 Geometry Shader로부터 Stream Output으로 화살표가 이어지는 점도 주목하자.
    • GS의 Output Vertex Data는 Stream Output 단계를 통해
      Memory의 Buffer에 저장해두고 나중에 활용하는 것이 가능하다.
      • 이는 고급 기법이므로 뒤에서 자세히 설명하겠다.

Clipping

  • Frustum을 벗어난 기하 구조를 폐기하고, 교차한 것은 Frustum 내부에 있는 것만 남도록 잘라내는 연산이다.
  • 이 연산은 Hardware가 수행해주므로 이 이상 설명은 생략한다.
    • 관심이 있다면 Sutherland-Hodgeman Clipping Algorith을 살펴보기 바란다.

Rasterizer

  • Rasterization Stage라고도 하며, 주 임무는 투영된 3차원 삼각형으로부터 Pixel 색상들을 계산하는 것이다.

Viewport Transform

  • Clipping을 마치고 나면 Hardware는 Prespective Divide를 수행해서 Homogeneous Clip Space Coordinate를
    Normalized Device Coordinate로 변환한다.
  • Vertex들이 NDC Space에 들어왔다면, 2차원 이미지를 형성하는 x, y 성분들을
    Back Buffer의 한 직사각형 영역으로 변환한다. 
    • 이 직사각형 영역이 Viewport이다.
  • 이 Transform을 마치면 x, y 성분은 Pixel 단위의 값이 된다.
    • 일반적으로 Viewport Transform은 z성분은 변경하지 않는다.
      • 이 성분을 Depth Buffering에 사용해야하기 때문이다.
    • 하지만 D3D12_VIEWPORT의 MinDepth와 MaxDepth의 값은 변경할 수 있다.
      • 단, 반드시 [0, 1] 범위 안에 들어와야 한다.

Backface Culling

  • 하나의 삼각형에는 두 개의 면이 있는데, 이를 구분하기 위해서는 다음 관례를 사용한다.
    • 삼각형의 한 Vertex를 기준으로, 다른 Vertex로 향하는 Vector e1, e2를 생성한다.
    • e1과 e2를 Cross Product 한 후 Normalize 한 결과를 n이라 하자.
    • Vector n과 같은 방향인 면을 Front Side, 반대 쪽을 Back Side라 한다.
  • 관찰자가 삼각형의 앞면을 보고 있는 경우, 그 삼각형을 Front-Facing 삼각형이라 한다.
    • 반대로 뒷면을 보고 있으면 Back-Facing 삼각형이라 한다.
  • 또한 DirectX의 관례를 통해 Vertex가 시계방향으로 나열된 삼각형을 Front-Facing 삼각형으로 판단 가능하다.
  • 3차원 장면에서 대부분의 물체는 Closed Solid Object이다.
  • 각 물체의 삼각형들을 항상 Normal Vector가 물체 바깥쪽으로 향하도록 구성한다고 하자.
    • 그럼 카메라에는 Solid Object의 Back-Facing 삼각형이 보이지 않는다.
      • Back-Facing 삼각형은 모두 Front-Facing 삼각형에 가려지기 때문이다.
    • 때문에 Back-Facing 삼각형은 화면에 그릴 필요가 전혀 없어진다.
  • 이러한 Backface Culling은 Pipeline에서 이러한 삼각형을 골라서 폐기하는 공정이다.
  • 이 과정을 통해 처리해야 할 삼각형의 수가 거의 절반으로 줄어들 수 있다.
  • Direct3D는 일반적으로 시계방향으로 감긴 삼각형을 Front-Facing 삼각형으로 간주한다.
    • 하지만 Render State의 설정에 따라 그 반대도 가능하다.

Vertex 특성 Interpolation

  • 이전에 한번 삼각형은 Vertex들로 정의된다고 말한 적이 있을 것이다.
    • 또한 Vertex Data에는 위치 정보뿐만 아니라 색상, Normal Vector, Texture Coordinates 같은 
      추가적인 특성을 붙일 수 있다는 점도 언급했을 것이다.
  • Viewport Transformation을 거친 후에는 Vertex의 그러한 특성들을 Pixel들에게 Interpolation 해야한다.
    • Vertex 뿐만 아니라 Depth value도 Interpolation 해야 한다.
  • 그럼 각 Pixel마다 Depth Buffering Algorithm을 위한 값이 생성된다.
  • 이러한 Vertex 특성들은 View Space에서 Interpolation되는데, 
    3차원 공간에서는 삼각형의 면을 따라 Linear하게 Interpolation 된다.
    • 이를 위해서는 원근 보정 보간(Perspective Correct Interpolation)이 필요하다.
  • Perspective Correct Interpolation은 Hardware가 수행하므로 수학적 세부사항을 굳이 알 필요는 없다.

Pixel Shader

  • Pixel Shader(PS)는 프로그래머가 작성해서 GPU에서 실행하는 프로그램으로, 각 Pixel Fragment마다 실행된다.
  • PS는 기본적으로 Interpolation 된 Vertex 특성들을 입력받아 하나의 색상을 출력한다.
    • 이는 고정된 상수 색을 돌려주는 간단한 형태서부터
      Pixel별 조명, 반사, 그림자 효과를 수행하는 복잡한 형태까지 다양하다.

Output Merger

  • Pixel Shder가 생성한 Pixel Fragment들은 Output Merger(OM)단계로 입력된다.
  • Output Merger에서는 일부 Pixel Fragment들이 폐기된다.
    • Depth나 Stencil 판정으로 인해
  • 기각되지 않은 Pixel Fragment는 Back Buffer에 기록된다.
  • Blending도 이 단계에서 일어난다.

Blending

  • Blending은 새 Pixel이 Back Buffer의 기존 Pixel을 덮어쓰는 것이 아니라
    두 Pixel을 일정한 공식에 따라 혼합된 결과를 기록하는 것을 말한다.
  • Blending은 주로 반투명과 같은 특수효과를 내는데 쓰인다.
  • 이에 대해서는 뒤에서 더 자세히 다룰 예정이다.

+ Recent posts