주의 : 잘못된 내용이 포함되어 있을 수 있으므로 이상하면 참고자료를 확인하세요.


[ PBR 이란 무엇인가 ] 9. Global Illumination & Indirect Lighting

빛의 경로

지금까지는 빛이 서피스에 반사되어 들어 오는 경우만을 이야기했습니다. 하지만 빛이 눈에 들어 오는 경로는 그림1 처럼 매우 복잡합니다. 산란( scattering ), 투과( Transmission ), 반사( Reflection ), 흡수( Absorbtion )가 모두 고려되어야 매우 자연스러운 결과가 나옵니다.

그림1. 다양한 경로로 눈에 들어 오는 빛.

Local Illumination

컴퓨팅 파워의 한계 때문에 실시간 그래픽스에서 그림1 에 나오는 모든 요소들을 처리할 수는 없습니다. 그래서 PBR 이전에는 빛이 직접적으로 닿는 부분만 고려해 렌더링을 했습니다. 그렇게 되면 빛이 직접적으로 닿지 않는 부분은 어두워지겠죠. 그렇지만 우리는 실세계에서는 완벽하게 어두운 부분은 존재할 수 없음을 알고 있습니다. 왜냐하면 한 서피스에 도달하는 빛은 여러 서피스로부터 반사된 후에 올 수 있다는 것을 알고 있기 때문입니다. 그래서 주변광( ambient light ) 라는 개념을 만들어서 어두운 부분을 대충 밝혀 줍니다.

Ambient 를 얼마만큼 밝혀줘야 하느냐? 그것은 아티스트의 감에 달려 있었습니다. 그래서 global ambient 와 material ambient 가 나뉘어 있었습니다. 오브젝트가 놓여 있는 환경이 다르다보니 어쩔 수 없는 선택이었죠.

이런 방식을 local illumination( 지역 조명 ) 이라고 부르며, 그 결과는 그림2 와 같습니다.

그림2. Local Illumination. 출처 : [1]

Global Illumination

사람들은 Local Illumination 이 부자연스럽다는 것을 알고 있습니다. 서피스에 들어 온 빛은 다시 다른 서피스를 위한 광원으로 사용될 수 있습니다. 물론 투과되는 빛도 다른 서피스를 위한 광원으로 사용될 수 있습니다. 이렇게 서피스에서 반사되거나 굴절되는 모든 빛을 새로운 광원으로 삼는 것을 Global illumination 이라 부릅니다.

그림3. Global Illumination. 출처 : [1]

그림3 을 보시면 그림2 와 비교했을 때 굴절과 반사가 제대로 제대로 적용되고 있음을 확인할 수 있습니다. 우리가 실세계에서 익숙하게 볼 수 있는 복잡한 결과가 나오게 되는겁니다.

이제 여기에서 여러분에게 GI 의 핵심 성분들에 대해서 이야기하도록 하겠습니다.

그림4. 눈에 들어 온 GI 성분들. 출처 : [2]

    • Direct light 는 광원에서 표면으로 직접 들어 온 빛을 의미합니다.

    • Indirect light 는 표면에 들어 온 빛이 반사되어 새로운 광원처럼 사용되는 경우를 의미합니다.

만약 direct light 성분만 계산을 하게 되면 그림5 와 같은 결과가 나옵니다.

그림5. Direct light Only. 출처 : [3].

바닥에 비춰진 빛이 반사되어( bounced ) 광원( indirect light )으로 작용하면, 그림6 과 같은 결과가 나옵니다.

그림6. Direct light + 1-bounced indirect light. 출처 : [3].

그렇다면 광원에서 나와서 한 번 반사된( 1-bounced ) 빛이 한 번 더 반사되면( 2-bounced ) 어떻게 될까요? 다시 다른 오브젝트나 바닥으로 반사되는 빛들도 존재하겠죠? 그러면 그림7 처럼 됩니다.

그림7. Direct light + 2-bounced indirect light. 출처 : [3].

이러한 bounce 가 많으면 많을수록 더 자연스러운 결과가 나오게 됩니다.

