본문 바로가기

렌더링 파이프라인

@iamrain2026. 1. 8. 18:11

1. 렌더링 파이프라인

렌더링 파이프라인은 3D 장면을 2D 이미지로 변환하여 화면에 표시하는 일련의 과정을 의미합니다. 렌더링 파이프라인을 이해하는 것은 성능 최적화, 시각적 품질 향상, 그리고 디버깅에 필수적입니다. 이 과정은 크게 애플리케이션 단계, 지오메트리 단계, 래스터화 단계로 나눌 수 있습니다.

1.1. 애플리케이션 단계 (Application Stage)

이 단계는 CPU에서 주로 처리되며, 게임 로직, 물리 시뮬레이션, 애니메이션, 그리고 렌더링을 위한 데이터 준비를 담당합니다.

  • 장면 관리 (Scene Management): 렌더링할 오브젝트들을 관리하고, 컬링(Culling)을 통해 화면에 보이지 않는 오브젝트를 미리 걸러냅니다.
    • 프러스텀 컬링 (Frustum Culling): 카메라의 시야(Frustum) 밖에 있는 오브젝트를 제외합니다.
    • 오클루전 컬링 (Occlusion Culling): 다른 오브젝트에 가려져 보이지 않는 오브젝트를 제외합니다.
    • LOD (Level of Detail): 카메라와의 거리에 따라 오브젝트의 디테일 수준을 조절하여 불필요한 연산을 줄입니다.
  • 애니메이션 (Animation): 캐릭터 및 오브젝트의 움직임을 계산하고 적용합니다. 스키닝(Skinning)을 통해 메시(Mesh)에 골격 애니메이션을 적용합니다.
  • 물리 시뮬레이션 (Physics Simulation): 오브젝트 간의 충돌, 중력 등의 물리적 상호작용을 계산합니다.
  • 렌더링 데이터 준비 (Prepare Render Data): 렌더링에 필요한 정점(Vertex) 데이터, 인덱스(Index) 데이터, 텍스처, 셰이더 등을 GPU로 전송할 준비를 합니다. 이 과정에서 드로우 콜(Draw Call)이 발생합니다. 드로우 콜은 CPU가 GPU에게 렌더링 명령을 내리는 것을 의미하며, 드로우 콜 수가 많아지면 CPU 오버헤드가 증가하여 성능 저하의 원인이 될 수 있습니다.

1.2. 지오메트리 단계 (Geometry Stage)

이 단계는 GPU에서 주로 처리되며, 3D 오브젝트의 정점들을 처리하고 화면에 그릴 준비를 합니다.

  • 정점 셰이더 (Vertex Shader): 각 정점의 위치, 색상, 노멀(Normal) 등의 속성을 변환합니다. 주로 모델-뷰-프로젝션(MVP) 행렬을 사용하여 3D 공간의 정점을 2D 화면 공간으로 투영하는 역할을 합니다.
  • 테셀레이션 단계 (Tessellation Stage - 선택 사항): 메시의 디테일을 동적으로 생성하거나 감소시킵니다. 주로 곡면을 부드럽게 표현하거나 LOD를 구현하는 데 사용됩니다.
    • 헐 셰이더 (Hull Shader): 테셀레이션 인자를 결정합니다.
    • 테셀레이터 (Tessellator): 헐 셰이더에서 결정된 인자를 바탕으로 새로운 정점을 생성합니다.
    • 도메인 셰이더 (Domain Shader): 새로 생성된 정점들의 위치를 계산합니다.
  • 지오메트리 셰이더 (Geometry Shader - 선택 사항): 정점, 선, 삼각형과 같은 기본 도형(Primitive)을 입력받아 새로운 기본 도형을 생성하거나 삭제할 수 있습니다. 파티클 시스템이나 동적인 메시 생성에 활용될 수 있습니다.
  • 클리핑 (Clipping): 카메라 시야(Frustum) 밖에 있는 기본 도형의 일부 또는 전체를 잘라냅니다.
  • 스크린 공간 변환 (Screen-Space Transformation): 클리핑된 기본 도형의 정점들을 최종적으로 화면의 픽셀 좌표계로 변환합니다.

1.3. 래스터화 단계 (Rasterization Stage)

