물리 기반 렌더링(PBR)의 핵심 이론을 소개하며, 마이크로페이싯 모델, 에너지 보존, 반사 방정식과 Cook-Torrance BRDF, 그리고 PBR 머티리얼 텍스처 작성 방법을 설명한다.
URL: https://learnopengl.com/PBR/Theory
Title: LearnOpenGL - Theory
PBR(보다 일반적으로는 physically based rendering, 물리 기반 렌더링으로 알려짐)은 물리 세계에 더 가깝게 맞아떨어지는 동일한 기저 이론에 (대체로) 기반한 여러 렌더링 기법들의 집합입니다. 물리 기반 렌더링은 빛을 물리적으로 그럴듯한 방식으로 모사하는 것을 목표로 하기 때문에, 일반적으로 Phong이나 Blinn-Phong 같은 기존 조명 알고리즘에 비해 더 사실적으로 보입니다. 실제 물리를 근사하기 때문에 보기 좋은 것뿐만 아니라, 우리(특히 아티스트)는 조명이 그럴듯해 보이도록 값싼 해킹이나 미세 조정에 의존하지 않고도 물리적 파라미터를 기반으로 표면 재질을 저작할 수 있습니다. 물리적 파라미터로 재질을 저작하는 큰 장점 중 하나는, 조명 조건이 달라져도 재질이 올바르게 보인다는 점입니다. 이는 비(非) PBR 파이프라인에서는 성립하지 않습니다.
그럼에도 물리 기반 렌더링은 현실의 근사(물리 원리에 기반한)일 뿐이므로 physical shading이 아니라 physically based shading이라 부릅니다. PBR 조명 모델이 물리 기반이라고 간주되려면 다음 3가지 조건을 만족해야 합니다(걱정하지 마세요, 곧 자세히 다룹니다):
다음 PBR 장들에서는 Disney가 처음 탐구하고 Epic Games가 실시간 표시를 위해 채택한 PBR 접근법에 집중할 것입니다. 이 접근은 metallic 워크플로우에 기반하며, 문서화가 꽤 잘 되어 있고, 가장 인기 있는 엔진 대부분에서 널리 채택되었으며, 시각적으로도 매우 훌륭합니다. 이 장들을 끝내면 다음과 같은 결과를 얻게 될 것입니다:

이 장들의 주제는 상당히 고급이므로 OpenGL과 셰이더 조명에 대한 이해가 충분할 것을 권장합니다. 이 시리즈에 필요한 좀 더 고급 지식은 다음과 같습니다: 프레임버퍼, 큐브맵, 감마 보정, HDR, 노멀 매핑. 또한 고급 수학도 일부 다루겠지만, 가능한 한 명확하게 개념을 설명하도록 하겠습니다.
모든 PBR 기법은 마이크로페이싯 이론에 기반합니다. 이 이론은 어떤 표면이든 미시적 스케일에서는 microfacet이라 불리는 아주 작고 완벽하게 반사하는 거울들로 기술될 수 있다고 말합니다. 표면의 거칠기(roughness)에 따라 이 작은 거울들의 정렬 상태는 크게 달라질 수 있습니다:

표면이 거칠수록 각 마이크로페이싯은 표면을 따라 더 혼란스럽게 정렬됩니다. 이 작은 거울 정렬의 효과는, 특히 정반사(specular) 조명/반사를 이야기할 때, 거친 표면에서는 들어오는 광선이 완전히 다른 방향으로 산란될 가능성이 더 크다는 점이며, 그 결과 정반사 반사가 더 넓게 퍼집니다. 반대로 매끄러운 표면에서는 광선이 대체로 같은 방향으로 반사될 가능성이 커서, 더 작고 날카로운 반사를 얻게 됩니다:

미시적 수준에서 완전히 매끄러운 표면은 존재하지 않습니다. 하지만 마이크로페이싯은 너무 작아서 픽셀 단위로 각각을 구분할 수 없으므로, 거칠기(roughness) 파라미터를 통해 표면의 마이크로페이싯 거칠기를 통계적으로 근사합니다. 표면의 거칠기에 기반해 어떤 벡터 에 대체로 정렬된 마이크로페이싯의 비율을 계산할 수 있습니다. 이 벡터 는 광원 벡터 과 뷰 벡터 사이의 중간(halfway) 벡터입니다. 중간 벡터는 고급 조명 장에서 이미 다뤘으며, 과 의 합을 그 길이로 나누어 계산합니다:
마이크로페이싯이 중간 벡터에 더 많이 정렬될수록 정반사 반사는 더 날카롭고 강해집니다. 0과 1 사이에서 변화하는 roughness 파라미터와 함께 마이크로페이싯의 정렬을 통계적으로 근사할 수 있습니다:

