유니티 엔진 (Unity Engine)

유니티 그래픽스 최적화 - 7.GI (Global Illumination)

원생계 2019. 9. 24. 00:43

.

.

7. GI (Global Illumination)

라이트와 그림자는 연산이 비싸기 때문에 라이트맵과 라이트 프로브 등 미리 연산하는 솔루션들을 적극 활용, 절약하면 좋다. GI 적용 가능. 광원이 태양광 하나로 출발해도 Direction 라이트 영향, 튕겨서 들어오는 Indirection 라이트 영향도 받음. 어떤 지점은 Direction 영향은 막히고, Indirection 영향만 받기도.

https://docs.unity3d.com/kr/current/Manual/LightMode-Baked.html

이 현상을 글로벌 일루미네이션(Global Illumination) 라이트맵과 라이트프로브를 이용해서 GI현상까지 미리 연상하여 기록해놓을수 있다. 실시간으로 GI를 처리하려면 많은 연산 필요. 실시간 라이팅은 라이팅 Source 에 들어오는 직접 라이트만 반영 가능. 로컬 일루미네이션(지역 조명)

그림자도 미리 계산해서 저장 가능. 빛 사물 뒤 영역은 빛이 닿지 않고 그림자. 그림자도 라이팅 결과물. 라이팅, 그림자 연산 실시간 힘들기 때문에 각각 따로 진행되는 것.

미리 라이팅 결과를 베이킹 하면 그림자도 적용. Ambient Occlusion 도 반영.

7-1 라이트맵 (Lightmap)

라이트맵, GI 및 그림자 등을 포함한 라이팅 정보를 미리 연산(Precompute)한 텍스처.

01) 라이트맵 구성 요소

씬에 라이트를 배치, 사전연산 과정. 완성된 텍스처는 베이크드 라이트맵 (Baked Lightmap)

정적 오브젝트에서만 적용 가능. Static 플래그가 체크된 오브젝트.

디렉셔널 라이트를 선택하고 Mode 를 Mixed 혹은 Baked 로 설정. 기본적으로 Realtime Mode. 라이트맵 Auto Generate 설정이 활성화 되어있는 경우, 프로그레스 바가 돌면서 베이킹.

리얼타임으로 생성된 오브젝트는 라이트맵 적용이 불가. 그래서 배경 오브젝트에 적용하기 좋음. 오브젝트 Mesh Renderer 의 Lightmap Static 플래그가 켜져 있어야 함.

오브젝트의 라이트맵이 깨지는 경우, UV 채널이 필요. Import 셋팅에서 자동생성. Model > Generate Lightmap UVs 플래그 체크, Apply.

라이트맵 설정 Window > Rendering > Lighting Settings 선택.

02) 실시간 GI (Realtime Global Illumination)

Lighting 설정 Realtime Global Illumination 플래그 꺼줌. 제약사항이 많음. 완전 실시간은 아니고, Enlighten 솔루션으로 사전 연산 데이터 저장. 런타임 동안 GI 적용으로 매우 큰 성능 소모. 라이트 설정이 바뀌면 점진적으로 연산되면서 업데이트 됨. 이 업데이트 간격은 Graphics 셋팅에서 조절 가능.

https://learn.unity.com/tutorial/precomputed-realtime-gi-global-illumination

https://docs.unity3d.com/kr/current/Manual/GIIntro.html

03) Progressive Lightmapper

Lightmapping Settings 카테고리, Lightmapper 는 Progressive 와 Enlighten 중 선택. Progressive 는 과정 보임. Unity 2018부터 Progressive 기본 셋팅.

씬뷰 좌상단, Draw Mode 드롭다운, Baked Lightmap 모드 선택으로 확인 가능. AmbientOcclusion 셋팅도 가능.

https://docs.unity3d.com/kr/current/Manual/GIIntro.html

04) 라이트맵의 해상도

Lightmapping Settins 항목, Lightmap Resolution, Lightmap Padding, Lightmap Size 는 텍스처 연관.

Lightmap Resolution 은 라이트맵 해상도라기보다는 텍셀 밀도를 나타내는 수치가 정확. (텍스처의 픽셀을 텍셀) 1유닛당 라이트맵 할당 텍셀 결정 수치. 숫자가 높을수록 필요 해상도가 커짐.

