[WebGL入門]二十四,補色着色

注:文章譯自http://wgld.org/,原做者杉本雅広(doxas),文章中假設有個人額外說明,我會加上[lufy:],另外,鄙人webgl研究還不夠深刻,一些專業詞語,假設翻譯有誤,歡迎你們指正。javascript



本次的demo的執行結果
java

着色方法

上次介紹了反射光,反射光是實現光澤的必不可少的概念,到此爲止,主要的光照效果都已經封裝完成了。
光照的效果主要就是擴散光,環境光和反射光三種方法,靈活運用這三種光照,應該就能實現很是逼真的照明效果了。
前幾篇一直在說光照,此次略微換個視點,看一下着色,着色是一個比較大的話題,此次講一下高氏着色和補色着色。

高氏着色(gouraud shading)

高氏着色從名字上看,是比較難明確詳細是什麼樣的着色的,這個高氏(gouraud)事實上是以研究該着色的Henri Gouraud來命名的。web

lufy:高氏着色又叫高洛德着色或高氏渲染(Gouraud Shading):這是一種光影渲染技術也是眼下較爲流行的着色方法,它可對3D模型各頂點的顏色進行平滑、融合處理,將每個多邊形上的每個點賦以一組色調值,同一時候將多邊形着上較爲順滑的漸變色,使其外觀具備更強烈的實時感和立體動感,只是其着色速度比平面着色慢得多但是效果要好得多。函數

高氏着色可以對多邊形的頂點之間的顏色進行補間,高氏着色的計算負荷並不是過高,但是,可以實現很是美麗的渲染,因此經常被使用。webgl

對頂點間的顏色進行補間是什麼意思呢?ui

簡單的說,用高氏着色計算獲得的終於的顏色情報,適用於全部頂點,並且對頂點和頂點之間的顏色進行補間處理,最後渲染模型。spa

使用高氏着色,想用少許的頂點渲染美麗的光照是很是難的。比方說,一個最簡單的三角形多邊形,三維空間中僅僅有這一個三角形,這個面就直接和光碰撞了。.net




放射性光源的時候(比方說燈泡),應該是三角形的中心就最亮,而頂點的部分要略微暗一些,但是高氏着色僅僅是在頂點之間進行顏色補間,因此沒法凸顯三角形中間的亮點。
另外,因爲是依據每個頂點進行顏色補間,顏色變化的時候會出現鋸齒。這個鋸齒隨着頂點數的增多而逐漸消失,但是這麼作的話,高氏着色計算負荷小的優點就沒有了,因此這是個難處理的地方。
翻譯

細心的朋友可能會發現,這個站點中全部的demo,都是用的高氏着色。頂點着色器的光的強度和顏色的進行計算,而後僅僅是將終於算出的顏色傳給了片斷着色器,這樣的依據每個頂點來計算顏色的方法就是高氏着色。
如下是證據,眼下爲止的demo中的顏色之間會存在鋸齒,會有一些不太天然的鏡面反射。
code


擴大以後看的話就比較清楚了吧,頂點數越少,這樣的現象就越明顯。

補色着色(phong shading)


理解了高氏着色以後,接着看補色着色。
像剛纔說的那樣,相對高氏着色是對頂點之間的顏色進行補間處理,補色着色是對各個像素進行顏色的補間處理。也就是說,計算量會比高氏着色增大很是多,但是可以將渲染出顏色的細節。
補色着色的名字跟高氏着色同樣,都是以人名(Bui Tuong Phong)來命名的。使用補色着色的話,會克服高氏着色的弱點,即便頂點數少的時候也能獲得很是天然的效果。

因爲補色着色是在像素之間對顏色進行補間,因此不會發生不天然的鋸齒。如下是和高氏着色的渲染效果作比較。

全然是一樣的頂點數,一樣的光源渲染出的補色着色和高氏着色。左邊是補色着色,無論陰影仍是高亮的部分,都很是的美麗和天然。

補色着色的封裝

知道了高氏着色和補色着色二者之間的不一樣,那麼就來看看補色着色的封裝吧。補色着色就是剛纔說的那樣,在像素之間進行顏色的補間處理,那麼眼下爲止的在頂點着色器中進行的光照處理,全部要交給片斷着色器。
詳細的說,追加一個處理,頂點着色器中的頂點的法線情報用varying變量傳給片斷着色器,而後其它的光照處理全部移到片斷着色器中。
首先看頂點着色器的代碼。


>頂點着色器的代碼
attribute vec3 position;
attribute vec3 normal;
attribute vec4 color;
uniform   mat4 mvpMatrix;
varying   vec3 vNormal;
varying   vec4 vColor;


void main(void){
    vNormal     = normal;
    vColor      = color;
    gl_Position = mvpMatrix * vec4(position, 1.0);
}

和眼下爲止的代碼不一樣,新定義了一個叫作vNormal的varying變量,用來將法線情報傳給片斷着色器。頂點的顏色情報和座標變換矩陣等地方不用變。
接着是片斷着色器。


>片斷着色器代碼
precision mediump float;


uniform mat4 invMatrix;
uniform vec3 lightDirection;
uniform vec3 eyeDirection;
uniform vec4 ambientColor;
varying vec3 vNormal;
varying vec4 vColor;


void main(void){
    vec3  invLight  = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz;
    vec3  invEye    = normalize(invMatrix * vec4(eyeDirection, 0.0)).xyz;
    vec3  halfLE    = normalize(invLight + invEye);
    float diffuse   = clamp(dot(vNormal, invLight), 0.0, 1.0);
    float specular  = pow(clamp(dot(vNormal, halfLE), 0.0, 1.0), 50.0);
    vec4  destColor = vColor * vec4(vec3(diffuse), 1.0) + vec4(vec3(specular), 1.0) + ambientColor;
    gl_FragColor    = destColor;
}

逆矩陣,光向量,視線向量等一直以來都在頂點着色器中使用的數據,全都移動到片斷着色器中來了。另外,利用剛纔在頂點着色器中定義的varying變量vNormal進行了計算。計算的方法和曾經同樣,沒有不論什麼改變。就是說,僅僅是把頂點着色器中的處理,放到了片斷着色器中而已。
此次的變化,並無加入新的uniform變量,也就是說,javascript部分基本上不用變。
簡單的來講,高氏着色和補色着色的主要差異就在於,依據頂點處理仍是依據像素處理,儘管這麼說跟定義相比有些奇怪,但是這麼理解的話也沒什麼錯。


總結

這一次分別說了高氏着色和補色着色兩種着色,高氏着色的長處是計算量比較低,而和補色着色相比的話,渲染效果不太天然。
補色着色正好相反,計算量很是高,但是渲染效果很是完美。
究竟選擇那種方法,取決於模型的頂點數和需要的渲染效果,以及執行環境可以承受的計算負荷。
實際應用中,依據利用的場景和描畫的模型,分別使用不一樣的方法是很是重要的。
此次也準備了demo,急着看執行效果的人可以點擊文章最後的連接來測試。

另外,補充一點,此次的demo中對圓環體的生成函數作了幾處改動,返回值是以對象的形勢返回的,可以指定圓環體的顏色了。事實上,也並無作什麼其它特別的處理。


下次,介紹一下電光源。

用補色着色來渲染的圓環體

http://wgld.org/s/sample_012/


轉載請註明:轉自lufy_legend的博客http://blog.csdn.net/lufy_legend

相關文章
相關標籤/搜索