寫在前面
[上一篇筆記](/articles/用 buffer 繪製多個點-webgl 筆記 5/) 中,我們利用 buffer 存儲了多個頂點數據,再一次性繪製出來。解決了數據輸入的問題,下面就可以繪製比 point 複雜一點的東西了,比如三角形、線條、矩形等等
一。圖元
圖元就是用來組成複雜模型的最小單元,WebGL 中可以直接繪製 7 種基本圖形,也就是所謂的圖元:
-
孤立點
-
孤立線段
-
連續線段
-
連續線圈
-
孤立三角形
-
三角帶
-
三角扇
「可以直接繪製」,反過來說就是只有這些東西能夠直接繪製,而其它稍微複雜一點點的都要自己想辦法用這 7 種圖元構造出來,比如矩形、六邊形、四面體、立方體...等等仔細想想也能算出頂點拼出來,但更複雜的,比如圓柱、球、半球...等等就需要從專業建模工具(比如 3ds max, maya, blender 等等)中導出頂點數據了
構造複雜模型通常使用三角帶,或者孤立三角形,比如用三角帶構造球,就像還原一條削下來的完整蘋果皮一樣,而用孤立三角形構造立方體,就完全是拼湊了
二。繪製圖元
之前繪製孤立點時,最終負責繪製的代碼只有一句:
// 繪製點
gl.drawArrays(gl.POINTS, 0, arrVtx.length / 2);
// gl.POINTS 孤立點
// gl.LINES 孤立線段
// gl.LINE_STRIP 連續線段
// gl.LINE_LOOP 連續線圈
// gl.TRIANGLES 孤立三角形
// gl.TRIANGLE_STRIP 三角帶
// gl.TRIANGLE_FAN 三角扇
繪製其它圖元只要修改 gl.drawArrays 的第一個參數即可,關於該函數的詳細說明請查看 [attribute 變量與頂點著色器_WebGL 筆記 2](/articles/attribute 變量與頂點著色器-webgl 筆記 2/#articleHeader9)。簡單理解,第一個參數用來告訴 WebGL 系統如何使用傳入的頂點數據,想要畫點還是畫線畫三角
P.S. 實際上,第一個參數影響的是光柵化之前的圖形裝配過程,此時會按照參數指定的圖元來把已處理過的頂點數據裝配成幾何圖形,然後光柵化的過程就是把幾何圖形分解成一個個片元(或者說像素點),再由片元著色器上色,完成之後就是我們最終看到的效果。從傳入頂點數據到繪製完成的具體過程,在下一篇關於 varying 變量的筆記中再詳細說明
三。畫矩形
最直接的方式有 2 種:
-
6 個頂點畫 2 個三角形
-
4 個頂點確定三角帶中的 2 個三角片
一般會考慮節省頂點數據,盡量減少傳入的頂點數,以提高性能。所以我們採用後一種方法,主要代碼如下:
var arrVtx = new Float32Array([
-0.5, 0.5,
-0.5, 0.0,
0.5, 0.5,
0.5, 0.0
]);
// 繪製矩形
gl.drawArrays(gl.TRIANGLE_STRIP, 0, arrVtx.length / 2);
看起來還是比較簡單的,其實繪製複雜圖形的最關鍵問題是頂點數據來源,矩形頂點可以直接用筆列出來,稍微複雜一點的畫畫草圖也能寫出來,再複雜一點的可能就需要專業建模工具了。從建模工具導出頂點數據文件,再解析文件獲取我們需要的頂點數據,當然,從需要掌握的知識上來看,畫一個球和畫一個矩形並沒有什麼差別
四。DEMO
包含上述代碼的完整的例子,請查看:
-
7 種圖元(每 2s 換一個):http://www.ayqy.net/temp/webgl/triangle/index.html
五。總結
指定圖元,就是告訴 WebGL 想要如何使用傳入的頂點數據,那麼就有這麼一種情況:傳入 5 個頂點說要畫孤立三角形,猜猜結果?當然是只畫出了 1 個三角形,因為最後的 2 個頂點無法裝配出三角形,所以也無法分解出這個三角形的一個個片元,最後就看不到它了
從傳入頂點數據到圖像被畫出來,其間的過程比較長但每一步都很關鍵,下一篇筆記再詳細說明
參考資料
- 《WebGL 編程指南》
暫無評論,快來發表你的看法吧