유니티 렌더링 파이프라인(그래픽스 파이프라인)

lenore·2026년 1월 31일

gpu 단계에서 간략한 렌더링 파이프라인개념
1. 정점 셰이더 (Vertex Shader)
3D 모델의 각 꼭짓점(정점) 위치를 계산해서 화면 좌표로 변환하는 단계

2. 래스터라이저 (Rasterizer)
정점들을 연결해서 삼각형을 만들고, 그 안을 픽셀로 채우는 단계

3. 픽셀 셰이더 (Fragment Shader)
각 픽셀의 최종 색상을 계산하는 단계

Fragment Shader = Pixel Shader (같은 것)

역사적 이유

DirectX (Microsoft)
"Pixel Shader"라는 용어 사용
Windows, Xbox 등 Microsoft 생태계

OpenGL (크로노스 그룹)
"Fragment Shader"라는 용어 사용
크로스 플랫폼, 웹, 모바일 등

렌더링 파이프라인 — 이론 수준 상세 설명


전체 구조

┌─────────────────────┐
│   애플리케이션 단계   │  ← CPU
├─────────────────────┤
│    지오메트리 단계    │  ← GPU (정점)
├─────────────────────┤
│   래스터라이저 단계   │  ← GPU (픽셀)
└─────────────────────┘

각 단계는 병렬로 파이프라인처럼 흐름 — 앞 단계가 끝나야 다음 단계 시작이 아니라, 동시에 진행됨.


1단계: 애플리케이션 단계 (Application Stage)

완전히 CPU에서 실행. 개발자가 가장 많이 제어하는 영역.

하는 일

① 씬 관리

어떤 오브젝트가 존재하는지, 각 오브젝트의 Transform 정보를 알아낸다

② 가시성 판단 (Culling)

Frustum Culling → 카메라 시야 밖 오브젝트 제거
Occlusion Culling → 다른 오브젝트에 완전히 가려진 것 제거
Backface Culling → 카메라를 등진 삼각형 면 제거 (이건 GPU에서도 가능)

③ 렌더 상태 설정

이 오브젝트는 어떤 셰이더를 쓸 것인가?
어떤 텍스처를 바인딩할 것인가?
블렌딩 모드는 무엇인가?

④ Draw Call 전송

CPU → GPU로 "이 메시를, 이 셰이더로, 그려라" 명령 전달
이 명령 하나 = Draw Call 1개

사실 Draw Call 안에 렌더 스테이트(렌더상태),DP Call 이 들어가 있다.

왜 중요한가

애플리케이션 단계의 출력이 다음 단계의 입력 품질을 결정함.
Draw Call이 많을수록 CPU-GPU 통신 비용 증가 → 병목 발생.

2단계: 지오메트리 단계 (Geometry Stage)

"무엇을 어디에 그릴 것인가"를 결정하는 단계.
정점(Vertex) 단위로 처리. 여러 서브 단계로 구성됨.


2-1. 모델 & 뷰 변환 (Model & View Transform)

오브젝트의 정점 좌표를 여러 공간으로 옮기는 과정.

오브젝트 공간 (Object Space)
↓ Model Matrix (월드 배치)
월드 공간 (World Space)
↓ View Matrix (카메라 시점)
뷰 공간 (View/Camera Space)

오브젝트 공간: 메시 자체의 로컬 좌표. 원점이 오브젝트 중심.

월드 공간: 씬 전체 기준 좌표. 모든 오브젝트가 같은 기준점 사용.

뷰 공간: 카메라가 원점이고 카메라가 -Z를 바라보는 좌표계.
조명 계산의 상당수가 여기서 이루어짐.


2-2. 정점 셰이딩 (Vertex Shading)

정점 셰이딩 단계는 각 정점의 위치를 변환하고, 노말·텍스처 좌표 등
픽셀 셰이더에 전달할 속성을 계산하는 단계다. 필요하다면 여기에서 정점 단위 조명/색을 계산할 수도 있다

정점셰이딩은 모서리만 계산하고 나머지를 보간한다.빠르지만 부정확 하기에 픽셸세이딩에서
모든 픽셀을 직접계산한다

per‑vertex(정점) 조명 설명

정점 조명(per‑vertex lighting, Gouraud Shading)에서는 정점 셰이더에서 각 정점의 조명·색을 계산하고, 래스터라이저가 삼각형 내부 픽셀에 대해 이 값을 보간한다. 이 방식은 빠르지만, 하이라이트나 실루엣 주변에서 정확도가 떨어진다.”

