Post Lists

2018년 8월 19일 일요일

Physically Based Rendering - Theory (1)

https://learnopengl.com/PBR/Theory

Theory
PRB, 또는 physically based rendering(물리 기반 렌더링)이라고 좀 더 흔히 알려진 것은 다소 물리적 세계에 좀 더 부합하는 같은 밑에 깔려있는 이론을 기반으로하는 렌더링 테크닉의 collection이다. PBR이 물리적으로 그럴듯한 방법으로 빛을 흉내내는 것을 목표로 하기 때문에, 그것은 일반적으로 Phong과 Blinn-Phong같은 우리의 원래 라이팅 알고리즘들과 비교해서 좀 더 현실적으로 보인다. 그것은 더 좋게 보일 뿐만 아니라, 그것은 실제 물리학을 근사하기 때문에, 우리는 (그리고 특히 예술가들) 가벼운 hacks와 lighting을 올게 보이게 만들려는 tweaks에 의존하는 것 없이 물리적 파라미터를 기반으로 surface materials를 관장할 수 있다. 물리적 파라미터들을 기반으로 materials들을 관리하는 것의 더욱 큰 이점 중의 하나는 이러한 물질들이 lighting conditions에 상관없이 옳게 보일 것이라는 것이다; non-PBR 파이프라인에서는 사실이 아닌 것이다.

PBR은 여전히 그럼에도 불구하고 현실에 대한 근사이다 (물리학의 원칙을 기반으로), 그리고 그것이 왜 physical shading이 아닌 physically based shading이라고 불려지는 이유이다. PBR lighting model을 물리적 기반으로 고려하는 것에 대해, 그것은 다음의 3개의 조건을 만족해야만 한다 (걱정하지 말아라, 우리는 곧 충분히 그것들을 이해할 거싱다):

  1. microfacet surface model을 기반으로 한다.
  2. energy conserving (에너지보존)적이여야 한다.
  3. physically based BRDF를 사용해라.
이 PBR 튜토리얼 시리즈/가이드에서, 우리는 Disney에서 원래 탐헌되고, Epic Games에 의해 만들어진 real-time display를 위해 채택된 PBR 접근법에 집중할 것이다. metallic workflow를 기반으로 한 그들의 접근법은 멋지게 문서화되어있고, 대부분의 인기 있는 엔진에서 널리 채택되고, 시각적으로 엄청 좋아 보인다. 그 시리즈의 끝에서, 우리는 이것처럼 보이는 어떤 것을 얻을 것이다:

이 튜토리얼 시리즈에서 그 주제들은 고급의 것이라고 명심해라. 그래서 OpenGL과 shader lighting에 대한 좋은 이해를 가질 것이 충고된다. 너가 이 시리즈들을 위해 필요할 고급 지식들은 : framebuffers, cubemaps, gamma correction, HDR, and normal mapping 이다. 우리는 또한 몇 가지 고급 수학을 알아볼 것이지만, 나는 그 개념을 가능한 깔끔하게 설명하도록 최선을 다 할 것이다.

The microfacet model
모든 PBR 기법들은 microfacets의 이론을 기반으로 한다. 그 이론은 미세한 scale에서의 어떤 표면은 microfacets이라고 불리는 아주 작은 완벽하게 반사시키는 거울에 의해 묘사되어질 수 있다는 것을 설명한다. 표면의 거칠기에 따라, 이러한 아주 작은 거울들의 정렬은 꽤 많이 다를 수 있다:

표면이 거칠수록, 각 microfacet는 표면을 따라 더 혼돈스럽게 정렬되어있을 것이다. 이러한 아주작은 것 같은 mirror alignments의 효과는 specular lighting/reflection에 대해 특정하게 말할 때, 들어오는 광선이 더 거친 표면에서 완전히 다른 방향을 따라서 흩뿌려질 가능성이 높다는 것이다. 그리고 이것은 좀 더 넓게 펄쳐진 specular reflection을 만들어낸다. 대조적으로 부드러운 표면에서, 광선들은 대강 같은 방향으로 반사할 가능성이 높다. 그리고 이것은 더 작고 더 날카로운 반사를 준다:

어떤 표면도 완전히 microscopic level에서 부드럽지 않지만, 이러한 microfacets들이 충분히 작아서 우리가 pixel마다를 기반으로 그것들 사이의 구분을 할 수 없을 정도라고 고려한다면, 우리는 통계적으로 roughness parameter를 고려하여 표면의 microfacet roughness를 근사한다. 한 표면의 roughness를 기반으로, 우리는 어떤 벡터 h에 대강 정렬된 microfacets의 ratio를 계산할 수 있다. 이 벡터 h는 빛 l과 view v vector 사이의 반쯤에 있는 halfway vector이다. 우리는 advanced lighting tutorial에서 이전에 그 halfway vector를 이야기 했다. 그것은 l과 v의 합을 그것의 길이로 나누어서 계산된다.

h = l + v / ||l + v||

microfacets이 그 halfway vector에 정렬될 수록, 그 specular reflection는 더 날카로워지고 더 강해진다. 0과 1사이의 roughness parameter로, 우리는 통계적으로 microfacets의 정렬을 근사할 수 있다:

우리는 더 높은 roughness values가 더 많은 specular reflection shape를 보여준다는 것을 볼 수 있다. 부드러운 표면의 더 작고 더 날카로운 sepcular reflection shape와 대조적으로.

Energy conservation
microfacet 근사는 energy conservation 형태를 이용한다: 떠나는 light energy는 결코 들어오는 빛 에너지를 초과해선 안된다 (emissive surfaces를 제외하고). 위의 이미지를 보면, 우리는 specular reflection area가 증가하는 것을 본다. 그 뿐마 아니라, 그것의 밝기가 roughness levels이 증가할 때 줄어드는 것을 본다. 만약 specular intensity가 specular shape의 크기와 상관없이 각 픽셀에 대해 같게 된다면, 더 거친 표면들은 더 많은 에너지를 방출하게 될 것이다. 이것은 에너지 보존 법칙을 위반한다. 이것은 우리가 specular reflections을 부드러운 표면에서 좀 더 강렬하게 보는 이유이고, 거친 표면에서 좀 더 희미하게 보는 이유이다.

유효한 에너지보존을 위해서, 우리는 diffuse and specular light 사이의 명백한 차이를 구분 할 필요가 있다. 한 광선이 표면에 닿는 순간에, 그것은 refraction part와 reflection part 둘 다로 쪼개진다. 그 반사 부분은 직접적으로 반사되는 빛이고, 표면에 들어가지 않는다; 이것이 우리가 specular lighting으로서 아는 것이다. 굴절 부분은 표면에 들어간 남아있는 빛이고, 흡수된다; 이것이 우리가 diffuse lighting으로 아는 것이다.

여기서 몇 가지 뉘앙스들이 있다. 굴절된 빛은 표면에 닿아 즉시 흡수되지 않기 때문이다. 물리학에서, 우리는 빛이 효과적으로 그것이 모든 에너지를 잃을 때 까지 앞으로 계속해서 나아가는 에너지 beam으로 고려될 수 있다는것을 안다; light beam이 에너리르 잃는 방식은 충돌에 의해서이다. 각 material은 아주 작은 particles로 이루어져있는데, 그것들은 아래에서 보여지듯이 광선과 충돌할 수 있다. 그 particles들은 각 충돌시에 빛의 광선을 흡수하고, 그것은 열로 변환된다.

일반적으로 모든 에너지가 흡수되는 것은 아니고, 그 빛은 계속해서 (대개) 무작위의 방향으로 흩뿌려질 것이다. 그리고 거기에서 그것은 그것의 에너지가 고갈되거나 표면을 다시 떠날 때까지 다른 particles들과 충돌한다. 표면에서 다시 떠오르는 광선들은 표면의 관찰된 (diffuse) color에 기여한다. PBR에서, 그러나 우리는 모든 굴절된 빛이 충돌하는 작은 지역에서 흡수되고 흩뿌려지는 가정을 간단하게 한다. 그리고 한 거리에서 표면을 떠난 흩뿌려진 광선을 무시한다. 이것을 고려하는 특정한 shader 기법은 subsurface scattering 기법이라고 알려져있는데, 이것은 피부, 대리석, 또는 밀랍 같은 물질들의 시각적 퀄리티를 크게 개선하고, 성능의 대가가 있다.

반사와 굴절에 대해 말할 때, 부가적인 미묘함은 금속성의 표면이다. 금속 표면들은 금속이 아닌 표면과 비교하여 빛에 다르게 행동한다 (dielectrics라고 또한 알려진). 금속 표면들은 반사와 굴절의 같은 원칙을 따르지만, 모든 굴절된 빛은 직접적으로 흩뿌려지는 것 없이 흡수된다. 이것은 반사되거나 또느 specular light만을 남긴다. 금속 표면은 어떠한 diffuse colors를 보여주지 않는다. 금속과 dielectrics 사이의 이 명백한 구분 때문에, 그것들은 우리가 자료에서 더 깊게 들어갈 PBR 파이프라인 에서 둘 다 다르게 다루어진다.

반사되거나 굴절된 빛 사이의 구분은 우리에게 에너지 보존과 관련하여 또 다른 관찰을 가져와준다: 그것들은 상호 배제적이다. 빛 에너지가 반사되는 무엇이든 material 그 자체에 의해 더 이상 흡수되지 않을 것이다. 따라서, 굴절된 빛으로서 표면에 들어가게 된 에너지는 직접적으로 우리가 반사에서 고려해야할 최종에너지 이다.

우리는 이 에너지 보존 관계를 처음에 들어오는 광선이 그것의 에너지를 반사하는 비율을 합하는 specular fraction을 계산하여 보존한다. 굴절된 빛의 fraction은 그러고나서 specular fraction으로부터 직접 계산된다:

  float kS = calculateSpecularComponent(...); // reflection/specular fraction
  float kD = 1.0 - kS;                               // refraction/diffuse fraction

이 방식으로, 우리는 에너지 보존 법칙을 고수하면서 들어오는 빛이 반사하는 양과, 들어오는 빛이 굴절되는 양을 둘 다 알 수 있다. 이 접근법을 고려한다면, refracted/diffuse and reflected/specular contribution 둘 다 1.0을 초과할 수 없다. 따라서 이것은 그것들의 에너지 합이 결코 들어오는 에너지 양을 초과하지 않도록 보장한다; 우리가 이전의 lighting tutorial에서 고려하지 않았던 것이다.

