에너지 보존: Multi-scattering과 에너지 배분

2026. 10. 5. 00:26·그래픽스

 

지금까지 그래픽스 관련 글을 적으면서 에너지 보존에 대한 언급이 몇 번 있었다.

PBR 글에서는 shadowing과 masking을 설명하면서, IBL 글에서는 마지막에 white furnace test를 해보면서 에너지 보존이 위반되고 있음을 짧게 언급했다.

 

이 글에서는 에너지 보존을 더 깊게 다룬다.

참고로, PBR와 IBL에 대한 내용을 모두 알고 있다는 전제 하에 진행한다.

 

물리 기반 렌더링(PBR)의 핵심 이론과 BRDF

Physically Based Rendering PBR은 어떠한 조명 환경에서도 일관되고 사실적으로 보이는 재질을 표현할 수 있게 해 준다.조명 환경에 따라 값을 미세조정할 필요가 없으므로, 작업 효율도 높일 수 있다.

mstone8370.tistory.com

 

Image Based Lighting - 2. Specular IBL

Specular IBL 현실의 물체를 보면, 매끄러운 표면에 반사되어 보이는 주변 환경의 모습은 선명하게 보이고, 비교적 거친 표면에서는 흐릿하게 보인다.그 이유는 표면이 거칠어질수록 미세면이 바라

mstone8370.tistory.com

 

Image Based Lighting - 3. Diffuse IBL + SH

Diffuse IBL Specular IBL에 이어서 Diffuse IBL에 대해 다룬다. Diffuse는 빛이 물체의 표면을 파고 들어갔다가 산란되어 나오는 빛으로, 반구의 모든 방향으로 퍼진다.반대로 생각해 보면, 눈에 들어오는 Di

mstone8370.tistory.com

 


기존 방식의 한계 

기존에는 단순하게 디퓨즈와 스페큘러 계산 결과를 그대로 더하는 방식을 적용했다.

 

\[f\;=\;f_d+f_s\]

 

하지만, 이 방식은 에너지 보존을 지키지 못하는 문제가 있다.

 

Single-scattering 

지금까지 다룬 모델은 빛이 미세면에서 한번만 반사되는 것을 고려한 single-scattering이었다.

Specular의 $G$ 함수가 이런 역할을 하고있다.

표면에 들어온 빛을 미세면이 가리면 shadowing, 미세면에선 반사된 빛을 다른 미세면이 가리면 masking이다.

표면이 거칠수록 미세면의 틈이 깊어지기 때문에, shadowing/masking에 의해 가려지는 빛들이 더 많아진다.

 

 

Single-scattering 모델에서는 미세면에서 한 번 반사되는 것만 고려하기 때문에 한번 가려진 빛들은 계산에서 제외된다.

따라서, 제외되는 빛이 많을수록 더 어두워지는 결과로 이어지게 된다.

이러면 표면에 들어온 빛의 에너지보다 반사되어 나오는 에너지의 양이 더 줄어드는 에너지 손실 문제가 발생한다.

만약, Roughness를 1로 지정하면 약 60%의 에너지 손실이 발생하게 된다.

 

하지만, 실제로는 빛이 가려지더라도 그 에너지가 어딘가로 사라지지는 않는다.

빛은 여러번 반사되어(multi-scattering) 미세면의 틈 밖으로 빠져나올 수 있다.

이런 경우까지 고려하여 계산하면 에너지 보존을 따를 수 있다.

 

 

기존에 사용하던 모델이 single-scattering이어서 잘못된 것은 아니다.

Single-scattering에 의해 빠져나오는 에너지만 분리하여, 이후 multi-scattering 에너지를 올바르게 계산할 수 있게 되었으니, 의도된 것에 더 가깝다.

대신, 이러한 의도에 맞게 multi-scattering까지 적용해야 더 나은 결과를 보여준다는 것에 주의해야한다.

 

Furnace test 

위에서 언급한 에너지 손실 문제를 직접 확인하기 위한 방법이 furnace test다.

