怎么通过HTML的WebGL2的vertexAttribDivisor实现实例化绘制大量重复物体

浅涛君_8861

浅涛君_8861

2026-05-27

307人浏览

原创

vertexattribdivisor 是 webgl2 中控制顶点属性按实例步进更新的关键机制;值为 0 表示每顶点更新,1 表示每实例更新,从而支持高效实例化渲染,避免多次 draw call 和 cpu 矩阵计算。

怎么通过html的webgl2的vertexattribdivisor实现实例化绘制大量重复物体

vertexAttribDivisor 是什么,为什么它能加速实例化

vertexAttribDivisor 是 WebGL2(及 OpenGL ES 3.0+)中控制顶点属性更新频率的关键机制。它不改变顶点数据本身,而是告诉 GPU:这个 vertexAttribPointer 绑定的 attribute,每多少个「实例」才取下一个值。值为 0 表示“每个顶点都取”,值为 1 表示“每个实例取一次”,值为 n 表示“每 n 个实例取一次”。

真正实现「大量重复物体」高效绘制的核心,是把变化量(如位置、颜色、缩放)从 CPU 逐个提交,变成一次性上传为「实例属性数组」,再靠 vertexAttribDivisor 让 shader 按实例步进读取——避免了成百上千次 drawArrays/drawElements 调用,也绕开了 JS 层循环拼接矩阵的性能瓶颈。

必须满足的 WebGL2 前置条件

不是所有环境都能直接用 vertexAttribDivisor,漏掉任一环节都会静默失败或报 INVALID_OPERATION:

  • 确保上下文是 webgl2:创建 canvas 时显式传 { alpha: false, antialias: false } 并检查 gl.getParameter(gl.VERSION) 是否含 WebGL 2.0
  • 必须启用扩展(即使 WebGL2 原生支持):gl.getExtension('ANGLE_instanced_arrays') 或 gl.getExtension('EXT_instanced_arrays') —— 某些旧 Chrome/Android WebView 仍需显式获取
  • 调用 vertexAttribPointer 后,**必须立刻**跟 gl.vertexAttribDivisor(index, divisor),顺序不能颠倒;否则 divisor 保持默认 0,实例化失效
  • shader 中对应 attribute 必须用 in 修饰符声明,且类型需匹配(如 vec3、mat4),不能是 uniform

如何上传实例数据并设置 divisor

假设你要绘制 1000 个立方体,每个带唯一 modelMatrix(4×4),共 16 个 float。你不能把整个矩阵塞进一个 attribute(单 attribute 最大 4 分量),得拆成 4 个 vec4 attribute:

Html2md
Html2md

使用 Readability + Turndown 将 HTML 页面转换为干净的、Agent 友好的 Markdown。去除导航栏、广告、页脚、Cookie 横幅、社交按钮等干扰元素。支持 URL...

下载
const matrices = new Float32Array(1000 * 16); // 按列主序排布
// ... 填充数据(注意:第0个矩阵的第0列 → matrices[0..3],第1列 → matrices[4..7]...)
<p>const matrixBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, matrixBuffer);
gl.bufferData(gl.ARRAY_BUFFER, matrices, gl.STATIC_DRAW);</p><p>// 绑定第0列到 location=3
gl.enableVertexAttribArray(3);
gl.vertexAttribPointer(3, 4, gl.FLOAT, false, 64, 0); // stride=16*4=64 字节,offset=0
gl.vertexAttribDivisor(3, 1); // ✅ 关键:每实例更新一次</p><p>// 绑定第1列到 location=4
gl.enableVertexAttribArray(4);
gl.vertexAttribPointer(4, 4, gl.FLOAT, false, 64, 16); // offset=16 字节
gl.vertexAttribDivisor(4, 1);</p><p>// 同理绑定第2、第3列(location=5,6),stride 和 offset 按 16 字节递增</p>

注意:stride 是整个矩阵的字节数(16×4),不是单列;offset 是该列在矩阵内的起始偏移(0, 16, 32, 48);divisor 全部设为 1,确保每实例读取完整矩阵。

drawElementsInstanced 的调用要点和常见崩溃点