이 단계는 GPU에서 주로 처리되며, 3D 기본 도형을 2D 픽셀로 변환하고 각 픽셀의 최종 색상을 결정합니다.

  • 래스터라이저 (Rasterizer): 스크린 공간으로 변환된 기본 도형(삼각형)을 구성하는 픽셀들을 식별합니다. 이 과정에서 각 픽셀의 깊이(Z-depth), 텍스처 좌표, 노멀 등의 보간된(Interpolated) 속성들이 생성됩니다.
  • 프래그먼트 셰이더 (Fragment Shader) / 픽셀 셰이더 (Pixel Shader): 래스터라이저에서 생성된 각 프래그먼트(픽셀 후보)에 대해 최종 색상을 계산합니다. 텍스처 샘플링, 조명 계산, 그림자 처리, 안개 효과 등 대부분의 시각적 효과가 이 단계에서 이루어집니다.
  • 깊이 및 스텐실 테스트 (Depth and Stencil Test): 각 픽셀이 화면에 그려질지 여부를 결정합니다.
    • 깊이 테스트 (Depth Test): 현재 픽셀의 깊이 값이 이전에 그려진 픽셀의 깊이 값보다 가까우면 통과하고, 그렇지 않으면 버려집니다. 이를 통해 올바른 원근감을 표현합니다.
    • 스텐실 테스트 (Stencil Test): 특정 영역만 렌더링하거나, 거울 효과, 아웃라인 효과 등 특수 효과를 구현하는 데 사용됩니다.
  • 블렌딩 (Blending): 현재 픽셀의 색상과 이미 프레임 버퍼에 있는 픽셀의 색상을 혼합합니다. 투명한 오브젝트를 렌더링할 때 사용됩니다.
  • 프레임 버퍼 (Frame Buffer): 최종적으로 렌더링된 픽셀 색상 정보가 저장되는 메모리 영역입니다. 이 버퍼의 내용이 화면에 표시됩니다.

2. 요약

렌더링 파이프라인은 3D 모델을 2D 화면에 그리기 위한 일련의 과정으로, 크게 CPU가 담당하는 애플리케이션 단계와 GPU가 담당하는 지오메트리 및 래스터화 단계로 나뉩니다. 애플리케이션 단계에서는 게임 로직을 처리하고 렌더링할 데이터를 준비하며, 특히 화면에 보이지 않는 오브젝트를 걸러내는 컬링과 GPU에 렌더링 명령을 내리는 드로우 콜 관리가 중요합니다. 지오메트리 단계에서는 정점 셰이더를 통해 3D 정점의 위치를 변환하고, 필요에 따라 테셀레이션이나 지오메트리 셰이더로 메시를 조작하며, 최종적으로 화면 공간으로 변환합니다. 마지막 래스터화 단계에서는 변환된 도형을 픽셀로 만들고, 프래그먼트 셰이더에서 각 픽셀의 최종 색상을 계산한 후, 깊이/스텐실 테스트와 블렌딩을 거쳐 프레임 버퍼에 저장하여 화면에 출력합니다.

3. 꼬리 질문 및 답변

3.1. 드로우 콜(Draw Call)이 게임 성능에 미치는 영향은 무엇이며, 이를 최적화하는 방법은 무엇인가요?

답변: 드로우 콜은 CPU가 GPU에게 렌더링 명령을 내리는 행위입니다. 드로우 콜 자체는 가볍지만, 각 드로우 콜마다 CPU와 GPU 간의 상태 전환(State Change) 및 데이터 전송 오버헤드가 발생합니다. 드로우 콜 수가 너무 많아지면 CPU가 GPU에게 명령을 내리는 데 시간을 너무 많이 소모하게 되어 CPU 바운드(CPU-bound) 현상이 발생하고, 이는 전체 프레임 레이트 저하로 이어집니다.

최적화 방법:

  • 배치(Batching): 동일한 재질(Material)이나 셰이더를 사용하는 오브젝트들을 하나로 묶어 하나의 드로우 콜로 처리합니다. 정적 배치(Static Batching)와 동적 배치(Dynamic Batching)가 있습니다.
  • 인스턴싱(Instancing): 동일한 메시를 여러 번 그릴 때, 각 인스턴스마다 다른 변환(위치, 회전, 크기) 정보만 GPU에 전달하여 하나의 드로우 콜로 여러 오브젝트를 렌더링합니다.
  • 어트라스(Atlas) 텍스처: 여러 작은 텍스처들을 하나의 큰 텍스처로 합쳐 재질 공유를 용이하게 하여 배치 효율을 높입니다.
  • 컬링(Culling): 프러스텀 컬링, 오클루전 컬링 등을 통해 화면에 보이지 않는 오브젝트는 드로우 콜에서 제외하여 불필요한 렌더링을 줄입니다.

3.2. 셰이더(Shader)는 렌더링 파이프라인에서 어떤 역할을 하며, 정점 셰이더와 프래그먼트 셰이더의 주요 차이점은 무엇인가요?