빛을 온전히 반사하는 재질을 가정했을 때, 들어오는 빛과 나오는 빛의 에너지를 비교하는 방법이다.

 

Fuenace test에 사용되는 재질은, 들어오는 빛을 모두 반사하는 $F=1$의 특성을 가진다.

여기에서 $F$ 는 스페큘러의 프레넬 항이다.

따라서, $D$ 와 $G$ 항에 기반한 미세면의 기하적인 특징 만으로 평가하게 된다.

 

그리고 들어오는 빛과 나오는 빛을 서로 비교하기 위해, 주변에서 들어오는 빛은 균일한 흰색을 사용한다.

에너지 손실만 평가하기 위해서는 완전한 흰색을 사용하면 되지만, 앞으로 다룰 에너지 과잉 문제도 동시에 확인하기 위해서는 중간쯤의 회색을 사용하면 된다.

이전 글에서 다뤘던 furnace test 이미지가 회색을 사용한 결과였고, 이를 통해 비금속의 에너지 과잉 문제도 동시에 확인했다.

Furnace test 결과

 

Single-scattering과 관련해서는 들어오는 빛이 모두 스페큘러로 배분되는 금속 재질을 중심으로 보면 된다.

Single-scattering (금속)

 

에너지 배분 

표면에 들어오는 빛 에너지 중 일부는 표면에서 바로 반사되고(스페큘러), 나머지는 표면의 내부로 들어갔다가 산란되어 밖으로 빠져나온다(디퓨즈).

외부에서 들어온 빛 에너지의 양은 정해져있고, 이 중에서 일부는 스페큘러로 보내고 나머지는 디퓨즈로 보내야한다.

 

이를 결정하는 것 중 하나는 Metallic 파라미터다.

셰이딩 과정에서 float3 F0 = lerp(0.04, BaseColor, Metallic) 연산을 통해 $f_0$ 값을 결정했고, 이 값은 물체가 빛을 얼마나 반사할지를 결정하게 한다.

그리고 그만큼 $k_d$를 낮추어 디퓨즈를 줄였다.

 

하지만, 이것 만으로는 에너지가 올바르게 배분되지는 않는다.

$F$ 항에서 생략했던 파라미터인 $f_{90}$은 대부분의 물체에서 흰색이므로 $1$로 가정하고 있음을 잊지 말아야한다.

그리고 $f_{90}$은 비스듬한 표면인 grazing angle에서의 Fresnel 값이 된다.

따라서 해당 영역은 스페큘러의 비중이 높아지고, 그만큼 디퓨즈에 배분되는 에너지의 양은 감소하는 것이 올바른 계산이다.

 

지금까지는 이를 고려하지 않고 단순히 더했으므로, 비금속 물체의 grazing angle에서 에너지가 과도하게 나오는 문제가 발생한다.

에너지 배분 문제 (비금속)

 


Multi-scattering 

이 글에서는 Emmanuel Turquin(2019)$^{\textrm{[Turquin]}}$의 방식을 다룬다.

이 방식은 multi-scattering에 해당하는 양의 에너지를 보상하는 방식으로 손실된 에너지를 채운다.

 

Turquin 방식을 선택한 이유는, 실시간 렌더러에 적용할 수 있을 정도로 계산이 간단하고 구현도 쉬우며, ground truth로 평가받는 Heitz et al.(2016)$^{\textrm{[Heitz16]}}$ 논문의 분석 결과에 착안한 근사 방식이라는 점 때문이다.

 

대신, 상호성(reciprocity, $\omega_i$와 $\omega_o$를 교환해도 대칭)을 지키지 못한다는 단점이 있지만, 카메라 시점만 보면 되는 일반적인 렌더러에서는 크게 문제되지 않는다.

관련하여 OpenPBR에서도, 상호성을 지키지 못하는 문제를 심각하게 다루지 않는다고 명시했다.

 

접근 방식 

Heitz(2014)$^{\textrm{[Heitz14]}}$가 제시한 multi-scattering을 고려한 BRDF 모델은 다음과 같고, Turquin의 방식도 여기에서 시작한다.

 

