You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否为每个顶点与每个实例设置不同的WebGL顶点属性?

解决方法

你要实现的是让颜色属性每个实例的每个顶点都用不同值,但现在你的颜色缓冲区是按实例堆在一起的(先放第一个三角形的三个颜色,再放第二个的),用drawArraysInstanced的话默认会重复读前三个颜色,第二个实例还是用color1-3,达不到你要的效果。

有两种直接的解决办法:

办法1:调整颜色缓冲区的排列方式(推荐)

把颜色按顶点来分组,每个顶点的所有实例颜色放一块儿:

// 调整后的Color buffer
[
  color1, color4,  // 顶点0对应实例0、实例1的颜色
  color2, color5,  // 顶点1对应实例0、实例1的颜色
  color3, color6   // 顶点2对应实例0、实例1的颜色
]

然后给colorLocation补充以下设置:

// 设置stride:每个顶点占2个颜色的字节数(2*4*4=32字节)
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 32, 0);
// 让颜色属性每切换一个实例更新一次
gl.vertexAttribDivisor(colorLocation, 1);

这样实例0会取每个顶点的第一个颜色,实例1取第二个,正好符合你的要求。

办法2:不改动缓冲区,靠着色器实现

要是不想改缓冲区结构,就得把颜色数据转成纹理(因为顶点缓冲区没法随机跳着读),然后在顶点着色器里用gl_InstanceID和gl_VertexID算索引:

  1. 把颜色缓冲区的数据传到一个2D纹理里
  2. 在着色器里算坐标:vec2 texCoord = vec2(gl_VertexID + gl_InstanceID * 3, 0.0)
  3. 用texelFetch读对应颜色
    这种办法JS端不用改colorLocation的设置,但着色器要写更多代码,效率也不如第一种高。

额外提醒

要是你非得用现在的缓冲区排列又不想改着色器,那其实没必要用实例化渲染,直接调用gl.drawArrays(gl.TRIANGLES, 0, 6)画6个顶点就行,反而更简单。


内容的提问来源于stack exchange,提问作者Holger Seelig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:20:50