国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

PBR——基于物理的實(shí)時(shí)渲染

2019-11-08 02:54:54
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

簡(jiǎn)介

PBR,或者用更通俗一些的稱(chēng)呼是指基于物理的渲染(Physically Based Rendering),它指的是一些在不同程度上都基于與現(xiàn)實(shí)世界的物理原理更相符的基本理論所構(gòu)成的渲染技術(shù)的集合。正因?yàn)榛谖锢淼匿秩灸康谋闶菫榱耸褂靡环N更符合物理學(xué)規(guī)律的方式來(lái)模擬光線(xiàn),因此這種渲染方式與我們?cè)瓉?lái)的Phong或者Blinn-Phong光照算法相比總體上看起來(lái)要更真實(shí)一些。除了看起來(lái)更好些以外,由于它與物理性質(zhì)非常接近,因此我們(尤其是美術(shù)師們)可以直接以物理參數(shù)為依據(jù)來(lái)編寫(xiě)表面材質(zhì),而不必依靠粗劣的修改與調(diào)整來(lái)讓光照效果看上去正常。使用基于物理參數(shù)的方法來(lái)編寫(xiě)材質(zhì)還有一個(gè)更大的好處,就是不論光照條件如何,這些材質(zhì)看上去都會(huì)是正確的,而在非PBR的渲染管線(xiàn)當(dāng)中有些東西就不會(huì)那么真實(shí)了。

這種渲染方式需要遵循以下三個(gè)條件: 1. 基于微平面(Microfacet)的表面模型。 2. 能量守恒。 3. 應(yīng)用基于物理的BRDF。

一、 微平面模型

所有的PBR技術(shù)都基于微平面理論。這項(xiàng)理論認(rèn)為,達(dá)到微觀尺度之后任何平面都可以用被稱(chēng)為微平面(Microfacets)的細(xì)小鏡面來(lái)進(jìn)行描繪。根據(jù)平面粗糙程度的不同,這些細(xì)小鏡面的取向排列可以相當(dāng)不一致: 這里寫(xiě)圖片描述 產(chǎn)生的效果就是:一個(gè)平面越是粗糙,這個(gè)平面上的微平面的排列就越混亂。這些微小鏡面這樣無(wú)序取向排列的影響就是,當(dāng)我們特指鏡面光/鏡面反射時(shí),入射光線(xiàn)更趨向于向完全不同的方向發(fā)散(Scatter)開(kāi)來(lái),進(jìn)而產(chǎn)生出分布范圍更廣泛的鏡面反射。而與之相反的是,對(duì)于一個(gè)光滑的平面,光線(xiàn)大體上會(huì)更趨向于向同一個(gè)方向反射,造成更小更銳利的反射: 這里寫(xiě)圖片描述 我們可以基于一個(gè)平面的粗糙度來(lái)計(jì)算出某個(gè)向量的方向與微平面平均取向方向一致的概率。這個(gè)向量便是位于光線(xiàn)向量LigthDir和視線(xiàn)向量ViewDir之間的中間向量(Halfway Vector)。H向量等于標(biāo)準(zhǔn)化后的(L向量+V向量)即:H=normalize(L+V)。

二、 能量守恒

微平面近似法使用了這樣一種形式的能量守恒(Energy Conservation):出射光線(xiàn)的能量永遠(yuǎn)不能超過(guò)入射光線(xiàn)的能量(發(fā)光面除外)。當(dāng)一束光線(xiàn)碰撞到一個(gè)表面的時(shí)候,它就會(huì)分離成一個(gè)折射部分和一個(gè)反射部分。反射部分就是會(huì)直接反射開(kāi)來(lái)而不會(huì)進(jìn)入平面的那部分光線(xiàn),這就是我們所說(shuō)的鏡面光照。而折射部分就是余下的會(huì)進(jìn)入表面并被吸收的那部分光線(xiàn),這也就是我們所說(shuō)的漫反射光照。 反射光與折射光它們二者之間是互斥的關(guān)系。無(wú)論何種光線(xiàn),其被材質(zhì)表面所反射的能量將無(wú)法再被材質(zhì)吸收。因此,諸如折射光這樣的余下的進(jìn)入表面之中的能量正好就是我們計(jì)算完反射之后余下的能量。我們按照能量守恒的關(guān)系,首先計(jì)算鏡面反射部分,它的值等于入射光線(xiàn)被反射的能量所占的百分比。然后折射光部分就可以直接由鏡面反射部分計(jì)算得出。