per‑pixel(픽셀) 조명 설명
“픽셀 조명(per‑pixel lighting)에서는 정점 셰이더가 조명 계산에 필요한 노말·위치 등을 넘겨 주고, 픽셀 셰이더가 각 픽셀마다 조명식을 직접 평가한다. 계산량은 늘어나지만 보다 정확한 조명과 하이라이트를 얻을 수 있다


2-3. 투영 (Projection)

뷰 공간 → 클립 공간으로 변환. 3D → 2D의 핵심.

원근 투영 (Perspective Projection)

멀리 있는 것은 작게, 가까운 것은 크게
FOV(시야각), Near/Far Plane 정의

직교 투영 (Orthographic Projection)

거리에 관계없이 동일한 크기
UI, 2D 게임, 기술 도면에 사용

투영 후 좌표계 = 클립 공간 (Clip Space)
모든 좌표가 -1 ~ +1 범위의 정규화된 값(NDC)으로 변환됨.


2-4. 클리핑 (Clipping)

카메라 절두체(Frustum) 경계를 벗어난 삼각형 처리.

완전히 안쪽 → 그대로 통과
완전히 바깥 → 완전 제거
걸쳐 있음 → 경계면에서 잘라내고 새 정점 생성

  /|
 / |  ← 절두체 경계

----/--+-----
/ |새 정점 생성됨
/ |

2-5. 화면 공간 변환 (Screen Mapping)

클립 공간의 NDC 좌표 → 실제 픽셀 좌표로 변환.

NDC (-1 ~ +1)  →  화면 픽셀 좌표 (0 ~ 1920 등)

3단계: 래스터라이저 단계 (Rasterizer Stage)

"픽셀 단위로 어떻게 채울 것인가"를 결정하는 단계.


3-1. 삼각형 설정 (Triangle Setup)

정점 3개로 정의된 삼각형의 엣지 방정식 계산.
"어떤 픽셀이 이 삼각형 안에 있는가?"를 판별하기 위한 수학적 준비.


3-2. 삼각형 순회 (Triangle Traversal)

삼각형 내부에 있는 모든 픽셀 후보(Fragment)를 찾아내는 과정.

┌───┬───┬───┬───┐
│ │ ▓ │ ▓ │ │
├───┼───┼───┼───┤
│ ▓ │ ▓ │ ▓ │ ▓ │ ← 삼각형이 덮는 픽셀들 = Fragment 생성
├───┼───┼───┼───┤
│ │ ▓ │ ▓ │ │
└───┴───┴───┴───┘

각 Fragment에는 보간된 값이 포함됨:

  • 깊이값(Z)
  • 텍스처 UV
  • 노말
  • 색상

3-3. 픽셀 셰이딩 (Pixel/Fragment Shading)

각 Fragment마다 최종 색상 계산.
개발자가 HLSL로 직접 작성하는 Fragment Shader가 여기서 실행.

텍스처 샘플링 + 조명 계산 + 그림자 + 반사 + ...
→ 최종 RGBA 색상 결정


3-4. 합성 (Merging / Output Merger)

픽셀 셰이더 결과를 실제 프레임버퍼에 합치는 과정.
여러 테스트가 순서대로 수행됨.

① Z-Buffer 테스트 (깊이 테스트)

이 픽셀의 깊이 vs 현재 버퍼에 저장된 깊이
더 앞에 있으면 → 덮어쓰기
더 뒤에 있으면 → 버리기

② 스텐실 테스트 (Stencil Test)

스텐실 버퍼의 값 조건을 만족하는 픽셀만 통과
마스킹, 포탈, 실루엣 효과 등에 활용

③ 알파 블렌딩 (Alpha Blending)

반투명 오브젝트: 기존 픽셀 색상과 새 픽셀 색상을 알파값으로 혼합
Source SrcAlpha + Destination (1 - SrcAlpha)

Early-Z: 원래 Z테스트는 픽셀 셰이더 이후지만,
최적화를 위해 픽셀 셰이더 이전에 미리 깊이 테스트를 하는 것.
Alpha Test(discard)를 쓰면 "픽셀이 살아남을지 모르니" Early-Z 불가.


전체 데이터 흐름 요약

[애플리케이션]
씬 데이터 → Culling → 렌더 상태 설정 → Draw Call
↓
[지오메트리] 정점 스트림 입력
오브젝트공간 → 월드공간 → 뷰공간 → 투영 → 클리핑 → 화면공간
↓
[래스터라이저] 삼각형 + 정점 데이터
삼각형 설정 → 순회 → Fragment 생성 → 픽셀 셰이딩 → 합성 → 프레임버퍼

