WebGL 尝试访问属性 2 错误中超出范围的顶点
WebGL attempt to access out of range vertices in attribute 2 error
我知道这个问题已经被问了很多,但是 none 的解决方案确实适合我的情况。我希望使用下面显示的代码向 canvas 添加第二种类型的对象。我知道我没有提供太多,但它是一个快速的开始。如果您认为自己有预感,就要求更多。下面的代码在我的渲染函数中。
到目前为止我已经检查过
- 我的点数组中有足够的顶点
- 我的法线数组中有足够的法向量
- 我的 texCoords 数组中有足够的纹理坐标
- 创建我的地形和我的螺旋桨时添加的矢量之间没有不匹配。
地形在纹理、光照等方面渲染得很好,但我无法渲染螺旋桨。我收到上面列出的错误。我之前已经将多个对象添加到 canvases 并且从来没有 运行 出现这样的错误。
//----------------------------------------- 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);
有什么方法可以使用错误消息中的 "Attribute 2" 来追踪给我这个问题的变量吗?
感谢您的帮助!
哪一部分你不明白?错误很明显,无论您附加到属性 2 的缓冲区都不够大,无法处理 propellerStart, points.length
绘制请求。
所以首先要弄清楚哪个属性是属性 2。通过打印出您的属性位置来做到这一点。您是点、法线还是纹理坐标?
你应该已经在某个地方用 gl.getAttribLocation
查找它们了,所以打印出这些值,找出哪个是 #2。
然后查看您附加到该属性的缓冲区的大小。在你会打电话的地方做那件事。
gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);
gl.vertexAttribPointer(locationForAttribute2, size, type, normalize, stride, offset);
所以我们从上面的代码中知道它是someBuffer
。我们还需要知道 size
、type
、stride
和 offset
您在其他地方使用
用数据填充了缓冲区
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,type
是gl.FLOAT
,stride
是32,offset
是12(注意:我个人从不使用任何东西但步幅 = 0 且偏移量 = 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)。你是不是算错点数了?
我知道这个问题已经被问了很多,但是 none 的解决方案确实适合我的情况。我希望使用下面显示的代码向 canvas 添加第二种类型的对象。我知道我没有提供太多,但它是一个快速的开始。如果您认为自己有预感,就要求更多。下面的代码在我的渲染函数中。
到目前为止我已经检查过
- 我的点数组中有足够的顶点
- 我的法线数组中有足够的法向量
- 我的 texCoords 数组中有足够的纹理坐标
- 创建我的地形和我的螺旋桨时添加的矢量之间没有不匹配。
地形在纹理、光照等方面渲染得很好,但我无法渲染螺旋桨。我收到上面列出的错误。我之前已经将多个对象添加到 canvases 并且从来没有 运行 出现这样的错误。
//----------------------------------------- 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);
有什么方法可以使用错误消息中的 "Attribute 2" 来追踪给我这个问题的变量吗?
感谢您的帮助!
哪一部分你不明白?错误很明显,无论您附加到属性 2 的缓冲区都不够大,无法处理 propellerStart, points.length
绘制请求。
所以首先要弄清楚哪个属性是属性 2。通过打印出您的属性位置来做到这一点。您是点、法线还是纹理坐标?
你应该已经在某个地方用 gl.getAttribLocation
查找它们了,所以打印出这些值,找出哪个是 #2。
然后查看您附加到该属性的缓冲区的大小。在你会打电话的地方做那件事。
gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);
gl.vertexAttribPointer(locationForAttribute2, size, type, normalize, stride, offset);
所以我们从上面的代码中知道它是someBuffer
。我们还需要知道 size
、type
、stride
和 offset
您在其他地方使用
用数据填充了缓冲区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,type
是gl.FLOAT
,stride
是32,offset
是12(注意:我个人从不使用任何东西但步幅 = 0 且偏移量 = 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)。你是不是算错点数了?