三、 反射率方程

這里寫(xiě)圖片描述 該函數(shù)是個(gè)連續(xù)函數(shù)所以我們需要對(duì)其進(jìn)行離散化,離散化后的各個(gè)符號(hào)代表的含義如下:p表示觀察點(diǎn)、ωo表示觀察方向即出射方向、ωi表示入射方向、L表示輻射率方程、fr表示雙向反射分布函數(shù)。

1、 輻射率方程

這個(gè)方程表示的是,一個(gè)擁有輻射通量Φ的光源在單位面積A,單位立體角ω上的輻射出的總能量: 這里寫(xiě)圖片描述 如果我們把立體角ω和面積A看作是無(wú)窮小的,那么我們就能用輻射率來(lái)表示單束光線(xiàn)穿過(guò)空間中的一個(gè)點(diǎn)的通量。這樣我們可以計(jì)算得出作用于單個(gè)(片段)點(diǎn)上的單束光線(xiàn)的輻射率,我們實(shí)際上把立體角ω轉(zhuǎn)變?yōu)榉较蛳蛄喀豬然后把面A轉(zhuǎn)換為點(diǎn)p。這樣我們可以直接在著色器中使用輻射率來(lái)計(jì)算單束光線(xiàn)對(duì)每個(gè)片段的作用了。 ps:事實(shí)上,當(dāng)涉及到輻射率時(shí),我們通常關(guān)心的是所有投射到點(diǎn)pp上的光線(xiàn)的總和,而這個(gè)和就稱(chēng)為輻射照度或者輻照度,輻照度公式如下。 這里寫(xiě)圖片描述

vec3 lightColor = vec3(23.47f, 21.31f, 20.79f);//我們一般用RGB代替輻射通量Φvec3 wi = normalize(lightPos - fragWorldPos);//入射方向float cosTheta = max(dot(n, wi), 0.0f);float attenuation = calculateAttenuation(fragWorldPos, lightPos);//光線(xiàn)衰減float radiance = lightColor * attenuation * cosTheta;

2、 BRDF雙向反射分布函數(shù)

它接受入射(光)方向ωi,出射(觀察)方向ωo,平面法線(xiàn)n以及一個(gè)用來(lái)表示微平面粗糙程度的參數(shù)a作為函數(shù)的輸入?yún)?shù)。BRDF可以近似的求出每束光線(xiàn)對(duì)一個(gè)給定了材質(zhì)屬性的平面上最終反射出來(lái)的光線(xiàn)所作出的貢獻(xiàn)程度。舉例來(lái)說(shuō),如果一個(gè)平面擁有完全光滑的表面(比如鏡面),那么對(duì)于所有的入射光線(xiàn)ωi(除了一束以外)而言BRDF函數(shù)都會(huì)返回0.0 ,只有一束與出射光線(xiàn)ωo擁有相同(被反射)角度的光線(xiàn)會(huì)得到1.0這個(gè)返回值。 我們一般使用Cook-Torrance BRDF模型: 這里寫(xiě)圖片描述 這里的kd是入射光線(xiàn)中被折射部分的能量所占的比率,而ks是被反射部分的比率。BRDF的左側(cè)表示的是漫反射部分,這里用flambert來(lái)表示。它被稱(chēng)為L(zhǎng)ambertian漫反射,這和我們之前在漫反射著色中使用的常數(shù)因子類(lèi)似,用如下的公式來(lái)表示: 這里寫(xiě)圖片描述 c表示表面顏色,除以ππ是為了對(duì)漫反射光進(jìn)行標(biāo)準(zhǔn)化。

RDF的鏡面反射部分要稍微更高級(jí)一些,它的形式如下所示: 這里寫(xiě)圖片描述 其中D表示正態(tài)分布函數(shù)、F表示菲涅爾方程、G表示幾何函數(shù)。 ? 正態(tài)分布函數(shù):估算在受到表面粗糙度的影響下,取向方向與中間向量一致的微平面的數(shù)量。這是用來(lái)估算微平面的主要函數(shù)。 ? 幾何函數(shù):描述了微平面自成陰影的屬性。當(dāng)一個(gè)平面相對(duì)比較粗糙的時(shí)候,平面表面上的微平面有可能擋住其他的微平面從而減少表面所反射的光線(xiàn)。 ? 菲涅爾方程:菲涅爾方程描述的是在不同的表面角下表面所反射的光線(xiàn)所占的比率。