Resolution 이 10이고 5x5 유닛 크기인 평면 라이트맵이라면 50x50 텍셀, 즉 2500개 텍셀이 필요. (실제로는 더 복잡)

Lightmap Size 는 텍스처 해상도. 필요한 해상도가 더 크면 여러 장의 라이트맵으로 나뉨. Lightmap Size 가 작고 Resolution 이 크게 설정돼있으면 여러 장으로 나뉘게 될 확률이 커진다. 라이트맵 여러장이면 배칭이 깨질 확률이 커짐. 프레임 디버거의 배칭 메시지

= Why this draw call can’t be batched with the previous one

Objects are lightmapped.

라이트맵도 텍스처인 이상 같은 머티리얼을 사용하도록 해야 배칭 됨.

Lighting Window 에서 Global Maps 탭에서 라이트맵 결과물 확인. 라이트맵이 많다면 배칭이 나눠짐. Resolution 을 줄이면 시각적인 해상도가 줄어들어 선명도는 떨어지지만 텍스처는 작아짐. Lightmap Size 를 1024 -> 2048 키우면 텍스처 사이즈는 4배. 단, 너무 커지면 대역폭 문제 생김. 저사양 디바이스는 2048 텍스처는 문제가 생길 수 있음.

-----

3D 공간은 센티미터, 등의 명확한 크기 기준이 없다. Unit이란 용어로 수치를 표현. 1유닛을 1미터로 할 것인지는 정하기 나름. 유니티는 1유닛 = 1미터 설정이 많다.

가령, Edit > Project Settings > Physics 의 PhysicsManager 의 Gravity 의 y값이 -9.81 = 중력가속도 9.80665m/s^2

-----

05) Directional Mode

Non-Directional / Directional 노멀맵의 적용 유무. 라이트맵 적용 오브젝트에 노멀맵 적용하려면 Directional 설정. 추가 리소스와 성능이 필요. Non-Directional 노멀맵 무시, 스페큘러 하이라이트 없음. 단, 리플렉션 프로브는 적용. Directional 모드는 추가 라이트맵 텍스처 생성. 표면에 맺히는 라이트의 방향 등 환경 추가 정보.

Lighting 창의 Global Maps 탭에서 라이트맵 결과물 확인. Directional모드는 추가 텍스처 생성/비용. 픽셀 쉐이더 비용 추가. 모바일에선 Directional 모드 점검 필요.

06) Light 모드

Realtime, Baked 외에 Mixed 모드 존재. Mixed 라도 리얼타임으로 라이트맵 수정 내용 반영은 되지 않아 라이트 변경 권장되지 않음. Mixed Lighting Mode 설정은 Window > Rendering > Lighting Settings 에서 Mixed Lighting 섹션에서 가능. 씬의 모든 Mixed 모드는 이 설정 사용. Baked Indirect, Subtractive, Shadowmask 중 하나. 차이 큼. (포워드 렌더링 패스 기준. SRP 로 Lightweight 나 HD Pipe 조건 달라질 수 있음. 가령, Lightweight Pipeline 에서는 Subtractive 만 지원.)

07) Baked Indirect

Baked Indirect면 GI만 라이트맵에 기록되고 그림자는 기록되지 않음. 그림자는 실시간으로 연산. GI만 미리 연산해 놓고 그림자는 실시간 처리할 만큼 그림자가 중요한 경우 유용.

그림자, 직접광(Direct lighting) 리얼타임으로 처리. 런타임 상 라이트, 컬러, 강도(Intensity) 변경 가능.

씬뷰에서 Baked Lightmap 모드로 선택, 확인. AO등의 GI는 반영돼있고, Directional Light 그림자는 반영되지 않음.

08) Subtractive

전통적인 라이트맵. GI, Directional Light, Shadow 모두 라이트맵에 베이킹됨. Static 오브젝트는 실시간 라이팅, 스페큘러 반영 없고, 오로니 라이트맵에서만 이루어짐.

베이킹된 건물 그림자에 실시간 캐릭터 그림자가 그려지는 부자연스러운 모습.

Mixed Lighting / Lighting Mode = Subtractive 일 경우, 실시간 그림자 컬러 조절해서 이질감을 줄일 수 있다.

Realtime Shadow Color 옵션 수정.

씬 뷰의 드로우 모드 Baked Lightmap 으로 확인해보면, 오브젝트 라이팅, 그림자, AO 까지 모두 라이트맵 처리 돼있음.

