언리얼 엔진의 렌더링

게임 엔진의 렌더링 소개
렌더링은 씬의 오브젝트 컬렉션에서 화면에 최종 이미지(프레임)를 생성하는 프로세스를 가리킵니다.
렌더링에 사용되는 소프트웨어는 렌더 엔진(render engine) 이라고 하며, 일반적으로 다음과 같이 분류됩니다.
-
오프라인 렌더링: 처리 시간보다 퀄리티를 우선시하는 고퀄리티 렌더링을 위해 디자인되었습니다. 보통 렌더링 시간보다 최종적으로 렌더링된 프레임의 퀄리티가 더 중요한 애플리케이션에서 사용됩니다.
-
리얼타임 렌더링: 퍼포먼스를 염두에 두고 프레임을 빠르게 렌더링하도록 디자인되었습니다. 일반적인 리얼타임 프레임 레이트 타깃은 초당 30프레임(33ms), 60프레임(16ms), 120프레임(8ms)이지만 실제 프레임 레이트는 인수의 수에 따라 시간별로 달라질 수 있습니다. 리얼타임 렌더링으로 개발된 프로젝트는 일정한 프레임 레이트를 유지하기 위해 퍼포먼스와 퀄리티 사이에서 균형을 이뤄야 합니다. 리얼타임 렌더링 엔진은 보통 비디오 게임, 시뮬레이션, 건축 시각화 등 인터랙티브 미디어에 사용됩니다.
언리얼 엔진 은 리얼타임 렌더링을 위해 디자인된 강력한 툴세트로, 모바일부터 강력한 데스크톱 컴퓨터까지 다양한 플랫폼 요구 사항을 충족합니다. 언리얼 엔진은 고퀄리티 렌더링과 오프라인 렌더링을 모두 지원합니다. 모바일, 콘솔 및 데스크톱 플랫폼의 인터랙티브 2D 및 3D 경험부터 영화 및 TV 프로덕션을 위한 최종 프레임 렌더링까지 콘텐츠 종류에 상관없이 언리얼 엔진을 활용할 수 있습니다.
시중의 여타 리얼타임 엔진과 달리, 언리얼 엔진은 리얼타임과 퍼포먼스를 모두 고려하여 디자인된 다양한 독점적인 기능을 갖추고 있습니다. 목표는 개발에서 복잡성을 최소화하고 결과를 빠르게 제공하는 동시에 높은 퀄리티와 퍼포먼스를 유지하는 것입니다.
루멘 글로벌 일루미네이션 및 리플렉션 시스템, 나나이트 가상화된 지오메트리, 버추얼 섀도 맵 등의 기능은 콘솔 및 데스크톱 애플리케이션에서 원활하게 작동하는 기능을 개발하는 과정에서 복잡성을 최소화해야 한다는 목표를 달성하는 데 중요한 역할을 합니다. 모바일 플랫폼은 다이내믹 라이팅과 라이팅을 텍스처에 베이킹해야 하는 프리컴퓨티드 라이팅 워크플로를 지원합니다.
언리얼 엔진의 렌더링 소개
게임 엔진은 일반적으로 렌더링 파이프라인(Rendering Pipeline) 이라고 하는 일련의 단계를 수행하여 이미지 또는 프레임을 화면에 렌더링합니다. 이 섹션에서는 언리얼 엔진이 디폴트 디퍼드 렌더링 패스를 활용하여 이를 수행하는 방법을 살펴보고, Unity의 디퍼드 렌더링 패스와 어떤 점에서 차이가 있는지 알아봅니다.
Unity에서는 내장(Built-In), 유니버설(Universal), 고해상도(High Definition)라는 세 가지 렌더 파이프라인을 제공합니다. 각 파이프라인은 특정 사용 사례를 위해 디자인되었으며, 보통은 새 프로젝트를 시작하기 전에 선택합니다.
언리얼 엔진에서는 핸드헬드부터 모바일 디바이스, 현세대 콘솔 및 PC에 이르기까지 타깃 플랫폼을 기반으로 개별 기능이 스케일 조절되는 통합 렌더링 파이프라인 을 제공합니다. 따라서 단일 패스에 얽매이지 않고 프로젝트에 가장 적합한 렌더링 패스와 지원 기능을 선택할 수 있습니다.
언리얼 엔진의 렌더 파이프라인은 디폴트 디퍼드 렌더링(deferred rendering) 패스와 함께 사용하거나 포워드 렌더링(forward rendering) 패스에서 실행하도록 환경설정할 수 있습니다. 또한 Vulkan 모바일 렌더러 같은 모바일 렌더링 패스를 활성화하여 저사양의 디바이스를 지원할 수도 있습니다. 각 렌더링 패스별로 지원되는 렌더링 기능에 대해서는 렌더링 패스별로 지원하는 기능 문서에서 자세히 살펴볼 수 있습니다.
아래 이미지는 언리얼 엔진이 디퍼드 렌더링 패스를 활용한 최종 이미지 렌더링을 위해 각 프레임마다 수행하는 단계를 간단하게 시각화한 것입니다.

