렌더링 (Rendering)
CPU가 GPU에게 화면에 그릴 데이터를 전달하고, GPU가 이를 실제 픽셀로 그리는 과정을 말한다.
CPU → (Draw Call) → GPU → (Rasterize) → 화면 출력
CPU는 게임 오브젝트, 메시, 머테리얼, 텍스텨 등 그려야 할 데이터와 명령을 GPU로 전송하고
GPU는 이를 기반으로 픽셀 단위로 이미지를 생성한다.
CPU 단계에서 "무엇을, 어떻게 그릴지" 를 결정하는 것이다.
GPU 내부 처리 단계를 조금 더 세분화하면 아래와 같다.
- Vertex Shader (정점 변환 및 속성 처리)
- Primitive Assembly / Clipping (삼각형 구성 및 화면 밖 제거)
- Rasterization (삼각형 → 픽셀화)
- Fragment/Pixel Shader (텍스처, 조명 연산)
- Depth/Stencil/Blend Test → Framebuffer 출력
드로우 콜 (Draw Call)
CPU가 GPU에 그리라고 명령하는 단 한번의 호출을 말한다.
모든 메시, 스프라이트, 파티클, UI는 결국 Draw Call 단위로 GPU에 전달된다.
오브젝트 1개당 Draw Call 1회 라는 뜻이다.
즉, Draw Call 수가 많을 수록 CPU가 매번 파이프라인 상태를 갱신해야 하므로,
GPU 보다 CPU가 먼저 병목에 걸리는 상황이 발생할 수 있다.
배칭 (Batching)
비슷한 오브젝트들을 하나의 Draw Call로 묶어 처리하는 최적화 기법이다.
이 과정을 통해 CPU → GPU 호출 횟수를 줄일 수 있다.
| Batch | GPU가 한 번에 그릴 수 있는 묶음 단위 |
| SetPass Call | 머티리얼(셰이더) 교체 시 발생하는 추가 렌더링 호출 |
| Batching | 여러 오브젝트를 하나로 합쳐 Draw Call을 최소화하는 과정 |
in Unity
- Static Batching : 움직이지 않는(Static) 오브젝트를 미리 합침
- Dynamic Batching : 동일 머티리얼을 공유하는 작은 오브젝트들을 런타임에 묶음
폴리곤 (Polygon)
3D 모델의 표면은 수많은 삼각형(Tris)으로 이루어져 있다.
각 삼각형은 3개의 정점(Vertex)으로 구성되며,
Unity의 Stats 창에서 보이는 Tris / Vertex 값이 바로 그 수를 의미한다.
삼지어 사각형(Quad) 모델도 내부적으로 삼각형(Tris) 두 개로 분리되어 처리된다.
법선 벡터 (Normal Vector)
폴리곤 면이 향하는 방향을 나타내는 벡터다.
조명 계산, 백페이스 컬링(Culling), 반사, 음영 처리 등에 사용된다.
벡터의 외적(Cross Product)을 통해 계산할 수 있다.
AB = B - A
AC = C - A
Normal = normalize(AB × AC) // 외적(Cross Product)
벡터의 외적 순서가 중요하다.
순서를 반대로 하면 법선이 안쪽을 향해 음수 방향으로 뒤집히게 되니 주의하자.
백페이스 컬링 (Backface Culling)
그래픽스 엔진은 보이지 않는 면(뒤쪽 면)을 굳이 그리지 않아 성능을 최적화 하는데 이것을 Culling 이라 부른다.
Unity의 Camera → Culling Mask 옵션은
"어떤 레이어의 오브젝트를 그릴지" 를 설정하는 역할을 하며,
이는 GPU가 불필요한 픽셀 계산을 건너뛰는 핵심 최적화 포인트다.
보통 픽셀 하나는 RGBA(4바이트)이므로 픽셀x4의 연산이기에 컬링으로 절감되는 비용은 매우 크다고 한다.
| View Frustum Culling | 카메라 시야 밖 오브젝트를 렌더링 대상에서 제외 |
| Backface Culling | 삼각형의 뒷면 제거 |
| Occlusion Culling | 다른 오브젝트에 완전히 가려진 오브젝트 제거 |
인덱스 버퍼 (Index Buffer)
GPU는 "어떤 정점들을 이용해 삼각형을 그릴지"를 알아야 한다.
이를 지정하는 배열이 Index Buffer다.
Vertices = [v0, v1, v2, v3]
Index = [0, 1, 2, 1, 3, 2]
인덱스 순서대로 뽑아내면
- (v0, v1, v2)
- (v1, v3, v2)
두 삼각형을 나타내게 된다.
인덱스를 이용해 정점을 재사용하면서 여러 폴리곤을 효율적으로 정의하는 방식이다.
새 폴리곤이 추가될 때마다 새 정점을 만들 필요 없이, 인덱스 배열만 확장된다.
GPU는 정점(Vertex)를 직접 나열하지 않고 인덱스(Index)를 통해 삼각형을 조립함으로써 메모리 대역폭을 절약하게 된다.
※주의 : 올바른 법선 벡터를 위해 인덱스 순서는 외적(Cross Product) 연산을 위한 순서를 고려하도록 하자.
UV Map
UV는 텍스쳐 시트(Texture Atlas) 내에서 "각 정점이 참조하는 상대좌표(0~1)"를 우ㅢ미한다.
즉, "이 삼각형의 정점이 텍스쳐의 어느 부분을 사용할지"를 정의한다.
- U: 텍스처의 가로축 (0~1)
- V: 텍스처의 세로축 (0~1)
UV Map은 결국 "시트 안에서의 로컬 좌표계"다.
폴리곤의 각 정점이 어떤 텍스쳐를 참조할지 매핑해주는 역할을 한다.
전체 렌더링 흐름
위에서 정리한 사전 내용을 기반으로 전체 렌더링 흐름을 정리해보자.
- CPU: Mesh, Vertex, Material, Texture 정보 준비
- Draw Call로 GPU에 렌더 명령 전달
- GPU: Vertex → Primitive → Fragment 단계로 렌더링
- Backface Culling & Lighting 계산
- 텍스처 샘플링(UV 맵 기반)
- 결과 픽셀을 프레임버퍼에 출력
이 모든 과정이 매 프레임 반복된다.
요약
| “렌더링이란?” | CPU가 GPU에 그릴 데이터를 전달하고, GPU가 이를 픽셀로 그리는 과정. |
| “Draw Call이란?” | CPU가 GPU에 한 번 그리라고 명령하는 호출입니다. 많을수록 CPU 부하가 커진다. |
| “Batching이란?” | 비슷한 오브젝트를 한 번에 묶어 렌더링 호출을 줄이는 최적화 기법. |
| “Normal Vector는 왜 필요한가?” | 면의 방향을 나타내며, 조명·컬링·반사 계산의 기준이 된다. |
| “Backface Culling이란?” | 카메라에서 보이지 않는 뒷면 삼각형을 렌더링하지 않는 최적화 기법. |
| “Index Buffer의 역할은?” | 정점을 재사용해 삼각형을 효율적으로 정의하고 메모리를 절약한다. |
| “UV는 뭐의 약자인가?” | 약자가 아니라 텍스처의 가로·세로축 좌표로, 시트 내부의 상대좌표(0~1) 이다. |