[WebGL入門]二十二,從環境光線源發出的光,webgl光源

來源:互聯網
上載者:User

[WebGL入門]二十二,從環境光線源發出的光,webgl光源

註:文章譯自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的額外說明,我會加上[lufy:],另外,鄙人webgl研究還不夠深入,一些專業詞語,如果翻譯有誤,歡迎大家指正。



本次的demo的運行結果

平行光源的弱點

上次挑戰了一下從平行光源發出的光。平行光源的光的方向是固定的。而且,為了類比這些,需要用到模型變換矩陣的逆矩陣,以及需要向模型資料中加入法線情報等等。
平行光源的計算負擔比較小,在一定程度上類比了光照效果,在3D類比世界中經常被用到。但是,平行光源也有弱點,陰面的部分,就是沒有被光照到的部分是無法完美的類比。
比如上次的demo中的定點著色器,仔細觀察的話,擷取光向量和法線的內積的部分,實際上是取巧的。
>上次的demo中的一部分代碼

float diffuse  = clamp(dot(normal, invLight), 0.1, 1.0);
這裡使用了GLSL的內建函數clamp,這個函數是將參數的數值限制到指定的範圍之內,上面的代碼,結果會限制在0.1 ~ 1.0之間。

但是,擷取光向量和法線的內積,根據使用場合的不同,可能會出現負數,而使用了clamp函數,即使有負數,也會被指定的最小值0.1代替,假設把clamp的範圍設定為0.0 ~ 1.0之間會是什麼效果呢,試著運行一下的話,出現效果。


這樣,完全沒有和光發生碰撞的地方會變成完全的黑色。這樣會導致無法分清楚模型的輪廓,這就是平行光源的缺點。

就像上次的demo那樣,將光照係數的範圍設定的大一些,在一定程度上可以解決上述問題。但是使用環境光線源的話,可以徹底解決這個問題。


什麼是環境光線源

環境光線是類比現實世界中的自然光的漫反射。現實世界中,從太陽或是照明器械等發射出的光,遇到物體或者大氣中的灰塵等遮擋而發生反射,將世界照亮。比如說,在一個漆黑的屋子裡面,只需要一個燈泡,背對著燈泡的話,就會看到自己的影子映射到床或者牆壁上,而自己的身體雖然沒有直接被光照到,但是也應該能看得見吧。

由於牆壁和屋頂,以及床和大氣中的灰塵等對燈泡發出的光的反射,即使是沒有直接被光照到的部分也會受到光的影響。這樣,呈現光的漫反射的就是環境光線源了。

環境光線源用於照亮三維空間中的所有部分。就是說,不是根據頂點的不同處理attribute變數,而是向著色器中傳遞uniform變數。進一步說,環境光線最終影響的是在context中輸出的顏色,處理包含四個元素的顏色情報。

>定義環境光線的例子

var ambientColor = [0.1,0.1,0.1,1.0];

使用環境光線源的時候,需要注意顏色的亮度。環境光線照的是全部,比如上面的代碼中指定的0.1,如果全都換成1.0的話,模型就會變成全白了。和平行光源不一樣,所以要注意。

環境光線的顏色,最好是限制在0.2左右以下,這次的demo使用的是0.1。


頂點著色器和javascript的修改

接著,看一下各個代碼部分的修改。先從頂點著色器開始看。

>頂點著色器代碼

attribute vec3 position;attribute vec3 normal;attribute vec4 color;uniform   mat4 mvpMatrix;uniform   mat4 invMatrix;uniform   vec3 lightDirection;uniform   vec4 ambientColor;varying   vec4 vColor;void main(void){    vec3  invLight = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz;    float diffuse  = clamp(dot(normal, invLight), 0.0, 1.0);    vColor         = color * vec4(vec3(diffuse), 1.0) + ambientColor;    gl_Position    = mvpMatrix * vec4(position, 1.0);}

上次追加了一個uniform變數,就是vec4型的變數ambientColor。環境光線是在平行光源等一連串的計算結束之後,最後輸出顏色的階段開始添加的。

這裡,如果不使用加法而使用乘法的話,整個畫面都會變暗,所以要特別注意。

接下來,修改主程式。

說起來,只是把環境光線作為參數傳給頂點著色器,追加的東西還是挺少的。

首先在程式中定義環境光線的參數。

>增加環境光線參數

var ambientColor = [0.1,0.1,0.1,1.0];

接著,為了正確的傳給頂點著色器,追加擷取著色器的uniformLocation的部分。

// 將uniformLocation儲存到數組中var uniLocation = new Array();uniLocation[0] = gl.getUniformLocation(prg, 'mvpMatrix');uniLocation[1] = gl.getUniformLocation(prg, 'invMatrix');uniLocation[2] = gl.getUniformLocation(prg, 'lightDirection');uniLocation[3] = gl.getUniformLocation(prg, 'ambientColor');

接著,作為uniform變數在持續迴圈的時候傳給著色器就行了。

>向著色器中傳送環境光線的參數

gl.uniformMatrix4fv(uniLocation[0], false, mvpMatrix);gl.uniformMatrix4fv(uniLocation[1], false, invMatrix);gl.uniform3fv(uniLocation[2], lightDirection);gl.uniform4fv(uniLocation[3], ambientColor);

這樣,就完成了頂點著色器和javascript程式的修改了。

其實,因為這次引入了環境光線源,所以平行光源部分的光照係數設定成了0.0 ~ 1.0,沒有被平行光源照到的部分,就會使用純粹的環境光線來照射。


總結

環境光線,類比了自然界的光的漫反射,彌補了平行光源的缺點。一般,這兩種光會同時使用。只使用環境光線的話,無法表現出模型的凹凸,只使用平行光源的話,陰影過於嚴重無法分清模型的輪廓。

3D類比中的擴散光的代表就是環境光線和平行光。這次的demo也實現到了這一步。下次會介紹一下反射光。


點擊下面的串連,可以確認一下今天的內容。

同時使用平行光源和環境光線源照射的圓環體

http://wgld.org/s/sample_010/


轉載請註明:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.