The reflection equation
이것은 우리에게 render equation이라는 어떤 것을 가져다 준다. 이것은 몇몇의 매우 똑똑한 사람들이 생각해내고, 빛의 visuals을 재현하기위해 현재 우리가 가진 가장 좋은 모델인  매우 정교한 방정식이다. PBR은 강력하게 reflectance equation이라고 알려진 render equation의 좀 더 특수화된 버전을 따른다. 적절히 PBR를 이해하기 위해서, 처음에 reflectance equation에 대해 튼튼한 이해를 구축하는 것이 중요하다:



reflectance 방정식은 처음에 무서운 것처럼 보이지만, 우리가 천천히 그것을 분해해감에 따라, 너는 그것이 이해되기 시작할 것이다. 방정식을 이해하기 위해서, 우리는 radiometry(방사선 측정법)에 대해 조금 알아야 만 한다. Radiometry는 electromagnetic radiation (visible light 를 포함하여)의 측정법이다. 몇 가지 표면과 방향에 대한 빛을 측정하기 위해 우리가 사용할 수 있는 몇 가지 radiometric quantities가 있지만, 우리는 radiance라고 알려진 reflectance equation과 관련된 한 가지 것만을 이야기 할 것이다. 여기에서 그것은 L로 표기된다. Radiance(빛)는 단일 방향으로부터 들어오는 빛의 크기 또는 강도를 수량화(quantify)하기 위해 사용된다. 처음에 이해하는 것은 까다롭다. radiance가 많은 물리적 양의 조합이기 때문이다. 그래서 우리는 그러한 것에 처음에 집중할 것이다:

Radiant flux : radian flux 𝚽 는 Watts로 측정되는 광원의 전도된 에너지이다. 빛은 다양한 다른 파장에 대해 에너지의 총합이다. 그 각각의 파장은 특정한 (눈에 보이는) 컬러와 연관되어 있다. 한 광원의 방출되는 에너지는 그러므로 모든 그것의 다른 파장의 함수로 생각되어질 수 있다. 390nm ~ 700nm (나노미터) 사이의 파장들은 가시광선 스펙트럼의 일부로 고려된다. 즉, 인간의 눈이 인지할 수 있는 파장이다. 아래에서 너는 햇빛의 파장마다의 다른 에너지의 이미지를 볼 것이다:

randiant flux는 다른 파장들의 이 함수의 total area를 측정한다. 이 파장의 척도를 컴퓨터 그래픽스에서 입력으로 직접적으로 취하는 것은 다소 비실용적이다. 그래서 우리는 종종 radiant flux를 다양한 파장 강도의 함수가 아닌, RGB로 인코딩된 빛의 색 triplet으로 나타내는 simplification을 한다. (또는 우리가 그것을 흔히 부르듯이, light color). 이 인코딩은 꽤 정보의 손일과 오지만, 이것은 일반적으로 시각적 측면에서 무시할 수 있는 것이다.

Solid angle(입체각) : ω로 표기되는 입체각은 우리에게 단위 구에 투영되는 한 모양의 크기 또는 면적을 말해준다. 이 단위 구에 투영되는 모양의 면적은 solid angle로 알려져있다; 너는 solid angle을 부피를 가진 방향으로 시각화 할 수 있다:

이 단위구의 중심에서 관찰자이고, 그 모양의 방향대로 바라보고 있다고 생각해라; 너가 그것에서 만드는 그 실루엣의 사이즈는 solid angle이다.

Radiant intensity : radiant intensity는 solid angle마다의 radiant flux의 양을 측정하거나 단위 구에 투영된 넓이에 대해 광원의 강도를 측정한다. 예를들어, 모든 방향으로 동일하게 뿜어내는 omnidirectional light가 주어진다면, 그 radiant intensity는 우리에게 특정한 지역에 대한 에너지를 줄 수 있다 (solid angle):

그 radiant intensity를 묘사하는 방정식은 다음과 같이 정의된다:



여기에서 I는 radiant flux 𝚽 / solid angle ω이다.

radiant flux, randiant intensity, 그리고 solid angle의 지식으로,  우리는 마침내 radiance에 대한 방정식을 묘사할 수 있다. 그리고 이것은 radiant intensity 𝚽인 한 빛의 solid angle ω에 대해 한 면적 A의 총 관찰된 에너지로 묘사된다:



Radiance는 표면의 normal에 대해 빛의 incident (또는 들어오는) 각 θ에 의해 cosθ로 스케일링된 한 구역에서 빛의 양의 radiometric measure이다: 빛은 그것이 직접적으로 표면에 덜 비출 때 더 약해지고, 그것이 직접적으로 표면과 수직일 때 가장 강하다. 이것은 basic lighting tutorial에서 diffuse lighting의 우리의 인지와 비슷하다. cosθ가 직접적으로 빛의 방향벡터와 표면의 normal vector사이의 내적과 일치하기 때문이다:

  float cosTheta = dot(lightDir, N);