하지만 실시간 그래픽스에서 이런 계산을 하는 것은 너무 힘듭니다. 그래서 이를 근사계산하기 위해서 LPV( Light Propagation Volume ), SVOGI( Sparse Voxel Octree Global Illumination ) 등의 실시간 GI 알고리즘들과 Image Based Lighting( IBL ) 과 같은 개념들이 나오게 되었습니다.

Indirect Lighting Bounce 설정

UE4 에서는 LPV 를 적용하지 않는 이상 Static 과 Stationary 에 대해서만 GI 를 적용해 줍니다. UE4 에서는 이를 "Lightmass Global Illumination" 이라고 표현합니다.

툴바에 있는 "Settings" 풀다운 버튼에는 "World Settings" 메뉴가 있습니다.

그림8. WorldSettings 메뉴.

거기에 보면 "Lightmass" 카테고리가 있죠. 그 중에 "Num Indirect Lighting Bounces" 항목이 있습니다. 위에서 언급했듯이, 광원에서 나온 빛이 반사되서 나오는 횟수를 의미합니다. 이것이 0 이라면 direct light 성분만을 고려하겠다는 겁니다.

그림9. Direct light only.

이제 bounce 를 2 와 4 로 주고 결과를 확인해 보도록 하겠습니다.

그림10. Direct Light + Indirect Light. Bounce 2 일 때와 4 일 때의 결과.

Bounce 가 2 일 때와 4 일 때 미약하지만 영향을 주는 범위가 넓어지는 것을 알 수 있습니다. 하지만 2 일 때와 4 일 때의 차이는 범위가 조금 넓어졌다는 것 말고는 큰 차이가 없습니다. 반사를 하면 할수록 빛이 감쇠되기 때문에 너무 높은 값을 잡아 봐야 별로 소용이 없습니다. 그러므로 2 정도의 값이 적절합니다. 이는 Lightmass 빌드 속도에도 영향을 주므로 신중하게 결정할 필요가 있습니다.

Indirect Lighting Intensity 설정

하지만 기대했던 것처럼 Indirect light 의 영향력이 크지 않아 실망하시는 분들이 계실겁니다. 이 때 사용할 수 있는 것이 "Indirect Lighting Intensity" 속성입니다. UE4 의 광원들에는 "Light" 카테고리에 "Indirect lighting Intensity" 라는 항목이 있습니다.

앞의 "Lightmass" 카테고리의  설정은 전역 설정이지만 "Light" 카테고리 설정은 개별 설정입니다. 이 값을 2 로 해 놓고 결과를 확인해 보도록 하겠습니다.

그림11. Direct Light + Indirect Light. Bounce 2 일 때와 Intensity 값을 2 배로 늘려서 결과 비교.

Intensity 를 올리면 굳이 bounce 를 올리지 않더라도 더 멀리까지 영향을 주는 것처럼 보일 수 있습니다. 물론 가까운 곳에서 indirect lighting 의 영향이 세지기는 하겠죠.

Direct Light 와 Indirect Light 의 관계

그런데 실무를 하다가 보면 이상한 의문이 드는 분들이 계실 겁니다. "Light intensity 를 내렸더니 direct lighting 성분이 내려 가고 indirect lighting 성분이 올라 가요!!!", "Lighting build 를 했더니 갑자기 결과가 너무 달라져요!!!"

그림11 까지의 스샷들은 5000 루멘을 기준으로 찍은 것입니다. 그림11 의 두 번째 환경에서 light intensity 만 100 으로 고쳐보겠습니다.

그림12. 5000 루멘에서 100 루멘으로 내렸을 때

이상한 결과가 나왔지만 매우 당연한 것입니다. Indirect lighting 이라는 것은 Lightmass 빌드를 돌려야만 계산되는 것입니다. 그래서 intensity 를 바꾸게 되면 direct lighting 성분에는 즉각 반영이 되지만, indirect lighting 성분은 이전에 계산했던 값 그대로 남아 있게 됩니다. 그러면 direct light 성분이 낮아졌으므로 indirect light 성분은 ( auto exposure 에 의해 ) 상대적으로 밝아지는 것이죠. 그러므로 stationary light 의 Intensity 값을 변경하면 반드시 Lightmass 빌드를 해 주셔야 합니다. 물론 Static 도 그래야 합니다.