\[\rho(\omega_o,\omega_i)\;=\;\rho_{ss}(\omega_o,\omega_i)\,+\,\rho_{ms}(\omega_o,\omega_i)\]

 

여기에서 $\rho_{ss}$는, 일반적인 single-scattering만 고려한 BRDF다.

 

\[\rho_{ss}\;=\;\frac{D(\mathbf{h},\alpha)\,G(\omega_o,\omega_i,\alpha)\,F(\omega_o,\mathbf{h},f_{0})}{4\left<\mathbf{n}\cdot \omega_o\right>\left<\mathbf{n}\cdot \omega_i\right>}\]

 

따라서, $\rho_{ms}$에 해당하는 multi-scattering 로브를 찾아서 더해줘야 한다.

 

여기에서 방향성 알베도($E$, directional albedo)라는 개념이 필요하다. (참고로, 머티리얼 파라미터인 albedo와는 관련 없다.)

방향성 알베도는, 반구 방향으로 부터 표면에 들어온 빛($\omega_i$) 에너지 중에서 특정 방향($\omega_o$)으로 나오는 에너지의 비율을 의미한다.

 

\[E(\omega_o)\;=\;\int_\Omega\rho(\omega_o,\omega_i)\,|\omega_i\cdot\mathbf{n}|\,\operatorname{d}\omega_i\]

 

만약 들어온 빛을 온전히 반사하는 물체가 있다고 가정해보자.

이러한 물체는 specular만 존재하는 금속 재질일 것이고, Cook-Torrance 식의 $F$ 함수의 값은 항상 $1$이 될 것이다.

Furnace 테스트에 사용되는 재질과 동일하다.

현실에 이러한 재질이 있다면, 방향성 알베도의 계산 결과는 항상 $1$이 될 것이다.

 

하지만, 현재는 $G$ 함수가 single-scattering 모델이므로 방향성 알베도의 계산 결과가 $1$보다 작은 경우가 발생한다.

그리고 그 원인은 mult-scattering에 의한 에너지를 고려하지 않았기 때문이다.

따라서, single-scattering 결과에 mult-scattering 에너지를 더하면, 에너지 보존이 성립되어 $1$이 나와야 한다.

 

\[E(\omega_o)\;=\;E_{ss}(\omega_o)+E_{ms}(\omega_o)\;=\;1\]

 

현재는 single-scattering에 따라 나오게 되는 에너지의 양을 정확히 계산할 수 있다.
($G$ 함수를 single-scattering으로 제한한 덕분)

따라서 $E_{ms}$는 다음과 같이 계산할 수 있다.

 

\[E_{ms}(\omega_o)\;=\;1-E_{ss}(\omega_o)\]

 

하지만, 이는 multi-scattering에 의한 에너지의 양이 어느 정도인지에 대한 것 뿐이다.

Multi-scattering 로브가 어떤 형태인지, fresnel을 실제로 적용하면 각각의 반사에 의한 에너지 감소는 어떻게 될 지에 대한 것은 모르는 상태다.

 

Multi-scattering Lobe 

여기에서 Turquin은 Heitz et al.(2016) 논문의 시뮬레이션 결과에 기반하여 로브 형태를 결정했다.

 

시뮬레이션 된 로브 형태 (원출처: [Heitz et al. 2016]. 재구성: [Turquin 2019])

 

시뮬레이션 결과, 2회 이상 반사된 로브의 형태는 1차 반사 로브의 형태와 유사하다.

이러한 점에 착안해서, single-scattering 로브를 스케일링 하여 multi-scattering 로브로 사용한다.

별도의 로브를 계산할 필요 없이, 기존에 존재하는 single-scattering 로브를 활용하는 간단한 방식이다.

 

여담으로, 여기에서 Kulla-Conty(2017)$^{\textrm{[Kulla]}}$의 방식과 차이가 발생한다.