그 radiance equation은 꽤 유용하다. 그것이 우리가 관심이 있는 대부분의 물리량으로 구성되어있기 때문이다. 만약 우리가 solid angle ω와 구역 A가 무한히 작다고 고려한다면, 우리는 공간에서 한 점에 닿는 빛의 한 광선의 flux를 측정하는 radiance를 사용할 수 있다. 이 관계는 우리가 단일의 (fragment) 점에 영향을 미치는 단일 광선의 radiance를 계산할 수 있도록 한다; 우리는 효과적으로 solid angle ω를 방향벡터 ω로, A를 점 p로 변환한다.ㅏ 이 방식으로 우리는 직접적으로 우리 쉐이더에서 단일 광선의 per-fragment contribution의 radiance를 사용할 수 있다.

사실, radiance에 대해서, 우리는 일반적으로 점 p로 가는 모든 들어오는 빛에 대해서만 신경쓴다. 그리고 이것은 irradiance라고 알려진 모든 radiance의 합이다. radiance와 irradiance의 지식으로, 우리는 reflectance equation에 돌아갈 수 있다:



우리는 L이 render equation에서 어떤 점 p와 들어오는 방향벡터 w_i로 생각될 수 있는 어떤 들어오는 무한히 작은 solid angle ω_i의 radiance를 나타낸다는 것을 안다. cosθ는 빛의 surface에 대한 incident angle을  기반으로 에너지를 스케일링 한다는 것을 기억해라. 그리고 우리는 이것을 reflectance equation에서 n * w_i로서 찾는다. 그 reflectance equation은 viewer쪽으로 나가는 방향인 방향 w_o에서 점 p에 대해 반사된 radiance L_o(p, w_o)의 합을 계산한다. 또는 다르게 말하자면: L_o는 w_o에서 보여지는 점 p에서의 light의 irradiance의 반사된 합계를 측정한다.

reflectance equation이 모든 들어오는 radiance의 합인 irradiance를 기반으로하기 때문에, 우리는 단일의 들어오는 빛의 방향이 아닌 점 p를 중심으로하는 반구 Ω 내에서의 모든 들어오는 빛의 방향의 빛을 측정한다. 한 반구는 표면의 normal n과 정렬된 구의 절반으로 묘사되어질 수 있다:

한 면적내에서, 또는 반구의 경우에, volume(부피) 내에서 값의 총합을 계산하기 위해, 우리는 반구 Ω냐애소 모든 들어오는 방향 dw_i에 대해 ∫로서 reflectance equation에 표기된 적분이라는 수학적 구성물을 사용한다. 적분은 한 함수의 넓이를 측정하고, 그것은 analytically 또는 numerically하게 계산되어질 수 있다. render and reflectance equation 둘 다에 analytical solution은 없기 때문에, 우리는 적분을 discretely하게 numerically하게 해결하길 원할 것이다. 이것은 반구 Ω에 대해 reflectance equation의 작은 discrete steps의 결과를 취하고, 그 step size에 대해 그것들의 결과를 평균화하는 것을 말한다. 이것은 다음과 같이 코드에서 대강 시각화할 수 있는 Riemman 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;
}

그 steps을 dW로 스케일링하여, 그 합은 적분 함수의 총 넓이 또는 부피와 동일할 것이다. 각 discrete step을 스케일하는 dW는 reflectance euqation에서 dW_i로 고려될 수 있다. 수학적으로 dw_i continuous symbol이다. 거기에서 우리는 적분을 계산한다. 그리고 그것이 직접적으로 코드에서 dW와 관련되지 않지만 (이것은 리만 합의 discrete step이기 때문에), 그것은 이러한 방식으로 생각하는데 도움을 준다. discrete steps을 취하는 것은 항상 그 함수의 총합의 근사를 준다는 것을 명심해라. 세심한 독자는 steps의 개수를 증가시켜 리만 합의 정확도를 증가시킬 수 있다는 것을 눈치챌 것이다.

그 reflectance equation은 점 p에 도달하는 f_r에 의해 스케일링 된 반구 Ω에 대한 모든 들어오는 light diretions w)i의 radiance를 합하고, viewer의 direction에서 반사된 빛 L_o의 합을 반환한다. 그 들어오는 radiance는 우리가 친숙한 것으로서 광원으로 부터오거나 우리가 IBL tutorials에서 다룰 모든 들어오는 방향의 radiance를 측정하는 environment map으로부터 온다.

남은 유일한 미지수는 표면의 material properties를 기반으로 들어오는 radiance를 스케일링하거나 가중치를 주는 BRDF or bidirectional reflective distribution function이라고 알려진 f_r symbol이다.

BRDF
BRDF or bidirectional reflective distribution function은 입력으로 들어오는 (light) 방향 w_i, 밝으로 나가는 (view) direction w_o, 표면 normal n 그리고 microsurface의 거칢을 나타내는 표면 계수 a를 받아들이는 함수이다. BRDF는 각 개별 광선 w_i가 그것의 물질 특성에 따라 불투명한 표면에서 최종 반사된 빛에 얼마나 많이 기여하는지를 근사한다. 예를들어, 만약 그 표면이 완벽히 부드러운 표면을 가진다면 (거울같은), 그 BRDF 함수는 모든 들어노느 광선 w_i에 대해 0.0을 반환한다. 하지만 나가는 광선 w_o로와 같은 (reflected) 각도를 가진 한 광선에 대해서는 제외한다. 그 떄 그 함수는 1.0을 반환한다.