이러한 사실을 이용하면 재밌는 비주얼 디버깅을 해 볼 수 있습니다. Intensity 값을 0 으로 해 버리면 direct light 성분이 평가되지 않으므로 indirect light 성분만 볼 수가 있습니다. 실제 영향을 준 범위가 어디까지인지 알 수가 있겠죠.

그림13. Intensity 를 0 으로 만들어 Indirect 성분만 확인.

Indirect light 성분을 조정하는 것은 direct light 성분에 전혀 영향을 주지 않습니다. 단지 상대적인 관계가 달라 보이는 것입니다.

Lighting Quality 와 메쉬

Lightmass 를 preview 로 빌드하면 indirect lighting 결과가 상당히 이상하게 나올 수 있습니다.

그림14. Lighting Quality 설정.

그림15 는 indirect light 가 테이블을 뚫고 나오는 것을 보여 줍니다.

그림15. Preview 에서 잘못 나오는 indirect lighting 결과.

제가 lightmass 구현을 안 봐서 잘 모르겠지만, 아마도 volume 에다가 illuminance 나 luminance 를 저장하는 것이 아닌가 싶습니다. 그리고 preview 에서 product 로 품질이 올라갈 수록 그 volume 의 크기가 조밀해지는 것이 아닌가 싶습니다. Ray 샘플 개수나 photon 개수 및 밀도 등 여러 요소들이 달라지기 때문입니다. 그렇기 때문에 샘플링되지 않은 부분들은 보간이 됩니다.

그래서 테이블의 두께를 3 배 정도로 해 봤습니다. 그랬더니 그림16 에서 볼 수 있듯이 preview 에서도 차폐가 거의 제대로 되는 것을 확인할 수 있었습니다.

그림16. 테이블의 두께를 3 배로 늘렸을 때의 결과.

사실 그림16 도 완벽한 결과는 아닙니다. Production 으로 빌드했을 때는 완벽하게 차폐가 됩니다.

여기에서 이야기하고자 하는 것은 메쉬의 두께가 얇으면 preview 에서 잘못된 결과를 산출할 수 있기 때문에 이를 고려하면서 작업을 하셔야 한다는 것입니다. 사실 너무 얇으면 production 에서도 문제가 발생합니다.

그러므로 가급적이면 너무 얇은 메쉬들은 안 만드는 것이 좋습니다. 만약 어쩔 수 없이 그런 메쉬들을 만들어야 한다면, bounce 를 1 로 설정하고 production 이나 high 품질에서 라이팅 결과를 확인하시는 것이 바람직할 것이라 생각합니다.

PostProcessVolume

전체 indirect lighting 성분을 전반적으로 올리고 싶은 경우가 있습니다. 그런 경우에는 PostProcessVolume 을 설치하시면 됩니다. "Rendering Features" 카테고리에 보면 "Global Illumination" 이라는 하위 카테고리가 있습니다.

"IndirectLightingColor" 는 전체 indirect light 성분의 색상에 곱해지며, "Indirect Lighting Intensity" 는 전체 indirect light 성분의 세기에 곱해집니다. 이런 설정은 전역적이므로 함부로 건드리지는 않는 것이 좋습니다. 라이트 설정을 다 해 놨는데 공식이 바뀌어서 전반적으로 intensity 가 달라졌다든가 하는 경우나 게임 그래픽스 컨셉상 이상한 조명을 만들고 싶다든가 하는 경우에만 사용해야겠죠.

그림17. PostProcessVolume 을 사용한 indirect 성분 조정.

여러분은 그림17 에서 보이듯이 이런 설정은 direct lighting 성분에 전혀 영향을 주지 않는다는 점을 이해해야만 합니다. Direct lighting 성분은 여전히 흰색으로 보이고 있음을 기억하세요.

참고자료

[1] Global illumination, Wikipeida.

[2] PRACTICAL REAL-TIME VOXEL-BASED GLOBAL ILLUMINATION FOR CURRENT GPUS, Alexey Panteleev, NVIDIA.

[3] Real-time Global Illumination Using Voxel Cone Tracing, Fredrik Prantare.

+ Recent posts