런타임 오버헤드가 극히 적다. 모바일, 저사양 기기에 적합.

09) Shadowmask

라이트맵 베이킹 시, 그림자 영역을 별도 텍스처로 따로 저장. 이 그림자 영역만 저장해놓은 텍스처가 Shadowmask.

Baked GI 와 비슷해보이지만, 런타임동안 그림자 캐스팅 연산 수행 없음. 대신, Shadowmask 로 그림자 여부를 판단, 신시간 그림자와 자연스럽게 합성. Subtractive 모드와 다르게 Static 옵젝트와 다이나믹 오브젝트 그림자가 자연스럽게 연결.

라이트맵 적용되는 오브젝트도 스페큘러 하이라이트 적용됨.

Subtractive 모드보단 스페큘러 하이라이트 픽셀쉐이더 실시간 연산 비용 추가.

Baked Indirect 모드보단 그림자 캐스팅 연산 비용이 상대적으로 절약됨.

Static 오브젝트 그림자 영역이 미리 Shadowmask 로 저장돼있기 때문에 런타임 쉐도맵 연산 없음.(Distance shadowmask 는 경우에 따라 달라짐) 다이나믹 오브젝트만 쉐도우맵 연산. 그림자 비용 절약.

씬뷰에서 Drwa Mode > Shadowmask 확인 가능.

그림자 연산 성능비용이 대폭 감소. 모바일 디바이스 적합. Subtractive 모드보단 시각적 품질이 좋지만(그림자 분리 없음) 성능이 좀 더 요구되고, Shadowmask 텍스처가 추가되어 메모리 추가 필요. 라이트맵 텍스처 생성 결과물은 Lighting Window / Global Maps 탭에서 확인.

두 번째 세 번째 열은 Directional, Shadowmask 모드로 인해 추가된 텍스처. 하단의 총 용량이 190.7MB 피씨나 콘솔에서는 문제 되지 않지만, 모바일에선 메모리 문제를 일으킬 수 있는 수치.

Shadowmask -> Distance Shadowmask 모드로 확장 가능.

Edit > Project Settings > Quality 에서 셋팅 가능. Shadows / Shadowmask Mode : Distance Shadowmask 설정을 활성화. 정적 오브젝트도 거리에 따라 쉐도우맵 적용/실시간 그림자 처리. 가까이 있는 오브젝트의 경우 고품질로 처리 가능. Shadow Distance 설정된 값 이하의 거리는 실시간으로 고품질 처리. 그 밖은 셰도우마스크 처리로 성능 효율.

7-2 라이트 프로브 (Light Probe)

저렴하고 자연스러운 라이팅 기법이 주로 라이트맵. 주로 배경 Static 오브젝트에 적용. 동적 오브젝트는 반영 안됨. 아웃도어는 큰 문제가 되지 않지만, 위치마다 빛 변화가 다른 실내 배경이나 늦은 저녁은 어색. 라이팅의 밝기와 상관 없이 캐릭터가 동일한 라이팅과 밝기를 가지면 이질감. 야외에서도 건물 그림자에 캐릭터가 들어가면 같이 어두워져야.

http://docs.unity3d.com/kr/current/Manual/LightProbes.html

동일한 두 캐릭터가, 그림자 속에 있든 들판에 있든 동일한 라이팅이 반영되면 매우 어색. Mixed Lighting Mode = Subtractive. Static Object 는 라이트맵 영향 받음. 캐릭터는 다이나믹 오브젝트 = 실시간 라이팅 적용.

Mixed Light Mode = Baked Indirect 로 두면 그림자 연산은 런타임 실시간이라 캐릭터도 그림자 적용. 성능상 모바일은 권장되지 않음.

GI의 영향도 문제. 배경 정적 오브젝트는 녹색 빛이 묻어나지만 캐릭터같은 동적 오브젝트에는 반영되지 않아 조화롭지 못함.

유니티 베이킹 시스템은 정적 오브젝트만 반영하고 있고, 동적 오브젝트는 연산 성능이 필요한 방식으로만 해결 가능.

라이트 프로브(Light Probe)는 문제를 해결 가능. 라이트맵처럼 빛을 저장해 놓았다가 실시간으로 다이내믹 라이트 반영해줄 수 있는 기능. 단, 라이트맵과 다른 형태로 저장.