最终绘制必须用 gl.drawElementsInstanced(或 drawArraysInstanced),传入实例数而非顶点数。最容易出错的是参数错位和未清空状态:

  • gl.drawElementsInstanced(mode, count, type, indicesOffset, instanceCount) —— 第 5 个参数才是实例数,不是第 2 个!写成 drawElementsInstanced(..., 1000) 才对,别写成 drawElements(..., 1000)
  • 如果之前用了 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo),确保 ibo 是索引缓冲区(非顶点缓冲区),且数据格式与 type 一致(gl.UNSIGNED_SHORT 或 gl.UNSIGNED_INT)
  • 每次绘制前,务必确认所有用到的 attribute 都已 enableVertexAttribArray,且 vertexAttribDivisor 已设;漏掉任意一个,该 attribute 会退化为 per-vertex 行为,导致模型错位或全黑
  • 移动端尤其注意:某些 Mali GPU 对 divisor > 1 支持不稳定,建议实例数超过 1000 时优先用 divisor = 1,避免用 divisor = 2 等非常规值

实例化不是银弹——矩阵计算仍发生在 GPU 上,但把「CPU 准备→GPU 传输→GPU 绘制」的链路压到了最低开销。真正卡点往往不在 shader,而在 buffer 上传时机和 divisor 设置的原子性:少一次 vertexAttribDivisor 调用,就可能让 10 万个实例退化成 10 万个 draw call。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

html

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
html版权符号
html版权符号

html版权符号是“©”,可以在html源文件中直接输入或者从word中复制粘贴过来,php中文网还为大家带来html的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.14

6475

7

html在线编辑器
html在线编辑器

html在线编辑器是用于在线编辑的工具,编辑的内容是基于HTML的文档。它经常被应用于留言板留言、论坛发贴、Blog编写日志或等需要用户输入普通HTML的地方,是Web应用的常用模块之一。php中文网为大家带来了html在线编辑器的相关教程、以及相关文章等内容,供大家免费下载使用。

2023.06.21

3612

4

html网页制作
html网页制作

html网页制作是指使用超文本标记语言来设计和创建网页的过程,html是一种标记语言,它使用标记来描述文档结构和语义,并定义了网页中的各种元素和内容的呈现方式。本专题为大家提供html网页制作的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.31

3290

5

html空格
html空格

html空格是一种用于在网页中添加间隔和对齐文本的特殊字符,被用于在网页中插入额外的空间,以改变元素之间的排列和对齐方式。本专题为大家提供html空格的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.01

3299

5

html是什么
html是什么

HTML是一种标准标记语言,用于创建和呈现网页的结构和内容,是互联网发展的基石,为网页开发提供了丰富的功能和灵活性。本专题为大家提供html相关的各种文章、以及下载和课程。

2023.08.11

4999

6

html字体大小怎么设置
html字体大小怎么设置

在网页设计中,字体大小的选择是至关重要的。合理的字体大小不仅可以提升网页的可读性,还能够影响用户对网页整体布局的感知。php中文网将介绍一些常用的方法和技巧,帮助您在HTML中设置合适的字体大小。

2023.08.11

3261

3

html转txt
html转txt

html转txt的方法有使用文本编辑器、使用在线转换工具和使用Python编程。本专题为大家提供html转txt相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.31

3069

3

html文本框代码怎么写
html文本框代码怎么写

html文本框代码:1、单行文本框【<input type="text" style="height:..;width:..;" />】;2、多行文本框【textarea style=";height:;"></textare】。

2023.09.01

2688

6

HTML嵌入CSS样式的方法
HTML嵌入CSS样式的方法

HTML嵌入CSS样式的方法有内联样式、内部样式表和外部样式表。本专题为大家提供CSS样式相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.20

2768

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
GDB 17.2 官方文档集合
GDB 17.2 官方文档集合

共0课时 | 0人学习

Bootstrap 入门安装配置
Bootstrap 入门安装配置

共0课时 | 0人学习

38+ PhpStorm 提示和技巧
38+ PhpStorm 提示和技巧

共1课时 | 225人学习