3D Video Production/Unreal Engine (5.6.1)

UE 5.6 Lighting: 그림자부터 Light Function까지

보별 2026. 9. 10. 16:05
반응형

지난 라이팅 포스트에서는 Directional Light와 Sky Light를 중심으로 씬 전체의 빛을 구성하고 Post Process Volume을 이용해 최종적인 화면을 조정했다.

이번에는 한 단계 더 들어가 언리얼 엔진 5.6에서 그림자가 어떤 방식으로 만들어지는지, 그리고 Point Light와 Spot Light를 어떻게 세부적으로 제어할 수 있는지 실습했다.

후반부에는 Media Texture를 이용한 스크린 조명, Light Function을 활용한 커스틱스와 움직이는 구름, Stained Glass 표현까지 만들어봤으며 마지막에는 실제 실내 씬을 대상으로 Lumen과 Volumetric Fog, IES Light를 조정했다.

단순히 값을 따라 입력하는 것보다는 어떤 설정이 그림자, 직접광, 간접광, 반사, 안개 중 무엇을 바꾸고 있는지를 구분하는 것이 이번 수업에서 특히 중요했다.

 

언리얼 엔진의 그림자 표현 방식

언리얼 엔진에서는 여러 그림자 방식을 사용할 수 있는데, 크게 Virtual Shadow Map, Shadow Map, Ray Traced Shadow 세 가지가 있다.

Virtual Shadow Map

Virtual Shadow Map, 줄여서 VSM은 언리얼 엔진 5에서 사용하는 고해상도 그림자 방식이다.

VSM은 하나의 거대한 그림자 맵을 그대로 사용하는 대신 16K 가상 섀도 맵을 작은 페이지 단위로 관리한다.
카메라에 실제로 필요한 부분을 중심으로 데이터를 처리하기 때문에 Nanite처럼 매우 세밀한 지오메트리에서도 높은 해상도의 그림자를 표현하기 좋다.

특히 광원과 오브젝트가 가까운 영역은 비교적 선명하고, 멀어질수록 자연스럽게 부드러워지는 형태의 그림자를 만들 수 있다는 장점이 있다.

Shadow Maps

Project Settings의 Shadow Map Method를 변경하면 기존 Shadow Maps 방식도 사용할 수 있다.

Rendering - Shadows - Shadow Map Method에서 다음 중 하나를 선택한다.

  • Shadow Maps
  • Virtual Shadow Maps

이번 작업에서는 Shadow Maps로 변경했을 때 Virtual Shadow Maps보다 그림자의 디테일이 떨어지고 상대적으로 흐릿해지는 차이를 확인했다.

다만 이것을 항상 "Shadow Maps는 흐린 그림자를 만든다"라고 이해하는 것보다는, VSM이 고해상도 지오메트리와 세밀한 그림자 표현에 더 적합하다고 이해하는 것이 정확하다.

Ray Traced Shadow

세 번째는 Hardware Ray Tracing을 이용해 그림자를 계산하는 방식이다.

Ray Traced Shadow는 실제 광선을 지오메트리에 추적하는 방식이기 때문에 높은 품질의 그림자를 만들 수 있지만 그만큼 GPU 비용도 증가한다.

프로젝트 전체의 기본값으로 사용하려면 Project Settings에서 Hardware Ray Tracing 지원과 Ray Traced Shadows를 활성화해야 한다.

반대로 특정 광원만 Ray Traced Shadow로 변경하고 싶은 경우 해당 Light의 Details에서 Cast Ray Traced Shadows를 Enabled로 설정할 수 있다.

Use Project Setting은 프로젝트 설정을 그대로 따르고 Disabled는 해당 Light에서 Ray Traced Shadow를 사용하지 않는다.

실제로 여러 방식을 바꿔보면 단순히 그림자가 있고 없고가 아니라 접촉 부분의 선명도와 먼 부분의 퍼짐, 작은 지오메트리의 디테일에서 차이가 느껴진다.

 

그림자가 이상할 때 확인할 부분

그림자를 만들 때 캐릭터나 모델의 지오메트리가 지나치게 단순하면 원하는 실루엣이 나오지 않을 수 있다.

Hardware Ray Tracing이나 MegaLights를 사용하는 Nanite Mesh에서는 또 하나 확인할 것이 있다.

