해당 포스팅은 이상윤님께서 공유해주신 2025 TA Campus 수업 문서 링크를 바탕으로 작성했습니다.
4. Rendering Path
Rendering Path는 앞서 설명했던 Render Pass들을 어떤 순서와 구조로 사용할 것인지를 정의한다.
대표적인 Rendering Path로는 다음과 같은 것들이 있다.
- Forward Rendering
- Forward+
- Deferred Rendering
Rendering Path는 이런 질문에 답한다.
- 라이팅을 언제 계산할 것인가?
- 어떤 정보들을 중간 버퍼에 저장할 것인가?
- Render Pass를 몇 번, 어떤 형태로 나눌 것인가?
즉, Rendering Path는 렌더링 파이프라인을 운영하는 방식 자체라고 볼 수 있다.
4-1. Forward Rendering
Forward Rendering은 가장 직관적이고 전통적인 렌더링 방식이다. 이 방식에서는 메시를 그리는 과정에서 바로 라이팅까지 계산해서 최종 색을 Render Target에 출력한다.
4-1-1. Forward Rendering의 한계
Forward Rendering은 구조가 단순하고 직관적이라 구현이 쉽다는 장점이 있다. 하지만 그만큼 한계도 뚜렷하다.
위 그림처럼, Forward Rendering에서는 하나의 오브젝트를 그릴 때마다 그 오브젝트에 영향을 주는 모든 라이트를 오브젝트마다 Pixel Shader에서 직접 계산해야 한다.
- 오브젝트 수 X 라이트 수 = 총 Draw Call 횟수
즉, 많은 오브젝트와 라이트를 쓰기는 어렵다.
4-2. Forward+ Rendering
기존의 Forward Rendering의 한계점을 개선하고자 나오는 것이 Forward+ Rendering이다. Forward+ Rendering은 Forward Rendering의 기본 구조는 그대로 유지하면서, 라이팅 계산에 사용되는 라이트의 개수만 줄인 방식이다.
핵심 아이디어는 다음과 같다.
- 화면을 작은 영역으로 나누고, 각 영역에 실제로 영향을 주는 라이트 목록을 미리 계산한다.
Forward+ Rendering은 보통 다음과 같은 순서로 구현된다.
1. 타일 분할 - 화면을 고정 크기의 타일 단위로 나눈다.
2. 라이트 컬링 (Compute Shader) - Compute Shader를 사용해 각 타일마다 영향을 주는 라이트 리스트를 생성한다. - 이 결과는 GPU 메모리(Buffer)에 저장된다.
3. Forward Rendering 패스 - 기존 Forward Rendering과 동일하게 메시를 그린다. - 단, Pixel Shader에서는 전체 라이트가 아니라 해당 타일의 라이트 리스트만 순회하며 라이팅을 계산한다.
4-3. Deferred Rendering
Deferred Rendering은 라이팅 계산을 메시 렌더링 이후로 미루는 방식이다. 즉, “오브젝트를 그리는 단계”와 “라이팅을 계산하는 단계”를 완전히 분리한다.
Forward 계열에서는
- 메시를 그릴 때 → 바로 라이팅 계산 → 최종 색 출력
이었다면, Deferred Rendering에서는
- 메시를 그릴 때 → 필요한 정보만 저장, 이후 별도의 패스에서 → 라이팅 계산
이라는 구조를 가진다. 이 구조의 핵심이 바로 GBuffer (Geometry Buffer) 이다.
4-3-1. GBuffer Pass
GBuffer는 Deferred Rendering의 첫 번째 패스(Geometry Pass)에서, 각 픽셀에 대해 라이팅에 필요한 정보들을 색 대신 데이터로 저장한다.
보통 다음과 같은 정보들이 GBuffer에 기록된다.
- Base Color (Albedo)
- Metallic
- Roughness
- Ambient Occulusion(AO)
- Normal
- World Position etc..
4-3-2. Lighting Pass
Lighting Pass는 GBuffer Pass에서 수집된 픽셀별 정보를 기반으로 실제 라이팅을 수행하는 단계이다. 이미 화면에 어떤 표면이 있는지는 GBuffer에 다 기록되어 있기 때문에, Lighting Pass에서는 “이 픽셀에 어떤 라이트가 영향을 주는가”만 계산하면 된다.
결과적으로 Forward Rendering 방식보다 더 많은 라이트를 계산하기에 적합하다.
4-4. 왜 라이트 처리를 기준으로 Path를 구분할까
Rendering Path의 차이는 단순히 “빛을 어떻게 계산하느냐”에서 끝나지 않는다.
라이팅을 언제, 어디서 처리하느냐는 그 이후에 추가되는 모든 라이팅들의 구현 난이도와 비용까지 결정한다.
이를 가장 직관적으로 보여주는 예시가 바로 SSAO(Screen Space Ambient Occlusion)다.
SSAO는 화면 공간에서 주변 픽셀을 샘플링해서 “이 픽셀이 주변 지형에 의해 얼마나 가려져 있는지”를 계산하는 효과다.
이를 위해 최소한 다음 정보 중 하나가 필요하다.
- Scene Depth (깊이 정보)- World Normal (월드 공간 노멀)
Forward Rendering의 경우
Forward Rendering에서는 메시를 그리면서 바로 최종 색을 Render Target에 출력한다 기본적으로 GBuffer 같은 중간 데이터가 존재하지 않는다.
그래서 SSAO를 추가하려면
- 기존 Forward Lighting Pass와는 별도로
- World Normal을 출력하는 추가 패스를 만들어야 한다
- Normal 전용 Render Target을 관리해야 한다.
그래서 SSAO를 추가하려면
1. 기존 Forward Lighting Pass와는 별도로 2. World Normal을 출력하는 추가 패스를 만들어야 한다 3. Normal 전용 Render Target을 관리해야 한다.
결과적으로
- 렌더 패스가 하나 더 늘어나고
- 메모리 사용량이 증가하고
- 파이프라인이 복잡해진다
Deferred Rendering의 경우
Deferred Rendering에서는 상황이 완전히 다르다. Geometry Pass에서 이미 GBuffer에 다음 정보들이 저장된다
- World Normal
- Depth etc..
따라서 Deferred Rendering에서는
- 추가 패스 없이
- 기존 GBuffer를 입력으로
- SSAO Pass만 하나 더 붙이면 된다
그렇다면 항상 Deferred Rendering을 사용해야 할까?
지금까지 보면 이런 생각이 들 수 있다. 라이트 수에 강하고 SSAO 효과 구현도 쉽고 라이팅 비용도 예측 가능하다
그렇다면 항상 Deferred Rendering이 더 좋은 선택 아닐까? 하지만 Deferred Rendering에도 분명한 단점과 한계가 존재한다.
1. 메모리 사용량이 크다.
Deferred Rendering의 핵심은 GBuffer다. 즉, 화면의 모든 픽셀에 대해 여러 장의 텍스처를 유지해야 한다.
따라서 해상도가 올라갈수록 GBuffer 메모리 사용량이 기하급수적으로 늘어난다. 만약 모바일 GPU나 저전력 환경에서는
- 대용량 GBuffer
- 다중 Render Target (MRT)
- 복잡한 메모리 접근
자체가 큰 부담이다.
그래서 모바일 환경에서는 여전히 Forward Rendering, Forward+가 많이 사용된다.
2. 반투명 오브젝트 처리에 불리하다.
Deferred Rendering은 구조상
- 불투명 오브젝트에 최적화되어 있다
- 반투명 오브젝트는 GBuffer에 제대로 담을 수 없다
그래서 일반적으로
- 불투명 오브젝트 → Deferred
- 반투명 오브젝트 → Forward
처럼 혼합 렌더링(Hybrid)을 사용한다.