BRDF는 이전에 이야기한 microfacet theory를 기반으로 물질의 반사, 굴절 특징을 근사한다. BRDF가 물리적으로 그럴듯하게 되기위해서, 그것은 에너지 보존 법칙을 따라야 한다. 즉, 반사된 빛의 합은 결코 들어오는 빛의 양을 초과해서는 안된다. 기술적으로 Blinn-Phong은 같은 w_i와 w_o를 입력으로 취하는 BRDF로 고려된다. 그러나, Blinn-Phong은 물리 기반이라고 고려되지 않는다. 그것이 에너지 보존 법칙을 고려하지 않기 때문이다. 빛에 대한 표면의 반응을 근사시키는 몇가지 물리 기반의 BRDF가 있다. 그러나, 거의 모든 real-time render pipelines은 Cook-Torrance BRDF로 알려진 BRDF를 사용한다.

Cook-Torrance BRDF는 diffuse and specular part 둘 다를 포함한다:



여기에서 k_s가 반사된 비율이 되고, k_d는 굴절된 들어오늘 빛의 에너지의 이전에 언급된 비율이다. BRDF의 왼쪽은 여기에서 f_lambert라고 표기되는 방정식의 diffuse part를 말한다. 이것은 diffuse shading을 위해 우리가 사용했던 것과 유사한 Lambertian diffuse라고 알려져 있다. 그것은 상수 factor로 다음과 같이 표기 된다:

  

c는 albedo 또는 surface color이다. (diffuse surface texture를 생각해라). 파이로 나누는 것은 diffuse light를 표준화하는 것이다. BRDF를 포함하는 이전에 표기한 적분이 pi로 스케일링 되기 때문이다. (우리는 IBL tutorials에서 그것에 대해 할 것이다).

  Green Box
  너는 어떻게 이 Lambertian diffuse가 우리가 이전에 사용하고 있는 diffuse 용어와 관련있는지를 궁금해할지도 모른다: surface의 normal과 빛의 방향사이의 내적에 의해 곱해지는 surface color를 말한다. 그 내적은 여전히 거기에 있고, BRDF에서 움직여졌다. 왜냐하면 우리는 L_o 적분의 끝에서 n * w_i (내적)을 찾았기 때문이다.

좀 더 현실적으로 보이지만 연산적으로는 더 비싼 BRDF의 diffuse part에 대한 다른 방정식들이 존재한다. 그러나 Epic Games에서 결론지어졌뜻이, Lambertian diffuse는 대부분의 real-time rendering 목적에 충분하다.

BRDF의 specular part는 좀 더 어렵고 다음과 같이 묘사된다:



Cook-Torrance speuclar BRDF는 세 개의 함수와 분모에 normalization factor로 구성된다. 각 D, F, 그리고 G 심볼들은 표면의 반사 특징의 특정한 부분을 근사하는 함수의 유형을 나타낸다. 이러한 것들은 normal Distribution function, Fresnel equation, Geometry function로 정의된다:

  • Normal distribution function : 는 표면의 microfacets이 표면의 거칢에 의해 영향받는 halfway vector에 정렬되는 양을 근사한다; 이것은 microfacets을 근사하는 주요 함수이다.
  • Geometry function : 는 microfacets의 self-shadowing 특징을 묘사한다. 한 표면이 상대적으로 거칠 때, 그 표면의 microfacets은 다른 microfacets에 대해 그림자를 만든다. 그것으로 인해 그 표면이 반사하는 빛을 줄인다.
  • Fresnel equation : Fresnel equation은 다른 표면 각도에서 표면 반사 비율을 묘사한다.
이러한 함수들 각각은 그것들의 물리학과 동일한 것의 근사이고, 너는 밑에 있는 물리학을 근사하려고 목표하는 각각의 한 가지 이상의 버전을 발견할 것이다; 몇 가지는 좀 더 현실적이고, 다른 것들은 좀 더 효율적이고. 이러한 함수들의 근사된 버전을 너가 무엇을 사용하든 고르는 것은 완벽히 허용된다. Epic Games의 Brian Karis는 여기에서 다양한 근사의 종류에 대해 좋은 양의 연구를 했다. 우리는 Epic Game의 Unreal Engine 4에 의해 사용되는 같은 함수를 고를 것이다. 그리고 그것은 D에 대해서는 Trowbridge-Reitz GGX이고, F에 대해서는 Fresnel-Schlick approximation이고, G에 대해 Smith's Schlick-GGX 이다.

Normal distribution function
normal distribution function D는 통계적으로 (halfway) vector h에 정확히 정렬된 macrofacets의 상대적인 표면 지역을 근사한다. 어떤 roughness parameter가 주어진다면 microfacets의 일반적인 정렬을 통계적으로 근사시키는 많은 정의된 NDF들이 있다. 그리고 우리가 사용할 것은 Trowbridge-Reitz GGX라고 알려져있다:



여기에서 h는 표면의 microfacets에 대해 측정하는 halfway vector이다. a는 surface의 거칢의 측정치이다. 만약 우리가 h를 다양한 roughness parameters에 대해 surface normal과 light direction사이의 halfway vector로 취한다면, 우리는 다음의 결과를 얻는다:

roughness가 낮을 때 (따라서 표면이 부드러울 때), 매우 집중되는 많은microfacets은 작은 반경에 대해 halfway vectors에 정렬된다. 이 높은 집중 때문에, 그 NDF는 매우 밝은 지점을 보여준다. 그러나 microfacets이 좀 더 무작위 방향으로 정렬되는 거친 표면에서, 너는 microfacets에 어느정도 정렬된 더욱 큰 수의 halfway vectors h를 발견할 것이지만, 이것은 우리에게 더 집중되어 좀 더 회색의 결과들을 준다.

GLSL 코드에서, Trowbridge-Reitz GGX normal distribution function은 이것처럼 보인다:


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;
}

Geometry function
geometry function은 통계적으로 relative surface area를 근사한다. 거기에서 그것의 micro surface-details는 광선이 가려지게 야기시키는 서로의 것에그림자를 만든다.

NDF와 유사하게, Geometry function은 더 거친 표면이 overshadowing microfacets의 더 높은 확률을 가진 채 material의 roughness parameter를 입력으로 받아들인다. 우리가 사용할 geometry function은 Schlick-GGX 라고 알려진 GGX와 Schlick-Beckmaan의 근사이다:



여기에서 k는 우리가 direct lighting 또는 IBL lighting 둘 중 하나에 대한 geometry function을 사용하는 것을 기반으로 a에 대해 remapping한 것이다:




a의 값이 너의 엔진이 a에 대한 roughness를 어떻게 바꾸냐를 기반으로 다를지도 모른다. 다음의 튜토리얼에서, 우리는 광범위하게 이 remmaping이 어떻게 관련있고 어디에서 관련있는 지를 이야기 한다.

효과적으로 geometry를 근사하기 위해, 우리는 view direction (geometry obstruction)과 light direction vector (geometry shadowing) 두 ㄹ다를 고려할 필요가 있다. 우리는 Smith's method를 사용하여 그 둘 다를 고려할 수 있다:



Schlick-GGX와 함께 Smith의 방법을 사용하여, G_sub는 다양한 roughness R에 대해 다음의 시각적 외관을 준다:

geometry function은 흰색과는 0.0 ~ 1.0사이의 multiplier이거나 어떠한 microfacet shadowing 과 black이 없다면 1.0이고 완전히 microfacet shadowing이면 0.0이다.

GLSL에서 그 geometry function은 다음의 코드로 바뀐다:


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 equation
(Freh-nel이라고 발음되는) Fresnel 방정식은 굴절되는 빛에 대해 반사되는 빛의 비율을 묘사한다. 그리고 이것은 우리가 표면을 바라보는 각도에 따라서 다양한다. 빛이 한 표면을 닿는 순간, view angle에 대한 표면을 기반으로, Fresnel 방정식은 우리에게 반사되는 빛의 percentage를 말해준다. 이 반사 비율과 에너지 보존 법칙으로부터, 우리는 직접적으로 그것의 나머지 에너지로부터 빛의 굴절된 부분을 얻을 수 있다.

모든 표면 또는 material은 그것의 표면을 정면으로 바라볼 때 기본 reflectivity의 한 level이 있다. 하지만 그 표면을 한 각도로부터 바라볼 때, 모든 반사는 표면의 base reflectivity와 비교적 더 명백해진다. 너는 스스로 너가 가정한 수직의 view angle로부터 어떤 수준의 base reflectivity를 가진 wooden/metallic desk로 이것을 확인할 수 있다. 그러나 너의 책상을 거의 90도로 봐서, 너는 그 반사가 좀 더 명백해진다는 것을 볼 것이다. 모든 표면은 이론적으로 완전히 빛을 반사한다. 만약 완벽한 90도 각도로 바라봐진다면. 이 현상은 Fresnel로 알려져있고 Fresnel equation으로 묘사된다.

그 Fresnel equation은 오히려 복잡하 방정식이지만, 운좋게도 Fresnel-Schlick 근사를 사요하여 근사되어질 수 있다:



F_0은 표면의 base reflectivity를 나타내고, 우리는 indices of refraction 또는 IOR이라고 불리는 어떤 것을 사용해서 이것을 계산한다. 너가 구의 표면에서 볼 수 있듯이, 우리가 그 표면을 바라보는 각도 쪽으로 더 바라보면 (halfway-view angle이 90도에 도달하면서) 그 Fresnel 은 더 강해지고 따라서 그 반사는:

Fresnel 방정식과 연관된 몇 가지 subtleties가 있다. 하나는 Fresnel-Schlick 근사가 정말 dielectric 또는 non-metal surfaces를 위해 정의된다는  것이다. conductor surface (metals)에 대해, 그것들의 indices of refraction을 사용하여 base reflectivity를 계산하는 것은 적절히 유효하지 않고, 우리는 conductors를 위해 전적으로 다른 Fresnel equation을 사용할 필요가 있다. 이것이 불편하기 때문에, 우리는 normal incidence (F_0)에서 표면의 반응을 미리 계산하여 근사한다. (0도에서, 마치 직접적으로 한 표면을 바라보는 것처럼) 그리고 view angle을 기반으로 이 값을 보간한다. 이것은 우리가 두 metals과 non-metals에 대해 같은 방정식을 사용할 수 있도록 하기 위해서이다.