Ray Tracing Scene에서는 상황에 따라 원본 Nanite Mesh보다 단순화된 Nanite Fallback Mesh를 사용할 수 있기 때문이다.
이 Fallback Mesh가 지나치게 단순하면 실제 화면의 모델과 그림자의 모양이 달라질 수 있다.

따라서 그림자가 이상하다면 무조건 폴리곤만 늘리기보다 Mesh 구조, Nanite, Fallback Mesh와 그림자 방식을 함께 확인하는 것이 좋다.

 

움직이는 오브젝트의 그림자가 갱신되지 않을 때

움직이는 대상의 그림자가 정상적으로 갱신되지 않는 경우, Directional Light의 Rotation을 약 0.1° 정도 변화시키는 키를 주어 그림자를 다시 계산하도록 만드는 방법을 사용했다.

이 방법은 VSM 캐시의 특성과 관련해 이해할 수 있다.

VSM은 성능을 위해 이전 프레임에서 계산한 Shadow Page를 캐싱하며, Light가 움직이거나 회전하면 해당 Light의 캐시 페이지가 무효화되어 다시 계산된다.

따라서 미세한 Rotation 변화가 그림자를 새로 계산시키는 계기가 될 수 있다.

다만 이것은 모든 움직이는 그림자 문제의 표준 해결법이라기보다는 우회 방법으로 보는 편이 좋다.

 

멀어지면 Point Light가 사라지는 이유

다음으로 라이트가 카메라에서 멀어졌을 때 사라지는 현상을 확인했다.

테스트를 위해 새 Level을 만들고 주변 환경을 어둡게 만든 뒤, Sphere와 Point Light를 배치했다.

가까이 있을 때는 Sphere와 Point Light의 영향을 모두 쉽게 확인할 수 있었지만 카메라가 멀어지자 Point Light의 효과가 사라지는 것을 볼 수 있었다.

언리얼 엔진은 화면에서 차지하는 크기가 매우 작은 라이트까지 계속 계산하지 않고 일정 크기 이하가 되면 컬링한다.

이 기준을 제어하는 콘솔 명령어가 다음과 같다.

r.MinScreenRadiusForLights 0.01

기본값은 0.03이며 값을 0.01로 낮추면 화면에서 더 작아진 라이트까지 유지할 수 있다.

다만 무작정 0에 가까운 값을 사용하는 것은 좋지 않다.
화면에서 거의 보이지 않는 수많은 Light까지 계산할 가능성이 있기 때문이다.

Point Light 자체의 Attenuation Radius를 증가시키는 것도 Light Bounds를 키우는 방법이다.

작은 Point Light가 많은 씬에서는 품질 문제처럼 보였던 현상이 사실은 이런 화면 크기 기반 최적화 때문인 경우도 있어, 먼저 라이트가 실제로 꺼진 것인지 컬링된 것인지 확인하는 것이 좋다.

 

Lighting Channel로 특정 오브젝트만 조명하기

하나의 광원이 모든 오브젝트에 영향을 주지 않도록 만들고 싶을 때는 Lighting Channels를 사용할 수 있다.

Channel 0, Channel 1, Channel 2까지 총 3개의 Lighting Channel이 있으며 기본값은 Channel 0이다.

이번 작업에서는 Point Light와 Sphere의 Channel을 서로 다르게 설정했다.

Point Light 설정

Point Light의 Lighting Channels에서 Channel 0 활성화 상태를 유지한다.

Sphere 설정

Sphere의 Lighting Channels에서는 Channel 0 비활성화 → Channel 1 활성화로 변경했다.

이렇게 하면 Point Light는 Channel 0에만 영향을 주고 Sphere는 Channel 1에만 속하기 때문에 두 채널이 겹치지 않는다.

그 결과 바닥에는 Point Light가 정상적으로 영향을 주고 있지만 Channel 1에 배치된 Sphere에는 동일한 Point Light가 영향을 주지 않는 것을 확인할 수 있다.

Lighting Channel은 특히 시네마틱에서 특정 캐릭터의 Rim Light나 보조광이 주변 배경까지 영향을 주는 것을 막을 때 유용하다.

단, 주로 Stationary/Movable Light의 동적 Direct Lighting을 대상으로 사용하는 기능이라는 제한도 기억할 필요가 있다.

 

Source Radius, Source Length와 Specular Scale

Point Light에는 단순히 Intensity와 Attenuation Radius만 있는 것이 아니다.

Source Radius는 광원의 반경을 나타낸다.

