使用了頂點緩衝技術後,繪製效率有了較大的提高。可是還有一點不盡如人意,那就是頂點的位置座標、法向量、紋理座標等不一樣方面的數據每次使用時須要單獨指定,重複了一些沒必要要的工做。WebGL2提供了一種專門用於解決此問題的對象——頂點數組對象(VAO)。本節將介紹頂點數組對象。數組
頂點數組對象,在WebGL1中,是一個擴展對象,該擴展對象的名稱是OES_vertex_array_object;而在WebGL2中能夠直接使用;若是你在WebGL1中已經使用過OES_vertex_array_object,那麼你只須要了解在WebGL2和WebGL1的調用方式的差別便可瀏覽器
下面會對頂點數組對象作詳細的介紹。緩存
頂點數組對象( VAO )是這樣一種對象: 它封裝了與頂點處理器有關的全部數據,它記錄了頂點緩存區和索引緩衝區的引用,以及頂點的各類屬性的佈局而不是實際的數據。函數
這樣作的優勢是: 一旦爲一個 對象指定了一個VAO以後,能夠ton經過對該VAO對象進行簡單的綁定操做來導入對象的全部引用和狀態。在以後繪製對象時候,不須要在手動來導入對象的引用和狀態,VAO替你記住了它。
經過VAO能夠簡化緩衝區的綁定過程,便可以減小代碼的調用次數,也提高了WebGL狀態切換的效率。佈局
下面經過代碼來講明頂點數組對象的使用,本案例代碼繪製兩個頂點色的三角形,最終顯示的效果以下:優化
var triangleArray = gl.createVertexArray(); gl.bindVertexArray(triangleArray); var positions = new Float32Array([ -0.5, -0.5, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0 ]); var positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(0); var colors = new Float32Array([ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ]); var colorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW); gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(1); var triangleArray2 = gl.createVertexArray(); gl.bindVertexArray(triangleArray2); var positions2 = new Float32Array([ 0.0, -0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0 ]); var positionBuffer2 = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer2); gl.bufferData(gl.ARRAY_BUFFER, positions2, gl.STATIC_DRAW); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(0); var colors2 = new Float32Array([ 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0 ]); var colorBuffer2 = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer2); gl.bufferData(gl.ARRAY_BUFFER, colors2, gl.STATIC_DRAW); gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(1); //////////////// // DRAW //////////////// gl.clear(gl.COLOR_BUFFER_BIT); gl.bindVertexArray(triangleArray); gl.drawArrays(gl.TRIANGLES, 0, 3); gl.bindVertexArray(triangleArray2); gl.drawArrays(gl.TRIANGLES, 0, 3);
首先,定義了三角形的頂點數據和緩衝區和WebGL1的代碼很相似,下面是一個三角相關數據定義的代碼code
var triangleArray = gl.createVertexArray(); gl.bindVertexArray(triangleArray); var positions = new Float32Array([ -0.5, -0.5, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0 ]); var positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(0); var colors = new Float32Array([ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ]); var colorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW); gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(1);
能夠看出除了前兩行 建立VAO和綁定VAO代碼外,其餘的代碼都是WebGL1同樣的代碼:對象
代碼中定義了兩種頂點信息:頂點座標和頂點顏色索引
建立另一個三角形的相關數據的代碼和第一個相似,不重複說明。開發
如今回到前面兩行代碼:
var triangleArray = gl.createVertexArray(); gl.bindVertexArray(triangleArray);
第一行代碼建立了一個VAO對象,第二行代碼綁定該VAO對象,這兩行代碼的做用是: 後面關於頂點緩衝對象的操做和狀態,都會被記錄到這個VAO對象中,之後繪製的時候,只須要調用gl.bindVertexArray方法,綁定該對象,就會自動使用相關的狀態。
下面在看繪製的代碼
gl.clear(gl.COLOR_BUFFER_BIT);// 清空顏色緩衝區 // 繪製第一個三角形 gl.bindVertexArray(triangleArray); gl.drawArrays(gl.TRIANGLES, 0, 3); // 繪製第二個三角形 gl.bindVertexArray(triangleArray2); gl.drawArrays(gl.TRIANGLES, 0, 3);
第一行代碼,清空顏色緩衝區,和WebGL1同樣;而後繪製第一個三角形,繪製時候,
繪製第二個三角形和第一個三角形相似;
回顧下,若是不使用頂點數組對象,繪製第一個三角形的代碼即是這樣:
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(0); gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(1); gl.drawArrays(gl.TRIANGLES, 0, 3);
繪製第二個三角形相似,由此能夠看出,使用VAO對象以後,gl.bindVertexArray這一行代碼至關於如下代碼:
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(0); gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(1);
也就是綁定緩衝區對象,分配attribute和啓用attribute變量等等操做均可以在繪製的時候能夠再也不調用了。 有次能夠看出,使用VAO對象的好處:
在WebGL1.0中VAO是經過擴展方式提供的,首先須要獲取對應的擴展對象:
var ext = gl.getExtension("OES_vertex_array_object");
若是返回的ext位null說明瀏覽器不支持該擴展。
有了上面的ext對象,即可以建立VAO了:
var vao = ext.createVertexArrayOES();
有了VAO對象以後,就能夠進行綁定操做:
// bind ext.bindVertexArrayOES(vao); // unbind ext.bindVertexArrayOES(null);