멈추지 않고 끈질기게

[Graphics][Unity] 라이트 맵(Light Map) 본문

Graphics

[Graphics][Unity] 라이트 맵(Light Map)

sam0308 2023. 3. 10. 16:07

※ 해당 포스팅은 개인의 공부 정리용 글입니다. 틀린 내용이 있다면 추후 수정될 수 있습니다.

※ 해당 포스팅은 Unity 2021.3.15f1 버전을 기준으로 작성되었습니다.

※ 해당 포스팅은 하기 출처들을 참조하였습니다.

- 오지현, 유니티 그래픽스 최적화 스타트업, 비엘북스, 2019

 

 

 

 

이번 포스팅에서는 정적 라이트를 표현하는 기법인 라이트 맵에 대해 알아보겠습니다.

1. 라이트 맵(Light Map)이란

 라이트 맵(Light Map)이란 전역 조명(GI, Global Illumination)과 그림자 등을 포함한 라이팅 정보를 미리 연산하여 텍스처로 저장하는 기능을 말합니다. 유니티에서 해당 기능을 사용하려면 씬에 광원을 배치하고 사전에 연산하여 라이트 맵을 생성해야 하며, 이 과정을 Bake 라고 부릅니다. 라이트 맵은 한번 Bake 되고 나면 런타임동안에는 라이트맵에 변경되지 않으므로, 정적(static) 오브젝트에만 적용 가능합니다. 또한 광원 쪽도 Type을 Baked로 설정해주어야 라이트맵에 그려지게 됩니다(디폴트 값인 Realtime일 경우 라이트맵에 영향을 주지 않습니다). 따라서 라이트 맵은 보통 static으로 설정하는 배경 오브젝트 등에 적용하기 좋은 방식입니다.

 

그림 1. (좌) UV 채널 생성 전, (우) UV 채널 생성 후

 오브젝트에 라이트 맵을 적용하려면 해당 오브젝트의 Mesh Renderer 컴포넌트에서 Lightmap Static 플래그가 체크되어 있어야 합니다. 라이트 맵이 적용된 오브젝트가 상기 사진 좌측처럼 깨져서 노출되는 경우가 있는데, 이는 라이트맵(텍스처)을 메시에 적용하려면 별도의 UV 채널이 필요한데 해당 오브젝트에는 없는 경우입니다. 이 경우에는 해당 오브젝트의 Model -> Generate Lightmap UVs를 체크하고 적용(Apply)하여 생성해주어야 합니다. 설정이 완료되면 상기 사진 우측처럼 라이트 맵이 정상적으로 적용되는 것을 확인할 수 있습니다.

 

 라이트 맵을 사용하는 이유는 간단히 말해 전역 조명을 런타임동안 실시간으로 업데이트 하는 것은 성능 소모가 매우 크기 때문입니다. 따라서 광원의 밝기나 각도 등이 변경되면 즉시 반영되지 못하고 점진적으로 연산되면서 업데이트되며,

 이 간격은 프로젝트 설정에서 조절할 수 있습니다(Edit -> Project Settings -> Grphics -> Tier별 Realtime Global Illumination CPU). 여기서 설정값을 낮게 조정하더라도 한계가 있으며, 특히 모바일의 경우 하이엔드 스펙의 디바이스가 아니라면 실시간 전역 조명을 사용하는 데에는 어려움이 있습니다.

 

 

 

2. 라이트 맵 옵션

Lightmapper

 Lightmapper 옵션에는 Enlighten, Progressive 두 종류가 있으며, 유니티 2018 버전 이후부터는 Progressive가 기본으로 설정되어 있습니다. Progressive의 가장 큰 장점은 베이킹 과정을 점진적으로 확인할 수 있다는 점입니다. 라이트맵 설정창 하단의 Auto Generate 플래그를 체크해두면 라이트맵에 영향을 주는 광원과 static 오브젝트 이동 시 자동으로 베이킹을 실시하며, Progrssive를 선택중이라면 해당 과정을 점진적으로 확인할 수 있습니다. 

 

Ambient Occlusion(AO)

그림 2. (좌) AO 적용 전, (우) AO 적용 후

 Ambient Occlusion(AO)지오메트리 사이에 빛이 차폐되어 어두워지는 현상을 의미하며, 해당 옵션을 킬 경우 깊이감이 좀 더 디테일하게 표현됩니다. 상기 사진을 비교하면 AO 옵션을 적용한 쪽이 오브젝트가 모여있는 공간에 좀 더 그림자가 지는 모습을 확인할 수 있습니다.

 

 

Lightmap Resolution & Size

 라이트맵의 해상도를 결정하는 옵션으로 Lighmap ResolutionLighmap Size가 있습니다. Lighmap Resolution은 해상도가 아닌 텍셀(texel, 텍스처의 픽셀) 밀도를 나타내는 수치로, 1유닛당 라이트맵의 할당 텍셀을 결정하는 수치입니다. Lighmap Size는 라이트맵 텍스처의 해상도로, 필요한 총 해상도가 이 수치를 넘어가면 여러장의 라이트맵으로 나뉘게 됩니다. Lighmap Size에 비해 Lighmap Resolution이 클 경우 특히 이런 상황이 발생할 확률이 커집니다. 라이트맵이 여러장으로 나뉠 경우 배칭이 깨져 드로우콜의 증가로 이어질 수 있으므로 주의해야 합니다.

 