normal incidence에서의 surface의 반응 또는 base reflectivity는 Naty Hoffman의 수업 노트에서 취해진 아래에 기재된 좀 더 흔한 값들의 몇몇이 있는 이러한 것과 같은 큰 데이터베이스들에서 발견되어질 수 있다:

여기에서 관찰하기에 흥미로운 것은 모든 dielectric surfaces에 대해, base reflectivity가 결코 0.17보다 높지 않다는 것이다. 그리고 그 것은 그 규칙보다는 예외이다. conductors에 대해서는 base reflectivity가 더 높게 시작하고 (때개) 0.5 ~ 1.0사이로 다양하다. 게다가, conductors 또는 metallic surface에 대해 base reflectivity는 색이 칠해진다. 이것은 F_0가 하나의 RGB triplet으로 표현되기 때문이다 (normal incidence에서 reflectivity는 파장마다 다양할 수 있다); 이것은 우리가 오직 metallic surfaces에서 보는 것이다.

dielectric surface와 비교하여 이러한 metallic surfaces의 특정한 특성들은 metallic workflow라는 어떤 것을 만들었다. 거기에서 우리는 한 표면이 metallic or a non-metallic surface인지를 묘사하는 metalness라고 알려진 추가 파라미터로 surface materials를 관리한다.

  Green Box
  이론적으로 한 표면의 metalness는 binary하다: 그것은 금속이거나 또는 아니다. 그것은 둘 다 될 수가 없다. 그러나, 대부분의 렌더링 파이프라인들은 한 표면이 0.0 ~ 1.0 사이에 선형으로 metalness로 설정하는 것을 허용한다. 이것은 대개 예를들어 metallic surface에 대해 작은 dust/sand같은 particles/scractches를 가진 표면을 묘사하는 material texture precision의 부족 떄문이다. particles/scratches같은 이러한 작은 non-metallic 주변의 metalness value를 균형있게 하여, 우리는 시각적으로 기뻐할만한 결과를 얻는다.

두 dielectrics와 conductors에 둘 다에 F_0를 미리 계산하여, 우리는 두 유형의 표면에 대해 같은 Fresnel-Schlick 근사를 사용할 수 있다.  그러나 만약 우리가 한 metallic surface를 갖는다면 그 base reflectivity를 색칠해야만 한다. 우리는 일반적으로 이것을 다음과 같이 달성한다:

  vec3 F0 = vec3(0.04);
  F0 = mix(F0, surfaceColor.rgb, metalness);

우리는 대부분의 dielectric surfaces에 대해 근사되는 base reflectivity를 정의한다. 이것은 그러나 다른 근사이다. F_0는 대부분의 흔한 dielectrics로 평균화되기 때문이다. 0.04의 base reflectivity는 대부분의 dielectrics에 유용하고, 부가적인 surface parameter를 관리할 필요없이 물리적으로 그럴듯한 결과를 생성한다. 그러고나서, 한 표면이 얼마나 metallic한지를 기반으로, 우리는 dielectric base reflectivity를 취하거나 또는 surface color로 관리되는 F_0을 취한다. metallic surfaces는 모든 굴절된 빛을 흡수하기 떄문에, 그것들은 어떠한 diffuse reflections이 없다. 그래서 우리는 직접적으로 그것들의 base reflectivity로서 surface color texture를 사용할 수 있다.

코드에서 Fresnel Schlick approximation은 다음으로 바뀐다:


vec3 fresnelSchlick(float cosTheta, vec3 F0)
{
 return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}

cosTheta가 surface의 normal n과 view direction v사이의 내적의 결과이다.

Cook-Torrance reflectance equation
Cook-Torrance BRDF의 모든 컴포넌트들이 설명되어, 우리는 physically based BRDF를 이제 최종 reflectance equation으로 포함지을 수 있다:



그러나 이 방정식은 완전히 수학적으로 옳지 않다. 너는 Fresnel term F가 한 표면에 반사되는 빛의 비율을 나타낸다는 것을 기억할지도 모른다. 이것은 효과적으로 우리의 비율 k_s이고, reflectance equation의 specular part가 내적으로 reflectance ratio k_s를 포함하는 것을 의미한다. 이것을 고려하면 우리의 최종 reflectance equation은 이렇게 된다:



이 방정식은 이제 완전히 이반적으로 우히가 흔히 PBR로 이해하는것으로 인식되는 physically based render model를 설명한다. 너가 아직 완전히 우리가 모든 이야기된 수학을 코드에 맞게하는 방법을 이해하지 못했더라도 걱정하지 말아라. 다음 튜토리얼에서, 우리는 우리의 렌더링된 조명에서 좀 더 물리적으로 그럴듯한 결과를 얻기위해 어떻게 reflectance equation을 활용할지를 알아볼 것이다. 모든 조그마한 것들과 조각들이 천천히 들어맞기 시작할 것이다.

