[Direct3D 12]렌더링 파이프라인에 대해서

개발하는 곰댕이·2023년 5월 2일
0

DirectX

목록 보기
5/8

렌더링 파이프라인이란 3차원 장면의 데이터들과 가상 카메라의 위치 및 방향이 주어졌을 때 해당 카메라에 비친 3차원 장면의 모습에 근거해서 2차원 이미지를 생성하는 데 필요한 일련의 단계들을 렌더링 파이프라인(Rendering Pipeline)이라고 한다.

출처 : Direct3D 12 파이프라인 및 셰이더
위 사진은 Microsoft의 Direc3D 12의 렌더링 파이프라인 과정을 나타낸 이미지다.
우측의 Input assembler에서 시작해서 아래로 쭉 내려가 Ouput merger까지가 렌더링 파이프라인의 과정이고 그 외 왼쪽과 오른쪽의 다른 데이터들은 해당 과정에 필요한 데이터들이 만들어지는 과정에 대해서 설명해주는 것이다.
우선은 이 렌더링 과정들에 대해서 간단하게 알아보고 세부 내용은 별도로 정리해서 올려보도록 하겠다.

입력 조립기(Input assembler)

입력 조립기(Input assember, IA)단계에서는 정점 버퍼에서 정점과 인덱스 정보들을 읽어서 기하학적 기본도형(삼각형, 선분 등)으로 조립하게 된다.

  • 정점 (Vertex)
    그래픽에서 정점은 수학에서의 정점과는 다르게 다양한 값들을 갖고있다.
    공간적인 위치 말고도 우리가 원하는 값들을 구조체화 시켜서 데이터를 쉐이더에 넘길 수 있다.

  • 색인 (Index)
    우선 3차원 물체의 기본 구축 요소는 삼각형이다. 예를들어서 사각형 하나를 그리기 위해서는 최소 삼각형 두 개가 만나 사각형을 이루게 된다.

    위 사진과 같이 하나의 사각형을 그리기 위해서 삼각형 두 개가 그려진다. 하지만 꼭짓점을 보면 단 4개만 있고, 그 4개의 정점만으로 삼각형 두 개를 그리기 위해서 인덱스가 필요하다.
    인덱스 정보는 정점 정보와 같이 넘겨주는데 각 정점이 어떤 순서로 어떻게 이어지는지 알려준다.
    예를들어 {v0, v1, v2}, {v0, v2, v3} 이런 식으로 어떤 순서로 삼각형을 그려나가는지를 인덱스 정보로 넘겨주게 된다.
    여기서 그려지는 방향이 시계방향이냐, 반시계방향이냐에 따라서 또 해당 삼각형이 렌더링 과정에 포함되어야 하는지, 아닌지도 판별할 수 있으니 그려지는 방향에 유의해야 한다.
    이를 감기 순서(winding order)라고 한다.

자세한 내용은 별도로 정리한 [ Direct3D12 ]입력 조립기(Input assembler) - 렌더링 파이프라인을 보자.

정점 쉐이더(Vertex shader)

입력 조립기 단계에서 기본 도형들을 조립한 후 해당 정점들을 정점 쉐이더로 정보를 넘겨준다.
화면에 그려질 모든 정점은 이 정점 쉐이더를 거쳐가게 되며 이 정점 쉐이더의 구체적인 정보들은 개발자가 구현하여 GPU에 제출하게된다.
이 정점 쉐이더 단계에서는 변환, 변위 매핑 등 수많은 작업을 수행하게 되는데 이 단계에서 우리가 화면에 그려낼 카메라에 맞게 각 정점들의 위치를 변환해준다.
하지만 추후 작업에 따라서 아무 작업도 안 할수도 있고, 기본적인 작업만 할 수도 있다.
예를 몇 가지 들면 테셀레이션 단계에서 정점을 추가하여 폴리곤의 갯수를 늘릴 수 있는데 여기서 추가하는 정점들도 변환과정이 필요하기에 그 부분에서 정점의 변환을 할 수 있다.

테셀레이션(Tessellation)

