首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebGL2系列之图元重启

WebGL2系列之图元重启

作者头像
用户3158888
发布2019-05-28 14:35:00
6110
发布2019-05-28 14:35:00
举报

背景

在使用WebGL绘制图形的时候,大多数情况下,绘制一个图形的时候,其各个图元都是相连的。 但是在一些情况下,我们需要绘制图元不相连的图形,如果绘制的模式是gl.TRAINGLES或者gl.LINES,也是可以达到的,但是如果绘制的模式是gl.TRAINGLE_STRIP,gl.TRAINGLE_FAN,gl.LINE_STRIP,gl.LINE_LOOP的时候,就没法在一次绘制下实现绘制多个不相连的图元了。 一般的做法就是,通过循环,多次绘制。比如如下代码:

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中,可以通过以下方法启动图元重启功能:

glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);

而在WEBGL2中,图元重启功能默认是开启的,而且总是开启的,不能通过gl.enable和gl.disable方法来控制。 参考WebGL2 文档:https://www.khronos.org/regis...

图元重启标志

之前提到了图元重启是在遇到特定的标志才重启的,那么这个标志应该是多少了,一般而言gl.drawElements方法的索引值的类型可以是以下几种:

  • 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
  ]);
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 图元重启
  • 启动图元重启功能
  • 图元重启标志
  • 代码片段
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档