Authoring PBR materials
PBR 밑에 있는 수학적 모델의 지식으로, 우리는 어떻게 아티스트들이 일반적으로 우리가 직접적으로 PBR 방정식으로 주는 한 표면의 물리적 특성을 관리하는지를 묘사하여 이 이야기를 끝낼 것이다. 우리가 PBR 파이프라인을 위해 피룡한 surface parameters 각각은 텍스쳐에 의해 정의되고 모델링 될 수 있다. 텍스쳐를 사용하는 것은 우리에게 어떻게 각 특정한 표면 점이 빛에 반응해야하는지에 대해 per-fragment control을 준다: 그 점이 metalli, rough, or smooth인지 또는 그 표면이 다른 빛의 파장에 어떻게 반응 해야하는지.

아래에서 너는 PBR에 공급된다면 시각적 output을 가질 너가 PBR 파이프라인에서 너가 자주 발견할 텍스쳐들의 목록을 볼 것이다:

Albedo : the albedo texture는 각 texel에 대해 surface의 color를 명시하고, 그 texel이 metallic하다면 base reflectivity를 명시한다. 이것은 크게 우리가 diffuse texture로서 이전에 사용한 것과 유사하지만, 모든 lighting information은 텍스쳐로부터 추출된다. Diffuse texture는 종종 작은 그림자 또는 image내에 어두운 틈들을 가지고 있다. 그리고 이것은 너가 albedo texture에서 원하는 것이 아니다; 그것은 오직 surface의 컬러 (또는 굴절된 흡수 계수)를 포함해야만 한다.

Normal : normal map texture는 정확히 우리가 normal mapping tutorial에서 이전에 사용했던 것이다. normal map은 우리가 fragment마다 한 표면이 평평한 것보다 더 울퉁불퉁 하다는 환각을 주는 독특한 normal를 명시하게 해준다.

Metallic : metallic map은 texel마다 한 texel이 metallic인지 아닌지를 명시한다. PBR엔진이 어떻게 설정되는지에 기반으로, 아티스트들은 grayscale values로할지 또는 binary black or white로 metalness를 관리할 수 있다.

Roughness : 그 roughness map은 한 표면이 texel basis마다 얼마나 거친지를 명시한다. 그 roughness의 샘플링된 roughness value는 표면의 statistical microfacet orientations에 영향을 준다. 더 거친 표면은 더 넓고 블러리한 반사를 얻는다. 반면에 부드러운 표면은 집중되고 깨끗한 반사를 얻는다. 몇 몇 PBR 엔진들은 예술가들이 좀 더 직관적이라고 아는 roughness map 대신에 smoothness map을 기대하기도 하지만, 이러한 값들은 샘플링 될 때 (1.0 - smoothness)가 roughness로 바뀐다.

AO : the ambient occlusion or AO map은 표면의 추가 shadowing factor를 명시하고 잠재적으로 주변 geometry를 명시한다. 만약 우리가 예를들어 brick surface를 가진다면, 그 albedo texture는 그 벽의 틈 안에 어떠한 shadowing information을 가지고 있지 안흥ㄹ 것이다. 그러나 AO map은 이러한 어두워진 edges들을 명시한다. 빛이 탈출하느 ㄴ것이 더 어렵기 떄문이다. ambient occlusion을 lighting stage의 끝에서 고려하는 것은 크게 너의 scene의 visual quality를 증가시킬 수 있다. mesh/surface의 ambient occlusion map은 수동으로 생성되거나 3D modeling programs에서 미리 계산되어질 수 있다.

아티스트들은 texel마다 기반으로 이러한 physically based input values를 설정하고 조절하고, 그것들의 텍스쳐 값들을 실 세계 물질의 physical surface propertise에 기반을 둔다. 이것은 PBR render pipeline의 가장 큰 장점중의 하나이다. 한 표면의 이러한 물리적 특성이 환경 또는 조명 설정에 상관없이 같게 남아있기 때문이다. 그리고 이것은 예술가들이 물리적으로 그럴듯한 결과를 얻기 쉽게 해준다. PBR pipeline에서 관리되는 표면들은 쉽게 다른 PBR render engines에서 공유되어질 수 있고, 그들이 있는 환경과 상관없이 옳게 보일것이다. 그리고 결과적으로 좀 더 자연스러워 보인다.

Further reading

===========================================
무슨 말인지 모르겠다. 대강 대강 이해했다.
너무 어려운 내용들이 많아서 기본 물리학 이해가 필요하다.
댓글에 보면 이 글의 원작자도 솔직히 다 이해하지 않고 어떤 공식이 어떤 역할을 하고, parameter를 이렇게 해주면 어떻게 렌더링이 된다만을 알아서 지금 활용하고 있다고 한다.
일단 계속 하루에 한 개씩 튜토리얼 나가는 것은 이대로 하면서, 나중에 좀 더 세부적인 내용을 다른 자료들 통해서 이해할 필요가 있다. 그래야 더 잘 활용할 수 있기 때문이다. 여튼 궁극의 PBR 첫 시작. 너무 오래 걸렸다. 어려워서.


댓글 없음:

댓글 쓰기