【问题标题】:WebGL attempt to access out of range vertices in attribute 2 errorWebGL 尝试访问属性 2 中超出范围的顶点错误
【发布时间】:2018-04-28 09:46:37
【问题描述】:

我知道这个问题被问了很多,但没有一个解决方案真正适合我的情况。我正在寻找使用下面显示的代码向画布添加第二种类型的对象。我知道我没有提供太多,但它是一个快速的开始。如果您认为自己有预感,请询问更多。下面的代码在我的渲染函数中。

到目前为止,我已经检查过了

  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);

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

感谢您的帮助!

【问题讨论】:

    标签: webgl render


    【解决方案1】:

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

    所以首先要弄清楚哪个属性是属性 2。通过打印出属性位置来做到这一点。你的点、法线还是 texcoords?

    您应该已经使用gl.getAttribLocation 在某个地方查找它们,所以打印出这些值,找出哪个是#2。

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

    gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);
    gl.vertexAttribPointer(locationForAttribute2, size, type, normalize, stride, offset);
    

    所以我们从上面的代码中知道它是someBuffer。我们还需要知道sizetypestrideoffset

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

    gl.bindBuffer(gl.ARRAEY_BUFFER, someBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, someData, ...);
    

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

    sizeOfBuffer = someData.length * someData.BYTES_PER_ELEMENT
    

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

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

    假设size 是 3,typegl.FLOATstride 是 32,offset 是 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;
    

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

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

    bufferSizeNeeded = offset + propellerStart + bytesNeeded
    

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

    在任何情况下,关键在于你要确定属性#2 使用了哪个缓冲区,然后去看看为什么你的缓冲区太小了。您对 drawArrays 的偏移量是否错误?你的步幅是不是太大了?您在 vertexAttribPointer 中的偏移量是否错误(它的字节数不是单位数)。你放错尺寸了吗(1,2,3,4)。你算错点数了吗?

    【讨论】:

    • 感谢详细的回复。我知道了,谢谢!
    • “你不明白哪一部分?错误很明显”——不清楚你是否刚接触 webgl/opengl...
    猜你喜欢
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多