關於WEBGL的那點破事

序章?

想來學習WEBGL也一年有餘了,多多少少有些心得也有些感想,然後又突然想開始寫寫博客,那我人生的第一篇博客就來談談這些心得與感想吧。

一開始接觸WEBGL的緣由那是相當簡單,僅僅是因爲需要。那是大二的時候,學校突然跟我們說,這裏有一堆項目,你們如果想參加的話就趕快報名。當時一羣人就那麼當看見項目裏面有黃金似的報名去了,我當時看這情況,雖然不是很明白到底怎麼回事,但總覺得很厲害的樣子,於是也跟風報名去了。然後?然後項目就升級了到現在都沒結題,平時還沒什麼事做。。

總而言之,我就這麼接觸WEBGL了。

之後就是學習過程了,這個我就不說了,說多了會得出我很懶的結論,這樣不太好所以還是不說了。

WEBGL實在是個相當底層的東西,接口說起來其實不多,常用的也就那幾個,然後這個特點直接導致瞭如果沒有圖形學基礎的話,原生WEBGL學起來是在是有夠複雜的。什麼你說你直接three.js 搞起?好吧請當我什麼都沒說。。

我纔不會跟人說當時我學WEBGL的時候從原生的跳到three.js,然後因爲許多東西搞不懂就又從three.js跳回原生的WEBGL呢。。


爲什麼學WEBGL?

WEBGL接口很低級,相關資料偏少,學習起來有一定的難度,一出問題調試起來,我就呵呵了;

WEBGL性能上毫無疑問輸給了OPENGL;

WEBGL似乎沒有關於燈光的效果的接口函數,具體效果需要編寫着色器程序來實現;

WEBGL甚至沒有相機的概念,要用的時候還得自己定義;

WEBGL沒有相機的概念就算了,它竟然連三維物體的轉換函數都沒有,還得利用第三方庫去進行各種矩陣運算,對沒錯,就是這樣,連矩陣堆棧都要自己定義是怎樣!

那爲什麼我還要學WEBGL啊?

項目需要啊!(滾!)

其實是這樣的:

WEBGL雖然性能上比不上OPENGL,但仍然擁有相當高的性能;

WEBGL通過對着色器的編程,甚至可以掌控所有顯示到屏幕上的像素的顏色;

