Phong에서 PBR까지 (6) - PBR과 Unreal Engine

Phong에서 시작한 조명 모델이 현대 PBR과 Unreal Engine의 Base Color, Metallic, Roughness, Specular로 어떻게 이어지는지 정리합니다.

Series Phong에서 PBR까지 6 / 6

이전 편

지금까지

Phong
  ↓
Blinn-Phong
  ↓
Half Vector
  ↓
BRDF
  ↓
Microfacet
  ↓
GGX / Smith / Fresnel

까지 왔다.

그렇다면 마지막으로 PBR이 어디에 들어가는지 정리해보자.


PBR은 특정한 공식 이름이 아니다

PBR은

Physically Based Rendering

의 약자다.

중요한 것은 PBR이 GGX처럼 특정 함수의 이름이 아니라는 것이다.

PBR은 크게 말하면

현실의 빛과 물질의 동작을 기반으로 렌더링을 설계하려는 접근 방법

이다. 이를 가장 간결하게 표현하는 출발점이 렌더링 방정식이다.

$$ L_o(\omega_o)=L_e(\omega_o)+\int_{\Omega} f_r(\omega_i,\omega_o) L_i(\omega_i)\max(n\cdot\omega_i,0)\,d\omega_i $$

여기서 $L_o$는 나가는 빛, $L_e$는 표면 자체의 방출광, $L_i$는 들어오는 빛, $f_r$은 표면의 BRDF다. 적분은 표면 위쪽 반구의 모든 입사 방향을 합한다. Phong의 Diffuse와 Specular는 이 반사를 근사하는 항들로 볼 수 있다.

따라서

PBR
 ├─ BRDF
 │   ├─ Diffuse
 │   └─ Specular
 │       └─ Microfacet
 │           ├─ D
 │           ├─ G
 │           └─ F
 │
 ├─ Energy Conservation
 ├─ Fresnel
 ├─ physically meaningful parameters
 └─ Image Based Lighting ...

처럼 여러 원칙과 기법이 포함된다.

GGX는 이 커다란 구조의 일부분이다.


PBR은 왜 등장했을까?

Phong에서는 재질을 이런 식으로 만들 수 있었다.

DiffuseColor = Red
SpecularColor = White
Shininess = 37

결과는 만들 수 있지만 이 숫자들이 실제 물질의 어떤 성질을 나타내는지는 애매하다.

또 조명 환경이 바뀌면 원하는 결과를 얻기 위해 파라미터를 다시 조정해야 하는 경우가 생긴다.

PBR에서는 재질을 가능하면 현실의 특성과 연결된 값으로 표현한다.

대표적인 방식이 Metallic-Roughness Workflow다.

Unreal Engine 역시 이 방식을 사용한다.


Unreal Engine의 핵심 Material Input

Unreal에서 익숙하게 볼 수 있는 값들이 있다.

Base Color
Metallic
Roughness
Specular

Phong을 알고 있다면 처음에는 이렇게 대응시키기 쉽다.

Phong Unreal PBR
Diffuse Color Base Color
Shininess Roughness
Specular Strength Specular
없음 Metallic

하지만 이는 개념적인 대응일 뿐 정확히 같은 값은 아니다.

특히 Base Color와 Specular의 의미는 Metallic에 따라 달라진다.


Roughness

가장 직접적으로 이해하기 쉬운 값이다.

Roughness = 0

이면 매우 매끄러운 표면이다.

Microfacet의 Normal이 비교적 한 방향으로 집중되어 있다고 볼 수 있다.

      ↑ ↑ ↑ ↑
----------------

따라서 Reflection과 Specular Highlight가 선명해진다.

반대로

Roughness = 1

에 가까워질수록 Microfacet 방향이 넓게 퍼진다.

    ↖ ↑ ↗ ↘ ↙
----------------

따라서 반사가 넓게 퍼지고 흐릿해진다.