a、正態(tài)分布函數(shù) 假設(shè)給定向量h,如果我們的微平面中有35%與向量h取向一致,則正態(tài)分布函數(shù)或者說(shuō)NDF將會(huì)返回0.35。 這里寫(xiě)圖片描述 h表示中間向量,n表示法向量,α表示表面粗糙程度。

float DistributionGGX(vec3 N, vec3 H, float roughness){ float a = roughness*roughness;//這里不是很懂為什么要把從main中傳遞過(guò)來(lái)的粗糙度進(jìn)行乘方處理 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;}

b、幾何函數(shù):從統(tǒng)計(jì)學(xué)上近似的求得了微平面間相互遮蔽的比率,這種相互遮蔽會(huì)損耗光線(xiàn)的能量。 這里寫(xiě)圖片描述 幾何函數(shù)采用一個(gè)材料的粗糙度參數(shù)作為輸入?yún)?shù),粗糙度較高的表面其微平面間相互遮蔽的概率就越高。我們將要使用的幾何函數(shù)是GGX與Schlick-Beckmann近似的結(jié)合體,因此又稱(chēng)為Schlick-GGX: 這里寫(xiě)圖片描述 為了有效的估算幾何部分,需要將觀察方向(幾何遮蔽(Geometry Obstruction))和光線(xiàn)方向向量(幾何陰影(Geometry Shadowing))都考慮進(jìn)去。我們可以使用史密斯法(Smith’s method)來(lái)把兩者都納入其中: 這里寫(xiě)圖片描述

