3D 게임 내에 존재하는 입체적인 캐릭터나 배경이 우리가 보는 2차원 모니터 화면에 그래픽으로 출력되기까지는 복잡한 연산 과정을 거쳐야 합니다. 3D 공간상의 좌표 데이터를 픽셀 단위의 2D 이미지로 변환하는 이 전체 일련의 프로세스를 ‘렌더링 파이프라인(Rendering Pipeline)’이라고 부릅니다.
게임 디벨로퍼 및 그래픽스 엔지니어가 하드웨어 성능을 극대화하고 프레임 드랍을 방지하기 위해서는 렌더링 파이프라인의 단계별 메커니즘을 정확히 이해하는 것이 필수적입니다. 이 글에서는 3D 모델의 최소 단위인 정점(Vertex) 데이터가 입력된 순간부터 최종 프레임 버퍼(Frame Buffer)에 기록되기까지의 핵심 구조를 단계별로 알아봅니다.
1. 정점 데이터 입력 및 애플리케이션 단계 (Application Stage)
렌더링 파이프라인의 출발점은 CPU 영역에서 시작됩니다. CPU는 메인 메모리에 로드된 3D 모델 파일(FBX, OBJ 등)에서 정점 위치, 텍스처 좌표(UV), 법선 벡터(Normal Vector) 등의 기본 지오메트리 데이터를 읽어와 GPU 메모리로 전달합니다.
- 정점(Vertex)의 정의: 3D 공간에서 위치를 나타내는 $x, y, z$ 좌표 정보와 색상, UV 값 등을 담고 있는 최소 단위 요소입니다.
- 드로우 콜(Draw Call): CPU가 GPU에게 “이 정점 데이터들을 사용해 화면에 그리라”고 명령을 내리는 단계입니다. 드로우 콜 횟수가 너무 많아지면 CPU 병목 현상(CPU Bottleneck)이 발생하므로 최적화가 요구됩니다.
2. 정점 셰이더 (Vertex Shader)
GPU로 넘어온 정점 데이터는 가장 먼저 정점 셰이더를 거칩니다. 정점 셰이더의 핵심 역할은 3D 공간 좌표계 변환입니다. 3D 모델 고유의 공간 좌표(Local Space)를 화면에 출력할 수 있는 절단 공간(Clip Space) 좌표로 전환하는 행렬 연산을 수행합니다.
이 과정에서 수행되는 MVP 변환 과정은 다음과 같습니다.
- Model Matrix (모델 변환): 물체 고유의 로컬 좌표를 월드 전체 기준의 좌표계(World Space)로 이동 및 회전, 크기 조정을 거칩니다.
- View Matrix (뷰 변환): 월드 좌표계의 객체들을 카메라 위치를 기준 정점으로 하는 카메라 좌표계(View Space)로 재배치합니다.
- Projection Matrix (투영 변환): 시야각(FOV) 및 원근감을 적용하여 3차원 공간을 2차원의 투영 평면(Clip Space) 단위로 변환합니다.
3. 테셀레이션 및 지오메트리 셰이더 (Tessellation & Geometry Shader)
선택적으로 수행되는 이 단계에서는 정점 셰이더에서 넘어온 지오메트리 데이터를 바탕으로 실시간으로 정점을 추가하거나 형태를 변경하는 고급 연산을 처리합니다.
- 테셀레이션(Tessellation): 낮은 폴리곤(Low-Poly) 모델의 폴리곤을 GPU 내부에서 실시간으로 세분화하여 아주 디테일한 고폴리곤(High-Poly) 형태를 형성하는 기술입니다.
- 지오메트리 셰이더(Geometry Shader): 점이나 선, 삼각면 단위의 도형을 기반으로 새로운 정점을 즉석에서 생성하거나 기존 정점을 삭제하는 기능을 제공합니다. (예: 파티클 생성, 실시간 풀/입자 표현)
4. 래스터라이제이션 (Rasterization)
정점 연산이 완료되고 투영 영역 밖의 폴리곤을 잘라내는 컬링(Culling)과 클리핑(Clipping)을 거치고 나면, 연속적인 벡터(Vector) 형태의 3D 삼각면(Primitive)을 모니터의 격자형 픽셀 데이터 단위로 조각내는 래스터라이제이션 단계가 실행됩니다.
- 프레그먼트(Fragment) 생성: 래스터라이저는 3D 삼각면 내부를 채우는 개별 픽셀 후보군인 ‘프레그먼트’를 생성합니다.
- 보간(Interpolation): 정점 간의 위치, 색상, UV 좌표 등 정점 데이터 값을 픽셀 사이의 거리 비례에 따라 보정하는 선형 보간 연산을 자동 수행합니다.
5. 프레그먼트/픽셀 셰이더 (Fragment / Pixel Shader)
래스터라이제이션을 통해 분할된 개별 프레그먼트의 최종 픽셀 색상을 계산하는 단계입니다. 렌더링 연산 중 GPU 자원을 가장 많이 소모하는 병목 구간이기도 합니다.
- 텍스처 맵핑(Texture Mapping): UV 좌표값을 참조하여 2D 이미지 텍스처 색상을 픽셀에 매핑합니다.
- 라이팅 연산(Lighting Computation): 광원의 위치, 색상, 감쇄율과 노멀 맵(Normal Map) 데이터를 기반으로 정반사광(Specular), 난반사광(Diffuse), 환경광(Ambient) 등의 실시간 음영을 연산합니다.
6. 출력 병합 단계 (Output Merger / ROP)
모든 색상 계산이 끝난 프레그먼트들은 최종적으로 화면에 표시되기 전에 심도(Depth) 및 스텐실(Stencil) 테스트, 그리고 혼합(Blending) 과정을 거칩니다.
- Z-버퍼 테스트 (Depth Test): 가려진 피사체를 판별하는 과정입니다. 카메라에서 더 가까운 오브젝트 픽셀의 Depth 값을 비교하여 뒤에 숨겨진 픽셀을 최종 그리기 대상에서 제거합니다.
- 알파 블렌딩 (Alpha Blending): 반투명 유리나 연기 같은 효과를 표현할 때 기존 뒤편 픽셀 색상과 현재 픽셀 색상을 알파 값에 맞춰 시각적으로 합성합니다.
- 프레임 버퍼 (Frame Buffer) 기록: 이 최종 단계를 거쳐 결정된 픽셀 색상값이 메모리의 컬러 버퍼(Color Buffer)에 최종 저장됩니다.
GPU의 더블 버퍼링(Double Buffering) 구조에 따라 백 버퍼(Back Buffer)에 프레임 작성이 완료되면, 화면 갱신 주기에 맞춰 프론트 버퍼(Front Buffer)와 교체(Swap)되어 비로소 모니터에 디스플레이됩니다.
요약 및 결론
렌더링 파이프라인은 정점 데이터를 다루는 지오메트리 단계, 3D 공간을 2D 픽셀로 변환하는 래스터라이제이션, 픽셀의 물리적 색값을 결정하는 프레그먼트 셰이더, 화면에 최종 기록하는 출력 병합 과정으로 일목요연하게 정리됩니다.
게임 렌더링 최적화를 진행할 때는 자신의 프로젝트가 정점 개수가 많아 생기는 Vertex Bound 문제인지, 프레그먼트 셰이더 연산이나 텍스처 용량이 과도하여 발생하는 Pixel/Fill-rate Bound 문제인지를 파이프라인 단계에 맞춰 정확히 진단하는 것이 성능 향상의 핵심입니다.