실시간 조명 및 사전 계산 조명
베이크 조명과 실시간 조명의 유연성·품질·런타임 비용을 비교하고 프로젝트 변화량에 맞는 하이브리드 전략을 선택합니다.
조명을 디버깅하는 방법까지 익혔다면, 이제 조명을 어떤 방식으로 처리할지 자체를 정해야 합니다. 언리얼 엔진의 조명은 크게 실행하기 전에 미리 계산해 두는 사전 계산 조명(precomputed lighting)과, 실행하는 동안 매 프레임 계산하는 실시간 조명(real-time lighting)으로 나뉩니다. 두 방식은 품질과 유연성, 성능 비용에서 성격이 달라서, 프로젝트의 목표에 맞게 고르거나 섞어 써야 합니다.
이 글에서는 두 방식이 각각 어떻게 동작하고 어떤 장단점이 있는지 비교한 뒤, 이동성마다 맡길 역할과 두 방식을 섞어 쓰는 기준을 정리합니다. 기능을 설명하는 것보다, 장면에서 무엇이 바뀌어야 하는지를 보고 언제 어떤 방식을 고를지 판단하는 기준을 세우는 것이 핵심입니다.
사전 계산 조명
사전 계산 조명은 게임이 실행되기 전에 에디터에서 조명 정보를 미리 계산해 물체에 저장해 두는 방식으로, 구운 조명(baked lighting)이라고도 부릅니다. 언리얼 엔진에서는 주로 라이트매스(Lightmass)가 이 계산을 맡습니다.
어떻게 동작하나
에디터에서 라이트 빌드를 하면, 주로 Static과 Stationary 광원의 직접광과 간접광이 계산됩니다. 계산한 결과는 주로 라이트맵(lightmap)이라는 텍스처에 저장되고, 각 스태틱 메시는 자기의 라이트맵 UV 채널로 이 텍스처를 읽어 씁니다.
그렇다면 캐릭터처럼 움직이는 물체는 구운 간접광을 어떻게 받을까요? 구운 조명 경로에서는 공간 곳곳의 간접광을 미리 계산해 담아 두는 볼류메트릭 라이트맵(Volumetric Lightmap)을 씁니다. 움직이는 물체는 자기가 지금 있는 위치의 값을 읽어 간접광을 받습니다. 이것은 공간에 저장한 조명 데이터를 읽는 것이지, 해상도가 낮은 메시를 자동으로 다른 방식으로 굽는 기능이 아닙니다.
장점
먼저 성능 면에서 효율적입니다. 미리 계산한 부분은 실행 중에 다시 계산하지 않아도 되기 때문입니다. 다만 라이트맵의 메모리와 읽어 오는 비용, 함께 쓰는 실시간 조명의 비용은 남습니다. 이 효율은 모바일이나 저사양 플랫폼에서 특히 중요합니다.
또 높은 품질의 간접광을 얻을 수 있습니다. 라이트매스는 여러 번 튕기는 복잡한 간접광을 시간을 들여 계산하므로, 매우 사실적이고 부드러운 결과를 냅니다. 장면이 고정되어 있다면, 빌드 시간을 써서 실행 중의 간접광 계산을 줄이는 선택이라고 볼 수 있습니다.
그림자도 부드럽게 만들 수 있습니다. 다만 라이트맵 해상도와 UV 조각 사이의 간격, 빌드 품질을 충분히 확보해야 그렇습니다. 굽기만 하면 계단 현상이 저절로 없어지는 것은 아닙니다.
단점
가장 큰 단점은 정적인 환경에만 맞는다는 것입니다. 빛의 위치나 색, 강도, 또는 빛을 받는 물체의 위치가 실행 중에 바뀌면, 구운 조명과 그림자가 갱신되지 않아 어색해집니다. 또 레벨의 크기와 복잡도, 간접광 품질 설정에 따라 라이트 빌드가 매우 오래 걸릴 수 있습니다.
라이트맵 텍스처를 저장해야 하므로 메모리도 더 씁니다. 그리고 라이트맵에 구울 메시에는 서로 겹치지 않는(non-overlapping) 라이트맵 UV 채널이 필요합니다. 이 조건은 라이트맵에 구울 메시에 대한 것이라, 완전히 동적인 경로에서는 모든 스태틱 메시에 요구되지 않습니다. 라이트맵 UV는 에셋 최적화 및 압축에서 다뤘습니다.
쓰는 광원
사전 계산 조명에는 Static과 Stationary 광원을 씁니다. Static 광원은 모든 빛과 그림자를 완전히 굽습니다. Stationary 광원은 간접광은 굽고 직접광은 실시간으로 계산하며, 그림자는 기존 섀도 맵 방식에서 미리 계산한 것과 실시간으로 만든 것을 섞어 씁니다. 가상 섀도 맵을 쓰면 Stationary 광원의 직접 그림자도 실시간으로 계산합니다.
더 깊이: 볼류메트릭 라이트맵은 공간을 어떻게 저장하나
볼류메트릭 라이트맵 문서에 따르면 라이트매스는 라이트 빌드 중에 레벨 곳곳에 조명 표본(lighting sample)을 놓고 간접광을 계산합니다. 표본은 4×4×4개의 셀(cell)로 이루어진 브릭(brick) 단위로 Lightmass Importance Volume 전체에 깔리고, 간접광이 가장 크게 바뀌는 스태틱 지오메트리 주변에는 더 촘촘하게 놓입니다. 표본 하나는 모든 방향에서 들어오는 빛을 3차 구면 조화 함수(third order spherical harmonic)로 저장합니다. 실행 중에는 움직이는 물체를 그릴 때 이 값을 GPU에서 픽셀마다 보간하므로, 예전의 간접광 캐시(Indirect Lighting Cache)처럼 컴포넌트 전체에 한 번 보간한 값을 쓰는 방식보다 빛샘이 적습니다.
몇 가지 동작도 이 구조에서 나옵니다. Importance Volume 밖의 위치는 볼류메트릭 라이트맵의 가장자리 텍셀 값을 그대로 쓰고, 모바일에서는 픽셀마다가 아니라 CPU에서 물체를 감싸는 범위(bounds)의 중심 한 곳에 대해 보간합니다. 조명을 구운 스태틱 메시를 옮기면 다음 라이트 빌드 전까지 볼류메트릭 라이트맵으로 조명을 미리 보여 주며, 볼류메트릭 안개도 이 값을 읽어 구운 조명을 반영합니다. 비용 면에서는 World Settings의 Volumetric Lightmap Detail Cell Size가 빌드 시간과 메모리에 큰 영향을 주며, 문서의 예에서 Paragon의 한 맵은 기본 설정에서 메모리가 간접광 캐시의 5MB에서 30MB로 늘었습니다.
실시간 조명
실시간 조명은 게임이 실행되는 동안 매 프레임 조명 정보를 계산해 그리는 방식으로, 동적 조명(dynamic lighting)이라고도 부릅니다. 사전 계산 조명과 달리 결과를 라이트맵에 저장해 두지 않으므로 라이트 빌드와 라이트맵 UV가 필요 없습니다. 대신 미리 해 두던 계산을 매 프레임 다시 하므로, 아래의 장단점은 사전 계산 조명과 거의 반대로 나타납니다.
어떻게 동작하나
매 프레임 셰이더가 광원의 위치와 성질, 카메라의 시점에 맞춰 빛과 그림자를 계산합니다. 실시간 그림자는 주로 섀도 맵(shadow map)이나 캐스케이드 섀도 맵, 가상 섀도 맵 같은 기술로 만듭니다.
장점
빛의 위치와 색, 강도가 실시간으로 바뀌거나 물체가 움직여도 조명과 그림자가 바로 갱신되므로, 낮과 밤의 주기나 플레이어의 손전등처럼 유연한 연출이 가능합니다. 또 조명을 빌드할 필요가 없어 작업이 빠르게 흘러갑니다.
단점
매 프레임 조명과 그림자를 계산하므로 CPU와 GPU에 큰 부담을 줍니다. 실시간 광원이 많으면 프레임 속도가 크게 떨어질 수 있습니다. 또 직접광은 쉽게 표현되지만, 빛이 여러 번 튕기는 사실적인 간접광은 구현하기 어렵거나, 루멘처럼 높은 사양을 요구하는 실시간 글로벌 일루미네이션이 필요합니다. 그림자도 미리 계산한 것보다 계단 현상이나 필터링 문제로 품질이 떨어질 수 있고, 이를 줄이는 캐스케이드 섀도 맵 같은 기술에도 비용이 따릅니다.
쓰는 광원
실시간 조명에는 Movable 광원을 씁니다. Movable 광원은 모든 빛과 그림자를 실시간으로 계산합니다.
두 방식을 섞어 쓰기
두 방식 가운데 무엇을 쓸지는 장면이 실행 중에 얼마나 바뀌는지와 목표 성능에 따라 달라집니다. 구운 조명 경로에서는 사전 계산 조명과 실시간 직접광을 섞어 쓸 수 있습니다. 반면 루멘 글로벌 일루미네이션을 쓰는 완전히 동적인 경로에서는 미리 구운 라이트맵이 쓰이지 않으므로, 먼저 프로젝트의 글로벌 일루미네이션 경로부터 정합니다.
이동성마다 맡길 역할
구운 조명 경로에서 Static 광원은 레벨의 기본 주변광과 정적인 물체의 간접광을 맡습니다. 건물의 벽과 바닥, 천장처럼 움직이지 않는 구조물과 고정된 소품을 비추며, 라이트맵 메모리와 빌드 시간을 함께 관리합니다.
Stationary 광원은 태양 같은 레벨의 주요 광원으로, 구운 간접광과 실시간 그림자를 함께 줍니다. 디렉셔널 라이트나 레벨의 주요 포인트 라이트와 스포트 라이트에 씁니다. 기존 섀도 맵 방식에서는 같은 지오메트리에 겹치는 Stationary 광원이 정적 그림자 채널 때문에 최대 4개로 제한됩니다. 이것은 레벨 전체의 광원 수와 다른 제한이므로, 최적화 뷰 모드의 Stationary Light Overlap으로 겹치는 곳을 확인합니다.
Movable 광원은 플레이어의 손전등, 총구의 불꽃, 폭발, 움직이는 차량의 전조등처럼 실행 중에 움직이거나 회전해야 하는 광원에 씁니다. 강도만 바꾼다면 Stationary도 쓸 수 있습니다. 완전히 동적인 프로젝트라면 Movable을 효과용으로만 제한할 이유는 없습니다. 어느 경우든 Movable 광원은 필요한 만큼만 쓰고, Attenuation Radius를 최대한 줄여 영향 범위를 제한합니다.
최적화할 때 다시 확인할 것
이동성은 먼저 글로벌 일루미네이션 경로를 정한 뒤, 위치와 회전, 색, 강도 가운데 무엇이 바뀌는지에 맞춰 고릅니다. 구운 조명에 영향을 주는 Static이나 Stationary 광원의 설정을 바꿨다면, 라이트 빌드를 다시 해 최신 조명을 레벨에 반영하고 빌드 품질을 알맞게 조절합니다. 구울 메시가 알맞은 라이트맵 UV 채널을 가지고 있는지, 겹치는 부분이 없는지도 확인하며, 이 확인에는 조명과 그림자의 디버깅에서 본 라이트맵 밀도 시각화를 씁니다.
그림자는 기존 캐스케이드 섀도 맵을 쓴다면 디렉셔널 라이트의 Dynamic Shadow Distance와 Num Dynamic Shadow Cascades로 품질과 성능의 균형을 맞추고, 필요 없는 물체의 Cast Shadows를 끕니다. 포인트 라이트와 스포트 라이트의 Attenuation Radius는 필요한 만큼만 정해 겹치는 실시간 광원의 수를 줄입니다. UE5에서 실시간 글로벌 일루미네이션이 꼭 필요하다면 루멘을 검토하되, 사양 요구가 높으므로 목표 플랫폼을 고려해 정합니다.
경로마다 먼저 확인할 비용
| 고를 경로 | 먼저 확인할 비용과 제약 |
|---|---|
| 구운 조명과 실시간 직접광의 조합 | 라이트맵 UV와 메모리, 다시 빌드하는 시간, 실행 중에 바뀌지 않는 간접광 |
| 루멘 글로벌 일루미네이션 중심 | 목표 플랫폼의 지원, 장면을 추적하고 갱신하는 비용, 큰 변화가 캐시에 반영되기까지의 시간 |
이 표는 어느 쪽이 빠른지를 매긴 순위가 아닙니다. 같은 장면과 목표 기기에서, 필요한 변화가 유지되는지를 비교하는 기준입니다.
요구사항을 나눠 판단하기
경로를 고를 때는 장면에서 무엇이 바뀌어야 하는지를 나눠 봅니다. 예를 들어 늘 같은 시간대를 보여 주는 전시실이라 벽과 조명이 고정되어 있다면, 구울 간접광의 품질과 라이트맵 비용을 비교해 고르면 됩니다. 하지만 같은 전시실이라도 실행 중에 벽의 색과 태양의 방향이 크게 바뀌고 그 변화가 간접광에도 반영되어야 한다면, 고정된 구운 데이터만으로는 이 요구를 맞출 수 없습니다. 그때는 지원되는 동적 글로벌 일루미네이션 경로와, 그 경로의 갱신 지연과 목표 프레임을 추가로 확인합니다.
이때 직접광만 움직이면 되는 요구와, 방 전체의 간접광까지 다시 계산해야 하는 요구를 구분합니다. 손전등의 직접광만 움직이면 되는 경우라면 구운 조명과 실시간 직접광의 조합으로 충분할 수 있습니다. 반면 방 전체의 간접광이 바뀌어야 한다면, 어떤 변화가 미리 계산한 데이터에 이미 들어 있고 어떤 변화가 빠져 있는지부터 설명할 수 있어야 합니다.
정리
- 사전 계산 조명은 실행 전에 라이트매스로 조명을 계산해 라이트맵에 저장하고, 움직이는 물체는 볼류메트릭 라이트맵에서 간접광을 읽습니다.
- 사전 계산 조명은 효율적이고 간접광의 품질이 높지만, 실행 중의 변화를 반영하지 못하고 빌드 시간과 라이트맵 메모리, 겹치지 않는 라이트맵 UV가 필요합니다.
- 실시간 조명은 매 프레임 계산해 변화에 바로 대응하고 빌드가 필요 없지만, 비용이 크고 사실적인 간접광에는 루멘 같은 방식이 필요합니다.
- 구운 조명 경로에서 Static은 고정된 간접광, Stationary는 주요 광원의 구운 간접광과 실시간 그림자, Movable은 움직이는 광원을 맡습니다.
- 기존 섀도 맵 방식에서 Stationary는 같은 지오메트리에 겹치는 수가 최대 4개이며, Stationary Light Overlap 뷰 모드로 확인합니다.
- 루멘 글로벌 일루미네이션을 쓰면 구운 라이트맵이 쓰이지 않으므로, 글로벌 일루미네이션 경로를 먼저 정한 뒤 이동성을 고릅니다.
- 직접광만 바뀌면 되는지, 간접광까지 다시 계산해야 하는지를 나눠 판단합니다.
연습 문제
1. 고정된 전시실과 바뀌는 전시실
늘 같은 시간대를 보여 주는 전시실 A와, 관람객이 버튼을 누르면 벽 색과 태양 방향이 바뀌고 그 변화가 방 전체의 은은한 빛에도 반영되어야 하는 전시실 B가 있습니다. 각각 어떤 조명 경로를 검토할까요?
해설 보기
전시실 A는 벽과 조명이 고정되어 있으므로, 사전 계산 조명으로 간접광을 구워 실행 중의 비용을 줄이는 경로를 검토할 수 있습니다. 이때 라이트맵의 품질과 메모리 비용을 비교합니다.
전시실 B는 벽 색과 태양 방향의 변화가 간접광에도 반영되어야 하므로, 고정된 구운 데이터로는 요구를 맞출 수 없습니다. 루멘 같은 동적 글로벌 일루미네이션 경로를 검토하고, 목표 플랫폼의 지원과 변화가 반영되기까지의 지연, 목표 프레임을 확인합니다.
2. 손전등 하나를 위해
구운 조명으로 만든 어두운 창고에서, 플레이어가 손전등을 들고 다니게 하려고 합니다. 손전등 때문에 창고 전체를 루멘으로 바꿔야 할까요?
해설 보기
꼭 그럴 필요는 없습니다. 손전등의 직접광만 움직이면 되는 요구라면, 창고의 고정된 조명은 구운 상태로 두고 손전등만 Movable 광원으로 만드는 조합을 검토할 수 있습니다.
다만 손전등의 빛이 벽에 튕겨 주변을 밝히는 간접광까지 필요하다면, 구운 데이터에는 그 변화가 들어 있지 않으므로 동적 글로벌 일루미네이션이 필요합니다. 어느 쪽인지는 장면에 어떤 변화가 꼭 보여야 하는지를 정한 뒤에 고릅니다. 손전등의 Attenuation Radius는 필요한 만큼만 정해 비용을 줄입니다.
3. 움직이는 캐릭터의 간접광
구운 조명으로 만든 실내에서, 걸어 다니는 캐릭터만 주변 간접광을 받지 못하고 붕 떠 보입니다. 정적인 벽과 바닥은 잘 구워져 있습니다. 무엇을 확인해야 할까요?
해설 보기
움직이는 캐릭터는 라이트맵을 쓰지 않고, 공간에 구워 둔 볼류메트릭 라이트맵에서 자기 위치의 간접광을 읽습니다. 그래서 그 레벨에서 볼류메트릭 라이트맵이 만들어졌는지, 캐릭터가 있는 곳의 데이터가 충분한 해상도로 구워졌는지를 확인합니다.
조명이나 레벨 구조를 바꾼 뒤 라이트 빌드를 다시 하지 않았다면 볼류메트릭 라이트맵도 예전 상태이므로, 다시 빌드한 뒤 캐릭터의 모습을 비교합니다.
미리 계산하는 조명과 동적 글로벌 일루미네이션의 종류는 Epic의 글로벌 일루미네이션 안내에서 확인할 수 있습니다.
이것으로 5장을 마칩니다. 5장에서는 광원의 종류와 이동성을 다시 정리하고, 이동성에 따른 그림자 방식과 그 비용을 줄이는 방법, 라이트매스와 루멘의 간접광과 여러 반사 방식, 시각화 모드와 콘솔 명령으로 조명 문제를 찾는 방법, 그리고 사전 계산 조명과 실시간 조명을 고르고 섞는 기준까지 조명과 그림자를 깊이 있게 다뤘습니다. 다음 장의 날씨 시스템 설정부터는 비와 눈 같은 날씨를 설정하는 데서 시작해, 시간 시스템과 낮밤 주기, 날씨와 시간 효과의 적용, 동적인 환경 변화, 날씨 효과의 성능 최적화까지 날씨와 시간 시스템을 다룹니다.