그림 3. (좌) Lighmap  Resolution 400 vs (우) Lighmap Resolution 40

 상기 사진은 다소 극단적인 비교 예시로, Lighmap Resolution이 400일때와 40일 때를 비교한 것입니다. 좌측은 무려 17장의 라이트맵이 생성되었고, 이 때문에 배칭이 전혀 이루어지지 않아 드로우콜이 무려 217회나 발생하고 있습니다. 우측은 1장의 라이트맵이 생성되어 배칭이 깨지지 않고 30회의 드로우콜로 처리되고 있는 것을 알 수 있습니다. 

 

 다만 Lighmap Resolution을 너무 줄일 경우 해상도가 부족하여 시각적인 품질이 떨어질 수 있습니다. Lighmap Size를 늘려 1장의 라이트맵에 담을 수 있는 텍셀 수를 늘려주면 이러한 부분을 해결할 수 있습니다. 그러나 라이트 맵의 사이즈 증가는 곧 필요 대역폭의 증가로 이어지기 때문에, 특히 대역폭 이슈에 민감한 모바일 게임이라면 신중하게 결정해야 합니다.

 

 

Directional Mode

 라이트 맵의 사이즈에 영향을 주는 또 다른 옵션으로 Directional Mode가 있습니다. Non-Directional 과 Directional 옵션이 있으며 가장 큰 차이점은 노멀맵의 적용 여부입니다. Directional 선택 시 라이트맵이 적용되는 오브젝트에도 노멀맵이 적용되어 오브젝트 표면의 디테일을 표현할 수 있습니다. Non-Directional 선택 시 라이팅, 그림자 등이 기록된 라이트맵만 사용합니다.

 

 물론 Directional  선택 시 추가적인 리소스와 성능을 요구합니다. 오브젝트의 표면에 맺히는 라이트의 방향 등의 정보를 저장하는 추가적인 라이트 맵을 생성하게 되며, 이는 특히 라이트맵 텍스처가 많을 경우 메모리 이슈를 유발할 수도 있습니다. 또한 추가 라이트 정보를 처리하는 연산이 추가되어 픽셀 쉐이더의 비용이 증가하므로, Directional 선택 시 GPU 성능 및 메모리 요구량이 증가하게 됩니다.

 

 

 

3. Mixed Light Mode

Light 모드에는 Realtime과 Baked 외에 Mixed라는 제 3의 옵션이 존재합니다. Realitime과 Baked의 역할을 모두 가지는 옵션으로, Mixed 광원은 사전 연산되는 솔루션(라이트맵)에도 적용되며 실시간 광원의 역할도 합니다. Mixed 광원의 세부 옵션은 Lighting Settings -> Mixed Lighting -> Lighting Mode에 의존합니다. 참고로 라이트 맵을 사용하려면 Baked Global Illumination 플래그를 체크해주어야 합니다. Mixed Light Mode에는 하기 3가지 옵션이 존재합니다.

 

Baked Indirect

해당 옵션의 경우 전역 조명(GI)만 라이트맵에 기록되고 그림자는 기록되지 않습니다. 즉, 전역 조명만 사전 연산하고 그림자는 런타임동안 실시간으로 연산하는 모드로 그림자의 퀄리티가 중요할 때 선택할만한 옵션입니다. 또한 직접 조명(Direct Lighting)도 실시간 처리의 영역에 들어갑니다. 하기 두 옵션과 비교하여 그림자의 품질이 가장 높지만 그만큼 많은 연산 비용을 요구합니다.

 

 

Subtractive 

그림 4. Subtractive Mode

 일반적인 라이트맵에 해당하는 옵션으로 전역 조명, 직접 조명 및 그림자까지 모두 라이트맵에 베이킹합니다. 따라서 static 오브젝트에는 실시간 연산 없이 오로지 라이트맵만 적용됩니다. 다만 라이트맵의 라이트나 그림자는 텍스처에 미리 그려진 이미지이기 때문에, 실시간 그림자와 함께 있으면 다소 부자연스럽게 노출될 수 있습니다(그림 4 참조). 이런 문제를 해결하기 위해 Subtractive 모드에서는 그림자 컬러 조절 옵션을 제공하며, 이를 통해 실시간 그림자와의 이질감을 다소 감소시킬 수 있습니다. Baked Indirect에 비해 성능 요구치가 훨씬 낮으므로 저사양 디바이스를 타겟으로 한 게임에서 사용하기 적합합니다.

 

 

Shadowmask

그림 5. Shadowmask Mode

 해당 옵션 선택 시 그림자 영역을 별도의 텍스처로 저장하며, 이 그림자가 저장된 텍스처를 shadowmask 라고 합니다. 그림자를 따로 저장해둠으로서 런타임동안 그림자 연산을 수행하지 않고, shadowmask를 통해 그림자 여부를 판단해서 실시간 그림자와 자연스럽게 합성합니다. 따라서 Subtractive 모드와 달리 실시간 그림자와 static 오브젝트의 그림자가 자연스럽게 이어집니다(그림 5 참조). 이 옵션 또한 모바일 게임에 사용하기 적합하나, Subtractive 보다는 성능이 조금 더 요구되며 추가적인 텍스처가 만들어지기 때문에 텍스처 메모리가 추가로 요구됩니다. 

 

 또한 프로젝트 옵션에서 Shadowmask Mode 옵션을 Distance Shadowmask로 설정하면 static 오브젝트에도 거리에 따라 쉐도우맵 연산을 수행합니다. 카메라와의 거리가 먼 static 오브젝트들은 원래대로 shadowmask를 통해 그림자를 생성하고, 가까운 경우에만 쉐도우맵 연산을 수행하여 화면에서 차지하는 비중이 높은 그림자의 퀄리티를 높일 수 있습니다. 그림자 전체를 실시간 연산하는 방법에 비해 성능을 절약하며 눈에 띄는 그림자의 품질을 높일 수 있는 방법입니다.