*추가설명

렌더 패스란

오해하기 쉬운 부분인데, 렌더 패스와 렌더링 파이프라인은 다른 레벨의 개념


관계 정리

렌더 패스 (Render Pass)
└── 각 패스마다 파이프라인 전체를 한 번씩 돌림

즉, 파이프라인이 렌더 패스 "안에" 들어가는 구조


비유

공장 생산라인(파이프라인)
제품을 여러 번 라인에 올리는 것 = 렌더 패스

  • 1회차: 밑칠만 하기 (Shadow Pass)
  • 2회차: 색 입히기 (Opaque Pass)
  • 3회차: 마감 처리 (Post Processing)

라인 자체의 구조(애플리케이션→지오메트리→래스터라이저)는 매번 동일


실제 URP 흐름

Shadow Pass
└── [파이프라인 전체 실행] → Shadow Map 텍스처 생성

Depth Prepass
└── [파이프라인 전체 실행] → Depth Buffer 생성

Opaque Pass
└── [파이프라인 전체 실행] → 불투명 오브젝트들 렌더링

Transparent Pass
└── [파이프라인 전체 실행] → 반투명 오브젝트 렌더링

Post Processing Pass
└── [파이프라인 전체 실행] → 화면 전체에 효과 적용

각 패스의 출력(텍스처, 버퍼)이 다음 패스의 입력으로 들어가는 구조예요.


한 줄 요약

파이프라인 = 정점 하나를 픽셀로 만드는 과정
렌더 패스 = 그 과정을 "무슨 목적으로, 몇 번" 돌릴지 결정하는 단위

Unity 렌더링에서 사용되는 버퍼 종류


Color Buffer

최종적으로 화면에 출력될 색상(RGBA)을 저장

각 픽셀의 R, G, B, A 값 저장
프레임버퍼라고도 불림
렌더링 결과가 여기에 쌓임

더블 버퍼링으로 운영됨:

Front Buffer → 현재 화면에 표시 중
Back Buffer → 다음 프레임 렌더링 중


Depth Buffer (Z-Buffer)

각 픽셀의 깊이값(카메라로부터의 거리)을 저장

0.0 = Near Plane (카메라 바로 앞)
1.0 = Far Plane (가장 멀리)

용도:

앞 오브젝트가 뒤 오브젝트를 가리는 판정
Early-Z 최적화의 기반
SSAO, DOF 등 Post Processing의 입력값


Stencil Buffer

픽셀마다 정수값(0~255)을 저장하는 마스크

Depth Buffer와 같은 메모리에 저장됨 (D24S8 포맷 — 깊이 24bit + 스텐실 8bit)

용도:

특정 영역만 렌더링 → 포탈, 거울 반사
실루엣 외곽선 → 값이 1인 픽셀 테두리만 그리기
마스킹 효과


G-Buffer (Deferred Rendering 전용)

Deferred Rendering에서 사용. 조명 계산에 필요한 정보를 여러 텍스처에 나눠 저장

G-Buffer 0 → Albedo (기본 색상)
G-Buffer 1 → Normal (노말 벡터)
G-Buffer 2 → Specular / Metallic / Roughness
G-Buffer 3 → Emission

  • Depth Buffer

Geometry Pass → G-Buffer 채우기
↓
Lighting Pass → G-Buffer 읽어서 조명 계산

Forward Rendering은 G-Buffer 없이 한 번에 처리.


Shadow Map Buffer

광원 시점에서 렌더링한 깊이값 저장

Shadow Pass에서 생성
Opaque Pass에서 읽어서
"이 픽셀이 그림자 안에 있나?" 판정에 사용


Frame Buffer (종합)

위 버퍼들을 묶어서 부르는 개념:

Frame Buffer
├── Color Buffer
├── Depth Buffer
└── Stencil Buffer

Unity에서 RenderTexture = 커스텀 Frame Buffer라고 볼 수 있어요.


버퍼들의 관계 흐름

Shadow Pass → Shadow Map Buffer 생성
Depth Prepass → Depth Buffer 채우기
Geometry Pass → G-Buffer 채우기 (Deferred만)
Opaque Pass → Color Buffer에 쓰기
Depth/Stencil Buffer로 판정
Post Processing → Color/Depth Buffer 읽어서 효과 적용
↓
Front Buffer로 스왑 → 화면 출력

profile
VFX Artist in Korea

0개의 댓글