如下圖:我們為物體構造好了模型,也為每個平面設置了顏色值,但最終畫出來的物體卻一點都不像真實世界中的物體。在真實世界中物體的表面最終呈現的顏色還取決於你觀察它的角度以及光源。
OpenGL提供了近似於真實世界的光照環境。在OpenGl中物體會被三種光照射:環境光,漫放射光,鏡面光。通過調整這三種光源的屬性,我們可以使得物體看起來更真實。
環境光沒有特定的方向。環境光的光線充滿著整個場景。場景中的物體都被環境光從各個方向照射著。環境光的特點是:照射在物體上的光來自周圍各個方向,又均勻地向各個方向反射。
漫放射光是一組來自特定方向,具有方向性的光。根據入射光線的角度在表面上均勻地向各個方向反射。漫反射的特點是:光源來自一個方向,反射光均勻地射向各個方向。漫反射光采用點光源照射物體。點光源是位於空間某個位置的一個點,向周圍所有的方向上輻射等光強的光。在點光源的照射下,物體表面的不同部分亮度不同,亮度的大小依賴於它的朝向以及它與點光源之間的距離。
鏡面光與漫反射光一樣是具有方向性的。高強度的鏡面光會在被照射的物體的表面上形成亮點。對於理想的高光澤度反射面,反射角等於入射角時,光線才會被反射,即只有在等於入射角的反射角方向上,觀察者才能看到反射光。對於這種理想的反射面,鏡面反射的光強要比環境光和漫反射的光強高出很多倍,這時,如果觀察者正好處在P點的鏡面反射方向上,就會看到一個比周圍亮得多的高光點。
事實上,光源是由各種強度不同的類型的光組成的。場景中的光源是由3種光組成的:環境光,漫反射光,鏡面光。每種光的成分也像顏色一樣是由RGBA值定義的。它描述了組成這種成分的紅光,綠光,藍光的強度(對於光的顏色而言,alpha值被忽略)。
紅色射線的光源成分分布:
紅色射線不包含綠光和藍光成分。這些光源成分的強度取值范圍在0.0到1.0之間。上面的表格說明了紅色射線包含非常高的鏡面光的成分,一點漫放射光成分,和非常少的環境光成分。(注:鏡面光的強度要大於其他成分才可能產生亮點).在被紅色光照射的地方你可能(取決於觀察點是否在光反射的方向上)會看到一個很亮的紅點。
材料的顏色是根據它所放射的光的波長來定義的。一個藍色的球體反射了絕大部分的藍色光子且吸收了其他顏色的光子。在現實世界中白光包含了所有顏色的光,所以我們能夠看到材料它本身的顏色。如果藍色的球體在單純的紅光照射下,我們看到的將是黑色的。
當我們使用光照時,我們是通過材料的反射屬性來描述它的顏色的。我們會說一個多邊形反射了絕大多數的紅光,而不會說這個多邊形是紅色的。我們為三種光源:環境光,漫放射光,鏡面光,指定材料相應的反射屬性。一個材料可能會很好的反射鏡面光,卻吸收了大多數的漫放射光和環境光。
物體有它自己反射的顏色,光源也有它自己的顏色。OpenGL是如何決定使用哪種顏色的?
若光源顏色為( LR , LG , LB ),材質顏色為( MR , MG , MB ),最終顏色為( LR*MR , LG*MG , LB*MB )。(B1+B2)*MB )。因此,材料的顏色成分決定了入射光被反射的百分比。例子:
光源顏色為(0.5, 0.5, 0.5), 材料的顏色為(0.5, 1.0, 0.5)那麼最終的顏色是
(0.5*0.5, 0.5*1.0, 0.5*0.5) = (0.25, 0.5, 0.25) 。
公式
ambient = Ka x globalAmbient
漫反射光具有方向性,而且照射在物體表面上光的強度與光源和表面的夾角、光源和表面的距離以及相關的衰減因素有關(在光源和物體之間是否有霧)。
反射光的計算通常用Lambert定律:
Ildiff = Kd * Il * Cos(θ)
其中Il是點光源強度,θ是入射光方向與頂點法線的夾角,稱入射角(0<=A<=90°),Ildiff是漫反射體與方向光交互反射的光強,若 N為頂點單位法向量,L表示從頂點指向光源的單位向量(注意頂點指向光源),則Cos(θ)等價於dot(N,L),故又有:
Ildiff = Kd * Il * dot(N,L)
鏡面光的計算方法比較復雜。最常用的計算方法是:先通過光線的方向向量和物體的平面法向量來計算出光線的反射方向向量。然後再用光線的反射方向向量和視線的方向向量做點積來計算出光線對眼睛的作用強度。再把這個計算得到的作用強度以光澤度值作乘方運算來增加高光部分的匯聚性,減少擴散。最後再把計算結果乘上光線本身的顏色。
馮氏模型公式如下:
spec = Ks * Il * ( dot(V,R) )^Ns
其中Ks 為鏡面反射系數,Ns是高光指數,V表示從頂點到視點的觀察方向,R代表反射光方向。由於反射光的方向R可以通過入射光方向L(從頂點指向光源)和物體的法向量求出,
R + L = 2 * dot(N, L) * N 即 R = 2 * dot(N,L) * N - L
所以最終的計算式為:
Ispec = Ks * Il * ( dot(V, (2 * dot(N,L) * N – L ) )^Ns
OpenGL超級寶典 第4版 中文版PDF+英文版+源代碼 見 http://www.linuxidc.com/Linux/2013-10/91413.htm
OpenGL編程指南(原書第7版)中文掃描版PDF 下載 http://www.linuxidc.com/Linux/2012-08/67925.htm
OpenGL 渲染篇 http://www.linuxidc.com/Linux/2011-10/45756.htm
Ubuntu 13.04 安裝 OpenGL http://www.linuxidc.com/Linux/2013-05/84815.htm
OpenGL三維球體數據生成與繪制【附源碼】 http://www.linuxidc.com/Linux/2013-04/83235.htm
Ubuntu下OpenGL編程基礎解析 http://www.linuxidc.com/Linux/2013-03/81675.htm
如何在Ubuntu使用eclipse for c++配置OpenGL http://www.linuxidc.com/Linux/2012-11/74191.htm
更多《OpenGL超級寶典學習筆記》相關知識 見 http://www.linuxidc.com/search.aspx?where=nkey&keyword=34581