WEBGL程序調試時可以極度挑戰你的耐心(—_—#!);

回到正題。。最重要的一點是,WEBGL可以在支持它的瀏覽器上,實現不需要插件就能運行的三維程序;

就衝最後一點,WEBGL學了也不會吃虧啊。


學習資料有那些?

爲了方便想學習WEBGL的看官,就介紹一下我用過的一些資料及教材。

目前網上有一個似乎叫做HiWebGL的系列,有中譯版本的,不過沒有圖形學基礎的同學我不太推薦,因爲我當時就是沒圖形學基礎就去看的,結果看完之後我的狀況就是:雖然不知道是怎麼回事,但總感覺很厲害的樣子。

現在O'Reilly也出有一本名爲《WEBGL》的動物書,封面是個奇怪的不明物種,現在似乎還沒有中譯版(更正,最近中譯版出來了)。很坑的是,雖然它封面寫的是WEBGL,但實際上介紹的卻是Three.js框架,而且除了Three.js框架外,裏面介紹的例子還使用了大量的第三方工具庫,讓讀者幾乎沒有可能接觸到WEBGL的原生接口,以及一些不懂是在不太好的圖形學原理。看完了原生WebGL想去了解Three.js框架的同學,我感覺可以入手這本書。

最後就是我有老老實實看完的一本書了,真的有看完哦不騙你。。書名是《WebGL Beginner's Guide》書中除了一些運算用的工具庫之外,幾乎沒有用到別的什麼奇怪的東西。書中有很詳細的介紹一個原生WEBGL應用的結構,幾乎從零開始介紹WEBGL原生接口的使用方法以及使用原因。着色器編程也花了不少的篇幅介紹。最重要的是,開頭就介紹了WEBGL的渲染管線,而且幾乎每一章都有適當地介紹相關的圖形學知識。這對沒有圖形學基礎的初學者是相當的合適啊~!好吧至少對我來說的確是相當的合適。。。這書依然沒有中譯版哦~,似乎。



要做什麼才畫得出來一個球?

那麼最簡單的一個WEBGL程序需要做什麼呢?

初始化畫板什麼的,就略過吧。

首先要編寫着色器程序,並編譯鏈接。着色器程序包含兩個部分,一個是頂點着色器,一個是片元着色器。最簡單的着色器程序用頂點着色器計算三維物體頂點的位置在哪,同時用片元着色器設定每個片元的顏色。

然後要初始化三維物體的Buffers,具體說來就是用WEBGL提供的接口新建一些Buffer,並向其打入數據。

再然後就是初始化燈光(A:餵你不是說沒有燈光接口嘛! 我:閉嘴!)。初始化燈光乾的事情其實是利用WEBGL提供的接口設置着色器程序中某些常量型數據的值,具體說來就是名爲uniform的變量。嚴格的說,這個步驟乾的並不僅僅是初始化燈光這件事

接下來做的就是設置視口,清除緩衝區,設置投影錐,進行矩陣運算並把矩陣數據打入到着色器程序中。當有多個着色器程序是,當然要先切換着色器。

上面的都幹完了之後,就進入繪製階段了,這個階段做的事情其實不多,也就把前面所定義的緩衝區的引用傳遞給着色器,並使用索引緩衝區進行網格片面的繪製就完了。

如果上面的步驟一切正常的話,希望繪製的場景就會顯示在瀏覽器的canvas畫板上了。

(喂!怎麼沒看見設置相機?)

(就說沒有相機對象了,給我閉嘴!)


爲什麼我的程序就是不正常?

初學WEBGL的時候很是容易碰到各種各樣的問題,一個不小心寫的程序出來的效果就詭異的跟什麼一樣,我在學習過程中碰到過的狀況也不少了,就果斷分享被折磨後得到的經驗吧!


狀況1: 場景只有背景色,其他什麼都沒有

解決方案:

先看看JS代碼是否有錯(這真不是廢話);

看看三維物體的緩衝區打入數據時是否發生錯誤,API參數是否設置正確,打入數據前是否有綁定;

看看繪製階段的緩衝區引用傳遞操作是不是有問題,相應API函數的第二個參數最有嫌疑,還應該看看綁定操作有沒有做,做的對不對;

仔細檢查下着色器程序是不是有奇怪的地方,或者是有沒有切換到正確的着色器程序;

檢查下相機是不是位置設置在了物體的內部,或者是指向了錯誤的方向。

(餵你不剛說了沒相機麼?)

(就說了是自己定義的,再不閉嘴砍你喔)


狀況2:我明明貼了材質,爲什麼那東西還是黑的?

解決方案:

總之先刷新一下( 就說我不會隨便說廢話的了);

檢查所使用的材質是否合法,WEBGL只支持長寬都爲2的n次方的材質;

檢查材質座標是不是正確的傳遞到了着色器程序中;

檢查着色器程序的相關代碼有沒有問題;

檢查繪製之前是否綁定了材質;

最後就是看看你是不是把材質貼到物體內側了。



狀況3:我明明用了很多個材質,爲什麼最後畫出來的東西用的都是同一個材質?

解決方案:

這肯定是繪製新的物體時沒有用gl.bindTexture()函數綁定相應的材質了。


狀況4:我明明設置了透明效果,爲什麼被擋住的部分還是消失了?

解決方案:

沒有完美的解決方案。這個並不是程序的錯誤導致的,而是WEBGL所使用的機制導致的。想知道具體原理可以參考http://stackoverflow.com/questions/8763603/transparent-textures-behaviour-in-webgl ;具體解決方案的話,可以參考以下:

首先繪製不透明的物體(在相當多的情況中可以解決問題)

餘下的透明物體,距離相機最遠的最先繪製

以上。什麼你問我相交的物體怎麼辦?我怎麼知道啊~我也只是個菜鳥啊~


狀況5:我的場景明明正確顯示了,爲什麼還會有一堆Index outof Range的提示?

解決方案:

這種情況問題多半出在着色器程序上,着色器程序編譯鏈接的時候,似乎會爲了效率起見,剔除掉對最終結果沒有任何貢獻的變量。如果你是懶人,那麼這種情況放着不管就好了。如果是在受不了那堆提示,那就好好檢查下着色器程序,手動剔除掉沒用的代碼,再適當的修改WEBGL代碼就好。


總之到現在爲止遇到的狀況也就上面這幾種了,以後還有遇到奇怪情況的話,解決後會來更新這一部分的。


----於2013/06/17----

狀況6:材質座標什麼的我調來又調去的,怎麼材質就是貼的亂七八糟的,就是不出現需要的效果?

可能的解決方案:

檢查下你的材質座標是跟哪個座標一一對應生成的,如果是跟索引數組意義對應生成的話,那試試改成與定點座標意義對應看看,很可能就bingo了.



居然有調試器?

最後再介紹個調試器,名叫WebGL Inspector,是Chrome下的一個插件,這東西可是調試WEBGL程序的神器哦~誰用誰知道。。


最後~

大概也沒什麼想說的了。熬夜不好就先睡了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章