Kulla와 Conty는 Kelemen et al.(2001)$^{\textrm{[Kelemen]}}$이 제시한 matte 재질의 다중 반사 보상 항에 착안하여 이를 미세면의 multi-scattering에 적용했는데, 해당 로브는 경험적인 측면에 의존했다보니 시뮬레이션 결과와 차이가 존재한다.

 

다시 돌아와서, single-scattering 로브를 multi-scattering 로브에 활용하는 BRDF 식은 다음과 같이 적을 수 있다.

 

\[\rho(\omega_o,\omega_i)\;=\;\rho_{ss}(\omega_o,\omega_i)+k_{ms}(\omega_o)\,\rho_{ss}(\omega_o,\omega_i)\]

 

이러한 접근 방식을 방향성 알베도에 적용하면 다음과 같다.

 

\[E_{ms}(\omega_o)\;=\;1-E_{ss}(\omega_o)\;=\;k_{ms}(\omega_o)\,E_{ss}(\omega_o)\]

\[k_{ms}(\omega_o)\;=\;\frac{1-E_{ss}(\omega_o)}{E_{ss}(\omega_o)}\]

\[\rho(\omega_o,\omega_i)\;=\;(1+k_{ms}(\omega_o))\,\rho_{ss}(\omega_o,\omega_i)\;=\;\frac{\rho_{ss}(\omega_o,\omega_i)}{E_{ss}(\omega_o)}\]

 

이 결과를 방향성 알베도 식에 다시 대입해보면 1이 나오는 것을 확인할 수 있다.

 

\[\begin{align}E(\omega_o)\;&=\;\int_\Omega\rho(\omega_o,\omega_i)\,|\omega_i\cdot\mathbf{n}|\,\operatorname{d}\omega_i\\[4pt]&=\;\int_\Omega\frac{\rho_{ss}(\omega_o,\omega_i)}{E_{ss}(\omega_o)}\,|\omega_i\cdot\mathbf{n}|\,\operatorname{d}\omega_i\\[4pt]&=\;\frac{E_{ss}(\omega_o)}{E_{ss}(\omega_o)}\\[4pt]&=\;1\end{align}\]

 

다음으로 필요한건 single-scattering 방향성 알베도다.

계산을 위해서는 적분을 해야하고, LUT을 사용하는 방법을 고려해볼 수 있다.

하지만 이 값은 IBL에서 이미 계산해둔 값이다.

 

Specular IBL을 적용하는 과정에서, split sum approximation을 적용하여 LD term과 DFG term으로 나누었다.

여기에서 DFG term이 single-scattering 방향성 알베도의 의미를 가진다.

 

해당 글에서 적었던 식을 그대로 가져오면,

 

\[\textrm{DFG term}\;=\;\frac{1}{N}\sum_{k}^{N}\frac{f(\mathbf{l}_k,\mathbf{v},\Theta)}{p_r(\mathbf{l}_k,\mathbf{v})}\left<\mathbf{n}\cdot\mathbf{l}_k\right>\]

 

이 식은 중요도 샘플링이 적용된 식이고 적분으로 되돌려서 방향성 알베도 식과 비교해보면,

 

\[\textrm{DFG term}\;=\;\int_\Omega f(\mathbf{l},\mathbf{v},\Theta)\left<\mathbf{n}\cdot\mathbf{l}\right>\operatorname{d}\mathbf{l}\]

\[E_{ss}(\omega_o)\;=\;\int_\Omega\rho_{ss}(\omega_o,\omega_i)\,|\omega_i\cdot\mathbf{n}|\,\operatorname{d}\omega_i\]

 

$f$는 표면에 대한 방정식으로, 이 글에서의 $\rho_{ss}$와 동일하다.

$\mathbf{l}\,$은 $\omega_i\,$이고, $\mathbf{v}\,$는 $\omega_o\,$다.

 

한 가지 차이점이라면, 여기에서는 $F=1$로 가정하고 있으니, $F_{Schlick}$ 식을 나눌 필요가 없다.

따라서, $\mathrm{DFG_1}$과 $\mathrm{DFG_2}$를 더해서 사용하면 된다.

 