값이 커지면 광원이 한 점에서 빛나는 Point Source가 아니라 어느 정도 크기를 가진 광원처럼 동작하게 된다.

그 결과 그림자의 경계가 달라지며, 반사성이 높은 Material에서는 표면에 보이는 광원 하이라이트의 크기도 달라진다.

Source Length는 광원의 길이를 조절한다.

Source Radius와 함께 사용하면 작은 점광원보다 형광등이나 긴 전구와 비슷한 형태의 광원을 만들 수 있다.

반사성이 강한 Material에서 광원의 하이라이트가 지나치게 눈에 띈다면 Specular Scale을 낮출 수 있다.

값을 줄일수록 광원이 표면의 Specular Highlight에 미치는 영향이 약해진다.

 

Volumetric Fog에서 빛줄기 만들기

다음은 Volumetric Fog와 Light의 관계를 확인했다.

Exponential Height Fog에서 Volumetric Fog 활성화 후 Extinction Scale을 약 5까지 높여 Fog가 확실하게 보이는 상태를 만들었다.

Volumetric Fog 효과가 약한 상태에서는 Point Light 주변이 비교적 또렷하게 보이고, Volumetric Fog의 영향을 높인 뒤에는 라이트 주변의 공기까지 밝아지면서 빛이 공간에 퍼지는 느낌이 강해진다.

각 라이트에는 Volumetric Scattering Intensity가 있다.

이 값은 해당 라이트가 Volumetric Fog에 얼마나 강하게 기여할 것인지를 조절한다.
0으로 만들면 그 라이트는 Volumetric Fog에 영향을 주지 않는다.

Spot Light에서도 같은 방식으로 값을 높이면 Fog 안의 빛줄기를 더 선명하게 만들 수 있다.

다만 너무 높은 값을 사용하면 Volumetric Fog의 낮은 볼륨 샘플링 해상도가 드러나면서 계단이나 노이즈 같은 아티팩트가 더 잘 보일 수 있다.
언리얼 엔진의 Volumetric Fog는 제한된 해상도의 3D 볼륨 텍스처와 Temporal Reprojection을 사용하기 때문에 이런 특성이 있다.

Fog는 효과가 잘 보인다는 이유로 계속 수치를 높이다 보면 어느 순간부터 분위기보다 렌더링 구조가 먼저 보이기 시작해서, 필요한 정도까지만 사용하는 것이 훨씬 자연스럽다.

 

영상 화면을 실제 광원처럼 사용하기

다음으로 영상이 재생되는 Plane을 만들고 화면에서 실제 빛이 나오는 것처럼 표현했다.

우선 동영상 파일을 Import한 뒤 Media Player를 생성하고, Media Player를 열어 영상이 정상적으로 재생되는지 확인한 후 새로운 Material을 생성했다.

Material의 기본값은 다음과 같이 설정했다.

  • Base Color : Black
  • Specular : 약 0.1
  • Roughness : 약 0.1
  • Media Texture → Emissive Color

Level에는 Plane을 배치하고 이 Material을 적용한 다음, Level Sequence를 생성하고 Media Track을 추가하여 Sequencer 재생 시 영상이 같이 움직이도록 설정했다.

영상 자체의 Emissive만으로 주변까지 충분히 밝히기 어렵다면 Plane과 같은 위치에 Rect Light를 배치한다.

Rect Light의 크기를 영상 화면과 비슷하게 맞추고 빛이 영상 앞쪽으로 향하도록 배치했다.

Rect Light에는 Source Texture를 지정할 수 있다.

Source Texture는 Rect Light가 방출하는 빛의 색과 Specular Reflection에 텍스처 정보를 반영하기 위한 기능이다.

여기에 Media Texture를 사용해 화면 영상의 색을 조명에도 반영했다.

커피 영상 자체가 Emissive로 보이는 것뿐 아니라 주변 바닥까지 화면 색에 맞춰 밝아지면서 단순한 발광 Plane보다 실제 디스플레이처럼 느껴지게 된다.

이런 방식은 TV, 모니터, 광고 전광판처럼 화면 자체가 주변 공간의 조명 역할도 해야 하는 경우 특히 효과적이다.

 

많은 동적 라이트 처리하기: MegaLights

Media Texture를 Source Texture로 사용하는 Rect Light처럼 복잡한 동적 라이트를 많이 배치하면 라이팅 비용도 증가한다.