이 프로세스는 왼쪽에서 오른쪽으로 진행되며, 2단계와 5단계는 동시에 이뤄집니다.
아래에서는 렌더링 파이프라인의 각 단계와 프레임 렌더링에 필요한 요소에 대해 보다 자세하게 살펴봅니다.
씬 준비 및 오클루전

언리얼 엔진은 게임(CPU), 드로, GPU라는 세 가지 기본 스레드를 갖추고 있습니다.
게임(CPU) 스레드는 렌더링 프로세스를 시작하기 전에 씬에 있는 모든 오브젝트의 트랜스폼을 수집합니다. 여기에는 각 오브젝트의 최종 트랜스폼 수집 전의 모든 애니메이션, 피직스 시뮬레이션 및 인공 지능(Artificial Intelligence, AI) 프로세스가 포함됩니다.
그런 다음 트랜스폼 정보가 CPU의 드로 스레드에 전달됩니다. 드로 스레드는 현재 카메라 뷰에서 표시되는 오브젝트의 목록을 빌드하고, 카메라에서 표시되지 않는 나머지 오브젝트를 모두 제거하는 컬링 프로세스를 실행합니다. 표시되지 않는 오브젝트는 드로할 필요가 없으므로 이를 렌더링하지 않으면 퍼포먼스가 향상됩니다.
이 프로세스는 다음 단계를 순서대로 수행합니다.
- 디스턴스 컬링(Distance Culling): 카메라에서 일정 거리 이상 떨어져 있는 오브젝트를 모두 제거합니다.
- 프러스텀 컬링(Frustum Culling): 카메라의 프러스텀(뷰) 안에서 표시되지 않는 오브젝트를 제거합니다.
- 오클루전 컬링(Occlusion Culling): 씬에 있는 나머지 모든 오브젝트의 비저빌리티 상태를 정확하게 확인합니다. 이 방법은 비용이 높기 때문에 눈에 보이는 나머지 오브젝트들이 다른 오브젝트에 의해 가려지지 않는지 추가로 확인되는 오클루전 프로세스의 마지막에 이뤄집니다.
최종 표시 오브젝트 목록이 GPU 스레드 로 전달되어 렌더링 프로세스가 시작됩니다.
Unity의 해당 항목
Unity는 렌더링 파이프라인 동안 프러스텀 및 오클루전 컬링 을 수행합니다. 또한 CullingGroup API를 사용하여 디스턴스 컬링을 수행합니다. 이러한 기법을 조합하여 씬의 최종 표시 오브젝트 목록을 생성합니다.
지오메트리 렌더링