테셀레이션은 주어진 메시의 삼각형들을 더 잘게 쪼개서 새로운 삼각형을 만드는 과정을 말한다.
이 과정에서 우리는 좀 더 디테일한 메시를 만들 수 있다.
이 테셀레이션에는 몇 가지 장점들이 있는데 다음과 같다.

  • 카메라에 가까운 삼각형들은 테셀레이션을 적용해서 디테일을 높이고, 먼 삼각형들은 테셀레이션을 적용하지 않는 level-of-detail, LOD 메커니즘을 구현할 수 있다.
  • 메모리에는 low-poly메시( 삼각형이 적은 메시 )를 넣어두고 즉석으로 삼각형을 추가해서 메모리를 절약할 수 있다.
  • 애니메이션이나 물리 처리 같은 연산들은 단순한 저다각형 메시에서 수행하고, 테셀레이션된 high-poly메시는 렌더링에만 사용함으로 계산량을 줄일 수 있다.
    이 테셀레이션은 Direct3D 11 이전에는 CPU에서 해당 작업을 한 후 GPU에 올리는 형태였는데 11부터는 전적으로 GPU에서 작업하게 된다. 그렇기 때문에 11 이전에는 해당 작업을 거의 하지 않았고 11 이후부터 사용하기 시작했다.

조금 더 자세한 내용은 [ Direct3D12 ] 테셀레이션(Tessellation) - 렌더링 파이프라인을 확인하자

덮개 쉐이더(Hull shader)

D3D12에서 테셀레이션은 Hull shader -> Tesselation -> Domain shader의 과정으로 이루어 진다.
그 중 덮개 쉐이더는 삼각형을 추가하는 단계에서 어떤 기준으로 추가하는지, 몇 개를 추가하게 될건지에 대한 정보를 설정하는데 이 두 가지 설정은 병렬로 동시에 이루어지기 때문에 두 개의 함수를 꼭 만들어서 설정해줘야한다.

영역 쉐이더 (Domain shader)

영역 쉐이더는 테셀레이션에서 계산된 무게중심에 따라서 새로운 정점을 만들어서 삼각형을 만들게 된다.
그리고 새로만들어진 정점또한 기존 정점과 동일하게 변환과정이 이루어져야 한다.

기하 쉐이더(Geometry shader)

기하 쉐이더 단계는 선택적이며 하나의 온전한 기본 도형을 입력받아서 그것을 임의로 변형하거나 특정 정점을 삭제하거나 추가할 수 있다.
예를들어 파티클 시스템을 만들려고 할 때 모든 정점을 넘기지 말고 하나의 정점 정보를 넘긴 후 해당 정점이 그려져야할 지 말아야 할 지 판단한 후 그려져야하면 다른 정점을 추가해서 삼각형을 만들고, 그게 아니라면 정점을 파괴하는 형태로 사용할 수 있다.

레스터라이저 (Rasterizer)

레스터라이저 단계에서는 다음과 같은 작업들을 하게된다.

  • 뷰포트 변환
    우리가 뷰포트에 렌더링한 것들은 사실 화면에 그대로 넘겨지는게 아니라 뷰포트라는 직사각형의 영역으로 변환되어 화면에 출력하는데 이 작업을 레스터라이저 단계에서 해준다.
  • 후면 선별
    이전에 인덱스 이야기를 할 때 삼각형이 그려지는 순서에 따라서 그려지고, 안 그려질 수 있다고 했는데 이 단계에서 그 판단을 하게된다.
  • 정점 특성의 보간
    뷰포트 변환을 거친 정점은 각 픽셀에 대해 보간을 해줘야 우리가 볼 수 있는 화면에 알맞게 들어오게 된다.

픽셀 쉐이더(Pixel shader)

이 곳에서는 우리가 만들어낸 쉐이더 프로그램에서 색상을 정해줄 수 있는 단계이다.
기본적으로 픽셀쉐이더는 보간된 정점 특성들을 입력받아서 각 픽셀의 색상을 출력하게 된다.
이 단계에서는 그냥 고정된 상수값을 리턴하는 아주 간단한 작업에서부터 픽셀당 조명, 반사, 그림자 등 복잡한 과정까지도 할 수 있다.

출력 병합 (Ouput merger)

픽셀쉐이더까지 거친 모든 픽셀들은 우리가 만든 후면 버퍼에 기록되어 Presenting을 기다리게된다.
뿐만아니라 blending 과정도 이 단계에서 일어나며 이 블렌딩이라는 과정은 새로운 픽셀이 후면 버퍼의 기존 픽셀을 완전히 덮어쓰는 것이 아니라 두 픽셀을 일정한 공식에 따라 섞은 결과물을 기록하는것을 말한다.

출처

0개의 댓글