렌더링 파이프라인
렌더링 파이프라인은 3D 세계에 대한 기하학적 표현과 이 세계를 바라보는 관점을 정의하는 가상 카메라를 이용해 2D 이미지를 만들어내는 역할을 담당한다.
기하학이란?
평면, 공간 상에 있는 도형이나 대상들의 치수, 면적, 부피, 위치 등을 연구하는 학문.
참고) DirectX 11에서의 렌더링 파이프라인
렌더링 파이프라인 과정
- 렌더링 파이프라인의 첫 단계
- 정점 데이터를 CPU에서 GPU로 운반하기 위한 자료 구조를 정점 버퍼라고 한다.
- 정점 버퍼는 위치, Normal, Color, UV등을 담고 있는데, 직렬화된 형태(배열)로 담고 있다.
- GPU에서 전달 받은 정점 버퍼를, 미리 전달 받은 렌더 상태의 Vertex 명세를 통해
정점 데이터(구조체)로 조립한다.
- Direct 3D에서는 Primitive Topology라는 형태로 정점이 표현하는 기본 도형을 정의한다.
- 정의해 준 기본 도형으로 정점을 모아 조립해준다. 그렇기 때문에 입력 조립 단계라고도 한다.
메모리에 사용자가 채워놓은 기본 데이터를
다른 파이프라인 단계에서 사용하기 위한 기본 형식으로 조립한다.
2. 꼭지점(정점) 셰이더(Vertex Shader)
- 정점 데이터를 입력 받아 공간 변환(Transformation)을 수행한다.
- 공간 변환은 총 3가지로 구성되어 있으며, 변환 행렬을 통해 수행한다.
- Model(World) , View , Projection 가 변환 행렬을 담당한다.
- Vertex Shader의 최종 출력은 Clip Space의 정점 데이터이다.
2-1. 오브젝트 공간(Object Space)
- 오브젝트 공간은 아직 변환이 되지 않은 폴리곤 메쉬들이 존재하는 공간.
- 로컬 공간(Local Space)이라고도 불린다.
- 월드 변환은 크기(Scale), 회전(Rotate), 이동(Translate)을 이용해 행렬을 만들어 정점을 변환한다.
- 계산이 끝난 후, 최종적으로 월드 공간(World Space)의 정보로 변환하게 된다.
2-3. 월드 공간(World Space)
- 오브젝트 공간에서 월드 변환을 통해 월드 공간으로 변환된다.
- 여러 메쉬들이 하나의 공간, 즉 하나의 좌표계에 모이는 곳.
- 월드 공간으로 변환된 정점들을 카메라가 보는 시점으로 보기 위한 변환.
- 카메라를 위치가 원점(0,0,0)이고, 바라보는 방향을 +Z축으로 변환한다.
- 카메라를 저 위치에 존재하게 하기 위해서, 정점에 카메라의 역행렬을 곱한다.
- 카메라의 역행렬은 V = T Rz Ry * Rx 로 구한다.
(T는 월드내의 개체를 재배치하는 평행이동 행렬, Rx ~ Rz는 x,y,z축으로 따라 개체를 회전하는 회전 행렬)
2-5. 뷰 공간(View Space)
- 카메라가 바라보는 시점에서의 상대적인 좌표를 갖고있는 공간이다.
- 최종적으로 화면에 보여야 할 물체들만 존재하는 클립 공간으로 변환하는 작업이다.
- 카메라 기준의 정점 위치를 화면에 보이기 위한 정점 위치로 변환한다.
- 원근감이 없는 직교 투영(Orthographic Projection) 또는 원근감이 있는 원근 투영(Perspective Projection)이 행해진다.
- 투영 행렬은 시야각(Field of View), 종횡비(Aspect) 그리고 절두체의 근평면(Near Clipping Plane)과 원평면(Far Clipping Plane)에 의해 정의된다.
2-7. 클립 공간(Clip Space)
- 카메라 공간에서 시야를 정하고 보이지 않는 메쉬들을 잘라내 최종적으로 카메라 시야에서 보이는 메쉬들만 위치한 공간을 클립 공간이라고 한다.
- 클립 공간의 모든 X,Y 좌표는 -1 ~ 1의 범위에 존재하며, Z좌표는 0 ~ 1 범위에 존재한다.
- W값은 카메라에서 멀수록 커지며, 추후에 NDC로의 변환에 사용된다.
- 클립 공간의 4D 좌표계를 동차 좌표계(Homogeneous Coordinates)라고 한다.
- NDC와 클립 공간은 다르다.
3. 테셀레이션(Tessellation)
- 삼각형의 개수를 늘리는 작업을 테셀레이션이라 한다.
- 테셀레이션에는 총 3가지 단계가 있으며, 프로그래머블 셰이더는 3-1과 3-3뿐이다.
3-1. 덮개 셰이더(Hull Shader)
- 다음 단계인 테셀레이션(Tessellation)을 위한 준비 단계.
- 테셀레이션 단계의 처음이며, 이를 수행하기 위해선 Vertex Shader에서 World 변환까지만 적용해야 한다.
- 각 기본 도형마다 실행된다.
- '폴리곤을 어떻게 분할할 것인가?' (Hull-Main Shader)와 '폴리곤을 얼마나 분할할 것인가?' (Hull-Constant Shader)를 정하는 셰이더다.
- 두 작업이 병렬적으로 이루어지며 각 패치마다 한 번 씩 발생한다.
(패치란, 구획(subdivision)을 이루는 최소 형태. 주로 삼각형이나 사각형을 사용한다.)
3-2. 테셀레이터(Tessellator)
- 프로그래머가 제어할 수 없는 영역
- 주어진 메쉬의 삼각형을 더 잘게 쪼개서 새로운 삼각형을 만드는 과정.
- Hull Shader의 결과를 받아 Domain Shader에서 사용할 무게 중심을 계산한다.
3-3. 영역 셰이더(Domain Shader)
- 테셀레이터가 출력한 정점(분할된 모든 정점)마다 호출된다.
- 기존의 Vertex Shader에서 수행하던 작업을 여기서 수행하게 된다.
- Hull-Shader가 생성한 제어점과 Tessellator의 무게중심을 통해 세분화된 꼭지점의 위치를 계산한다. 즉, 정점의 투영 변환까지 수행한다.
- 정점은 실제 위치가 아닌 패치 영역 공간안에서 그 정점의 매개변수 좌표(u,v)를 받는다.
( 테셀레이터의 출력 UV 좌표이다. )
4. 기하 셰이더(Geometry Shader)
- 입력받은 정점 데이터에 정보를 추가하거나 삭제할 수 있다.
- 위의 과정을 통해 기본 도형을 다른 도형으로 확장하거나 출력하지 않을 수 있다.
5. 래스터라이즈(Rasterize)
- 투영된 3차원의 삼각형으로 부터 픽셀의 색상을 계산하는 단계
5-1. 클리핑(Clipping)
- 투영 변환 이후에 클립 공간 볼륨 바깥에 놓인 폴리곤을 잘라내는 작업.
5-2. 원근 나누기(Perspective Division)
- 투영 변환을 통해 원근법이 적용된 3차원 물체를 2차원 공간으로 변환시키는 작업.
- 클립 공간(Clip Space) 좌표의 모든 요소를 W로 나누게된다.
- 원근 나누기를 수행한 좌표계를 NDC(Normalized Device Coordinates)라 한다.
5-3. 후면 추려내기(Back-face Culling)
- 카메라에 등을 돌리고 있어 보이지 않는 폴리곤을 제거하는 작업.
- 폴리곤의 법선 벡터와 시선 벡터를 통해 이 두개의 벡터가 예각인지 둔각인지에 따라 판별.
- 3D NDC 공간의 물체들을 2D 스크린 공간으로 이전시키는 변환.
- -1 ~ 1의 범위였던 X,Y 좌표를 화면 해상도 범위로 변환한다.
- 기본 도형(프리미티브)를 통해 프래그먼트를 생성하고 프래그먼트를 채우는 픽셀을 찾는 과정.
- 각 픽셀마다 정점 데이터(위치, 색상, 노말, UV)를 보간해 할당한다.
6. 픽셀 셰이더(Pixel Shader)
- 각 픽셀의 데이터를 생성하는 단계.
- 모델이 화면에서 차지하는 픽셀의 개수만큼 실행.
- 조명을 계산하거나 텍스쳐를 입혀서 프래그먼트를 색칠하는 단계.
7. 출력 병합(Output Merge)
- 픽셀 셰이더가 생성한 데이터들을 입력받아 최종적으로 픽셀의 색상을 생성해 렌더 타겟에 출력하는 단계.
- 최종적으로 출력하기 위해 3개의 테스트를 거친다.
1) Z-Test
2) Stencil Test
3) Alpha Blending
- 후면 버퍼에 기록된다.
알고 있는 정보를 정리하기 위해 작성한 게시물입니다.
틀린 내용이 있으면 알려주시면 감사하겠습니다.