언리얼 엔진 5.6의 MegaLights는 많은 수의 동적이고 그림자를 생성하는 Local Light를 하나의 새로운 Direct Lighting 경로에서 효율적으로 처리하기 위한 기능이다.
Project Settings의 Rendering - Direct Lighting - MegaLights에서 활성화할 수 있으며, Post Process Volume을 통해 특정 영역에서 활성화 여부를 따로 Override할 수도 있다.

따라서 Project Settings와 Post Process Volume 양쪽을 모두 활성화해야 하는 것은 아니다.
프로젝트 전체 설정을 기본으로 사용하고, 필요하면 PPV에서 해당 영역만 별도로 변경하는 구조다.

MegaLights는 언리얼 엔진 5.6 기준 Beta 기능이며, 화면의 한 영역에 너무 많은 라이트가 겹치면 샘플 수가 제한되어 Noise나 Blur, Ghosting이 나타날 수 있다.
이런 경우 Attenuation Radius를 줄이거나 불필요한 Light의 범위를 정리하는 것이 좋다.

또한 언리얼 엔진 5.6에서는 Directional Light를 MegaLights가 직접 지원하지 않으며 기존 VSM 또는 Ray Traced Shadow 방식으로 처리한다.

 

빛에 무늬 입히기: Light Function

Light Function은 Light가 조사하는 영역에 Material을 이용한 패턴을 넣는 기능이다.

새 Material을 만들고 Material Domain을 Light Function으로 변경한 다음, 무늬 텍스처를 Emissive Color에 연결한다.

완성된 Material을 Spot Light의 Light Function Material에 지정하면 Spot Light가 단순한 원형 빛이 아니라 Material의 패턴을 투사하게 된다.

Caustics 표현하기

첫 번째 Light Function 작업으로 물을 통과한 빛처럼 보이는 Caustics를 만들었다.

물결 모양 텍스처를 준비하고 Light Function Material의 Emissive Color에 연결한다.

Level에 Spot Light를 배치한 뒤 해당 Material을 Light Function Material에 지정하면 바닥에 물결 형태의 밝고 어두운 패턴이 나타난다.

Spot Light의 조사 영역을 따라 바닥에 커스틱스 패턴이 투사되는 것을 확인할 수 있다.

Light Function 해상도 높이기

Light Function 패턴이 흐리게 보이는 경우 다음 콘솔 명령어를 사용했다.

r.LightFunctionAtlas.SlotResolution 2048

SlotResolution은 Light Function Atlas에서 하나의 Light Function에 할당되는 Tile 해상도를 결정한다.

값을 높이면 패턴의 세부 표현을 개선할 수 있지만, 그만큼 높은 품질을 처리해야 하므로 무조건 높은 값을 고정하기보다는 최종 화면에서 필요한 만큼 사용하는 것이 좋다.

움직이는 Caustics 만들기: Motion_4WayChaos

고정된 물결 텍스처만 사용하면 바닥에 붙어 있는 그림처럼 보인다.

이를 움직이게 만들기 위해 Engine Content에서 Motion_4WayChaos를 사용했다.

사용할 물결 텍스처를 우클릭 - Convert to Texture Object로 변경한다.

Texture Object는 Texture Sample처럼 바로 픽셀의 RGB 값을 읽어내는 노드가 아니다.

텍스처 자체를 하나의 객체로 Material Function에 전달하기 위한 형태이며 Motion_4WayChaos처럼 T2D Texture 입력을 요구하는 Material Function에서 사용한다.

Texture Object를 Motion_4WayChaos의 Texture(T2d)에 연결하고, Motion_4WayChaos의 Result를 Emissive Color에 연결했다.

Speed 조절

Motion_4WayChaos의 Speed 입력을 Promote to Parameter하여 Scalar Parameter로 만들고, 이와 함께 TexCoord와 Multiply 노드를 추가해 Coordinates 입력도 별도로 제어할 수 있도록 구성했다.

Speed는 패턴이 움직이는 속도를, TexCoord와 Multiply는 패턴의 UV 타일링을 조절하는 역할을 한다.
Speed 값을 변경하면 물결 패턴이 움직이는 속도를 Material Instance에서 쉽게 조절할 수 있다.

물결 크기 조절

TexCoord 뒤에 Multiply를 추가하고 값을 조절한 뒤 Motion_4WayChaos의 Coordinates에 연결한다.

