在實時渲染中Physically-Based Rendering(PBR)中文爲基於物理的渲染
它能爲渲染的物體帶來更真實的效果,並且能量守恆
php
稍微解釋一下字母的意思,爲對後文的理解有幫助,
從右到左
L爲光線方向,H爲半角向量,L是和V的中間,N爲法線方向,V爲咱們眼睛的觀察方向(相機看的方向),R爲反射方向
Torrance-Sparrow光照模型的鏡面反射公式
D爲法線分佈函數(NDF)
F爲反射函數(Fresnel 函數)
G爲陰影遮罩函數(幾何函數),未被shadow或mask的比例
此處的E就是上面的V
Cook-Torrance光照模型的鏡面反射公式
接下來咱們只用Cook-Torrance光照來作實驗
一般來講BRDF是關於表面多種屬性的反射結果之間的線性組合(在實時渲染中通常只考慮diffuse和specular兩種便可)
segmentfault
看起來是否是特別像塑料?仍是粗糙的塑料
接下來咱們就來討論D函數的不一樣帶來的specular的不一樣
函數
Call of Duty : black Ops 2/使命召喚:黑色行動2就使用了它
在http://segmentfault.com/blog/wwt_warp/1190000000436286中說明
Microfacet 微平面模型是普遍應用的對rough surface建模的工具, blinn,ward,beckmann都屬於microfacet的推導結果。基本思想也很簡單,就是用很小的微平面的組合去模擬粗糙的物體表面。而這 些微小的平面元則能夠當作完美的反射或者折射表面。每一個microfacet把一個入射方向的光反射到單獨的一個出射方向,這取決於microfacet 的法向m。當計算BRDF的時候,光源方向l和視線方向v都得給定。這意味着在表面上的全部microfacet中,只有恰好把l反射到v的那部分對 BRDF有貢獻。在下圖中,咱們能夠看到這些有效microfacet的表面法向m正好在l和v的中間,也就是h。
工具
D 爲法線分佈函數(NDF),在大部分表面上,microfacet的方向不是均勻分佈的。Microfacet的法線越接近宏表面的法線,就越光滑。這個 分佈由microfacet的法線分佈函數D(m)來定義。函數D()決定了specular高光的大小、亮度和形狀。 法線分佈函數通常有相似於「粗糙度」這樣的參數。
F爲反射函數(Fresnel 函數),計算光學上的反射比率。
分母4(n•l)(n•v)是個校訂因子,用來校訂從microfacet的局部空間轉到總體表面的數量差別。
V爲能見度函數,陰影遮罩分類爲透視縮減
關於G ,
http://www.klayge.org/wiki/index.php/%E5%9F%BA%E4%BA%8E%E7%89%A9%E7%90%86%E7%9A%84BRDF
給出瞭解釋
G爲陰影遮罩函數(幾何函數),未被shadow或mask的比例
在 上半部分,平的宏表面爲綠色,粗糙的微觀表面爲藍色。m = h的 microfacet標記爲紅色。宏表面投到視線方向就是左上角的綠線。同時,投出來的單個紅色的microfacet顯示成獨立的紅線。左下圖表示在沒 有遮擋項的狀況下,紅色的microfacet加起來的面積,結果就是有效面積大於總面積,因此BRDF的反射能量錯誤地大於了接收能量。右下圖裏紅色區 域考慮了遮擋,重疊的區域再也不計算屢次,因此有效面積小於總面積。
α爲Specular的強度,Specular的強度是根據光澤度gloss肯定的
Schlick提出的fresnel方法:
rf0是反射顏色,也是roughness粗糙程度
遮擋項使用了Schlick-Smith提出的方法
處於能量守恆考慮,漫反射多了鏡面反射就要少,反之亦然
因此:
效果以下:
看起來很像拋光的大理石效果吧
主要代碼以下:
插入代碼:
spa
#define PIE 3.1415926535 float4 frag(v2f i) :COLOR { float3 viewDir = normalize(i.viewDir); float3 lightDir = normalize(i.lightDir); float3 H = normalize(lightDir + viewDir); float3 N = normalize(i.normal); float d = (_SP + 2) / 8 * pow(dot(N, H), _SP) / 4 * PIE; float f = _SC + (1 - _SC)*pow((1 - dot(H, lightDir)), 5); float k = 2 / sqrt(PIE * (_SP + 2)); float v = 1 / ((dot(N, lightDir)*(1 - k) + k)*(dot(N, viewDir)*(1 - k) + k)); float all = d*f*v; float3 c = tex2D(_MainTex, i.uv_MainTex); float3 diff = dot(lightDir, N); diff = (1 - all)*diff; return float4(c *(diff+all), 1) * _LightColor0; }
_SC 爲specular color,_SP 爲specular power
code
爲D值(NDF)
cosθ值爲N與H的點積,如下皆是如此,H爲半角向量,也就是light direct光線方向和view direct視角的一半。α即爲本函數的specular power
這是不一樣specular power的實現曲線,越高表明約粗糙,越低表明約光滑
效果也很不錯
核心代碼以下:
orm
float d = (_SP + 2) / 8 * pow(dot(N, H), _SP)/(2*PIE);
secθ爲1/cosθ;blog
曲線以下
本曲線爲α值爲0.75時,局部出現了0的0次方,這與phong不一樣,使得粗糙表面的統一分部可行
若是超過了0.75就會出現上面這種不應出現的狀況,局部出現了近似0的最小值
it
這是Beckmann和phong的對比(粉色爲Beckmann,藍色爲phong)io
左面的圖是關於粗糙表面的曲線,二者都差很少,對於右側光滑的表面,二者相差不少。
效果以下:
主要代碼以下:
float cosT = dot(N, H); float secT = 1 / cosT; float d = pow(E, -((1 - pow(cosT, 2))*pow(secT, 4) / _AB))*pow(secT, 4) / (PIE*pow(_AB, 2));
爲實現方程
曲線以下:
左側是參數值較低的狀況,右側是參數值較高的狀況
左側有點像Beckmann(越高越粗糙),右側也是像Beckmann出現了最粗糙的地方
這是與phong的比較
他們兩個差很少,可是Trowbridge-Reitz高的地方比較尖,矮的地方拖尾較長
與phong的最終比較。
效果以下:
我的感受這是效果第二好的方法
核心代碼以下:
float cosT = dot(N, H); float d = pow(_SP, 2) / (PIE *pow((1 + (-1 + pow(_SP, 2))*pow(cosT, 2)), 2));
沒錯,就是這麼長,
alpha和gamma都是外部可控變量
效果以下:
我的認爲效果最好的方法,可控變量多,出來的效果多,可是感受計算起來很消耗啊
代碼以下:
#define E 2.71828 float4 frag(v2f i) :COLOR { float3 viewDir = normalize(i.viewDir); float3 lightDir = normalize(i.lightDir); float3 H = normalize(lightDir + viewDir); float3 N = normalize(i.normal); float cosT = dot(H, N); float secT = 1 / cosT; float d = (pow(E, -(_SP*_SP + (1 - cosT * cosT)*secT *secT) / _SP))* pow(_SP, -1 + _TP)*pow(secT, 4) *pow(_SP*_SP + (1 - cosT *cosT)*secT *secT, -_TP) / (PIE * _GM); float f = _SC + (1 - _SC)*pow((1 - dot(H, lightDir)), 5); float k = 2 / sqrt(PIE * (_SP + 2)); float v = 1 / ((dot(N, lightDir)*(1 - k) + k)*(dot(N, viewDir)*(1 - k) + k)); float all = d*f*v; float3 c = tex2D(_MainTex, i.uv_MainTex); float3 diff = dot(lightDir, N); diff = (1 - all)*diff; return float4(c *(diff + all), 1) * _LightColor0; }
最後放上一個全家福
參考:
1. Mathematica Notebook for the SIGGRAPH 2013 talk 「 Background: Physics and Math of Shading」
2. PhysicallyBased Lighting in Call of Duty: Black Ops
----- by wolf96