\[E_{ss}(\omega_o)\;=\;\mathrm{DFG_1}+\mathrm{DFG_2}\]

 

$E_{ss}$

 

Fresnel 

지금까지는 $F=1$인 재질을 가정해서 빛을 전부 반사했다.

하지만 대부분의 재질에서는 빛의 일부가 굴절/흡수되기 때문에, 그에 따른 나머지만 반사하게 된다.

따라서 미세면에 여러번 반사될 수록 빛의 에너지는 점점 감소하게된다.

 

한 번 반사될 때마다 $F$가 곱해지므로, $k$번 반사되면 빛은 대략 $F^{k}$ 만큼 남게 된다.

이로 인해 $F<1$인 경우에는 multi-scattering에 따른 빛이 어두워지면서 채도가 올라가는 현상이 나타난다.

왼쪽부터 single-scattering, $F_{ms}$ 제외한 보상, $F_{ms}$ 포함한 보상 결과 (출처: [Turquin 2019])

 

여기에서 문제점은, $F$는 입사각에 따라 변하는데 미세면에서 여러번 반사되는 빛의 각도를 모두 알 수 없다는 것이다.

따라서 각 반사의 정확한 $F$를 구하는 대신, $F_{ms}$ 하나로 근사하는 방법을 사용한다.

Fresnel의 방향성을 고려하지 않게 되므로 상당히 많은 정보를 잃는 근사 방법이라고 볼 수 있다.

 

$F_{ms}$에 대해 다루기 전에, BRDF 식을 다시 정리하면 다음과 같이 된다.

 

\[\begin{align}\rho(\omega_o,\omega_i)\;&=\;\rho_{ss}(\omega_o,\omega_i)+F_{ms}\,k_{ms}(\omega_o)\,\rho_{ss}(\omega_o,\omega_i)\\[4pt]&=\;\left(1+F_{ms}\,k_{ms}(\omega_o)\right)\,\rho_{ss}(\omega_o,\omega_i)\\[4pt]&=\;\left(1+F_{ms}\,\frac{1-E_{ss}(\omega_o)}{E_{ss}(\omega_o)}\right)\,\rho_{ss}(\omega_o,\omega_i)\end{align}\]

 

다음으로 $F_{ms}$를 찾아야한다.

Jakob et al.(2014)$^{\textrm{[Jakob]}}$은 기하급수 유도를 통해 $F_{ms}$를 다음과 같이 정리했다. (Expanded technical report의 5.6 섹션 참고)

 

\[F_{ms}\;=\;\frac{F_{avg}\,E_{avg}}{1-F_{avg}(1-E_{avg})}\]

 

이번에 처음 나온 $F_{avg}$와 $E_{avg}$는 다음과 같다.

 

\[\begin{align}F_{avg}\;&=\;2\int_0^1F(\mu)\,\mu\,\operatorname{d}\mu\\[4pt]E_{avg}\;&=\;2\int_0^1E_{ss}(\mu)\,\mu\,\operatorname{d}\mu\\[4pt]\mu\;&=\;\left|\omega\cdot\mathbf{n}\right|\end{align}\]

 

$F_{avg}$는 Schlick 식을 쓰면 적분이 가능하다.

 

\[F_{avg}\;=\;\frac{1+20\,f_0}{21}\]

 

$E_{avg}$의 경우에는 위에서 미리 계산하여 LUT에 저장한 결과를 NoV 방향으로도 한번 적분하는 방식으로 미리 계산해둘 수 있다.

하지만, 사전 연산 과정과 LUT이 하나 더 추가되는 번거로움이 있으므로 $F_{ms}$ 식을 더 단순화하여 이 과정을 생략할 수 있다.

 

Emmanuel Turquin은 최종적으로 $F_{ms}=f_0$으로 근사했고, 다른 것들과 비교했을 때 시각적으로는 큰 차이가 없다고 했다.$^{\textrm{[Turquin]}}$