UV 값이 커질수록 텍스처가 같은 영역에 더 많이 반복되므로 물결 무늬가 작아지고 촘촘해진다.

반대로 값을 낮추면 물결 패턴 하나하나가 더 크게 보인다.

정적인 텍스처와 달리 실제로 패턴이 흐르기 시작하면 커스틱스라는 느낌이 훨씬 강해지는 것을 확인할 수 있었다.

나뭇가지 그림자 표현하기

같은 Light Function 구조를 이용해 이번에는 나뭇가지 그림자를 만들었다.

새 Light Function Material을 만들고 나뭇가지가 들어간 흑백 텍스처를 Emissive Color에 연결한다.

이 Material을 Spot Light의 Light Function Material에 적용하면 실제 나무 모델을 배치하지 않아도 바닥에 나뭇가지 그림자가 나타난다.

창문 바깥에 나무가 있다고 가정한 실내 장면이나, 직접 나무를 카메라에 보여줄 필요 없이 그림자만 필요한 장면에서 활용하기 좋은 방식이다.

이런 방식은 실제 지오메트리를 추가하지 않고도 그림자를 연출할 수 있기 때문에 화면에 필요한 정보만 선택적으로 만드는 데 효과적이다.

구름이 흘러가는 듯한 그림자 만들기

이번에는 Noise 텍스처와 Panner를 이용해 움직이는 구름 그림자를 만들었다.

마찬가지로 Material Domain을 Light Function으로 설정한 다음, Noise 텍스처 앞에 Panner를 배치하고 Panner에는 TexCoord와 Time을 연결한다.

Panner의 Speed X 또는 Speed Y 값을 설정하면 시간이 지남에 따라 Noise 텍스처의 UV 위치가 이동한다.

그 결과 Spot Light가 비추는 영역에서 구름 그림자가 천천히 이동하는 것처럼 보인다.

구름 그림자의 크기 조절

TexCoord와 Scalar Parameter를 Multiply한 뒤 Panner의 Coordinates에 연결했다.

Scale 값이 커지면 텍스처 반복 횟수가 증가하여 Noise 패턴이 작아지고, 값을 줄이면 커다란 구름 덩어리처럼 보인다.

구름 명암 정리하기: SmoothStep

Noise 텍스처를 그대로 사용하면 전체적으로 회색이 많은 부드러운 Noise가 투사된다.

구름과 맑은 영역을 조금 더 명확하게 분리하기 위해 SmoothStep 노드를 추가했다.

SmoothStep은 입력값을 단순히 흑백으로 잘라내는 노드가 아니다.

  • Value ≤ Min → 0, 검은색
  • Value ≥ Max → 1, 흰색
  • Min과 Max 사이 → 0~1 사이를 부드럽게 보간

따라서 Min과 Max의 간격을 좁히면 흑백 영역의 경계가 더욱 뚜렷해지고, 간격을 넓히면 부드러운 전환이 많아진다.

Noise 텍스처의 회색 영역을 그대로 쓰는 것보다 SmoothStep을 거치면 구름의 덩어리가 훨씬 읽기 쉬워지는 차이가 있었다.

Stained Glass 만들기

Light Function의 응용으로 Stained Glass가 바닥에 비치는 효과도 제작했다.

먼저 Stained Glass 텍스처를 Light Function Material의 Emissive Color에 연결하고 Spot Light에 적용했다.

형태 자체는 제대로 투사되지만 결과가 흑백에 가깝게 나타났다.

언리얼 엔진 5.6에서는 Light Function Atlas의 기본 포맷이 8 Bits Gray Scale로 설정되어 있다.
따라서 기본 설정에서는 Light Function에 사용한 컬러 텍스처도 밝기 정보를 중심으로 처리되어 흑백 형태로 나타난다.

이번 실습에서는 이 문제를 해결하면서 RGB Channel의 원리도 확인하기 위해 R, G, B 세 개의 Spot Light로 텍스처의 각 Color Channel을 분리한 뒤 다시 합성하는 방식을 사용했다.

R, G, B 세 개의 Spot Light 사용하기

기존 Spot Light를 두 개 복제해 총 3개의 Spot Light를 만든다.

각 Light는 다음 색을 담당한다.

  • R Light → Red
  • G Light → Green
  • B Light → Blue

각 Spot Light의 Light Color도 담당 채널과 같은 색으로 변경한다.

