WebGL2系列之圖元重啓

背景

在使用WebGL繪製圖形的時候,大多數狀況下,繪製一個圖形的時候,其各個圖元都是相連的。 可是在一些狀況下,咱們須要繪製圖元不相連的圖形,若是繪製的模式是gl.TRAINGLES或者gl.LINES,也是能夠達到的,可是若是繪製的模式是gl.TRAINGLE_STRIP,gl.TRAINGLE_FAN,gl.LINE_STRIP,gl.LINE_LOOP的時候,就無法在一次繪製下實現繪製多個不相連的圖元了。 通常的作法就是,經過循環,屢次繪製。好比以下代碼:web

for (var i = 0; i < num_objects; i++) {
    gl.drawArrays(gl.TRIANGLES,0,count);
}

咱們知道,每次調用一次gl.drawArrays或者gl.drawElements方法都是一次很高的系統開銷,若是調用方法的次數不少,會致使程序的性能下降。
在OPENGL中,一種解決方法是能夠經過glMultiDrawElements方法來批量繪製多個圖元。可是這個函數在WebGL中並不支持。並且使用這個函數,仍然須要將每個分散的圖形維護一組單獨的頂點座標/紋理座標,這個是免不了的,這些數據仍然須要分開上傳,仍是會消耗必定的資源。
在WebGL2中,能夠經過圖元重啓的特性來解決這個問題。數組

圖元重啓

前面說過,若是繪製模式是gl.TRAINGLE_STRIP,gl.TRAINGLE_FAN,gl.LINE_STRIP,gl.LINE_LOOP的時候
,繪製的全部點都是按照特定的順序被鏈接在一塊兒的,以造成複雜的圖形,也就是說最終的圖形必定是又多個相連的三角形或者線段組成,而不能是由分散的三角形或者線段組成。
若是要繪製分散的三角形或者線段,一種是前面所說的循環的方法;還有另一種方式,就是圖元重啓(Primitive restart)。
圖元重啓能夠繪製分散的三角形或者線段。所謂圖元重啓,就是當咱們使用gl.drawElements方法繪製圖形的時候,能夠在索引數組裏面指定特定的重啓標誌,當drawElements方法遇到重啓標誌的時候,就會從頭開始從新繪製一個圖元,好比下面的索引數組函數

var flag = primitiveRestartFlag;
var indices = [0,1,2,3,4,flag,5,6,7,8,9]

假設繪製的模式是gl.TRAINGLE_FAN,那麼若是沒有重啓標誌,點0和點1-9 會組成一個以點0位中心的扇形,如今加入了重啓標誌,那麼點0會和點1-4組成一個以點0爲中心的扇形;以後遇到了flag,此時圖元重啓,遇到這個值的時候,WebGL不會繼續繪製圖元,而是結束上一段繪製,而後從新啓動新的繪製,也就是說用後面的索引所指定的頂點來從頭繪製一個圖形;會繪製一個以點5和點6-9組成的以點5位中心點的扇形。性能

啓動圖元重啓功能

在OPENGL中,能夠經過如下方法啓動圖元重啓功能:webgl

glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);

而在WEBGL2中,圖元重啓功能默認是開啓的,並且老是開啓的,不能經過gl.enable和gl.disable方法來控制。
參考WebGL2 文檔:https://www.khronos.org/regis...rest

圖元重啓標誌

以前提到了圖元重啓是在遇到特定的標誌才重啓的,那麼這個標誌應該是多少了,通常而言gl.drawElements方法的索引值的類型能夠是如下幾種:code

  • gl.UNSIGNED_BYTE
  • gl.UNSIGNED_SHORT
  • gl.UNSIGNED_INT

那麼分別對應的重啓的標誌就是索引

  • 2^8 - 1
  • 2^16 - 1
  • 2^32 - 1

也就是說重啓的標誌的數值就是indices數組所能容許的最大值。這個值通常來講是不會被用到的,拿來當標誌正好。資源

代碼片斷

下面的代碼,在定義的indices數組中加入了圖元重啓標誌:文檔

/*https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.18
 *WebGL 2.0 behaves as though PRIMITIVE_RESTART_FIXED_INDEX were always enabled. 
*/
var MAX_UNSIGNED_SHORT = 65535;
var num_vertices = 7;
 var indices = new Uint16Array([
       0, 1, 2, MAX_UNSIGNED_SHORT, 2, 3, 1
  ]);
相關文章
相關標籤/搜索