실시간 렌더러에서 사용하기 충분할 정도로 단순한 식이다.

하지만, 아티스트가 grazing angle의 색상을 임의로 지정할 수 있도록 허용하는 경우에는 $F_{ms}=F_{avg}$를 사용하는 것이 권장된다.

(참고로, Turquin 논문에서는 $F_{avg}$를 $F_{ss}$로 표기하므로, 헷갈리지 않게 주의해야한다.)

 

$F_{ms}=f_0$를 적용하여 최종적으로 식을 정리하면 다음과 같다.

 

\[\rho(\omega_o,\omega_i)\;=\;\left(1+f_{0}\,\frac{1-E_{ss}(\omega_o)}{E_{ss}(\omega_o)}\right)\,\rho_{ss}(\omega_o,\omega_i)\]

 

적용 

코드는 다음과 같이 간단하게 적용할 수 있다.

 

먼저 직접광의 경우다.

float Ess = EnvBRDF.x + EnvBRDF.y;
Specular *= 1.0 + F0 * (1.0 / Ess - 1.0);

IBL 글에서의 변수명을 그대로 가져와서 LUT의 값은 EnvBRDF로 적었다.

Specular 변수는 Cook-Torrance 계산이 끝난 스페큘러 값이다.

 

IBL에 적용하면 다음과 같다.

float3 EnvSpecular = PrefilteredColor * (F0 * EnvBRDF.x + EnvBRDF.y);

float Ess = EnvBRDF.x + EnvBRDF.y;
EnvSpecular *= 1.0 + F0 * (1.0 / Ess - 1.0);

 

결과 

각 구체의 왼쪽: multi-scattering 보상 전, 오른쪽: 보상 후

오른쪽으로 갈 수록 roughness가 증가하는 금속 재질이다.

각 구체는 이미지를 반으로 나눠서 왼쪽은 multi-scattering 보상 전, 오른쪽은 보상 후 이미지를 붙여놨다.

Multi-scattering 보상을 한 결과를 보면, roughness가 높을 수록 어두워지는 증상은 사라지고 채도가 올라가는 것을 볼 수 있다.

 

Furnace test 결과는 아래와 같다.

Furnace test 결과 (금속)

 


에너지 배분 

다음으로, 비금속의 grazing angle에서 발생하는 과도한 에너지를 방지하기 위해 에너지를 올바르게 배분해야한다.

디퓨즈는 표면 내부에 빛이 산란되어 나오는 현상이기 때문에 정확히 계산하는데에는 어려움이 있다.

대신, 스페큘러는 위에서도 다룬 것처럼 정확한 계산이 가능하기 때문에, 스페큘러를 기준으로 활용하여 디퓨즈로 가는 에너지의 양을 결정한다.

 

여기에서 위에서 다뤘던 방향성 알베도를 사용한다.

방향성 알베도 값이 특정 방향(여기에서는 시야 방향)으로 나오는 빛의 비중이므로, multi-scattering 보정까지 처리 된 이 값의 나머지는 디퓨즈로 가게 됨을 알 수 있다.

또한, 디퓨즈는 비금속에만 존재하기 때문에, 방향성 알베도는 비금속을 기준으로 계산한다.

float A = EnvBRDF.x;
float B = EnvBRDF.y;

float Ess = max(A + B, 1e-4);
float Kms = (1.0 - Ess) / Ess;

float F0 = 0.04;
float E_Dielectric  = (F0 * A + B) * (1.0 + F0 * Kms);

Diffuse *= (1.0 - E_Dielectric);

Multi-scattering 섹션의 예시 코드와 동일하게, Diffuse 변수에 담긴 값은 셰이딩이 끝난 디퓨즈 값이다.

 

결과 

각 구체의 왼쪽: 에너지 배분 전, 오른쪽: 배분 후
Furnace test 결과 (비금속)

비금속의 grazing angle에서 과하게 나오는 에너지가 없어진 것을 확인할 수 있다.

 

일반적인 배경에서는 다음과 같은 차이가 있다.

구체의 왼쪽: 에너지 배분 전, 오른쪽: 배분 후

직접광에 적용하면 다음과 같다.

왼쪽: 에너지 배분 전, 오른쪽: 배분 후

Grazing angle이 어두워지는 현상 덕분에 roughness가 낮은 비금속 재질의 묘사가 더 좋아졌다.

 


구현 

Muti-scattering과 에너지 배분을 모두 적용한 에너지 보존 코드는 다음과 같이 적을 수 있다.

// 잘못 적용된 식

float A = EnvBRDF.x;
float B = EnvBRDF.y;

float Ess = max(A + B, 1e-4);
float Kms = (1.0 - Ess) / Ess;

float3 F0 = lerp(0.04, BaseColor, Metallic);

float3 E = (F0 * A + B) * (1.0 + F0 * Kms);

Diffuse  *= (1.0 - E);
Specular *= (1.0 + F0 * Kms);

하지만, 이렇게 계산하면 중간 metallic 값을 가진 경우에는 에너지 보존이 잘못 적용되는 문제가 있다.

중간 metallic 값을 가진 경우 에너지 손실 발생

$f_0$이 이미 metallic 파라미터에 의해 보간된 값을 사용해서 발생한 문제다.

이 문제를 해결하려면, 금속과 비금속에 대한 결과를 계산한 후에 metallic 파라미터로 결과를 보간해야한다.

 

// 올바르게 적용된 식

float3 SpecularDirectionalAlbedoMS(float3 F0, float2 EnvBRDF)
{
    float A = EnvBRDF.x;
    float B = EnvBRDF.y;

    float Ess = max(A + B, 1e-4);
    float Kms = (1.0 - Ess) / Ess;
    float3 FssEss = F0 * A + B;

    return FssEss * (1.0 + F0 * Kms);
}

void ApplyEnergyConservation(float3 BaseColor, float Metallic, float2 EnvBRDF,
    inout float3 Diffuse, inout float3 Specular)
{
    float3 F0 = lerp(0.04, BaseColor, Metallic);
    float3 E_Current = F0 * EnvBRDF.x + EnvBRDF.y;

    float3 E_Dielectric = SpecularDirectionalAlbedoMS(0.04, EnvBRDF);
    float3 E_Metallic = SpecularDirectionalAlbedoMS(BaseColor, EnvBRDF);
    float3 E_Target = lerp(E_Dielectric, E_Metallic, Metallic);

    Diffuse *= (1.0 - E_Dielectric);
    Specular *= E_Target / max(E_Current, 1e-4);
}

// ...

// IBL
float3 PrefilteredColor = SpecularIBL_SplitSumApprox(Roughness, N, V);
float2 EnvBRDF = EnvironmentBRDF.SampleLevel(SamplerLinearClamp, float2(NoV, Roughness), 0).rg;

float3 EnvDiffuse = DiffuseColor * Irradiance;
float3 EnvSpecular = PrefilteredColor * (F0 * EnvBRDF.x + EnvBRDF.y);

ApplyEnergyConservation(BaseColor, Metallic, EnvBRDF, EnvDiffuse, EnvSpecular);

// ...

// 직접광
float3 AccumulatedDiffuseColor = /* 누적된 디퓨즈 셰이딩 결과 */;
float3 AccumulatedSpecularColor = /* 누적된 스페큘러 셰이딩 결과 */;

ApplyEnergyConservation(BaseColor, Metallic, EnvBRDF, AccumulatedDiffuseColor, AccumulatedSpecularColor);

 

이렇게 하면 furnace test 결과는 다음과 같다.

Furnace test 결과
IBL 결과

IBL

 

직접광

 


추가 정보 

참고하면 좋은 블로그 글 

Stephen Hill의 Self Shadow 블로그에 Multi-scattering을 자세하게 다루는 시리즈가 있다.

첫번째 글은 도입부로, 두번째 글 부터 봐도 무방하다.

Link: https://blog.selfshadow.com/2018/06/04/multi-faceted-part-2/

 