이 단계에서는 같은 텍스처가 세 Light에 들어가 있기 때문에 각각이 독립적인 RGB 정보를 가지고 있지 않아 원하는 Stained Glass 색상이 나오지 않는다.

Texture Channel 분리하기

Light Function Material도 R, G, B용으로 각각 만든다.

R용 Material에서는 텍스처의 R Channel만 Emissive Color에 연결하고, G용 Material에서는 G Channel, B용 Material에서는 B Channel만 연결해 사용하도록 한다.

이후 각 Material을 같은 색의 Spot Light에 연결하게 되면, R Channel의 밝기는 빨간 Light가 담당하고 G와 B 역시 같은 방식으로 계산되면서 세 빛이 다시 합쳐진다.

그 결과 원본 Stained Glass에 가까운 컬러 패턴이 바닥에 나타난다.

Volumetric Fog를 사용하는 경우 각 Spot Light의 Volumetric Scattering Intensity를 높이면 바닥의 패턴뿐 아니라 공기 중의 컬러 Light Beam도 더욱 선명하게 표현할 수 있다.

 

실제 실내 씬 라이팅

마지막에는 지금까지 배운 내용을 실제 실내 씬에 적용했다.

기본 환경에는 다음 Actor를 사용했다.

  • Directional Light
  • Sky Light
  • Post Process Volume
  • Sky Atmosphere
  • Volumetric Cloud
  • Exponential Height Fog

먼저 Post Process Volume의 Infinite Extent (Unbound)를 활성화하고, Min EV100 / Max EV100을 동일하게 1로 고정한 뒤, Exposure Compensation은 4로 설정했다.

처음에는 빛 자체를 확인하기 위해 Fog를 꺼둔 상태에서 작업했다.

Directional Light 각도부터 잡기

실내 라이팅에서 가장 먼저 한 것은 Directional Light의 세기를 무작정 올리는 것이 아니라 창문을 통해 빛이 가장 자연스럽게 들어오는 방향을 찾는 것이다.

창문으로 들어온 Directional Light가 바닥에 강한 형태의 빛과 긴 그림자를 만들도록 했다.

실내 라이팅은 Directional Light의 Rotation을 조금만 바꿔도 바닥의 빛 모양과 가구의 그림자 위치가 크게 달라진다.

따라서 Intensity보다 먼저 화면에서 가장 중요한 빛의 형태를 결정하는 것이 좋다.

Indirect Lighting Intensity로 실내 전체 밝기 조절하기

Directional Light의 Indirect Lighting Intensity를 높이면 해당 Light가 간접광에 기여하는 정도를 높일 수 있다.

창문으로 들어온 직접광뿐 아니라 빛이 벽과 바닥에서 반사되어 실내에 퍼지는 느낌이 강해지기 때문에 어두운 실내를 밝히는 데 도움이 된다.

하지만 지나치게 높이면 직접광과 간접광의 차이가 줄어들면서 바닥의 빛 무늬가 희미해질 수 있다.

따라서 창문에서 들어오는 빛의 형태가 유지되는 범위까지만 사용하는 것이 좋다.

Diffuse Color Boost로 어두운 영역 보완하기

바닥이나 벽 Material의 Base Color가 어두우면 표면에서 반사되는 간접광 역시 줄어들기 때문에 실내 전체가 더 어둡게 느껴질 수 있다.

이때 Post Process Volume의 Lumen Global Illumination 설정에 있는 Diffuse Color Boost를 이용할 수 있다.

Diffuse Color Boost를 높이면 Lumen이 간접광 계산에 사용하는 Diffuse Color를 밝게 보정하여 어두운 영역의 간접광을 강화한다.

하지만 1보다 큰 값은 물리적으로 정확한 설정이 아니며 반사까지 과도하게 밝아질 수 있기 때문에 Epic에서는 가급적 2 미만 사용을 권장한다.

실내를 밝히기 위해 모든 Light의 Intensity를 동시에 올리는 것보다 이런 간접광 설정을 구분해서 조절하면 명암 구조를 유지하기가 훨씬 수월했다.

창문에 Rect Light를 추가해 천공광 느낌 보완하기

Directional Light만 사용하면 창문 바로 옆은 매우 밝지만 빛이 닿지 않는 벽과 구석은 지나치게 어두워질 수 있다.

이 영역을 보완하기 위해 창문에 Rect Light를 배치했다.