이 단계에서 언리얼 엔진은 씬에 포함된 표시 오브젝트 목록을 처리하고 3D 버텍스 데이터를 화면에 표시되는 픽셀 데이터로 변환하는 다음 단계를 준비합니다.
버텍스 셰이더
셰이더는 GPU에서 직접 실행되는 코드로, 계산 세트를 수행하는 데 사용됩니다. 효율성이 뛰어날 뿐 아니라 GPU가 여러 셰이더 계산을 병렬로 실행할 수 있게 해줍니다.
버텍스 셰이더는 다음 단계를 수행합니다.
- 로컬 버텍스 위치를 월드 위치로 변환: 오브젝트 버텍스 데이터는 로컬 스페이스에 저장되지만, 오브젝트가 월드에 배치되면 버텍스 정보를 월드 스페이스 좌표로 변환해야 합니다.
- 버텍스 셰이딩 및 컬러링 처리: 버텍스 셰이더는 버텍스 스무딩과 오브젝트 자체의 버텍스 컬러 데이터도 처리합니다.
- 버텍스 위치에 추가 오프셋 적용: 버텍스 셰이더는 화면에서 버텍스 위치를 오프셋하여 특정 이펙트를 달성할 수 있습니다. 이는 오브젝트의 머티리얼을 통해 이뤄지며, 월드 포지션 오프셋이라고 부릅니다.
뎁스 패스
개별 오브젝트를 렌더링하기 전에 언리얼 엔진은 뎁스 패스(depth pass), 즉 초기 Z 패스를 수행하여 오브젝트의 상대적 위치를 판정합니다. 이를 통해 언리얼 엔진은 화면에서 동일한 픽셀을 여러 번 렌더링하지 않게 됩니다. 동일한 픽셀을 여러 번 렌더링하는 것을 오버드로(overdraw) 라고 하며, 퍼포먼스에 막대한 영향을 미칠 수 있습니다. 언리얼 엔진은 가능한 한 오버드로를 방지하려고 시도합니다.
드로 콜
뎁스 패스 이후 GPU는 메시, 머티리얼 등 동일한 프로퍼티를 공유하는 모든 폴리곤을 동시에 드로하여 각 오브젝트를 렌더링합니다. 이를 드로 콜(drawcall) 이라고 합니다.
동일한 머티리얼에 할당된 모든 오브젝트의 폴리곤은 동일한 드로 콜로 취급됩니다. 하지만 각 고유 머티리얼에는 별도의 드로 콜이 필요합니다. 예를 들어 화면의 각 오브젝트에는 최소 1개 드로 콜이 필요하지만, 오브젝트에 할당된 머티리얼 수에 따라 더 많은 드로 콜이 이뤄질 수도 있습니다.
언리얼 엔진의 나나이트 가상화된 지오메트리는 지정된 머티리얼이 있는 모든 오브젝트의 모든 폴리곤을 동시에 렌더링합니다. 따라서 프레임 예산이 폴리곤 수, 드로 콜 및 메시 메모리 사용량에 의해 제한을 받지 않게 됩니다.
Unity의 해당 항목
Unity의 렌더링 파이프라인은 뎁스 패스를 수행하고 드로 콜을 사용하여 씬의 오브젝트를 드로하는 등 유사한 단계를 수행합니다.
래스터화 및 지오메트리 버퍼

래스터화 프로세스(rasterization process) 는 3D 버텍스 데이터를 화면에 표시되는 2D 픽셀 데이터로 변환합니다. 이 프로세스는 버텍스 셰이더가 모든 데이터를 처리한 뒤에 시작됩니다.
언리얼 엔진의 지오메트리 버퍼(Geometry Buffer, GBuffer) 에는 씬의 지오메트리 관련 정보를 저장하는 일련의 이미지가 포함됩니다. 이 이미지에는 일반적으로 씬의 베이스 컬러, 월드 노멀, 메탈릭, 러프니스 및 스페큘러 를 위한 라이팅 정보가 포함됩니다. GBuffer의 이러한 이미지가 합성되어 화면에 표시되는 최종 이미지를 구성합니다.
이러한 합성된 이미지를 변환하는 과정은 렌더링되는 프레임마다 버텍스 데이터가 픽셀 데이터로 변환되고 적합한 이미지 부분을 GBuffer에 드로하는 드로 콜마다 발생합니다.
Unity의 해당 항목
Unity의 디퍼드 렌더링 패스 또한 GBuffer를 사용하여 씬과 관련된 중요한 정보를 저장합니다. Unity의 경우, GBuffer는 오브젝트의 알베도, 스페큘러, 노멀, 이미시브/라이팅 정보 등 언리얼 엔진과 유사하지만 다른 이름으로 불리는 씬 관련 정보를 저장합니다.
텍스처 렌더링