A Multi-Faceted Exploration (Part 2)

A Random Walk to the Ground Truth In the last post, we saw that significant energy was being lost due to the common single-scattering limitation of microfacet-based shading models: An intuitive way to think about this is that these BRDFs are only modelling

blog.selfshadow.com

 

Multi-scattering을 더 자세히 알고싶다면, 특히 Kulla-Conty 방식을 보고있다면 이 시리즈는 꼭 보길 바란다.

Kulla-Conty 자료에는 오류가 있어서 한번 수정된 내역이 있고, 이와 관련한 내용이 이 시리즈에 포함되어있다.

 


참고 문헌 및 자료 

$\textrm{[Turquin]}$ Emmanuel Turquin. 2019. Practical Multiple Scattering Compensation for Microfacet Models. Technical Report, Industrial Light & Magic [Link]

 

$\textrm{[Heitz14]}$ Eric Heitz. 2014. Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs. Journal of Computer Graphics Techniques (JCGT), vol. 3, no. 2 [Link]

 

$\textrm{[Heitz16]}$ Eric Heitz, Johannes Hanika, Eugene d'Eon, Carsten Dachsbacher. 2016. Multiple-Scattering Microfacet BSDFs with the Smith Model. ACM Transactions on Graphics (Proc. SIGGRAPH 2016), vol. 35, no. 4 [Link]

 

$\textrm{[Kulla]}$ Christopher Kulla, Alejandro Conty. 2017. Revisiting Physically Based Shading at Imageworks. SIGGRAPH 2017 Course: Physically Based Shading in Theory and Practice [Link]

 

$\textrm{[Kelemen]}$ Csaba Kelemen, László Szirmay-Kalos. 2001. A Microfacet Based Coupled Specular-Matte BRDF Model with Importance Sampling. Eurographics 2001 Short Presentations [Link]

 

$\textrm{[Jakob]}$ Wenzel Jakob, Eugene d'Eon, Otto Jakob, Steve Marschner. 2014. A Comprehensive Framework for Rendering Layered Materials. ACM Transactions on Graphics (Proc. SIGGRAPH 2014), vol. 33, no. 4 [Link]

 

 

'그래픽스' 카테고리의 다른 글

Image Based Lighting - 3. Diffuse IBL + SH  (0) 2026.07.12
Image Based Lighting - 2. Specular IBL  (0) 2026.05.24
Image Based Lighting - 1. Cube map  (2) 2026.03.08
물리 기반 렌더링(PBR)의 핵심 이론과 BRDF  (0) 2026.01.05
'그래픽스' 카테고리의 다른 글
  • Image Based Lighting - 3. Diffuse IBL + SH
  • Image Based Lighting - 2. Specular IBL
  • Image Based Lighting - 1. Cube map
  • 물리 기반 렌더링(PBR)의 핵심 이론과 BRDF
MildStannum
MildStannum
프로젝트의 진행 상황과 공부하면서 기억해둬야 하는 내용을 정리해서 올립니다.
  • MildStannum
    // 주석
    MildStannum
  • 전체
    오늘
    어제
    • 분류 전체보기 (56)
      • 언리얼엔진 (35)
        • 노노그램 (16)
        • FPS 프로젝트 (10)
        • 그 외 (9)
      • 그래픽스 (5)
      • 게임테크랩 1기 (8)
        • Direct3D 11 엔진 (1)
        • Audio Tracing (7)
      • DirectX11 (7)
      • etc. (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 카테고리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    루트 모션
    애니메이션
    캐릭터 무브먼트 컴포넌트
    PBR
    언리얼엔진
    Audio Tracing
    애니메이션 블루프린트 링크
    DirectX11
    슬레이트
    Unreal Engine 5
    에디터 유틸리티
    NetSerialize
    IBL
    위젯
    FPS
    게임플레이 태그
    Direct3D 11
    노노그램
    언리얼 엔진
    그래픽스
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
MildStannum
에너지 보존: Multi-scattering과 에너지 배분
상단으로

티스토리툴바