거칠기 값이 높을수록 정반사 반사 형태가 훨씬 더 크게 나타나는 반면, 매끄러운 표면은 더 작고 날카로운 정반사 형태를 보입니다.
마이크로페이싯 근사는 에너지 보존의 한 형태를 사용합니다: (발광 표면을 제외하면) 나가는 빛 에너지는 들어오는 빛 에너지를 절대 초과해서는 안 됩니다. 위 이미지를 보면 거칠기가 증가할수록 정반사 영역은 커지지만 밝기는 줄어듭니다. 만약 정반사 강도가 각 픽셀에서 동일했다면(정반사 형태의 크기와 무관하게), 거친 표면은 훨씬 더 많은 에너지를 방출하게 되어 에너지 보존 원리를 위반했을 것입니다. 그래서 매끄러운 표면에서는 정반사가 더 강하게, 거친 표면에서는 더 약하게 보입니다.
에너지 보존이 성립하려면 난반사(diffuse)와 정반사(specular) 빛을 명확히 구분해야 합니다. 광선이 표면에 닿는 순간, 굴절(refraction) 성분과 반사(reflection) 성분으로 나뉩니다. 반사 성분은 표면 내부로 들어가지 않고 바로 반사되는 빛으로, 우리가 정반사 조명이라 부르는 것입니다. 굴절 성분은 나머지 빛으로 표면 안으로 들어가 흡수되며, 우리가 난반사 조명이라 부르는 것입니다.
여기에는 미묘한 점이 있는데, 굴절된 빛은 표면에 닿자마자 즉시 흡수되지 않습니다. 물리학적으로 빛은 에너지의 빔으로 모델링할 수 있고, 에너지가 모두 소진될 때까지 앞으로 나아갑니다. 빛의 빔이 에너지를 잃는 방식은 충돌입니다. 각 재질은 아래 그림처럼 광선과 충돌할 수 있는 아주 작은 입자들로 이루어져 있습니다. 입자들은 충돌 때마다 빛 에너지의 일부 또는 전부를 흡수하고, 이는 열로 전환됩니다.

일반적으로 에너지가 전부 흡수되지는 않으며, 빛은 (대체로) 무작위 방향으로 계속 산란하다가 다른 입자들과 충돌하는 과정을 반복해 에너지가 고갈되거나 표면 밖으로 다시 빠져나옵니다. 표면 밖으로 재출현하는 광선은 표면에서 관측되는(난반사) 색에 기여합니다. 하지만 물리 기반 렌더링에서는 단순화를 위해, 굴절된 모든 빛이 충돌 지점의 매우 작은 영역에서 흡수되고 산란된다고 가정하여, 표면에서 떨어진 거리에서 빠져나왔을 산란광의 효과는 무시합니다. 이를 고려하는 구체적인 셰이더 기법들은 subsurface scattering(피부 산란) 기법으로 알려져 있으며, 피부/대리석/왁스 같은 재질에서 시각적 품질을 크게 높이지만 성능 비용이 듭니다.
반사와 굴절과 관련된 또 다른 미묘한 점은 금속 표면입니다. 금속 표면은 비금속(유전체, dielectrics) 표면과 빛에 대한 반응이 다릅니다. 금속 표면도 반사와 굴절의 동일한 원리를 따르지만, 굴절된 빛은 산란 없이 전부 즉시 흡수됩니다. 즉 금속 표면에는 반사/정반사 빛만 남고 난반사 색은 나타나지 않습니다. 금속과 유전체 사이의 이러한 명백한 차이 때문에, PBR 파이프라인에서 둘은 다르게 취급되며 이는 아래에서 더 다룹니다.
반사광과 굴절광의 구분은 에너지 보존에 대한 또 다른 관찰로 이어집니다: 둘은 상호 배타적입니다. 반사된 빛 에너지는 더 이상 재질에 흡수되지 않습니다. 따라서 굴절광으로 표면에 들어갈 수 있는 에너지는 반사를 고려한 뒤 남은 에너지입니다.
우리는 먼저 들어오는 빛 에너지 중 반사되는 비율(정반사 비율)을 계산함으로써 이 에너지 보존 관계를 유지합니다. 굴절광의 비율은 정반사 비율에서 바로 계산됩니다:
float kS = calculateSpecularComponent(...); // reflection/specular fraction
float kD = 1.0 - kS; // refraction/diffuse fraction
이렇게 하면 들어오는 빛이 얼마나 반사되고 얼마나 굴절되는지 알 수 있으며, 에너지 보존 원리를 지키게 됩니다. 이 접근에서는 굴절/난반사 기여와 반사/정반사 기여가 동시에 1.0을 초과하는 것이 불가능하므로, 둘의 에너지 합이 들어오는 빛 에너지를 넘지 않도록 보장합니다. 이는 이전 조명 장들에서는 고려하지 않았던 부분입니다.
여기서 렌더 방정식이라 불리는 것으로 넘어갑니다. 이는 매우 똑똑한 사람들이 고안한 정교한 방정식으로, 현재 우리가 빛의 시각적 현상을 시뮬레이션하기 위해 가진 최고의 모델입니다. 물리 기반 렌더링은 렌더 방정식의 더 특수한 버전인 반사율 방정식(reflectance equation)을 강하게 따릅니다. PBR을 제대로 이해하려면 먼저 반사율 방정식을 탄탄히 이해하는 것이 중요합니다:
반사율 방정식은 처음 보면 위압적이지만, 하나씩 해부해 보면 점차 의미가 드러납니다. 이 방정식을 이해하기 위해 약간의 복사측정학(radiometry)을 살펴봅시다. 복사측정학은 가시광을 포함한 전자기 복사의 측정입니다. 표면과 방향에 걸친 빛을 측정하는 여러 복사량이 있지만, 여기서는 반사율 방정식과 관련 있는 하나인 radiance(복사휘도)만 다루며, 여기서는 로 표기합니다. Radiance는 단일 방향에서 오는 빛의 크기/세기를 정량화하는 데 사용됩니다. Radiance는 여러 물리량의 결합이라 처음엔 이해하기 어려울 수 있으므로, 먼저 구성 요소를 살펴봅시다:
Radiant flux: radiant flux 는 광원의 전달 에너지로, 와트(W)로 측정합니다. 빛은 여러 파장에 걸친 에너지의 총합이며, 각 파장은 특정(가시) 색에 대응합니다. 따라서 광원이 방출하는 에너지는 서로 다른 파장들의 함수로 생각할 수 있습니다. 390nm에서 700nm(나노미터) 사이의 파장은 가시광 스펙트럼, 즉 사람의 눈이 지각할 수 있는 파장으로 간주됩니다. 아래는 일광의 파장별 에너지 분포 이미지입니다:

Radiant flux는 서로 다른 파장 함수의 전체 면적을 측정합니다. 파장 측정치를 직접 입력으로 쓰는 것은 다소 비실용적이므로, 우리는 종종 radiant flux를 파장별 세기의 함수가 아니라 RGB로 인코딩된 빛의 색 삼중항(보통 “빛 색”)으로 표현하는 단순화를 사용합니다. 이 인코딩은 정보 손실이 꽤 있지만, 시각적 측면에서는 보통 무시할 수 있습니다.
Solid angle: 솔리드 앵글(입체각)은 로 표기하며, 단위 구(unit sphere) 위에 투영된 도형의 크기 또는 면적을 말합니다. 단위 구에 투영된 도형의 면적이 입체각이며, 입체각은 부피를 가진 방향으로 시각화할 수 있습니다:

이 단위 구의 중심에 관측자가 있다고 생각하고 도형 방향을 바라보면, 그 실루엣의 크기가 입체각입니다.
Radiant intensity: radiant intensity(복사강도)는 입체각당 radiant flux, 즉 단위 구에 투영된 면적에 대한 광원의 세기입니다. 예를 들어 모든 방향으로 동일하게 방사하는 전방향 광원이 주어졌을 때, 복사강도는 특정 영역(입체각)에 대한 에너지를 알려줍니다:

복사강도를 나타내는 식은 다음과 같습니다:
여기서 는 입체각 에 대한 radiant flux 입니다.
Radiant flux, radiant intensity, solid angle을 알면 마침내 radiance의 방정식을 설명할 수 있습니다. Radiance는 면적 에서 입체각 에 걸친 (복사강도 를 갖는) 빛의 관측 에너지 총량으로 다음과 같이 기술됩니다:

