在使用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
那么分别对应的重启的标志就是索引
也就是說重启的标志的数值就是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 ]);