Phong光照模型的簡單說明


轉自:http://hi.baidu.com/gltracy/item/37f5852939404af850fd87d5

我簡單地介紹一下Phong光照模型...雖然這種光照模型算是比較古老的,

但是通過合適的參數設置,仍然可以實現真實的效果。

我們的目標是渲染出以下效果,這里以Doom3的男主角為例(終於不是怪物了...)

 

一般而言,Phong光照模型分為三個累加階段:漫反射,鏡面反射和環境光

以下按順序說明:

1.漫反射(Diffuse)

對於表面比較粗糙的物體,基本表面的明暗就是漫反射效果,比如褲子的材質。某一個象素的明暗系數只取決於該點與光源的相對位置,而與眼睛的位置無關。

diffuse_color = base_map * ( N * V_L )* mat_diffuse * light_diffuse;

上式中base_map代表該點的基礎顏色,一般通過紋理索引;

N 是該點的法線;

V_L是該點到光源方向的單位向量;

N * V_L 即兩者的點積,注意需要用max( ( N * V_L ), 0 ),因為負的值是沒有意義的;

mat_diffuse和light_diffuse分別是材質和光源的漫反射系數,用來宏觀調制漫反射的顏色。

下圖是只有N * V_L 項的渲染結果:

 

2.鏡面反射(Specular)

盡管漫反射已經可以很好地表達光照,但是由於它是與視點無關的,所以多少有些欠缺生動,

而鏡面反射是視點相關的,所以會隨着眼睛位置的變化而“流動”。

specular_color = pow( v_e' * v_l, gloss ) * mat_specular * light_specular;

這里解釋一下:

v_e' 是e_v的反射向量(v_e' = reflect( e_v, n ) ),

而e_v是眼睛到該點的單位向量,

所謂反射向量,即以與該點的法線所垂直的平面做鏡面反射所得到的向量

(雖然按照原理來說,應該是光線反射,而非視線反射...都沒有問題吧);

v_l是該點到光源的單位向量;

v_e' * v_l 是兩者的點積, 同樣要用max(v_e' * v_l, 0),負的值也是不需要的;

pow是冪積,點積是底,gloss是指數;

gloss用來調制亮斑的大小,一般來說,gloss越大,光斑越細小,gloss越小,光斑分布越寬泛。

mat_specular,light_specular分別是材質和光源的鏡面反射系數,用來宏觀調制鏡面反射的顏色。

注意不是點乘,而是各項分別相乘,就是所謂的調制...

下圖是只有鏡面反射系數的渲染結果:

 

3.環境光(ambient)

光照不到的地方是不是就是全黑的呢,對於受空氣散射影響比較大的環境來說不是的

(比如說室外環境),這里只是簡單的對base_map調制了一下:

ambient_color = base_map * mat_amvient * light_ambient;

4.累加(accumulate)

最后就是將他們相加了:

result_color = diffuse_color + specular_color + ambient_color;

5.其他

(1)在以上式中所使用的法線是由各頂點的法線插值得到的,我們可以使用法線貼圖來編碼

各點的實際法線值,以獲得更細致的表面:

這里是將一個法線的三維向量封裝入紋理的RGB分量,另外還涉及一個世界空間到紋理空間的轉換,

這里不做描述,因為我的實際做法是錯誤的,卻換來正確的結果,所以...我也不清楚啦...

(2)使用一張單獨的圖來編碼各點的鏡面反射系數,比如有油漆的地方反射較弱,而磨光的地方則反射較強烈(見盔甲部分)

(3)以上效果都是利用光照產生的立體錯覺,

如果失去光照,立體感也將隨之消失。

對於環境光,我們應該有更好的處理方法,如利用虛擬的光源等等。

我在該渲染中使用了兩盞燈,產生的效果還不錯。

(4)說到底,phong模型對金屬表面渲染很成功,但對人物表面渲染欠佳,所以才有SSS等等更為先進的模型;但另一方面,Phong模型仍然是最基礎和重要的光照模型,當初的固定流水線采用的就是它(當然鏡面反射略有不同)

先這些吧....

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM