유니티 3D 렌더링 파이프라인

1. 렌더링 파이프라인이란?
렌더링 파이프라인은 3D 오브젝트의 정점(Vertex) 데이터를 모니터에 보이는 최종 픽셀(Pixel)로 바꾸는 전체 과정이다.
핵심은 공간 변환과 GPU 연산이 따로 떨어진 개념이 아니라, 하나의 연속된 흐름이라는 점이다.
정점(Vertex)은 폴리곤을 이루는 하나의 점
- Vertex 1개 = 위치를 가진 점
- Vertex 2개를 연결 = 선(Edge)
- Vertex 3개를 연결 = 삼각형 폴리곤(Face)
전체 흐름: Local → World → CPU 선별 → View → Projection → Screen → Rasterization → Fragment Shader → Output Merging
이 과정은 다음 네 구역으로 나누어 이해할 수 있다.
| 구역 | 단계 | 중심 내용 |
|---|---|---|
| Zone A: Foundation | 1~2 | 로컬 공간의 모델을 월드 공간에 배치 |
| Zone B: Camera & CPU | 3~5 | 카메라에 보일 대상을 선별하고 뷰 공간으로 변환 |
| Zone C: Geometry | 6~9 | 정점과 삼각형을 화면의 2D 좌표로 변환 |
| Zone D: Pixel & Output | 10~14 | 픽셀 후보의 색을 계산하고 최종 화면을 합성 |
2. 14단계 전체 흐름
| 단계 | 이름 | 핵심 역할 | 주 처리 위치 |
|---|---|---|---|
| 1 | Local Space | 모델 자체의 원점을 기준으로 정점 데이터를 표현 | 모델 데이터 |
| 2 | World Space | 모든 오브젝트를 씬의 공통 좌표계에 배치 | 좌표 변환 |
| 3 | View Frustum Culling | 카메라 시야 밖의 오브젝트를 통째로 제외 | CPU |
| 4 | Draw Call | 남은 오브젝트의 렌더링 명령과 데이터를 GPU에 전달 | CPU → GPU |
| 5 | View Space | 카메라가 원점에 고정된 것처럼 월드 전체를 변환 | GPU 정점 처리 |
| 6 | Back-face Culling | 카메라의 반대쪽을 향한 삼각형의 뒷면을 제외 | GPU |
| 7 | Clipping | 시야 경계에 걸친 폴리곤을 경계에 맞게 잘라냄 | GPU |
| 8 | Projection | 원근감을 적용해 3D 좌표를 정규화된 2D 평면으로 투영 | GPU |
| 9 | Viewport Transform | 정규화된 좌표를 실제 모니터의 픽셀 좌표로 매핑 | GPU |
| 10 | Rasterization(레스터화) | 삼각형이 덮는 픽셀 위치를 찾아 Fragment를 생성 | GPU |
| 11 | Material 연산 | Base Color, Metallic 등 재질 값을 계산 | Fragment Shader |
| 12 | Lighting 연산 | 조명과 표면 정보를 이용해 색을 계산 | Fragment Shader |
| 13 | Depth Test | 같은 위치의 후보 중 카메라에 더 가까운 것을 선택 | GPU 출력 단계 |
| 14 | Alpha Blending | 반투명 색을 배경과 혼합하여 최종 화면을 합성 | GPU 출력 단계 |
※ 위 단계 번호는 이 PPT에서 설명한 학습용 구분을 따른 것이다.
3. 공간 변환의 시작: Local Space와 World Space
3-1. Local Space
Local Space는 모델마다 가지고 있는 고유 좌표계이다.
- 모델 자신의 원점이 기준이다.
- 모델링 도구에서 만들어진 최초의 정점 데이터가 이 좌표를 사용한다.
- 같은 모델이라도 위치, 회전, 크기 값에 따라 월드에서 다르게 배치할 수 있다.
3-2. World Space
World Space는 씬 전체가 함께 사용하는 공통 좌표계이다.
- 독립된 모든 오브젝트가 하나의 기준 안에 배치된다.
- Local Space의 정점에 오브젝트의 위치·회전·크기 변환을 적용하면 World Space 좌표가 된다.
| 구분 | Local Space | World Space |
|---|---|---|
| 기준점 | 각 모델의 자체 원점 | 씬 전체의 공통 원점 |
| 의미 | 모델 내부에서의 위치 | 게임 세계 안에서의 실제 배치 |
| 예시 | 캐릭터 발밑을 원점으로 한 정점 | 캐릭터가 맵의 특정 위치에 놓인 상태 |
4. CPU 단계: 보이지 않는 것을 먼저 줄인다
4-1. View Frustum Culling
카메라의 시야 영역을 View Frustum이라고 한다. CPU는 이 영역 밖에 있는 오브젝트를 렌더링 대상에서 미리 제외한다.
- 오브젝트 전체를 기준으로 판단한다.
- 시야 밖의 물체는 이후 GPU 계산에서 제외된다.
- 불필요한 계산을 초기에 막기 때문에 렌더링 성능에 큰 영향을 준다.
View Frustum Culling은 카메라 시야 밖에 있는 오브젝트를 제외하고, 시야 안에 있는 오브젝트만 렌더링 대상으로 남기는 과정이다. 렌더링 대상으로 남은 오브젝트에는 GPU로 Draw Call이 전달되며, 카메라가 움직일 때마다 매 프레임 실시간으로 다시 계산되므로 시야가 빠르게 변해도 화면을 갱신할 수 있다.
4-2. Draw Call과 Batching
Draw Call은 CPU가 GPU에 “이 오브젝트를 이 재질로 그려라”라고 전달하는 렌더링 명령이다.
- 컬링을 통과한 오브젝트의 데이터와 렌더링 명령이 GPU로 전달된다.
- Draw Call이 지나치게 많으면 CPU와 GPU 사이의 명령 전달 오버헤드가 증가한다.
- 여러 오브젝트를 묶어 한 번에 처리하는 Batching은 Draw Call 수를 줄이는 핵심 최적화 방법이다.
Draw Call이란? CPU가 GPU에 “이 오브젝트를 이 재질과 설정으로 화면에 그려라”라고 전달하는 렌더링 명령이다. Draw Call이 너무 많으면 CPU와 GPU 사이의 명령 전달 부담이 커지므로, Batching을 이용해 여러 오브젝트를 묶어 처리하기도 한다.
Batching이란? 함께 처리할 수 있는 여러 오브젝트의 렌더링 작업을 하나로 묶어 GPU에 전달하는 방법이다. Draw Call 횟수와 CPU·GPU 사이의 통신 부담을 줄여 렌더링 성능을 높인다.
함께 처리할 수 있는지는 주로 같은 Material·Shader·렌더링 설정을 사용하는지에 따라 결정된다. Batching 방식에 따라 움직이지 않는 오브젝트를 묶거나, 같은 Mesh와 Material을 사용하는 오브젝트들을 한꺼번에 처리한다.
Batching의 대표적인 방법
- Static Batching: 움직이지 않는 오브젝트들을 미리 하나로 묶어 처리한다.
- Dynamic Batching: 크기가 작은 움직이는 오브젝트들을 실행 중에 자동으로 묶어 처리한다.
- GPU Instancing: 같은 Mesh와 Material을 사용하는 여러 오브젝트를 GPU에서 한꺼번에 그린다.
5. View Space: 카메라를 기준으로 세상을 다시 배치한다
직관적으로는 카메라가 월드 안을 이동한다고 생각하기 쉽다. 하지만 렌더링 계산에서는 카메라를 원점에 고정하고, 세상 전체에 카메라 변환의 역변환을 적용한다고 이해하면 쉽다.
- 카메라는 View Space의 중심에 놓인다.
- 카메라가 오른쪽으로 움직이면 계산상 월드 전체가 왼쪽으로 이동한다.
- 모든 정점을 동일한 카메라 기준으로 바꾸면 이후 투영 계산을 일관되게 처리할 수 있다.
핵심: 카메라를 움직여 계산하는 것이 아니라, 카메라를 원점에 둔 좌표계로 모든 물체를 변환한다.
만일 카메라가 여러 개라면?
각 카메라마다 서로 다른 View Space를 만들어 같은 World Space를 각각의 시점으로 변환한다. 예를 들어 게임 카메라와 미니맵 카메라는 동일한 오브젝트를 서로 다른 View Matrix로 변환하여 별도로 렌더링한다. 따라서 카메라가 많아지면 컬링과 렌더링도 카메라별로 수행되어 성능 비용이 증가할 수 있다.
6. 이름은 같지만 목적이 다른 두 가지 컬링
| 비교 항목 | View Frustum Culling | Back-face Culling |
|---|---|---|
| 단계 | 3단계 | 6단계 |
| 제외 대상 | 오브젝트 전체 | 삼각형 표면의 뒷면 |
| 처리 위치 | CPU, 파이프라인 앞부분 | GPU, 정점·지오메트리 처리 구간 |
| 판단 기준 | 카메라 시야 안에 있는가? | 표면이 카메라를 향하고 있는가? |
| 목적 | 시야 밖 오브젝트의 계산을 처음부터 제거 | 보이는 물체 안에서도 뒤를 향한 면의 계산을 제거 |
두 컬링은 서로 대립하는 개념이 아니라, 서로 다른 시점과 단위에서 불필요한 연산을 줄이는 최적화 과정이다.
Back-face Culling에 대한 알기 쉬운 설명은 해당 페이지에서 볼 수 있다.
-> Unity 오브젝트가 안에서 보이고 밖에선 안 보일 때 해결하기 https://sungmin08.tistory.com/17
7. 3D 정점이 2D 화면 좌표가 되는 과정
7-1. Clipping (클리핑)
카메라 시야 경계에 걸쳐 있는 폴리곤을 경계에 맞게 잘라낸다.
- 시야 안쪽 부분은 남긴다.
- 시야 바깥쪽 부분은 제거한다.
- 경계에 걸친 삼각형은 필요한 형태로 다시 구성된다.
- 매 프레임 실시간으로 처리
7-2. Projection (투영)
View Space의 3D 좌표를 원근감이 적용된 2D 평면으로 변환한다.
- 멀리 있는 물체는 작게, 가까이 있는 물체는 크게 보이도록 만든다.
- 이 지점까지가 정점 좌표를 다루는 Vertex 처리의 핵심 구간이다.
7-3. Viewport Transform (뷰포트 변환)
정규화된 2D 좌표를 실제 화면 해상도의 픽셀 좌표로 바꾼다.
- 예: 정규화된 화면 좌표 → 1920×1080 모니터의 실제 위치
- 이 과정을 거치면 각 정점이 화면의 어느 지점에 놓일지가 정해진다.
8. Rasterization(레지스터화) : 삼각형을 픽셀 후보로 바꾼다
Rasterization은 화면에 매핑된 삼각형이 실제로 어떤 픽셀 위치를 덮는지 판정하는 과정이다.
- 기하학적 폴리곤을 촘촘한 화면 격자에 대응시킨다.
- 삼각형 내부에 포함되는 픽셀 위치를 찾아낸다.
- 결과로 만들어지는 것은 최종 픽셀이 아니라 Fragment, 즉 픽셀 후보 목록이다.
- 이 단계에서는 아직 최종 색이 계산되지 않는다.
| 구분 | Rasterization | Fragment Shader |
|---|---|---|
| 질문 | “이 픽셀 위치가 삼각형에 포함되는가?” | “이 Fragment의 색은 무엇인가?” |
| 입력 | 화면에 투영된 삼각형 | Rasterization으로 생성된 Fragment |
| 결과 | 픽셀 후보 목록 | 재질과 조명이 반영된 색 후보 |
| 색 계산 | 하지 않음 | 수행함 |
주의: Rasterization과 픽셀 색 계산은 서로 다른 과정이다.
9. Fragment Shader: 픽셀 후보의 색과 조명을 계산한다
Rasterization으로 생성된 각 Fragment는 Fragment Shader에서 서로 독립적으로 처리된다.
- Base Color, Metallic 같은 재질 속성을 계산한다.
- 빛의 방향, 표면의 Normal, 그림자 등의 정보를 이용해 조명을 계산한다.
- 최신 Unity 렌더링 파이프라인에서는 픽셀 단위 조명(Per-pixel Lighting)이 중요하므로 Fragment Shader의 역할이 크다.
- GPU는 수많은 Fragment를 동시에 병렬 처리하여 높은 해상도에서도 빠르게 색을 계산한다.
예를 들어 1920×1080 화면은 약 207만 개의 픽셀로 이루어진다. GPU는 많은 코어를 이용해 이 픽셀 후보들을 병렬로 처리한다.
Fragment와 Pixel의 차이
| 구분 | Fragment | Pixel |
|---|---|---|
| 의미 | Rasterization이 만든 픽셀 후보 | 최종 화면에 기록된 결과 |
| 색 상태 | Shader에서 계산 중인 후보 색 | Depth Test와 Blending까지 통과한 최종 색 |
| 생존 여부 | 가려지거나 버려질 수 있음 | Frame Buffer에 남아 화면에 표시됨 |
Fragment는 아직 최종 결과가 아니다. Fragment Shader에서 색을 계산한 뒤에도 Depth Test와 Alpha Blending 같은 출력 과정을 통과해야 최종 Pixel이 된다.
10. GPU 병렬 처리의 특징
Fragment Shader의 강점은 같은 연산을 수많은 Fragment에 동시에 적용할 수 있다는 점이다.
- 각 Fragment는 기본적으로 독립적으로 연산된다.
- 하나의 Fragment Shader 실행이 이웃 픽셀의 계산 결과와 직접 대화하는 방식은 사용할 수 없다.
- 이러한 제약은 GPU가 대규모 병렬 연산에 최적화된 구조이기 때문에 생긴다.
즉, GPU는 복잡한 하나의 작업을 순서대로 처리하기보다, 같은 종류의 작은 작업을 대량으로 동시에 처리하는 데 강하다.
11. Output Merging: 최종 1프레임을 완성한다
11-1. Depth Test
여러 물체가 같은 화면 위치를 차지할 때, 깊이값(Z값)을 비교해 카메라에 더 가까운 Fragment를 남긴다.
- 앞의 물체가 뒤의 물체를 가리도록 한다.
- 불투명 물체의 앞뒤 관계를 정확하게 표현한다.
11-2. Alpha Blending
반투명 물체의 색을 이미 그려진 배경 색과 혼합한다.
- 유리, 연기, 마법 효과 같은 반투명 표현에 사용된다.
- 투명 오브젝트는 그리는 순서가 결과에 큰 영향을 줄 수 있다.
Depth Test와 Alpha Blending을 거친 최종 색이 Frame Buffer에 기록되고, 이것이 모니터에 출력되는 한 장의 프레임이 된다.
12. 이론적 파이프라인과 Unity Shader Graph의 연결
| 이론적 과정 | Shader Graph에서 연결되는 부분 | 대표 데이터 |
|---|---|---|
| 5~9단계의 정점·좌표 처리 | Vertex Block | Position, Normal, Tangent |
| 10단계의 픽셀 후보 생성 | Fragment라는 이름의 배경 | Rasterization이 만든 픽셀 후보 |
| 11~12단계의 재질·조명 연산 | Fragment Block | Base Color, Emission 등 |
| 13~14단계의 최종 합성 | 렌더 상태와 출력 처리 | Depth, Alpha, Blend 설정 |
Shader Graph의 마지막 출력 부분이 Fragment Block이라고 불리는 이유는 Rasterization에서 생성된 Fragment를 받아 색과 재질을 계산하는 단계이기 때문이다.
13. 최적화를 이해하는 기준
렌더링 성능은 “얼마나 많은 계산을 시작하기 전에 제거했는가”와 “남은 계산을 GPU가 얼마나 병렬로 처리할 수 있는가”에 크게 좌우된다.
- View Frustum Culling으로 화면 밖 오브젝트를 제거한다.
- Batching으로 Draw Call 수를 줄인다.
- Back-face Culling으로 보이지 않는 뒷면을 제거한다.
- Fragment Shader의 계산이 지나치게 복잡하지 않은지 확인한다.
- 투명 오브젝트와 Overdraw가 많아 같은 픽셀을 반복 계산하지 않는지 확인한다.
14. 최종 핵심 요약
- 렌더링은 정점 데이터를 최종 픽셀로 바꾸는 연속적인 과정이다.
- 좌표는 Local → World → View → Projection → Viewport 순서로 변환된다.
- CPU는 View Frustum Culling과 Draw Call을 통해 GPU에 보낼 작업량을 줄인다.
- GPU는 정점 처리, Back-face Culling, Clipping, Projection, Rasterization을 거쳐 Fragment를 만든다.
- Rasterization은 색을 계산하지 않고 픽셀 후보만 만든다.
- Fragment Shader는 각 후보의 재질과 조명을 병렬로 계산한다.
- Fragment는 최종 Pixel이 아니며, Depth Test와 Alpha Blending을 통과해야 화면에 남는다.
- Shader Graph의 Vertex Block과 Fragment Block은 이론적 렌더링 파이프라인을 실무에서 제어하는 접점이다.
- 최적화의 핵심은 불필요한 오브젝트·면·Fragment 계산과 Draw Call을 최대한 줄이는 것이다.
한 문장 정리: CPU가 그릴 대상을 줄여 GPU에 넘기고, GPU는 3D 정점을 2D Fragment로 바꾼 뒤 색·깊이·투명도를 계산하여 최종 1프레임을 만든다.
참고 자료 PPT (강사님 제공) : https://docs.google.com/presentation/d/1v22uD7Me_CWYFCybI1rwtvTWrmUSWkN5/edit?slide=id.p1#slide=id.p1



