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

WebGL尝试访问属性2中超出范围的顶点时出错,webgl,render,Webgl,Render,我知道这个问题被问了很多次,但没有一个解决方案真正适合我的情况。我希望使用下面显示的代码向画布添加第二种类型的对象。我知道我没有提供太多,但这是一个快速的开始。如果你觉得自己有预感,就要求更多。下面的代码在我的渲染函数中 到目前为止,我已经检查过了 我的点数组中有足够的顶点 我的法线数组中有足够的法向量 我的texCoords数组中有足够的纹理坐标 创建地形和螺旋桨时添加的矢量之间没有不匹配 地形渲染与纹理,照明和所有,但我无法得到螺旋桨渲染很好。我得到上面列出的错误。我以前在画布上添加过多个对

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

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

  • 我的点数组中有足够的顶点
  • 我的法线数组中有足够的法向量
  • 我的texCoords数组中有足够的纹理坐标
  • 创建地形和螺旋桨时添加的矢量之间没有不匹配 地形渲染与纹理,照明和所有,但我无法得到螺旋桨渲染很好。我得到上面列出的错误。我以前在画布上添加过多个对象,从未遇到过这样的错误

    //----------------------------------------- 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);
    
    /---------------------------------------绘制地形------------------------------------
    var i=0;
    
    对于(var row=0-dimension;row您不了解哪一部分?错误很明显,您附加到属性2的任何缓冲区都不足以处理
    properterstart,points.length
    draw请求

    所以第一件事是找出哪个属性是属性2。通过打印出属性位置来实现。是点、法线还是纹理坐标

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

    然后查看附加到该属性的缓冲区的大小。若要在某个地方执行此操作,您可能会调用

    gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);
    gl.vertexAttribPointer(locationForAttribute2, size, type, normalize, stride, offset);
    
    因此,我们从上面的代码中知道它是
    someBuffer
    。我们还需要知道
    大小
    类型
    步幅
    ,以及
    偏移量

    在其他地方,您使用

    gl.bindBuffer(gl.ARRAEY_BUFFER, someBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, someData, ...);
    
    所以你需要找到一些数据的大小

    sizeOfBuffer = someData.length * someData.BYTES_PER_ELEMENT
    
    让我们看一下它是一个1000个元素
    Float32Array
    所以它是someData.length是1000,而
    someData.BYTES\u/u element
    是4,所以
    sizeOfBuffer
    是4000

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

    假设
    size
    为3,
    type
    gl.FLOAT
    stride
    为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;
    
    需要字节数
    在本例中为(64*49)+12=3148

    现在我们知道需要多少字节了。缓冲区有足够的数据吗?当您调用draw时,我们将看到您传入的偏移量
    properterstart
    。让我们假设它是900,并且属性So中有
    偏移量

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


    在任何情况下,关键是你要找出属性#2使用哪个缓冲区,然后看看为什么缓冲区太小。你到DrawArray的偏移量错了吗?你的步幅太大了吗?你在VertexAttributePointer中的偏移量错了吗(是字节数而不是单位数)。你的大小(1,2,3,4)错了吗.您是否计算错了点数?

    您不了解什么部分?错误很明显,您附加到属性2的任何缓冲区都不够大,无法处理
    螺旋桨开始,点数。长度
    绘图请求

    所以第一件事是找出哪个属性是属性2。通过打印出属性位置来实现。是点、法线还是纹理坐标

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

    然后查看附加到该属性的缓冲区的大小。若要在某个地方执行此操作,您可能会调用

    gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);
    gl.vertexAttribPointer(locationForAttribute2, size, type, normalize, stride, offset);
    
    因此,我们从上面的代码中知道它是
    someBuffer
    。我们还需要知道
    大小
    类型
    步幅
    ,以及
    偏移量

    在其他地方,您使用

    gl.bindBuffer(gl.ARRAEY_BUFFER, someBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, someData, ...);
    
    所以你需要找到一些数据的大小

    sizeOfBuffer = someData.length * someData.BYTES_PER_ELEMENT
    
    让我们看一下它是一个1000个元素
    Float32Array
    所以它是someData.length是1000,而
    someData.BYTES\u/u element
    是4,所以
    sizeOfBuffer
    是4000

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

    假设
    size
    为3,
    type
    gl.FLOAT
    stride
    为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;
    
    需要字节数
    在本例中为(64*49)+12=3148

    现在我们知道需要多少字节了。缓冲区有足够的数据吗?当您调用draw时,我们将看到您传入的偏移量
    properterstart
    。让我们假设它是900,并且属性So中有
    偏移量

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


    在任何情况下,关键是你要找出属性#2使用哪个缓冲区,然后看看为什么缓冲区太小。你到DrawArray的偏移量错了吗?你的步幅太大了吗?你在VertexAttributePointer中的偏移量错了吗(是字节数而不是单位数)。你的大小(1,2,3,4)错了吗.你计算错分数了吗?

    谢谢你的详细回答。我算出来了,谢谢!“你不明白哪部分?错误是cl