차이점

라이트 = 표면에 맺히는 라이팅 정보를 저장.

라이트 프로브 = 라이팅이 지나가는 빈 공간의 지점을 저장해 놓음. 그 공간에 위치하는 다이내믹 오브젝트에 라이팅을 반영하는 것.

라이트 프로브는 다양한 지점의 빛을 수집해서 미리 저장해둘 수 있음. 프로브 하나하나가 주변의 빛을 미리 연산해서 가지고 있. 동작 원리는 다르지만, 라이트맵 베이킹과 비슷. Baked, Mixed 로 설정된 라이트들을 대상으로. 런타임 중에 다이나믹 오브젝트가 주변의 라이트 프로브를 수집해서 라이팅 적용.

라이트 프로브가 실제 라이트는 아님. 각각 주변의 라이팅 결과를 미리 구워 저장해놓은 별도의 샘플 포인트.

수집된 라이트 프로브들은 주변 빛을 어떠한 형태의 수치들로 인코딩. 런타임상에 디코딩해서 사용. 미리 연산된 정보 활용이라 실제 라이팅 연산보단 훨씬 저렴.

01) 프로브(Probe)의 설치

실제 라이트가 아니기 때문에, 라이트 오브젝트와 별개로 씬에 따로 설치해야 함.

Light Probe Group 생성.

Component > Rendering > Light Probe Group ||

Hierarchy View / Create > Light > Light Probe Group

Edit Light Probes

편집 모드가 되면, 라이트 프로브들은 노란색으로 표시. 가까운 프로브들은 보라색 라인으로 연결. 밀도를 조절하면서 배치.

라이트맵은 일정한 해상도가 존재하지만, 라이트 프로브의 밀도는 어떻게 설치하느냐에 따라 달라짐.

라이트 프로브는 라이트맵에 비해 데이터가 작지만 남발 노노. 런타임 중 동적 오브젝트들이 주변 라이트 프로브들을 탐색하는데, 데이터 양이 많아지면 탐색 비용이 커져서 활용 의미가 퇴색됨. 캐릭터가 갈 수 없는 영역은 설치할 필요 없음. 건물 그림자 영역 근처가 라이팅 변화가 큼. 건물 주변의 라이트 프로브 밀도가 높음. 광장쪽은 라이트 변화가 적으니 밀도 낮게.

02) 데이터의 크기와 정밀도

라이트 프로브 정보는 단순 몇 개의 숫자 값. 구면 조화 함수(Spherical Harmonics)라는 복잡한 함수 결과.

구면 조화 함수는 구면 기준, 주변 공간의 에너지 분포를 근사하여 표현할 수 있는 함수. 양자 물리 주사용, 게임 그래픽의 라이팅 결과 저장 용도로 응용. 이 함수는 차수를 반복하여 더 많은 정밀도 표현 가능.

게임 실시간 렌더링은 성능상 문제로 많아야 3단계(l=3)로 제한하여 사용.

< Light Probe Interpolation Using Tetrahedral Tessellations, by Robert Cupisz >

라이트 프로브는 커다란 데이터가 아님. 9개의 float * 3 (channel) = float 27

압축하지 않은 32bpp 텍스처의 6.75 픽셀 크기.

정밀도가 높지 않음. 구면 조화 함수로는 디퓨즈 라이팅만 표현 가능. 스페큘러 라이팅 표현 불가, 완벽한 입체감은 한계. 그래서 동적 오브젝트 실시간 라이팅은 여전히 적용되지만, GI같은 버거운 라이팅 환경들은 라이트 프로브로 보조 가능.

03) 프로브의 적용

Lighting 창 하단에 Auto Generate 켜져있으면 라이트 프로브 수정 시 자동 업데이트. 라이트 프로브 설치 > 업데이트 이후엔 라이트맵 영향주는 라이트들이 동적 오브젝트에도 영향.

동적 오브젝트가 씬에 존재하면, Mesh Renderer 주변의 라이트 프로브들을 선별하고 값을 보간. 씬 뷰에서 동적 오브젝트 선택하면 영향 주는 라이트 프로브들이 표시됨.

Mesh Renderer || Skinned Mesh Renderer / Lighting / Light Probes 에서 라이트 프로브 적용 끌 수 있음. (Reflection Probes 는 라이트 프로브가 아니니 다른 기능. 혼동 주의)