Radiance는 면적당 빛의 양을 나타내는 복사측정학적 척도이며, 표면 법선에 대한 입사각(들어오는 각) 의 로 스케일됩니다. 빛이 표면에 직접적으로(수직으로) 닿을수록 강하고, 비스듬할수록 약합니다. 이는 기본 조명 장에서의 난반사 조명 인식과 유사하며, 는 광선 방향 벡터와 표면 법선의 내적과 직접적으로 대응합니다:
float cosTheta = dot(lightDir, N);
Radiance 방정식은 관심 있는 물리량 대부분을 포함하므로 꽤 유용합니다. 입체각 와 면적 를 무한히 작게 생각하면, 한 점에 들어오는 단일 광선의 flux를 radiance로 측정할 수 있습니다. 이 관계는 한 광선이 한 (프래그먼트) 지점에 미치는 radiance를 계산하게 해주며, 우리는 사실상 입체각 를 방향 벡터 로, 를 점 로 치환합니다. 이렇게 하면 셰이더에서 radiance를 직접 사용해 단일 광선의 프래그먼트별 기여를 계산할 수 있습니다.
실제로 radiance에 관해 우리는 보통 점 로 들어오는 모든 빛(모든 incoming radiance)의 합에 관심이 있는데, 이를 irradiance(복사조도)라 합니다. Radiance와 irradiance를 알면 반사율 방정식으로 돌아올 수 있습니다:
이제 렌더 방정식의 이 어떤 점 와 무한히 작은 입체각 (즉 들어오는 방향 벡터 로 생각 가능)에 대한 radiance를 뜻한다는 것을 알았습니다. 가 표면에 대한 입사각에 따라 에너지를 스케일하는 것을 기억하세요. 반사율 방정식에서는 이것이 로 등장합니다. 반사율 방정식은 점 에서 방향 (관측자 쪽으로 나가는 방향)로 나가는 반사 radiance 의 합을 계산합니다. 다르게 말하면 는 에서 바라볼 때 점 에 입사한 조도(irradiance)의 반사 합을 측정합니다.
반사율 방정식은 irradiance를 중심으로 합니다. 이는 단일 incoming 방향의 radiance뿐 아니라, 점 를 중심으로 한 반구 내 모든 incoming 방향의 radiance 합입니다. 반구는 표면 법선 을 중심축으로 정렬된 반쪽 구로 설명할 수 있습니다:

어떤 영역(또는 반구의 경우 부피) 안의 값의 총합을 계산하기 위해, 반사율 방정식에서는 반구 내 모든 incoming 방향 에 대해 적분(∫)이라는 수학적 도구를 사용합니다. 적분은 함수의 면적을 측정하며, 해석적으로 또는 수치적으로 계산할 수 있습니다. 렌더 방정식과 반사율 방정식 모두 해석해가 없으므로, 우리는 적분을 이산적으로 수치 해석해야 합니다. 이는 반구 에서 반사율 방정식을 작은 이산 단계로 평가한 결과를 단계 크기만큼 평균내는 것으로 바뀝니다. 이는 리만 합(Riemann sum)으로 알려져 있으며, 대략 다음 코드처럼 시각화할 수 있습니다:
int steps = 100;
float sum = 0.0f;
vec3 P = ...;
vec3 Wo = ...;
vec3 N = ...;
float dW = 1.0f / steps;
for(int i = 0; i < steps; ++i)
{
vec3 Wi = getNextIncomingLightDir(i);
sum += Fr(P, Wi, Wo) * L(P, Wi) * dot(N, Wi) * dW;
}
단계를 dW로 스케일하면 합은 적분 함수의 전체 면적/부피가 됩니다. 각 이산 단계를 스케일하는 dW는 반사율 방정식의 로 생각할 수 있습니다. 수학적으로 는 적분을 계산하는 연속적인 기호이며, 코드의 dW(리만 합의 이산 스텝)과 직접적으로 동일하진 않지만, 이런 식으로 생각하는 것이 도움이 됩니다. 이산 스텝은 항상 함수 전체 면적에 대한 근사치를 제공합니다. 주의 깊은 독자는 스텝 수를 늘리면 리만 합의 _정확도_가 올라간다는 것을 알아차릴 것입니다.
반사율 방정식은 반구 위의 모든 incoming 방향 의 radiance를, 점 에 맞고 로 스케일된 값을 합산해 관측자 방향의 반사광 를 반환합니다. Incoming radiance는 우리가 익숙한 광원에서 올 수도 있고, IBL 장에서 다룰 환경 맵(모든 incoming 방향의 radiance 측정치)에서 올 수도 있습니다.
이제 남은 유일한 미지수는 기호인데, 이는 BRDF(bidirectional reflective distribution function, 양방향 반사 분포 함수)로, 표면 재질 특성에 기반해 incoming radiance를 스케일/가중합니다.
BRDF(양방향 반사 분포 함수)는 incoming(빛) 방향 , outgoing(뷰) 방향 , 표면 법선 , 그리고 마이크로표면 거칠기를 나타내는 표면 파라미터 를 입력으로 받는 함수입니다. BRDF는 재질 특성이 주어졌을 때, 불투명(opaque) 표면에서 각 개별 광선 가 최종 반사광에 얼마나 기여하는지 근사합니다. 예를 들어 표면이 완전히 매끄럽다면(거울처럼), BRDF는 outgoing 광선 와 같은 (반사) 각도를 갖는 incoming 광선 한 개를 제외하고는 모든 에 대해 0.0을 반환하고, 그 한 광선에 대해서만 1.0을 반환할 것입니다.
BRDF는 앞서 논의한 마이크로페이싯 이론에 기반해 재질의 반사 및 굴절 특성을 근사합니다. BRDF가 물리적으로 그럴듯하려면 에너지 보존 법칙을 지켜야 합니다. 즉 반사된 빛의 합은 들어오는 빛의 양을 초과하지 않아야 합니다. 기술적으로 Blinn-Phong도 와 를 같은 입력으로 받는 BRDF로 볼 수 있습니다. 하지만 Blinn-Phong은 에너지 보존 원리를 지키지 않으므로 물리 기반으로 간주되진 않습니다. 표면의 빛 반응을 근사하는 물리 기반 BRDF는 여러 가지가 있지만, 실시간 PBR 렌더 파이프라인의 거의 대부분은 Cook-Torrance BRDF를 사용합니다.
Cook-Torrance BRDF는 난반사와 정반사 부분을 모두 포함합니다:
여기서 는 들어오는 빛 에너지 중 _굴절_되는 비율이며, 는 _반사_되는 비율입니다. BRDF의 왼쪽 항은 로 표기된 난반사 부분으로, 우리가 난반사 셰이딩에 사용했던 것과 유사한 Lambertian diffuse이며 상수 계수로 다음과 같이 표현됩니다:
여기서 는 알베도(albedo), 즉 표면 색(난반사 표면 텍스처라고 생각하면 됨)입니다. 로 나누는 것은 난반사광을 정규화하기 위함인데, 앞서 언급한 BRDF를 포함한 적분이 로 스케일되기 때문입니다(이는 IBL 장에서 다룹니다).
Lambertian diffuse가 우리가 이전에 사용한 난반사 조명(표면 색 × 법선과 빛 방향의 내적)과 어떻게 연결되는지 궁금할 수 있습니다. 내적은 여전히 존재하지만, BRDF 밖으로 이동했을 뿐입니다. 적분의 끝에 로 등장하는 것을 볼 수 있습니다. 난반사 BRDF에는 더 사실적으로 보이는 다른 방정식들도 존재하지만, 계산 비용이 더 큽니다. Epic Games의 결론에 따르면 Lambertian diffuse는 대부분의 실시간 렌더링 목적에 충분합니다.
BRDF의 정반사 부분은 좀 더 고급이며 다음과 같이 기술됩니다:
Cook-Torrance 정반사 BRDF는 세 함수와 분모의 정규화 항으로 구성됩니다. , , 는 각각 표면 반사 특성의 특정 부분을 근사하는 함수 유형을 나타냅니다. 이들은 법선 Distribution function(분포 함수), Fresnel 방정식, Geometry 함수로 정의됩니다:
각 함수는 물리학의 대응식을 근사한 것이며, 기저 물리를 서로 다른 방식으로 근사하려는 여러 버전이 존재합니다. 어떤 것은 더 현실적이고, 어떤 것은 더 효율적입니다. 어떤 근사 버전을 선택하든 괜찮습니다. Epic Games의 Brian Karis가 다양한 근사들에 대한 훌륭한 리서치를 여기에 정리해 두었습니다. 우리는 Epic Games의 Unreal Engine 4에서 사용한 것과 같은 함수를 선택할 것인데, 에는 Trowbridge-Reitz GGX, 에는 Fresnel-Schlick 근사, 에는 Smith의 Schlick-GGX를 사용합니다.
법선 분포 함수 는 (중간) 벡터 에 정확히 정렬된 마이크로페이싯의 상대 표면 면적을 통계적으로 근사합니다. Roughness 파라미터가 주어졌을 때 마이크로페이싯의 일반적 정렬을 통계적으로 근사하는 NDF는 매우 많으며, 우리가 사용할 것은 Trowbridge-Reitz GGX로 알려진 것입니다:
여기서 는 표면 마이크로페이싯과 비교할 중간 벡터이며, 는 표면 거칠기의 척도입니다. 표면 법선과 빛 방향 사이의 중간 벡터를 로 두고 다양한 roughness 파라미터에 대해 보면 다음과 같은 시각적 결과를 얻습니다:

거칠기가 낮을 때(표면이 매끄러울 때) 많은 마이크로페이싯이 작은 반경 내의 중간 벡터들에 매우 집중되어 정렬됩니다. 이 높은 집중도 때문에 NDF는 매우 밝은 점을 보여줍니다. 반면 거친 표면에서는 마이크로페이싯이 훨씬 무작위 방향으로 정렬되므로, 마이크로페이싯에 어느 정도 정렬된 중간 벡터 가 훨씬 많아지지만 덜 집중되어 더 회색빛 결과를 얻게 됩니다.
GLSL에서 Trowbridge-Reitz GGX 법선 분포 함수는 다음 코드로 옮겨집니다:
float DistributionGGX(vec3 N, vec3 H, float a)
{
float a2 = a*a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH*NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
기하 함수는 마이크로 표면 디테일이 서로를 가려 광선이 차폐(occluded)되는 상대 표면 면적을 통계적으로 근사합니다.

NDF와 마찬가지로 기하 함수는 재질의 roughness 파라미터를 입력으로 받으며, 표면이 거칠수록 마이크로페이싯이 서로를 가릴 확률이 커집니다. 우리가 사용할 기하 함수는 GGX와 Schlick-Beckmann 근사를 결합한 Schlick-GGX입니다:
여기서 는 이 기하 함수를 직접 조명(direct lighting)에 쓰는지 IBL 조명에 쓰는지에 따라 를 재매핑한 값입니다:
의 값은 엔진이 roughness를 로 변환하는 방식에 따라 달라질 수 있다는 점에 유의하세요. 다음 장들에서 이 재매핑이 어떻게/어디서 중요해지는지 자세히 논의할 것입니다.
기하를 효과적으로 근사하려면 뷰 방향(기하적 obstruction)과 광원 방향(기하적 shadowing)을 모두 고려해야 합니다. Smith의 방법을 사용하면 둘을 모두 고려할 수 있습니다:
Schlick-GGX를 로 두고 Smith의 방법을 사용하면, 다양한 roughness R에 대해 다음과 같은 시각적 결과를 얻습니다:

기하 함수는 [0.0, 1.0] 범위의 곱셈 계수이며, 1.0(흰색)은 마이크로페이싯 음영이 없음을, 0.0(검은색)은 완전한 마이크로페이싯 음영을 의미합니다.
GLSL에서 기하 함수는 다음 코드로 옮겨집니다:
float GeometrySchlickGGX(float NdotV, float k)
{
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float GeometrySmith(vec3 N, vec3 V, vec3 L, float k)
{
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx1 = GeometrySchlickGGX(NdotV, k);
float ggx2 = GeometrySchlickGGX(NdotL, k);
return ggx1 * ggx2;
}
Fresnel 방정식(발음: Freh-nel)은 굴절되는 빛에 비해 반사되는 빛의 비율을 설명하며, 이 비율은 표면을 바라보는 각도에 따라 달라집니다. 빛이 표면에 닿는 순간, 표면-뷰 각도에 따라 Fresnel 방정식이 반사되는 빛의 퍼센트를 알려줍니다. 이 반사 비율과 에너지 보존 원리로부터 굴절되는 빛의 비율을 바로 얻을 수 있습니다.
모든 표면/재질은 정면에서 볼 때의 기본 반사율(base reflectivity)을 가지지만, 각도를 두고 표면을 볼 때는 표면의 기본 반사율에 비해 모든 반사가 더 두드러지게 됩니다. 예를 들어 (아마도) 나무/금속 책상을 수직에 가깝게 볼 때는 어느 정도의 기본 반사율만 보이지만, 거의 90도에 가깝게 비스듬히 보면 반사가 훨씬 더 뚜렷해지는 것을 직접 확인할 수 있습니다. 이론적으로 모든 표면은 정확히 90도 각도에서는 빛을 완전히 반사합니다. 이 현상이 Fresnel이며 Fresnel 방정식으로 기술됩니다.
Fresnel 방정식은 꽤 복잡하지만, 다행히 Fresnel-Schlick 근사로 근사할 수 있습니다:
는 표면의 기본 반사율이며, 굴절률(indices of refraction, IOR)이라는 것으로 계산합니다. 구 표면에서 보듯이, 표면의 글레이징 각(grazing angles)으로 갈수록(중간-뷰 각도가 90도에 가까워질수록) Fresnel이 강해져 반사가 더 강해집니다:

Fresnel 방정식에는 몇 가지 미묘한 점이 있습니다. 그중 하나는 Fresnel-Schlick 근사가 사실상 유전체(비금속) 표면에 대해서만 정의된다는 점입니다. 도체(금속) 표면의 경우 굴절률로 기본 반사율을 계산하는 것이 잘 맞지 않아, 도체를 위한 다른 Fresnel 방정식이 필요합니다. 이는 번거로우므로, 우리는 표면에 정면(normal incidence)으로 입사했을 때(0도) 표면의 응답 을 미리 계산해 두는 추가 근사를 사용합니다. 그리고 Fresnel-Schlick 근사에 따라 뷰 각도에 기반해 이 값을 보간하여, 금속과 비금속 모두에 같은 방정식을 사용할 수 있게 합니다.
정면 입사에서의 표면 응답(기본 반사율)은 이런 큰 데이터베이스에서 찾을 수 있으며, Naty Hoffman의 강의 노트에서 가져온 더 흔한 값들을 아래에 나열합니다:
| Material | F 0 (Linear) | F 0 (sRGB) | Color |
|---|---|---|---|
| Water | (0.02, 0.02, 0.02) | (0.15, 0.15, 0.15) | |
| Plastic / Glass (Low) | (0.03, 0.03, 0.03) | (0.21, 0.21, 0.21) | |
| Plastic High | (0.05, 0.05, 0.05) | (0.24, 0.24, 0.24) | |
| Glass (high) / Ruby | (0.08, 0.08, 0.08) | (0.31, 0.31, 0.31) | |
| Diamond | (0.17, 0.17, 0.17) | (0.45, 0.45, 0.45) | |
| Iron | (0.56, 0.57, 0.58) | (0.77, 0.78, 0.78) | |
| Copper | (0.95, 0.64, 0.54) | (0.98, 0.82, 0.76) | |
| Gold | (1.00, 0.71, 0.29) | (1.00, 0.86, 0.57) | |
| Aluminium | (0.91, 0.92, 0.92) | (0.96, 0.96, 0.97) | |
| Silver | (0.95, 0.93, 0.88) | (0.98, 0.97, 0.95) |
흥미로운 점은 모든 유전체 표면의 기본 반사율이 0.17을 넘지 않는다는 것입니다(0.17은 오히려 예외에 가깝습니다). 반면 도체의 기본 반사율은 훨씬 높게 시작하며 (대체로) 0.5에서 1.0 사이에서 변합니다. 또한 도체(금속 표면)의 기본 반사율은 색이 입혀져(tinted) 있습니다. 그래서 를 RGB 삼중항으로 제시합니다(정면 입사의 반사율은 파장별로 달라질 수 있음). 이는 금속 표면에서만 오직 관찰되는 특징입니다.
유전체와 비교한 금속 표면의 이런 특정 속성은 metallic workflow라는 개념을 낳았습니다. metallic workflow에서는 표면이 금속인지 비금속인지(유전체인지)를 나타내는 metalness라는 추가 파라미터로 재질을 저작합니다.
이론적으로 재질의 metalness는 이진입니다. 금속이거나 아니거나 둘 중 하나이지, 둘 다일 수는 없습니다. 그러나 대부분의 렌더 파이프라인은 metalness를 0.0과 1.0 사이에서 선형으로 설정할 수 있게 합니다. 이는 주로 재질 텍스처 정밀도가 부족하기 때문입니다. 예를 들어 금속 표면 위에 작은(비금속) 먼지/모래 같은 입자/스크래치가 있는 경우, 이진 metalness 값으로는 표현하기 어렵습니다.
유전체와 도체에 대해 을 미리 계산해두면 두 표면 타입 모두에 같은 Fresnel-Schlick 근사를 사용할 수 있지만, 금속 표면이라면 기본 반사율에 색을 입혀야 합니다. 보통 다음과 같이 처리합니다:
vec3 F0 = vec3(0.04);
F0 = mix(F0, surfaceColor.rgb, metalness);
대부분의 유전체에 대해 근사한 기본 반사율을 정의합니다. 이 또한 근사인데, 가 대부분의 흔한 유전체 주변에서 평균화되었기 때문입니다. 기본 반사율 0.04는 대부분의 유전체에 잘 맞으며, 추가 표면 파라미터를 저작하지 않아도 물리적으로 그럴듯한 결과를 만듭니다. 그 다음 표면이 얼마나 금속인지에 따라 유전체 기본 반사율을 쓰거나, 표면 색으로 저작된 을 사용합니다. 금속 표면은 굴절된 빛을 전부 흡수하므로 난반사 반사가 없고, 표면 색 텍스처를 기본 반사율로 바로 사용할 수 있습니다.
코드에서 Fresnel Schlick 근사는 다음과 같습니다:
vec3 fresnelSchlick(float cosTheta, vec3 F0)
{
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}
여기서 cosTheta는 표면 법선 과 중간 벡터 (또는 뷰 ) 방향 간의 내적 결과입니다.
Cook-Torrance BRDF의 모든 구성 요소를 설명했으니, 물리 기반 BRDF를 최종 반사율 방정식에 포함할 수 있습니다:
다만 이 방정식은 완전히 수학적으로 정확하진 않습니다. Fresnel 항 가 표면에서 _반사_되는 빛의 비율을 나타낸다는 것을 기억할 것입니다. 이는 사실상 우리의 비율 이므로, 반사율 방정식의 정반사(BRDF) 부분에는 반사 비율 가 암묵적으로 포함되어 있습니다. 따라서 최종(최종의 최종) 반사율 방정식은 다음과 같습니다:
이 방정식은 이제 일반적으로 우리가 물리 기반 렌더링(PBR)이라 이해하는 물리 기반 렌더 모델을 완전히 기술합니다. 지금 당장 논의된 수학을 코드에서 어떻게 맞춰 넣어야 하는지 완전히 이해하지 못해도 괜찮습니다. 다음 장들에서 반사율 방정식을 활용해 렌더 조명에서 훨씬 더 물리적으로 그럴듯한 결과를 얻는 방법을 탐구할 것이며, 모든 조각들이 서서히 맞춰질 것입니다.
PBR의 기저 수학 모델을 이해했으니, 마지막으로 아티스트들이 표면의 물리적 속성을 어떻게 저작하여 PBR 방정식에 직접 넣는지 설명하겠습니다. PBR 파이프라인에 필요한 각 표면 파라미터는 텍스처로 정의하거나 모델링할 수 있습니다. 텍스처를 사용하면 프래그먼트 단위로 각 표면 점이 빛에 어떻게 반응할지 제어할 수 있습니다. 즉 그 점이 금속인지, 거친지 매끈한지, 또는 서로 다른 파장의 빛에 표면이 어떻게 반응하는지 등을 제어합니다.
아래는 PBR 파이프라인에서 자주 보게 되는 텍스처 목록과, 이를 PBR 렌더러에 제공했을 때의 시각적 출력입니다:

Albedo: 알베도 텍스처는 각 텍셀마다 표면의 색을 지정하거나, 해당 텍셀이 금속이라면 기본 반사율을 지정합니다. 이는 이전에 사용했던 diffuse 텍스처와 대체로 비슷하지만, 텍스처에서 모든 조명 정보가 제거되어 있습니다. Diffuse 텍스처에는 종종 약한 그림자나 어두워진 틈새가 이미지에 포함되는데, 알베도 텍스처에는 이런 것이 있으면 안 됩니다. 알베도는 표면의 색(또는 굴절에 의한 흡수 계수)만을 담아야 합니다.
Normal: 노멀 맵 텍스처는 노멀 매핑 장에서 사용했던 것과 동일합니다. 노멀 맵은 프래그먼트마다 고유한 법선을 지정해, 평평한 표면보다 더 울퉁불퉁한 듯한 착시를 줍니다.
Metallic: 메탈릭 맵은 텍셀마다 금속인지 아닌지를 지정합니다. PBR 엔진 설정에 따라 아티스트는 metalness를 그레이스케일 값으로 저작하거나, 흑/백의 이진 값으로 저작할 수 있습니다.
Roughness: 러프니스 맵은 텍셀마다 표면이 얼마나 거친지 지정합니다. 샘플링된 roughness 값은 표면의 통계적 마이크로페이싯 방향에 영향을 줍니다. 거친 표면은 더 넓고 더 흐릿한 반사를 만들고, 매끈한 표면은 집중되고 선명한 반사를 만듭니다. 일부 PBR 엔진은 roughness 맵 대신 smoothness 맵을 기대하는데, 이를 더 직관적이라 느끼는 아티스트도 있습니다. 이런 값들은 샘플링 시점에 (1.0 - smoothness)로 roughness로 변환됩니다.
AO: 앰비언트 오클루전(AO) 맵은 표면 및 주변 지오메트리의 추가적인 음영 계수를 지정합니다. 예를 들어 벽돌 표면이라면, 알베도 텍스처에는 벽돌 틈새 내부의 그림자 정보가 없어야 합니다. 그러나 AO 맵에는 빛이 빠져나가기 더 어려운 어두운 모서리들이 포함됩니다. 조명 단계 끝에서 앰비언트 오클루전을 고려하면 씬의 시각적 품질이 크게 향상될 수 있습니다. 메시/표면의 앰비언트 오클루전 맵은 수동으로 생성하거나 3D 모델링 프로그램에서 사전 계산됩니다.
아티스트는 이러한 물리 기반 입력값을 텍셀 단위로 설정/조정하며, 텍스처 값을 실세계 재질의 물리적 표면 특성에 기반해 만들 수 있습니다. 이는 PBR 렌더 파이프라인의 가장 큰 장점 중 하나로, 표면의 물리적 속성은 환경이나 조명 설정과 무관하게 동일하게 유지되므로, 아티스트가 물리적으로 그럴듯한 결과를 얻기가 훨씬 쉬워집니다. PBR 파이프라인으로 저작된 표면은 서로 다른 PBR 렌더 엔진 간에도 쉽게 공유될 수 있고, 어떤 환경에서도 올바르게 보이며, 결과적으로 훨씬 더 자연스럽게 보입니다.