포스트

렌더링 파이프라인 - 1

렌더링 파이프라인의 정점 조립과 정점 변환에 대해서 공부하고 정리했습니다.

렌더링 파이프라인 - 1

렌더링 파이프라인은 아래의 그림과 같이 구성된다.

이번 글에서는 지오메트리 단계를 알아볼 예정이다.
지오메트리 단계 중에서도 Input assembler, Vertex Shader를 중점적으로 볼 것이다.

Tesselation와 Geometry Shader는 생략이 가능하고 실시간 렌더링에서는 거의 사용하지 않기 때문에 내용을 생략한다.



Input assembler

입력 어셈블러(Input assembler)는 렌더링 파이프라인의 제일 처음에 위치하는 단계다.
정점 버퍼와 인덱스 버퍼를 읽어 프리미티브를 구성하고 다음 단계로 이동시킨다.

프리미티브GPU가 렌더링하는 가장 기본적인 기하 단위를 말한다.
예를 들면 , , 삼각형이 이에 해당한다.


입력 어셈블러의 주요 역할은 정점 조립(Vertex assembly)이다.

정점 조립 단계에서는 정점 서술자(Input Layout)을 보고 오프셋과 스트라이드에 따라 필요한 바이트를 읽는다.
그리고 읽어들인 바이트를 정점 셰이더(Vertex Shader)의 입력 레지스터에 입력한다.

정점 조립 과정은 Unity와 같은 엔진 내부에서 알아서 처리된다.
우리가 직접 해야하는 것은 사용할 정점의 구성을 구조체로 선언하는 것이다.



Vertex Shader

정점 셰이더(Vertex Shader)는 입력 어셈블러가 입력한 정점 속성 데이터를 받아 다른 형태의 정점으로 변환한다.

정점 셰이더의 주요 역할은 3D 공간 상의 정점의 위치를 카메라를 통해 바라보는 위치로 변환하는 것이다.
쉽게 말하면 정점을 어떤 공간에서 다른 공간으로 투영하는 작업이다.


이때 정점을 다른 공간 기준으로 변환하기 위해 사용하는 방법은 아핀 변환에 행렬 곱을 사용하는 것이다.
행렬 곱은 결합 법칙이 성립하기 때문에 아핀 변환들을 미리 캐싱해둘 수 있다. 이때 MVP를 변환 행렬이라고 한다.

$MVP = P \cdot V \cdot M$

MVP 행렬은 모델 행렬의 Model, 뷰 행렬은 View, 투영 행렬의 Projection의 앞글자를 따서 지어졌다.
이렇게 각 정점들을 MVP 행렬을 이용하여 변환한다. 이를 정점 변환이라고 한다.


맨 처음 정점들은 메시를 원점으로 상대 좌표만을 가지는 로컬 공간에 존재한다.
이를 월드 공간으로 옮기기 위해 모델 행렬을 이용하여 변환을 적용한다. 이를 월드 트랜스폼이라고 한다.

메시를 월드 공간으로 옮겼다고 끝이 아니다.
월드 공간을 볼 수 있는 시야는 카메라로 한정되기 때문에 카메라 시점 변환이 또 필요하다.
따라서 카메라 공간으로 옮기기 위해 뷰 행렬을 이용하여 변환을 적용한다. 이를 뷰 트랜스폼이라고 한다.

카메라를 원점으로 메시를 옮겼지만 카메라의 시야와 원근감을 반영하진 않았다.
카메라 시점을 반영한 클립 공간으로 옮기기 위해 투영 행렬을 이용하여 변환을 적용한다.

이를 통해 카메라에 보이는 공간이 결정되고 원근감이 반영된다.



View Frustum Cliping

정점 셰이더를 거쳐 정점들을 조립한 프리미티브가 구성된다.
이 프리미티브를 가지고 뷰 프러스텀 클리핑 단계가 일어난다.
뷰 프러스텀 클리핑은 파이프라인에 위치하는 고정 함수로 프로그래밍이 불가능하다.

뷰 프러스텀은 카메라가 가지는 시야, 카메라가 렌더링하는 영역을 말한다. 다른 말로는 절두체라고도 한다.

월드 상에 존재하는 모든 오브젝트를 렌더링하게 되면 게임 성능이 낮아진다.
따라서 뷰 프러스텀에 보이는 오브젝트만 렌더링하여 성능을 개선한다.

뷰 프러스텀은 근평면(Near clip plane)과 원평면(Far clip plane)을 가진다.
근평면보다 가까운 오브젝트나 원평면보다먼 오브젝트는 렌더링 대상에서 제외된다.

원근 투영 카메라인 경우에 뷰포트는 절두체지만, 직교 투영 카메라인 경우 뷰포트는 직육면체가 된다.
어쨌거나 카메라가 보는 영역이 클립 공간으로 축소된다.

원근 투영 카메라의 경우는 왜 원근감이 생길까? 정답은 투영 행렬에 있다.
뷰 프러스텀이 투영 행렬을 거쳐서 클립 공간으로 변환될 때 근평면에 가까운 물체는 적게 축소되고 원평면에 가까운 물체는 많이 축소된다.

변환을 마친 정점들은 레스터라이저로 이동한다.



마무리

GPU 디바이스는 커맨드 큐에서 커맨드 버퍼와 명령들을 불러온다.
이때 데이터들은 스트림 형태로 전달되는데 입력 어셈블러의 정점 조립 과정을 거쳐 정점 데이터를 해석한다.
그리고 해석된 정점 데이터를 정점 셰이더에 전달한다.

정점 셰이더에서는 정점 데이터를 기반으로 로컬 공간의 정점을 MVP 행렬을 통해 클립 공간의 정점으로 변환한다.

이제 이 정점들을 레스터라이저와 프래그먼트 셰이더를 통해 화면에 렌더링할 일만 남았다.
이는 다음 글에서 알아보도록 하겠다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.