두 창문 영역에 각각 Rect Light를 배치했고, Light Source의 크기도 창문의 크기와 비슷하게 맞춰줬다.

Rect Light의 Intensity는 낮게 유지하고 Indirect Lighting Intensity를 약간 높여 창문 전체에서 부드러운 천공광이 들어오는 것처럼 만들었다.

이 Light의 목적은 강한 그림자를 새로 만드는 것이 아니라 창문 근처에서 자연스럽게 들어오는 Fill Light를 보충하는 것이다.

그래서 효과가 분명하게 보일 정도까지 올리기보다, Light를 끄면 약간 어둡게 느껴질 정도로 맞추는 편이 자연스럽다.

Volumetric Fog & 빛 줄기

실내의 기본 라이팅을 정리한 뒤 Exponential Height Fog를 다시 활성화했다.

Volumetric Fog를 켜고 Extinction Scale을 높인 뒤 Directional Light의 Volumetric Scattering Intensity를 증가시키면 창문으로 들어오는 빛이 공기 중에서도 보이기 시작한다.
즉 바닥에 생긴 밝은 영역뿐 아니라 창문에서 실내로 이어지는 빛 줄기가 형성된다.

이 값 역시 너무 높으면 화면 전체가 뿌옇게 되거나 Volumetric Fog의 해상도가 드러날 수 있으므로 빛줄기 자체가 주인공처럼 보이지 않는 범위에서 조절하는 것이 좋다.

실제 조명 형태 만들기: IES Light

실내의 인공 조명에는 IES Light Profile도 사용했다.

IES는 실제 조명 기구에서 측정한 빛의 방향별 밝기와 분포를 기록하는 표준 형식이다.

단순 Point Light처럼 모든 방향에 일정한 빛을 내는 것이 아니라 실제 벽등이나 다운라이트에서 나타나는 독특한 빛의 퍼짐을 표현할 수 있다.
언리얼 엔진에서는 Point, Spot, Rect Light 등에 IES Profile을 적용할 수 있다.

이번에는 Spot Light를 추가한 뒤 IES Texture에 IES Profile을 지정하고, Intensity, Attenuation Radius, Temperature 등을 조절하여 실내에서 지나치게 튀지 않고 은은하게 보이도록 맞췄다.

IES를 적용한 뒤에는 단순한 Spot Light보다 조명 기구 특유의 빛 분포가 실내에 나타나는 것을 확인할 수 있다.

바닥 Roughness 조정하기

실내 라이팅에서는 Light만 조절해서는 원하는 결과를 만들기 어렵다.

특히 강화마루처럼 코팅된 바닥은 어느 정도 Specular Reflection이 있어야 주변 Light가 자연스럽게 반사된다.

따라서 바닥 Material의 Roughness를 조절해 광원이 적절히 반사되도록 했다.

Roughness를 지나치게 낮추면 거울처럼 보일 수 있고 너무 높으면 빛의 반사가 거의 사라지므로 실제 바닥 소재에 맞는 범위를 찾는 것이 중요하다.

라이팅을 수정하다 보면 사실 Light가 부족한 것이 아니라 Material의 Roughness 때문에 빛이 보이지 않았던 경우도 있어, 둘을 따로 생각하지 않는 것이 중요했다.

실내의 빛샘 현상

벽이나 천장처럼 빛을 완전히 막아야 할 곳에서 외부 빛이 안으로 들어오는 현상을 보통 Light Leak, 빛샘 현상이라고 부른다.

이런 문제가 보이는 부분의 건물 바깥쪽에 Cube를 배치해 빛을 추가로 막을 수 있다.

이는 화면 밖에서 사용하는 실무적인 차광용 지오메트리라고 볼 수 있다.

다만 Light Leak은 지오메트리 두께나 Lumen 표현, Mesh 구조 등 여러 원인으로 나타날 수 있기 때문에 차광 Cube는 특히 영상 제작에서 빠르게 해결하기 위한 방법으로 이해하는 것이 좋다.

Lumen 품질 & Reflection 조정하기

기본 라이팅이 완성된 뒤에는 Post Process Volume의 Lumen 설정을 이용해 최종 품질을 조정했다.

Reflection의 Ray Lighting Mode를 Hit Lighting for Reflections로 설정하면 Hardware Ray Tracing을 사용할 때 Lumen Surface Cache에서 조명을 가져오는 대신 실제 Ray Hit 지점에서 Lighting을 계산한다.