언리얼 엔진은 텍스처 스트리밍을 사용하여 텍스처를 렌더링함으로써 씬에서의 텍스처 로딩을 최적화합니다. 텍스처 스트리밍 시스템은 텍스처 밉맵(mipmap) 을 사용합니다. 이는 동일한 텍스처 이미지 시퀀스를 다른 해상도로 사전 계산한 것입니다. 메시가 아닌 텍스처를 위한 레벨 오브 디테일(Level of Detail, LOD) 이라고 할 수 있습니다. 언리얼 엔진은 각 이미지가 이전 단계의 절반 해상도인 밉맵을 자동으로 생성합니다.
언리얼 엔진은 카메라와의 거리에 따라 게임플레이 동안 텍스처의 밉맵을 스트리밍합니다. 이는 대역폭 및 메모리 소비를 최적화하고 카메라에서 멀어질수록 노이즈를 줄이기 위해 자동으로 수행됩니다.
밉맵을 수신하려면 텍스처 크기가 2의 제곱이어야 합니다. 일반적인 텍스처 크기는 3840 x 2160 픽셀(4K) 및 1920 x 1080 픽셀(HD)입니다. 텍스처가 특정 비율일 필요는 없으며, 1920 x 480 픽셀 텍스처도 밉맵을 수신합니다.
Unity의 해당 항목
Unity의 밉맵 스트리밍 시스템은 텍스처 밉맵을 사용하여 런타임에서 텍스처를 스트리밍합니다. 언리얼 엔진과 유사하게 이 시스템은 카메라와의 거리 및 각도에 따라 적절한 텍스처 밉맵을 자동으로 스트리밍합니다.
픽셀 셰이더 및 머티리얼

오브젝트가 GBuffer에서 완전히 렌더링되면 언리얼 엔진은 각 오브젝트의 머티리얼 프로퍼티를 사용하여 픽셀 셰이더로 화면에서 각 오브젝트의 셰이딩을 시작합니다.
픽셀 셰이더(pixel shader) 는 화면에서 픽셀의 컬러를 수정하는 일련의 계산을 수행합니다. 픽셀 셰이더는 GPU에서 실행되며, 매우 뛰어난 효율성을 제공합니다. 언리얼 엔진의 머티리얼 시스템을 제어하는 픽셀 셰이더는 라이팅, 포그, 리플렉션 및 포스트 프로세스 이펙트를 계산하는 데 사용됩니다.
머티리얼 시스템은 하이 레벨 셰이더 언어(High-Level Shader Language, HLSL) 셰이더 템플릿을 머티리얼 에디터와 함께 사용하여 화면의 오브젝트에 적용되는 최종 머티리얼을 생성합니다. 이러한 머티리얼은 텍스처처럼 파라미터를 사용하여 각 오브젝트의 외형을 정의할 수 있습니다.
Unity의 해당 항목
Unity에서는 언리얼 엔진의 머티리얼에 해당하는 사전 빌드된 셰이더 몇 가지와 프로젝트 셰이더를 제작하기 위한 셰이더 그래프(Shader Graph) 를 제공합니다. 언리얼 엔진의 머티리얼 에디터가 Unity의 셰이더 그래프에 해당합니다.
리플렉션

