該文章於一天前發表在 github,如有問題可提至 github。git
在上一篇文章WebGL 初探中,咱們熟悉了 WebGL 的簡單背景以及如何繪製一個簡單的點。可是隻繪製點咱們是沒法進入三維世界的,本篇章將講解如何使用 WebGL 繪製三角形,由於不少 3D 圖形都是使用三角形爲基礎進行渲染的,因此有些對 GPU 性能指標的評價就是渲染三角形的能力。github
前一篇文章中,繪製一個點直接將一個硬編碼的矢量賦給了位置屬性。可是,顯然這樣寫是不夠靈活的。因此在這篇文章的前一部分會使用變量重些前一篇文章的例子。咱們的目標是將位置信心從 JavaScript 程序中傳遞到頂點着色器,而 attribute 變量就傳輸的是那些和頂點相關的數據。下圖展現瞭如何使用 attribute 變量傳輸數據:數組
var VSHADER_SOURCE = 'attribute vec4 a_Position;\n' + 'void main() {\n' + ' gl_Position = a_Position;\n' + ' gl_PointSize = 10.0;\n' + '}\n';
如上所示,前一篇文章中,直接將使用矢量進行賦值 gl_Position = vec4(0.0, 0.0, 0.0, 1.0)
。而這裏使用 attribute vec4 a_Position
聲明一個 attribute 變量。關鍵字 attribute 被稱爲存儲限定符,表示聲明一個 attribute 變量,並且 attribute 變量必須聲明成全局變量,數據將從着色器外傳入。gl_Position = a_Position
將 attribute 變量 a_Position 賦值給 gl_Position。ide
// 得到 attribute 變量 a_Position 的存儲位置 var a_Position = gl.getAttribLocation(gl.program, 'a_Position'); if (a_Position < 0) { console.log('Failed to get the storage location of a_Position'); return; } // 將頂點位置傳遞給 attribute 變量 gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
上面,咱們使用 vertexAttrib3f(location, v0, v1, v2)
方法將數據 (v0, v1, v2) 傳遞給 location 參數指向的 attribute 變量。而這裏的 location 是要修改的 attribute 變量的存儲位置。因此在這以前咱們須要獲取 attribute 變量的存儲位置。這裏,能夠經過 getAttribLocation(program, name)
獲取 attribute 變量的存儲位置。進行完這些更改以後,運行會發現和上一篇文章相同的效果。函數
到如今,咱們一次只能繪製一個點,沒法一次性繪製多個點,甚至是線和麪。想要一次繪製多個點,咱們須要藉助一個叫作緩衝區對象的東西。緩衝區對象是 WebGL 中的一塊存儲區域,其中保存了大量的頂點數據,能夠一次性的向頂點着色器傳入多個頂點到 attribute 變量。下圖展現瞭如何使用緩衝區對象:性能
var vertices = new Float32Array([ 0, 0.5, -0.5, -0.5, 0.5, -0.5 ]); // 建立緩衝區對象 var vertexBuffer = gl.createBuffer(); if (!vertexBuffer) { console.log('建立緩衝區對象失敗。'); return -1; } // 綁定緩衝區對象到目標 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 將數據寫入緩衝區對象 gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); var a_Position = gl.getAttribLocation(gl.program, 'a_Position'); if (a_Position < 0) { console.log('得到 attriute 變量 a_Position 失敗'); return -1; } // 將緩衝區對象賦值給 attriute 變量 a_Position gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); // 開啓 attribute 變量 gl.enableVertexAttribArray(a_Position);
首先,是經過 createBuffer()
方法建立一個緩衝區對象,對應的方法還有 deleteBuffer()
用於刪除一個緩衝區對象。接着,使用 bindBuffer(target, buffer)
將緩衝區對象綁定到 WebGL 已經存在的目標上,以通知 WebGL 正確的處理其內容。緊接着,使用 bufferData(target, data, useage)
方法將數據寫入緩衝區,這裏實際是將數據寫入到綁定的目標對象上,因此在第二步中進行了緩衝區對象的綁定。而第二個參數是一個定義好的類型化數組。這裏的第三個參數,STATIC_DRAW 表明只會想緩衝區寫入一次,繪製屢次,其它用法參數可查相關 API。而後,使用 vertexAttribPointer(location, size, type, normalized, stride, offset)
將緩衝區對象賦值給 attribute 變量。這裏的第二個參數制定緩衝區對象的每一個頂點的份量(1到4之間),若是 size 比 attribute 變量須要的份量小,則按照必定規則補全。第三個參數指定了數據格式。第四個參數表示是否將非浮點型數據歸一到 [0, 1] 或[-1,1] 之間。最後兩個參數通常默認爲0,此處不作具體介紹。最後經過 enableVertexAttribArray(a_Position)
方法開啓緩衝區對象和 attribute 變量的鏈接。測試
最後,我麼可經過 drawArrays(gl.TRIANGLES, 0, n)
繪製三角形。可是,前一篇文章中提到 drawArrays 函數功能很是強大。如今,咱們就看一下該函數有哪些強大的特性。該函數中第一個參數是指定繪製方式,第二個參數指定從哪一個頂點開始繪製,第三個參數指定繪製須要多少個頂點。下表展現了第一個參數對應的繪製方式:編碼
參數 | 基本圖形 | 呈現效果 |
---|---|---|
gl.POINTS | 點 | 一系列的點繪製在v0,v1,v2等處。 |
gl.LINES | 線段 | 一系列單獨線段。 |
gl.LINE_STRIP | 連線 | 一個相連的線段。 |
gl.LINE_LOOP | 迴路 | 一個相鏈接的迴路。 |
gl.TRIANGLES | 三角形 | 一系列單獨的三角形。 |
gl.TRIANGLE_STRIP | 三角帶 | 一個相鄰三角形組成的圖形。 |
下圖是 new Float32Array([0, 0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5])
矢量的一個測試:spa
這篇文章主要講了如何利用緩衝區對象在空間中繪製點、線、面。下一篇文章將講解矩陣變換,有了這兩個知識的積累,理論上能夠畫出咱們想要的 3D 圖形。WebGL 的 API 看似複雜,但基本都很相似。當咱們對這一套熟悉以後,咱們會愈發輕車熟路。code