즉 Unreal의 Roughness 입력 뒤에는 지금까지 살펴본 Microfacet Distribution이라는 개념이 숨어 있다. 많은 실시간 셰이더에서 입력 Roughness $r$를 분포 함수의 매개변수 $\alpha$로 바꿀 때 다음과 같은 매핑을 사용한다.

$$ \alpha = r^2 $$

이 매핑은 흔한 선택이지 모든 렌더러에 적용되는 규칙은 아니다.


Metallic

Metallic은 물체가 금속인지 비금속인지 나타낸다.

기본적으로

Metallic = 0

이면 Dielectric, 즉 비금속으로 취급한다.

예를 들면

  • 플라스틱
  • 나무
  • 돌
  • 고무
  • 피부

등이다.

Metallic = 1

이면 Conductor, 즉 금속으로 취급한다.

예를 들면

  • 철
  • 구리
  • 금
  • 알루미늄

등이다.

순수한 재질이라면 보통 0 또는 1로 생각하는 것이 좋다.

녹이 슬거나 페인트가 벗겨진 금속처럼 서로 다른 재질이 한 texture 안에 섞일 때 중간 영역이 생길 수 있다.


왜 금속을 따로 구분할까?

금속과 비금속은 빛을 반사하는 방식이 크게 다르다.

비금속

일부 빛은 표면에서 Specular로 반사되고,

일부는 내부로 들어간 뒤 산란되어 Diffuse로 나온다.

빛
 ↓
────────
 ↗ Specular

 ↓ 내부 진입
 ↙ 산란
Diffuse

금속

빛이 내부로 들어가 Diffuse 형태로 다시 나오는 성분이 거의 없다.

대부분 표면에서 반사된다.

또 금속의 Specular Reflection에는 재질 고유의 색이 나타난다.

그래서 금, 구리 등의 반사는 색을 띤다.

Metallic이라는 하나의 값은 이러한 차이를 렌더러가 처리할 수 있도록 알려준다.


Base Color

비금속에서 Base Color는 우리가 흔히 생각하는 물체의 색, 즉 Diffuse Albedo와 가까운 의미를 가진다.

반면 금속에서는 Diffuse가 거의 존재하지 않기 때문에 Base Color가 반사 색상에 영향을 준다.

따라서

Base Color = 그냥 Diffuse Color

라고만 생각하면 PBR에서는 정확하지 않다.

Metallic 값과 함께 해석해야 한다. 전형적인 metallic-roughness 워크플로의 단순화된 해석은 다음처럼 쓸 수 있다.

$$ F_0 = (1-m)\,0.04 + m\,C_{base}, \qquad C_{diffuse}=(1-m)\,C_{base} $$

여기서 $m$은 Metallic, $C_{base}$는 Base Color다. 비금속($m=0$)은 약 0.04의 무채색 정면 반사율과 Base Color 기반 Diffuse를 갖고, 금속($m=1$)은 Base Color가 Specular 반사 색상에 들어가며 Diffuse가 사라진다. 실제 엔진은 추가 입력과 보정도 적용한다.


Specular

Unreal의 Specular는 Phong에서의 Specular Color와 같은 역할이라고 생각하면 곤란하다.

일반적인 비금속 재질에서는 기본값을 크게 건드릴 일이 많지 않다.

기본 Lit 머티리얼에서 Specular의 기본값은 0.5다. Unreal 문서는 이 값을 일반적인 비금속 재질의 약 4% 정면 반사율에 대응하는 값으로 설명한다.

따라서 물체를 덜 반짝이게 만들고 싶다고

Specular = 0

으로 만드는 것보다 대부분의 경우 Roughness를 증가시키는 것이 더 자연스럽다.


Unreal의 Material 입력은 BRDF와 어떻게 연결될까?

Material Editor의 Base Color, Metallic, Roughness, Specular는 재질을 기술하는 입력이다. 입력값을 최종 반사광으로 바꾸는 일은 선택한 Shading Model이 맡는다. 따라서 Material 입력만 보고 특정 버전의 내부 구현을 단정할 수는 없다.

Epic이 공개한 Unreal Engine 4의 실시간 셰이딩 자료는 Specular BRDF를 다음 구조로 설명한다.