언리얼 엔진은 씬에 포함된 모든 오브젝트를 셰이딩한 다음 오브젝트의 머티리얼 프로퍼티를 기반으로 오브젝트의 리플렉션 렌더링을 시작합니다.
언리얼 엔진은 네 가지 시스템을 사용하여 리플렉션을 씬에 렌더링합니다. 이러한 시스템은 다음 순서로 실행됩니다.
- 리플렉션 캡처: 사전 계산되며, 특정 위치의 스태틱 큐브맵에 저장됩니다.
- 플레이너 리플렉션: 평면 리플렉션을 캡처합니다.
- 스크린 스페이스 리플렉션(Screen Space Reflection, SSR): 사용 가능한 화면 정보를 사용하여 실시간으로 정확한 오브젝트 리플렉션을 드로합니다.
- 루멘 리플렉션: 씬에서 전체 러프니스 값 범위에 대한 리플렉션을 솔브합니다. 이 리플렉션에는 스카이라이트, 클리어 코트 머티리얼 및 반투명, 단일 레이어 워터 머티리얼에 대한 지원이 포함됩니다.
언리얼 엔진은 이 세 가지 방법을 조합하여 활용합니다. 스크린 스페이스 리플렉션을 우선시하며, 그다음 플레이너 리플렉션으로 전환되고, 마지막으로 리플렉션 캡처로 전환됩니다. 최종 리플렉션 결과는 GBuffer에서 러프니스, 스페큘러 및 메탈릭 이미지와 결합됩니다.
루멘 글로벌 일루미네이션을 사용하는 경우, 루멘 리플렉션이 자동으로 사용됩니다. 하지만 루멘 GI 없이도 루멘 리플렉션을 사용할 수 있습니다. 이 경우, 언리얼 엔진은 베이킹된 라이팅을 루멘 리플렉션과 함께 사용합니다.
Unity의 해당 항목
Unity의 리플렉션 프로브(Reflection Probe) 가 유사한 기능을 제공하며, 씬의 리플렉션 데이터를 사전 계산하는 데 사용됩니다.
스태틱 라이팅 및 섀도

언리얼 엔진은 리플렉션이 렌더링된 이후 씬에 있는 모든 오브젝트에 대해 스태틱 라이팅 및 섀도를 렌더링합니다.
언리얼 엔진은 라이트매스 글로벌 일루미네이션 시스템을 사용하여 씬의 라이팅 정보를 사전 계산합니다. 라이팅 및 섀도 정보는 라이트맵 UV 텍스처에 저장되며, 이 텍스처는 씬에서 오브젝트를 렌더링할 때 오브젝트의 베이스 컬러와 블렌딩됩니다.
이 시스템은 아주 빠르지만 더 많은 메모리를 필요로 하며, 씬에 변경사항이 있을 때마다 사전 계산됩니다.
라이트매스 글로벌 일루미네이션 시스템은 모바일 및 저사양 디바이스를 대상으로 하는 프로젝트에 적합합니다.
Unity의 해당 항목
Unity의 프로그레시브 라이트매퍼(Progressive Lightmapper) 및 인라이튼 베이크드 글로벌 일루미네이션(Enlighten Baked Global Illumination) 시스템이 씬에서 라이팅을 사전 계산할 때 유사한 기능을 제공합니다.
다이내믹 라이팅 및 섀도

언리얼 엔진은 스태틱 라이팅이 렌더링된 다음 다이내믹 글로벌 일루미네이션 시스템인 루멘을 사용하여 다이내믹(리얼타임) 라이팅 및 섀도를 렌더링합니다.
루멘 은 차세대 콘솔 및 고사양 PC를 위해 디자인된 완전한 다이내믹 글로벌 일루미네이션 및 리플렉션 시스템입니다. 이 시스템은 글로벌 일루미네이션 및 리플렉션을 대규모로 처리하기 위해 다양한 레이 트레이싱 메서드를 사용합니다.
루멘은 무제한의 디퓨즈 바운스를 제공하며 나나이트 가상화된 지오메트리와 함께 원활하게 작동합니다. 또한 이 시스템은 버추얼 섀도 맵과 함께 작동하여 고해상도 리얼타임 소프트 섀도를 생성합니다.
루멘은 씬에서 전체 러프니스 값 범위에 대한 리플렉션을 솔브하는 루멘 리플렉션 을 제공합니다. 이 리플렉션에는 스카이라이트, 클리어 코트 머티리얼 및 반투명, 단일 레이어 워터 머티리얼에 대한 지원이 포함됩니다.
루멘을 씬에서 사용하는 경우 스크린 스페이스 리플렉션을 대체합니다.
Unity의 해당 항목
Unity는 인라이튼 리얼타임 글로벌 일루미네이션(Enlighten Realtime Global Illumination) 을 사용하여 씬에서 다이내믹 라이팅을 제공합니다. 이 시스템은 사전 계산된 비저빌리티 정보를 라이트맵과 함께 사용하여 런타임에서 간접광 바운스를 계산하는 리얼타임 글로벌 일루미네이션을 제공합니다.
루멘은 간접광 바운스를 제공하기 위해 사전 계산된 데이터를 필요로 하지 않으므로 이는 루멘과 다릅니다.
포그 및 투명

