Yu-ki 016 군의 재미있는 리서치 기록을 번역 해 봤습니다.~ 관련 된 몇 가지 그의 글과 엮일 타래글 모두 조만간 번역글로 올려보겠습니다.
작성자 : Yu-ki016
1. 서론
이전 글에서는 직접 조명을 추가했으며, 이번에는 환경광과 GI를 추가하는 방법에 대해 다루겠습니다.

이 글에서 언급하는 Lumen은 실제로 Lumen의 Diffuse를 의미하며, Specular에 대한 수정은 포함하지 않습니다. 현재 Specular에 대해서는 특별한 아이디어가 없는 상황입니다.
1.1 구면 조화 함수와 Lumen
Unity를 사용하는 경우, 많은 분들이 구면 조화 조명을 환경광으로 사용합니다. 일반적으로 법선을 평평하게 만들어 좀 더 평평한 구면 조화 조명을 계산하거나, 1차 구면 조화 함수를 환경광으로 직접 사용합니다.
养乐多 님의 영상에서도 UE에서 구면 조화 함수를 사용하는 방법을 제공하고 있습니다:
float4 NormalVector = float4 (Normal,1.0f);
float3 Intermediate0,Intermediate1,Intermediate2;
Intermediate0.x = dot(View_SkyIrradianceEnvironmentMap[0],NormalVector);
Intermediate0.y = dot(View_SkyIrradianceEnvironmentMap[1],NormalVector);
Intermediate0.z = dot(View_SkyIrradianceEnvironmentMap[2],NormalVector);
float4 vB = NormalVector.xyzz * NormalVector.yzzx;
Intermediate1.x = dot(View_SkyIrradianceEnvironmentMap[3],NormalVector);
Intermediate1.y = dot(View_SkyIrradianceEnvironmentMap[4],NormalVector);
Intermediate1.z = dot(View_SkyIrradianceEnvironmentMap[5],NormalVector);
float4 Vc = NormalVector.x * NormalVector.x - NormalVector.y * NormalVector.y;
Intermediate2 = View_SkyIrradianceEnvironmentMap[6].xyz * Vc;
return max(0,Intermediate0+Intermediate1+Intermediate2);
하지만 UE에는 이미 Lumen이 있는데 구면 조화 함수를 사용하는 것은 Lumen의 특성을 충분히 활용하지 못하는 것입니다. 게다가 Lumen은 GI 정보도 포함하고 있어, GI가 포함된 카툰 렌더링은 상당히 흥미로운 결과를 만들어냅니다.
구면 조화 함수 자체도 GI를 포함할 수 있지만, UE는 Unity와 같은 라이트 프로브가 없습니다.
역자 추가.
↑해당 설명은 부정확합니다.
원문에서는 "UE는 Unity와 같은 라이트 프로브가 없습니다"라고 했지만 Lumen은 실제로 화면 공간 실시간 프로브(Screen Space Radiance Cache)를 사용합니다. Lumen의 GI 시스템은 Software Ray Tracing, Surface Cache, Radiance Cache 등 여러 기술을 조합하여 작동합니다.
따라서 더 올바른 설명으로 교정 하자면 "UE는 Unity와 같은 정적 라이트 프로브가 없지만, Lumen의 동적 프로브 시스템을 통해 실시간으로 GI 정보를 수집합니다" 라고 여겨져야 합니다.
Lumen의 화면 공간 프로브
맞습니다. Lumen은 실제로 화면 공간 실시간 프로브(Screen Space Radiance Cache)를 사용합니다. Lumen의 GI 시스템은 다음과 같은 여러 기술을 조합하여 작동합니다:
- Software Ray Tracing: 거리 필드를 사용한 소프트웨어 레이 트레이싱으로 장면의 기하학 정보를 추적합니다.
- Surface Cache: 장면의 표면에 대한 라이팅 정보를 캐싱하여 재사용합니다.
- Radiance Cache: 화면 공간에 배치된 프로브들이 간접광 정보를 수집하고 저장합니다.
- Screen Space Tracing: 화면에 보이는 영역에 대해 빠른 레이 트레이싱을 수행합니다.
이러한 프로브 기반 시스템 덕분에 Lumen은 실시간으로 동적 GI를 계산할 수 있지만, 동시에 이로 인해 발생하는 높은 주파수의 디테일이 카툰 렌더링에는 과도할 수 있습니다. 따라서 본문에서 제안한 DownSample과 blur를 통한 주파수 감소 처리가 필요한 것입니다.
1.2 Lumen 수정 방향

Lumen의 효과를 관찰해 보겠습니다:

어두운 환경에서 Lumen이 계산한 간접광 효과는 매우 견고하고 입체감이 강한 것을 확인할 수 있습니다.
Lumen의 효과를 강조하기 위해 위 이미지에서는 SkyLight를 껐습니다.
그러나 밝은 조명 환경에서는 Lumen의 과도한 입체감으로 인해 캐릭터의 어두운 부분이 다소 "플라스틱 같은" 느낌을 주게 됩니다.
Lumen은 강한 입체감과 풍부한 GI 정보를 가지고 있지만, 카툰 렌더링 관점에서 보면 이러한 정보의 "주파수"가 너무 높습니다(카툰 렌더링은 본래 화면을 단순화하는 작업이므로). 따라서 Lumen에 대해 주파수 감소 처리가 필요합니다.
주파수 감소를 수행하려면, 가장 먼저 떠오르는 알고리즘은 blur일 것입니다. 넓은 범위의 blur를 수행하려면 많은 양의 컨볼루션 연산이 필요하여 비용이 상당히 높습니다. 하지만 GI의 정확도에 대한 요구사항이 그리 높지 않으므로, 좀 더 과감하게 DownSample을 여러 번 수행한 후 blur를 적용할 수 있습니다.
다음은 Lumen에 대해 6번의 DownSample을 수행한 후 쌍선형 보간 샘플링을 적용한 결과입니다. 이미 매우 부드러우며 기본적으로 사용 가능한 수준이지만, 픽셀 간의 격자가 약간 보일 수 있습니다:

결함을 더 줄이고 싶다면, 위의 결과에 컨볼루션을 한 번 더 적용할 수 있습니다:

이제 이 결과를 원본 Lumen과 Lerp 처리하면 거의 완성입니다. 핵심 코드는 다음과 같습니다:

위 코드에서 Lerp 전에 Lumen을 Lab 색공간으로 변환한 후, L과 ab를 각각 보간하여 명도와 색상의 보간 비율을 개별적으로 조정할 수 있도록 했습니다.

밝은 조명 환경에서의 Toon Lumen 표현도 확인해 보겠습니다:

위 이미지의 보간 비율은 명도 0.75, 색상 0.5입니다.
2. 코드 구현
이번 글의 코드 구현은 매우 간단하며, 수정할 부분이 많지 않습니다.
2.1 Post 매개변수 및 DownSample 추가
먼저 후처리 박스에 Toon Lumen 효과를 조정하기 위한 매개변수를 추가하겠습니다.
FPostProcessSettings에 새로운 속성들을 추가합니다:

Scene.h

Scene.h

위 매개변수들의 기본값은 다음과 같습니다:

Scene.cpp
이 부분은 후처리 박스 매개변수 보간을 제어하는 곳으로 보이며, 여기에도 추가해 줍니다:

SceneView.cpp
FLumenToonParameters를 추가하여, 이 구조체를 통해 매개변수를 shader에 전달합니다:

LumenReflections.h
FLumenToonParameters의 Get 메서드입니다:

LumenReflectionTracing.cpp
FDiffuseIndirectCompositePS에 매개변수를 추가합니다. DownSampleInput은 나중에 전달할 DownSample LumenDiffuse입니다:

IndirectLightRendering.cpp
이제 Toon 관련 Lumen 매개변수를 shader에 전달하고, Lumen Diffuse에 대해 DownSample을 수행합니다. 여기서는 FSceneDownsampleChain을 사용하여 DownSample을 수행합니다. UE가 Bloom을 계산할 때 사용하는 것으로, 직접 가져다 사용하면 매우 편리합니다.

IndirectLightRendering.cpp
shader에 매개변수 선언을 추가합니다:

DiffuseIndirectComposite.usf
2.2 Toon Lumen 계산
이전에 비활성화했던 Lumen 효과를 다시 활성화합니다:

DiffuseIndirectComposite.usf
Toon Lumen의 계산은 이것이 전부입니다:

DiffuseIndirectComposite.usf
3. 참고 자료 및 링크
3.1 링크
본문의 Markdown 파일과 이미지는 github에 업로드되어 있으며, 이미지가 잘 보이지 않는 경우 여기에서 원본을 확인하실 수 있습니다:
본문의 모든 수정 사항은 github에 업로드되어 있으며, 아래 이미지의 커밋 기록에 해당합니다:
https://github.com/Yu-ki016/UnrealEngine/tree/YK_Engine
3.2 참고 자료
【Unity/虚幻5/Blender】3가지 엔진 붕괴: 성궤열차 스타일 카툰 렌더링 구면 조화 조명부터 눈썹이 앞머리를 투과하는 것까지 전체 프로세스:
虚幻5 렌더링 프로그래밍(스타일라이즈드 렌더링 편)[제8권: Toon Lumen GI in UnrealEngine5]:
UE5【실전】3.카툰 렌더링 개선-Shadow&Shading&Lumen:
虚幻5 Lumen 조명 하에서의 ToonShading과 AO 수정:
원문
(45 封私信 / 21 条消息) 【UE5】卡通渲染着色篇4:环境光与GI - 知乎
'TECH.ART.FLOW.IO' 카테고리의 다른 글
| [번역] Unity - PBR과 PBR+NPR 캐릭터 렌더링 연구 (0) | 2025.10.25 |
|---|---|
| [번역] UE5. 앰비언트 라이트 및 GI 2: 노멀 스무딩하기 (0) | 2025.10.23 |
| [번역] UE5 Shell-Fur 모발 렌더링 구현 (0) | 2025.10.23 |
| [번역] UE5 머티리얼에서 렌더링 파이프라인 텍스처 접근하기 (1) | 2025.10.20 |
| [번역] PredictFootIK 구현 (0) | 2025.10.15 |