7-3 리플렉션 프로브 (Reflection Probe)

스탠다드 쉐이더 = 물리 기반 쉐이더 처리.

에너지 보존 (Energy Conservation)

01) 라이트의 리플렉션(Reflection)

어떤 물체에 빛이 닿았을 때, 물체는 더 많은 광원을 반사하지 못함.

일부는 흡수, 일부는 산란 발산.

바로 반사되는 라이트 = 스페큘러(Specular)

발산되는 라이트 = 디퓨즈(diffuse)

< Physics and Math of Shading, by Naty Hoffman >

미세한 표면(microfacet)이 매끄러울수록 반사가 선명, 거칠수록 분산. 오브젝트 재질따라 다르고, 텍스처 등의 파라미터화 시킨 것이 물리 기반 쉐이더의 머티리얼.

더 많이 반사할수록 발산은 덜 일어나야. 머티리얼에서 스페큘러의 비율이 노ㅠ을수록 디퓨즈의 비율이 낮아짐.

표면이 매끄러울 수록 하이라이트 = 작고 강함. 주변 이미지가 선명하게 반사, 거칠면 그만큼 희미하게 반사.

하지만, 유니티의 기본적인 Reflection 이미지는 Lighting window 의 스카이박스로 설정돼있기 때문에, 복잡한 씬에서는 어색함.

02) 리플렉션 프로브(Reflection Probe)의 적용

리플렉션 프로브는 스카이박스 반사 어색함 대신, 주변 환경 반사 이미지를 만들어냄. 저장해두었다가 리플렉션 프로브 영역으로 들어오면 반사 이미지를 저장된 이미지로 대체. 라이트 프로브처럼 씬에 배치해야 함. 다른 점은, 프로브 그룹이 없고 하나의 프로브 포인트만 가짐.

360도 카메라같은 개념. 배치하고 Box Size 를 조절. 영역 안에 있다면 리플렉션 프로브를, 밖이라면 스카이박스를 반사 소스로. 어느 위치에서 캡쳐하느냐에 따라 반사 소스가 달라질 수 있어서 적절한 프로브 배치 필요.

03) 메모리 및 성능에 대한 고려사항들

텍스처 메모리 유의. 리플렉션 브로브로 캡쳐한 이미지는 큐브맵 형태. 라이트 프로브는 float 27개 이지만, 큐브맵은 텍스쳐라서 메모리가 큼.

컴포넌트의 Cubemap capture settings / Resolution 에서 해상도 조절. 128 = 한 장이 128. 128 * 6 텍스처 구성. 가급적 작게 설정하는 것이 좋음. 모바일 디바이스라면 더 유의.

HDR 플래그, 밝은 빛 반영. Bloom Post Processing 사용한다면 중요. 카메라 Allow HDR, 디바이스 HDR 버퍼 지원 필요. 일반적인 HDR 텍스처는 용량 2배. 픽셀 값의 범위가 실제 라이팅 범위를 포함할 수 있는 정밀도의 텍스처. 일반 텍스처와는 다르게 HDR은 0~1 범위를 넘는 값 저장하는 실수형 float 데이터. 64bpp 로 높은 용량 필요한 단점. 유니티는 저장할 때 0~8의 범위를 0~1로 압축, 알파 채널에 Multiply 적용, 32bpp 텍스처에 HDR 정보 기록 가능. 그래서 메모리 용량은 절약되나, Multiply 적용해서 값을 늘리는 부작용, 마하 밴드가 생길 수 있음. (예제, 하늘색의 경계가 발생하는 문제)

Type Realtime / Baked.

Realtime 은 특수한 경우에만, 자동차의 반사 이미지. 자동차의 자식으로 Reflection Probe 를 붙이고, Culling Mask 로 자동차 제외. Refresh Mode 를 Every Frame. 매우 큰 성능 소모. 추가적 렌더링, 드로우콜 추가.

성능 고려, 정말 필요한 곳에만 최소한으로, 해상도도 작게.

https://docs.unity3d.com/Manual/ReflectionProbes.html

.

유니티 그래픽스 최적화 스타트업 : coupa.ng/bOkEbG

 

유니티 에반젤리스트의 유니티 그래픽스 최적화 스타트업

COUPANG

www.coupang.com

.

728x90
반응형