float GeometrySchlickGGX(float NdotV, float roughness){ float r = (roughness + 1.0); float k = (r*r) / 8.0;//計(jì)算K,這里是直接光照 float nom = NdotV; float denom = NdotV * (1.0 - k) + k; return nom / denom;}float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness){ float NdotV = max(dot(N, V), 0.0); float NdotL = max(dot(N, L), 0.0); float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx1 = GeometrySchlickGGX(NdotL, roughness); return ggx1 * ggx2;}

c、菲涅爾方程: 該方程描述的是被反射的光線(xiàn)對(duì)比光線(xiàn)被折射的部分所占的比率,這個(gè)比率會(huì)隨著我們觀察的角度不同而不同。當(dāng)光線(xiàn)碰撞到一個(gè)表面的時(shí)候,菲涅爾方程會(huì)根據(jù)觀察角度告訴我們被反射的光線(xiàn)所占的百分比。利用這個(gè)反射比率和能量守恒原則,我們可以直接得出光線(xiàn)被折射的部分以及光線(xiàn)剩余的能量。 當(dāng)垂直觀察的時(shí)候,任何物體或者材質(zhì)表面都有一個(gè)基礎(chǔ)反射率(Base Reflectivity),但是如果以一定的角度往平面上看的時(shí)候所有反光都會(huì)變得明顯起來(lái)。你可以自己嘗試一下,用垂直的視角觀察你自己的木制/金屬桌面,此時(shí)一定只有最基本的反射性。但是如果你從近乎90度(譯注:應(yīng)該是指和法線(xiàn)的夾角)的角度觀察的話(huà)反光就會(huì)變得明顯的多。如果從理想的角度觀察,所有的平面理論上來(lái)說(shuō)都能完全的反射光線(xiàn)。這種現(xiàn)象因菲涅爾而聞名,并體現(xiàn)在了菲涅爾方程之中。 菲涅爾方程是一個(gè)相當(dāng)復(fù)雜的方程式,不過(guò)幸運(yùn)的是菲涅爾方程可以用Fresnel-Schlick近似法求得近似解: 這里寫(xiě)圖片描述 Fo表示平面基礎(chǔ)反射率,N為法線(xiàn)向量,V為觀察向量。

vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness){ return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);} void main(){ vec3 F0 = vec3(0.04);//平面的基礎(chǔ)反射率 F0 = mix(F0, albedo, metallic);//根據(jù)材質(zhì)的反射率和金屬程度計(jì)算較為準(zhǔn)確的反射率 vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);//菲涅爾方程計(jì)算出被反射光線(xiàn)的百分比}

最終方程:

這里寫(xiě)圖片描述

#version 330 coreout vec4 FragColor;in vec2 TexCoords;in vec3 WorldPos;in vec3 Normal;// 材質(zhì)參數(shù)uniform vec3 albedo;//反射率uniform float metallic;//金屬程度uniform float roughness;//粗糙程度uniform float ao;//// 燈屬性u(píng)niform vec3 lightPositions[4];uniform vec3 lightColors[4];uniform vec3 camPos;const float PI = 3.14159265359; //正態(tài)分布函數(shù)float DistributionGGX(vec3 N, vec3 H, float roughness){ float a = roughness*roughness; 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;}float GeometrySchlickGGX(float NdotV, float roughness){ float r = (roughness + 1.0); float k = (r*r) / 8.0; float nom = NdotV; float denom = NdotV * (1.0 - k) + k; return nom / denom;}//幾何函數(shù)float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness){ float NdotV = max(dot(N, V), 0.0); float NdotL = max(dot(N, L), 0.0); float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx1 = GeometrySchlickGGX(NdotL, roughness); return ggx1 * ggx2;}//菲涅爾方程vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness){ return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);} void main(){ vec3 N = normalize(Normal);//得到法線(xiàn)向量 vec3 V = normalize(camPos - WorldPos);//得到觀察方向向量 vec3 F0 = vec3(0.04);//平面的基礎(chǔ)反射率 F0 = mix(F0, albedo, metallic);//根據(jù)材質(zhì)的反射率和金屬程度計(jì)算較為準(zhǔn)確的反射率 vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);//菲涅爾方程計(jì)算出被反射光線(xiàn)的百分比 vec3 kS = F; vec3 kD = vec3(1.0) - kS; kD *= 1.0 - metallic; // 反射比方程式 vec3 Lo = vec3(0.0); for(int i = 0; i < 4; ++i) { // 計(jì)算每個(gè)燈光的輻射率 vec3 L = normalize(lightPositions[i] - WorldPos);//入射光方向 vec3 H = normalize(V + L);//得到半程向量 float distance = length(lightPositions[i] - WorldPos); float attenuation = 1.0 / (distance * distance);//計(jì)算衰減 vec3 radiance = lightColors[i] * attenuation;//衰減后的燈光 // cook-torrance brdf //雙向反射分布函數(shù),它接受入射(光)方向ωi,出射(觀察)方向ωo, //平面法線(xiàn)nn以及一個(gè)用來(lái)表示微平面粗糙程度的參數(shù)aa作為函數(shù)的輸入?yún)?shù)。 //BRDF可以近似的求出每束光線(xiàn)對(duì)一個(gè)給定了材質(zhì)屬性的平面上最終反射出來(lái)的光線(xiàn)所作出的貢獻(xiàn)程度。 float NDF = DistributionGGX(N, H, roughness);//正態(tài)分布函數(shù),這是用來(lái)估算微平面的主要函數(shù)。 float G = GeometrySmith(N, V, L, roughness);//幾何函數(shù),從統(tǒng)計(jì)學(xué)上近似的求得了微平面間相互遮蔽的比率 //BRDF鏡面反射部分 vec3 nominator = NDF * G * F;//分子 float denominator = 4 * max(dot(V, N), 0.0) * max(dot(L, N), 0.0) + 0.001;//分母 vec3 brdf = nominator / denominator; float NdotL = max(dot(N, L), 0.0); Lo += (kD * albedo / PI + brdf) * radiance * NdotL; //得到最終的反射率方程 } vec3 ambient = vec3(0.03) * albedo * ao; vec3 color = ambient + Lo; color = color / (color + vec3(1.0)); color = pow(color, vec3(1.0/2.2)); //gamma矯正 FragColor = vec4(color, 1.0);}
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 平阴县| 随州市| 禹州市| 绍兴县| 九龙城区| 大英县| 肇东市| 乐亭县| 榆树市| 登封市| 黎平县| 利川市| 弥勒县| 宜都市| 淳安县| 府谷县| 射阳县| 株洲市| 唐山市| 安达市| 开原市| 鹤山市| 南宁市| 华阴市| 甘泉县| 隆回县| 慈利县| 怀集县| 宝兴县| 泸州市| 尤溪县| 柳河县| 九台市| 大邑县| 偏关县| 宁陵县| 杂多县| 岗巴县| 内丘县| 敦煌市| 杭锦后旗|