언리얼 엔진은 다이내믹 라이팅 및 섀도를 렌더링한 다음 포그 및 투명 이펙트를 렌더링합니다.
언리얼 엔진은 카메라로부터의 높이와 거리에 따라 포그 밀도를 렌더링하는 익스포넨셜 하이트 포그 시스템을 사용하여 포그 이펙트 를 렌더링합니다. 또한 이 시스템은 볼류메트릭 포그를 생성할 수 있습니다.
투명 오브젝트는 반투명 머티리얼을 사용하며, 프로세스의 이 단계에서 렌더링됩니다. 디퍼드 렌더링 패스를 사용하는 경우 언리얼 엔진은 GBuffer에서 사용 가능한 정보를 통해 투명을 렌더링합니다. 또는 포워드 렌더링 패스를 사용하도록 머티리얼을 환경설정하여 보다 정확한 투명 이펙트를 생성할 수 있습니다.
Unity의 해당 항목
Unity는 선형(Linear), 익스포넨셜(Exponential) 및 익스포넨셜 스퀘어드(Exponential Squared) 포그를 씬에서 지원합니다.
포스트 프로세스 이펙트

언리얼 엔진은 포그 및 투명이 렌더링된 후 이미지에 추가 이펙트를 적용합니다. 이러한 이펙트는 최종 이미지가 처리된 이후에 적용되므로 포스트 프로세스 이펙트라고 합니다. 이 이펙트는 픽셀 셰이더에 의존하며, GBuffer에서 사용 가능한 정보를 활용합니다.
일반적인 포스트 프로세스 이펙트로는 라이트 블룸, 뎁스 오브 필드, 라이트 섀프트, 톤매핑, 모션 블러 등이 있습니다.
언리얼 엔진은 포스트 프로세스 단계의 일부로 템포럴 슈퍼 해상도(Temporal Super Resolution, TSR)를 적용할 수 있습니다. TSR은 플랫폼에 구애받지 않는 템포럴 업스케일러로, 언리얼 엔진이 고해상도의 4K 이미지를 렌더링하는 데 사용합니다. 비용이 많이 드는 렌더링 계산의 일부를 여러 프레임에 걸쳐 분할하여 적은 비용으로 이미지를 얻습니다.
렌더링 체인에서 템포럴 슈퍼 해상도는 뎁스 오브 필드 이후에 발생하며, 그 이후에 산출되는 모션 블러, 블룸 등은 모두 업스케일됩니다.

이러한 이펙트가 GBuffer에 적용되면 언리얼 엔진은 최종 이미지를 화면에 렌더링합니다.
위에 설명된 단계는 화면에 단일 프레임 을 생성합니다. 이 단계는 게임의 타깃 프레임레이트에 따라 종종 초당 30~60회 반복됩니다.
Unity의 해당 항목
Unity에서는 선택한 렌더 파이프라인에 기반하여 포스트 프로세스 솔루션을 제공합니다. 사용 가능한 이펙트 대부분은 언리얼 엔진에서 사용할 수 있는 것과 유사합니다.
또한 Unity 6에는 스페이셜 및 템포럴 업샘플링 기법을 사용하여 안티 에일리어싱된 고퀄리티 이미지를 생성하는 네이티브 소프트웨어 기반 스케일러인 스페이셜-템포럴 포스트 프로세싱(Spatial-Temporal Post-processing, STP) 이 포함되어 있습니다.
언리얼 엔진의 렌더링 기능 개요
이제 언리얼 엔진이 프레임을 화면에 렌더링하는 단계를 알아봤으므로, 언리얼 엔진에 포함된 렌더링 기능을 보다 구체적으로 배워볼 차례입니다.
인바이런먼트 라이팅 문서에서 언리얼 엔진의 렌더링 기능에 대해 자세히 알아보세요.