답변: 셰이더는 GPU에서 실행되는 작은 프로그램으로, 렌더링 파이프라인의 특정 단계에서 그래픽 데이터를 처리하고 변환하는 역할을 합니다. 셰이더를 통해 개발자는 렌더링 과정을 프로그래밍하여 다양한 시각적 효과를 구현할 수 있습니다.

  • 정점 셰이더 (Vertex Shader):
    • 역할: 3D 모델의 각 정점(Vertex) 데이터를 처리합니다. 주로 정점의 위치를 3D 공간에서 2D 화면 공간으로 변환하고, 정점의 색상, 노멀, 텍스처 좌표 등의 속성을 조작합니다.
    • 입력: 단일 정점의 속성(위치, 색상, 노멀, 텍스처 좌표 등).
    • 출력: 변환된 정점의 위치 및 다음 단계로 전달될 정점 속성.
    • 주요 사용처: 모델 변환, 스키닝 애니메이션, 지형 변형 등.
  • 프래그먼트 셰이더 (Fragment Shader) / 픽셀 셰이더 (Pixel Shader):
    • 역할: 래스터화 단계에서 생성된 각 프래그먼트(픽셀 후보)에 대해 최종 색상을 계산합니다. 이 단계에서 텍스처 샘플링, 조명 계산, 그림자, 반사, 굴절 등 대부분의 시각적 효과가 적용됩니다.
    • 입력: 래스터라이저에 의해 보간된 프래그먼트의 속성(위치, 색상, 노멀, 텍스처 좌표 등).
    • 출력: 최종적으로 화면에 그려질 픽셀의 색상.
    • 주요 사용처: 텍스처 매핑, 조명 모델(Phong, PBR 등), 그림자 매핑, 후처리 효과 등.

주요 차이점: 정점 셰이더는 '정점' 단위로 작동하여 3D 기하학적 데이터를 변환하는 반면, 프래그먼트 셰이더는 '픽셀 후보' 단위로 작동하여 각 픽셀의 최종 '색상'을 결정합니다. 정점 셰이더는 기하학적 변환에, 프래그먼트 셰이더는 시각적 효과 및 색상 계산에 중점을 둡니다.

3.3. 깊이 버퍼(Depth Buffer)와 스텐실 버퍼(Stencil Buffer)는 각각 어떤 목적으로 사용되며, 렌더링 파이프라인에서 어떤 단계에 관여하나요?

답변: 깊이 버퍼와 스텐실 버퍼는 래스터화 단계의 깊이 및 스텐실 테스트에서 사용되어 올바른 렌더링 순서와 특수 효과를 구현하는 데 기여합니다.

  • 깊이 버퍼 (Depth Buffer / Z-Buffer):
    • 목적: 3D 공간에서 오브젝트들의 원근감을 올바르게 표현하기 위해 사용됩니다. 각 픽셀의 깊이(카메라로부터의 거리) 정보를 저장합니다.
    • 관여 단계: 래스터화 단계의 깊이 테스트(Depth Test)에서 사용됩니다. 새로운 픽셀을 그릴 때, 해당 픽셀의 깊이 값이 깊이 버퍼에 저장된 값보다 작으면(더 가까우면) 픽셀이 그려지고 깊이 버퍼가 업데이트됩니다. 그렇지 않으면 픽셀은 버려집니다. 이를 통해 멀리 있는 오브젝트가 가까이 있는 오브젝트에 의해 가려지는 현상을 처리합니다.
  • 스텐실 버퍼 (Stencil Buffer):
    • 목적: 렌더링할 영역을 제한하거나, 특정 픽셀에 대한 렌더링 조건을 설정하여 다양한 특수 효과를 구현하는 데 사용됩니다. 각 픽셀에 대해 8비트 또는 16비트의 정수 값을 저장합니다.
    • 관여 단계: 래스터화 단계의 스텐실 테스트(Stencil Test)에서 사용됩니다. 스텐실 버퍼의 값과 설정된 참조 값, 마스크를 비교하여 픽셀이 그려질지 여부를 결정합니다.
    • 주요 사용처: 거울 효과, 포털, 아웃라인 효과, 그림자 볼륨, UI 마스킹 등.

두 버퍼 모두 픽셀 단위로 작동하며, 프래그먼트 셰이더가 실행된 후 블렌딩이 일어나기 전에 테스트가 수행되어 최종적으로 프레임 버퍼에 기록될 픽셀을 결정하는 데 중요한 역할을 합니다.

'Computer Science' 카테고리의 다른 글

MMU (Memory Management Unit)  (0) 2026.01.16
커널 (Kernel)  (0) 2026.01.15
페이지(Page)와 프레임(Frame)의 차이  (0) 2026.01.07
다익스트라 (Dijkstra) 알고리즘  (1) 2025.12.22
고아 프로세스와 좀비 프로세스  (0) 2025.12.11
iamrain
@iamrain :: Annals of Unreal

iamrain 님의 블로그 입니다.

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차