Lumen Scene Lighting Quality값을 높이면 Lumen Scene의 Lighting 계산 품질이 올라간다.

특히 Reflection에 보이는 Lumen Lighting의 품질에도 영향을 줄 수 있지만 GPU 비용이 증가한다.

Lumen Scene Detail은 Lumen Scene에 어느 정도 작은 오브젝트까지 포함할지를 조절한다.

값을 높이면 작은 오브젝트까지 Lumen Scene에서 표현될 가능성이 높아지는 대신 계산량이 증가한다.

Final Gather Quality는 Lumen GI의 Final Gather 품질을 높인다.

값을 높이면 간접광의 Noise를 줄이는 데 도움이 되지만 역시 GPU 비용이 증가한다.

Lumen Reflection Quality는 Lumen Reflection의 전체적인 품질을 조절한다.
값을 높이면 Reflection에 발생하는 Noise를 줄일 수 있지만 GPU 비용도 함께 증가한다.

High Quality Translucency Reflections를 활성화하면 유리와 같은 Translucent Material의 가장 앞쪽 Layer에서 보다 높은 품질의 Mirror Reflection을 사용할 수 있다.
다만 GPU 비용이 증가하며, Project Settings에서도 해당 기능이 활성화되어 있어야 한다.

Max Reflection Bounces는 거울처럼 반사가 반복되는 표면에서 Reflection을 몇 단계까지 추적할지를 결정한다.
기본값 1에서는 2차 Reflection이 계산되지 않으며, 값을 2 이상으로 높이면 거울 속에 다시 거울이 보이는 상황 등에서 검게 빠지는 영역을 줄이는 데 도움이 될 수 있다.
다만 이 기능은 Hardware Ray Tracing과 Hit Lighting for Reflections를 사용하는 경우에 적용되며 값이 높을수록 연산 비용도 증가한다.

Max Refraction Bounces는 유리처럼 빛이 투과되는 Material에서 Refraction을 몇 단계까지 추적할지를 결정한다.
Hit Lighting을 사용할 때 0보다 높은 값을 설정하면 Translucent Mesh까지 추가로 추적하므로 유리 표현을 개선할 수 있지만 Reflection 연산 비용도 증가한다.

Lumen Scene Lighting Quality, Lumen Scene Detail, Final Gather Quality, Reflection Quality와 Reflection/Refraction Bounce 관련 값들은 모두 높일수록 품질을 개선할 수 있지만 그만큼 GPU 비용도 증가한다.
따라서 무조건 최대값으로 설정하기보다 실제 화면에서 문제가 보이는 항목만 필요한 범위까지 단계적으로 높이는 것이 좋다.

마지막으로 Sky Light의 Cubemap Resolution을 1024로 높여 환경 조명과 반사 품질을 보강했다.

Cubemap Resolution은 Sky Light가 처리하는 Cubemap의 최상위 Mip 해상도이며 2의 거듭제곱 단위로 설정된다.

최종 영상의 Reflection이나 Sky Lighting에 충분한 디테일이 필요한 경우 높은 값을 사용하고, 실시간 성능이 더 중요하다면 낮은 값과 비교하여 결정하는 것이 좋다.

 

이번 포스트에서는 단순히 Light의 Intensity를 높이고 낮추는 것보다 훨씬 다양한 요소를 다뤘다.

Virtual Shadow Map, Shadow Map, Ray Traced Shadow처럼 그림자 계산 방식 자체를 바꿀 수도 있었고 Lighting Channel을 이용해 어떤 Light가 어떤 오브젝트를 비출 것인지까지 제한할 수 있었다.

또 Light Function을 이용하면 별도의 지오메트리 없이 커스틱스와 나뭇가지 그림자, 움직이는 구름과 Stained Glass 같은 복잡한 패턴도 실제 Light처럼 투사할 수 있었다.

실내 씬에서는 Directional Light 하나를 강하게 만드는 것보다 Indirect Lighting, Diffuse Color Boost, Rect Light, Volumetric Fog, IES와 Lumen Reflection을 단계적으로 조합했을 때 훨씬 자연스러운 결과를 만들 수 있었다.

결국 라이팅에서 중요한 것은 설정을 많이 사용하는 것이 아니라, 지금 수정하고 있는 값이 직접광·간접광·그림자·반사·볼류메트릭 중 어디에 영향을 주고 있는지를 알고 조절하는 것이라고 정리할 수 있다.