D : GGX / Trowbridge-Reitz 분포
G : Smith 계열의 Geometry 항
F : Schlick 근사 Fresnel 항

이 자료는 GGX가 Unreal의 물리 기반 Specular를 이해하는 데 중요한 구체적 사례임을 보여준다. 다만 엔진 버전과 Shading Model에 따라 구현은 달라질 수 있다. Unreal Engine 5.8의 Substrate는 기존 고정 Shading Model보다 더 모듈식으로 재질을 구성하는 프레임워크다. 여기서는 특정 셰이더 구현을 모든 설정에 일반화하지 않고, 지금까지 살펴본 D / G / F를 PBR의 대표적인 설명 틀로 사용한다.

Filament는 Unreal과 별개의 렌더링 엔진이다. 따라서 Filament 문서는 Unreal의 내부 구현을 증명하는 자료가 아니라, 다른 실시간 PBR 엔진이 이 대표적인 모델을 어떻게 구체화하는지 보여주는 참고 자료로 사용한다.

Material Editor

Base Color ─────┐
Metallic ───────┤
Roughness ──────┤
Specular ───────┘
        ↓
 Unreal Shading Model
        ↓
 BRDF / Lighting 계산
        ↓
      Pixel

젖은 표면이 반짝이는 이유

여기까지 이해하면 Wetness 표현도 훨씬 자연스럽게 이해할 수 있다.

마른 표면을 생각해보자.

   ↖ ↑ ↗ ↙ ↘
----------------
Roughness 높음

표면이 젖으면 물이 미세한 요철 일부를 메우면서 광학적으로 더 매끄러운 표면처럼 보이게 된다.

     ↑ ↑ ↑
~~~~~~~~~~~~~~~~  Water
----------------
Roughness 낮음

따라서 실시간 렌더링에서는 Wetness가 증가할수록

Roughness ↓

하도록 만들어 젖은 표면 특유의 선명한 Specular Highlight를 표현할 수 있다.

즉,

Wetness ↑
    ↓
Roughness ↓
    ↓
GGX Distribution이 좁아짐
    ↓
더 선명한 Specular

이라는 관계다.

단순히

젖었으니까 Roughness를 낮춘다.

라고 외우는 것보다

Microfacet의 Normal 분포가 좁아진 것으로 모델링하기 때문에 Specular가 선명해진다.

라고 이해하면 PBR 관점에서 훨씬 자연스럽다.


Phong에서 PBR까지

지금까지의 시리즈를 한 번에 정리하면 다음과 같다.

[Phong]

R과 V가 가까운가?
        ↓
pow(R·V, Shininess)
        ↓
Specular


[Blinn-Phong]

N과 H가 가까운가?
        ↓
pow(N·H, Shininess)
        ↓
Specular


[Microfacet]

H 방향의 작은 거울이
얼마나 존재하는가?
        ↓
D

그 거울이 가려지는가?
        ↓
G

현재 각도에서
얼마나 반사하는가?
        ↓
F

        ↓

Cook-Torrance BRDF


[PBR]

물리적인 제약과
재질 파라미터를 이용해
BRDF를 구성


[Unreal Engine]

Base Color
Metallic
Roughness
Specular

        ↓

엔진 내부의
Physically Based Shading

처음에는 Phong의

pow(dot(R, V), shininess);

한 줄이면 끝나던 Specular가 왜 갑자기 GGX, Fresnel, Roughness 같은 복잡한 이야기로 변했는지 의아했다.

결국 둘은 전혀 단절된 개념이 아니었다.

Phong은 반짝임의 결과를 직접 만들어냈고, 현대 PBR은 그 반짝임이 발생하는 표면의 물리적 구조를 모델링하려고 한다.

그리고 그 사이를 연결하는 핵심 아이디어가

Half Vector → Microfacet → D/G/F

였다.

Phong을 알고 있었다면, 사실 PBR의 출발점도 이미 알고 있었던 셈이다.

참고 자료