WebGL 尝试访问属性 2 错误中超出范围的顶点

Tyl*_*iss 0 render webgl

我知道这个问题已经被问了很多次,但没有一个解决方案真正适合我的情况。我希望使用下面所示的代码将第二种类型的对象添加到画布中。我知道我没有提供太多,但这是一个快速的开始。如果您认为自己有预感,请要求更多。下面的代码位于我的渲染函数中。

到目前为止我已经检查过

  1. 我的点数组中有足够的顶点
  2. 我的法线数组中有足够的法线向量
  3. 我的 texCoords 数组中有足够的纹理坐标
  4. 创建地形和螺旋桨时添加的矢量之间没有不匹配。

地形的纹理、光照等渲染得很好,但是我无法让螺旋桨渲染。我收到上面列出的错误。我之前曾向画布添加过多个对象,但从未遇到过这样的错误。

//----------------------------------------- Draw Terrain ------------------------------------
  var i = 0;
  for(var row=0-dimension; row<dimension; row+=3){
    for(var col=0-dimension; col<dimension; col+=3, i++){
      var mv = mult(viewer, mult(translate(row, -1, col), mult(scale[i],rot[i])));
      gl.uniformMatrix4fv(modelViewLoc, false, flatten(mv));
      gl.uniformMatrix3fv(normalLoc, false, flatten(normalMatrix(mv, true)));
      gl.drawArrays( gl.TRIANGLES, 0, index);
    }
  }

  //----------------------------------------- Draw Propeller ------------------------------------
  mv = mult(viewer, mult( translate(-2.1, -2.9, -.2), scalem(4,5,5)));
  gl.uniformMatrix4fv(modelViewLoc, false, flatten(mv));
  gl.uniformMatrix3fv(normalLoc, false, flatten(normalMatrix(mv, true)));
  gl.drawArrays( gl.TRIANGLES, propellerStart, points.length);
Run Code Online (Sandbox Code Playgroud)

有什么方法可以使用错误消息中的“属性 2”来追踪给我带来此问题的变量吗?

感谢您的帮助!

gma*_*man 5

哪一部分你不明白?错误很明显,无论您附加到属性 2 的缓冲区都不够大,无法处理propellerStart, points.length绘制请求。

因此,第一件事是找出哪个属性是属性 2。通过打印出属性位置来完成此操作。你的点、法线还是纹理坐标?

您应该已经在某处查找它们,gl.getAttribLocation因此打印出这些值,找出哪个是#2。

然后查看附加到该属性的缓冲区的大小。要在某个地方做到这一点,你会打电话。

gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);
gl.vertexAttribPointer(locationForAttribute2, size, type, normalize, stride, offset);
Run Code Online (Sandbox Code Playgroud)

someBuffer所以我们从上面的代码就知道了。我们还需要知道size, type, stride, 和offset

在其他地方,您使用数据填充了该缓冲区

gl.bindBuffer(gl.ARRAEY_BUFFER, someBuffer);
gl.bufferData(gl.ARRAY_BUFFER, someData, ...);
Run Code Online (Sandbox Code Playgroud)

所以你需要找到someData的大小。

sizeOfBuffer = someData.length * someData.BYTES_PER_ELEMENT
Run Code Online (Sandbox Code Playgroud)

假设它是一个 1000 个元素Float32Array,因此 someData.length 是 1000,并且someData.BYTES_PER_ELEMENT是 4,因此sizeOfBuffer是 4000。

使用所有这些,您现在可以检查缓冲区是否太小。(注意:我们已经知道它太小了,因为浏览器告诉我们如此,但如果您想知道如何自己计算它)

假设sizeis 3、typeis gl.FLOATstrideis 32、offsetis 12 (注意:我个人从不使用除了 stride = 0 和 offset = 0 之外的任何东西)

比方说points.length = 50

numPoints = points.length;
bytesPerElement = size * 4;   // because a gl.FLOAT is 4 bytes
realStride = stride === 0 ? bytesPerElement : stride;
bytesNeeded = realStride * (numPoints - 1) + bytesPerElement;
Run Code Online (Sandbox Code Playgroud)

bytesNeeded在这种情况下是 (64 * 49) + 12 = 3148

现在我们知道需要多少字节。缓冲区是否有足够的数据?当您调用 Draw 时,我们会传入一个 offset propellerStart。我们假设它是 900 并且offset属性中有 。

bufferSizeNeeded = offset + propellerStart + bytesNeeded
Run Code Online (Sandbox Code Playgroud)

所以bufferSizeNeeded = 12 + 900 + 3148这是 4060。由于 4060 >sizeOfBuffer这是 4000,所以你会得到你得到的错误。

无论如何,关键是你要弄清楚属性 #2 使用哪个缓冲区,然后看看为什么你的缓冲区太小。你的drawArrays偏移量是错误的吗?你的步幅是否太大了?您在 vertexAttribPointer 中的偏移量是否错误(它是字节数而不是单位数)。您是否输入了错误的尺寸(1、2、3、4)。你是否计算错了分数?

  • “你不明白哪一部分?错误很明显” - 不清楚你是否是 webgl/opengl 的新手...... (6认同)