WebGL 中缓冲区范围超出范围的常见原因是什么
What is common cause of range out of bounds of buffer in WebGL
我正在从事一个 webgl 项目。
当我调用 gl.DrawElements 时,显示错误 'range out of bounds of buffer'。
我确实确保传递了正确的缓冲区长度或偏移量。但是,仍然显示错误。
我认为有多种原因可能会引发错误。因此,我想问一下你的项目中是否有同样的问题,你检查了什么来解决这个问题?
调用 gl.drawElements
时出现该错误的原因只有 3 个
您的索引引用了超出缓冲区范围的顶点
例如你制作了一个缓冲区并在其中放入了 3 个位置值
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
var data = [1,2,3,4,5,6,7,8,9]; // 3 (3 value) positions
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
由于只有 3 个位置,因此唯一可能的索引是 0、1 和 2。因此,如果您在索引缓冲区中放入任何其他值,就会出现该错误。
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
var indices = [0,1,3]; // ERROR! That 3 is out of range
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
// This will generate an out of bounds error because
// the 3 index we put in the index buffer is out of range
// as the only valid indices are 0, 1, and 2.
gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 0);
您试图绘制太多索引或设置的偏移量超出范围
考虑到上面的设置,如果你这样做了
gl.drawElements(gl.TRIANGLE, 4, gl.UNSIGNED_SHORT, 0);
你会超出范围,因为你只放入了 3 个索引,但你要求绘制 4 个。同样,如果你更改偏移量
gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 1);
同样,您只放入了 3 个索引,但您要求它绘制索引 1,2 和 3 而不是 0、1 和 2。
您将属性设置为访问过多数据
假设我们像上面那样放置了三个 3 值位置。如果我们设置属性像这样拉出3个4值位置
var size = 4; // ERROR! There are only 3 value per position
gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
该设置将尝试访问 12 个数据浮点数(假设您的索引正确)但您只输入了 9 个数据浮点数。大小应等于 3
如果您将步幅或偏移量(gl.vertexAtrribPointer
的最后 2 个参数设置为错误的值,您同样会搞砸。几乎所有 WebGL 程序总是在那里使用 0、0。如果您正在做更花哨的东西确保你设置正确。
您可能没有将数组作为正确的类型传递。很容易忘记将顶点或索引从一般 Javascript 数组转换为 an explicitly typed array.
例如(改编自 gman 的第一个例子):
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
var data = [1,2,3, 4,5,6, 7,8,9, 10,11,12]; // 4 3-D positions
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
// ^^^^^^^^^^^^^^^^
// Failure to explicitly construct a typed array here can give this WebGL error,
// if you bind this array to an attribute:
// GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
var indices = [3,2,1];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
// ^^^^^^^^^^^^^^^
// Failure to explicitly construct a typed array here gives this WebGL error:
// GL_INVALID_OPERATION : glDrawElements: range out of bounds for buffer
gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 0);
在 Javascript、every numeric value is represented by default as an object of type Number 中,这是一个 IEEE 64 位浮点数。因此,例如,indices
数组的第一个元素 3
由以下 64 位表示:
0000 0000 0001 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
如果您将常规 Javascript 数组传递到元素数组缓冲区,那么当 gl.drawElements()
要求将缓冲区解释为无符号短整型(16 位整数)时,它会首先看到那些64位为4组16位,读出如下值:
0000 0000 0001 1000 = 24
0000 0000 0000 0000 = 0
0000 0000 0000 0000 = 0
0000 0000 0000 0000 = 0
当然,24 超出了我们的 4 元素顶点位置数组缓冲区的范围。
出现此错误是因为我正在使用:
gl.drawElements(drawingMode, count, this.gl.UNSIGNED_INT, 0)
而不是:
gl.drawElements(drawingMode, count, this.gl.UNSIGNED_SHORT, 0)
(加载的数据当然是 Uint16Array 而不是 Uint32Array)。
我正在从事一个 webgl 项目。 当我调用 gl.DrawElements 时,显示错误 'range out of bounds of buffer'。
我确实确保传递了正确的缓冲区长度或偏移量。但是,仍然显示错误。
我认为有多种原因可能会引发错误。因此,我想问一下你的项目中是否有同样的问题,你检查了什么来解决这个问题?
调用 gl.drawElements
您的索引引用了超出缓冲区范围的顶点
例如你制作了一个缓冲区并在其中放入了 3 个位置值
var buf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buf); var data = [1,2,3,4,5,6,7,8,9]; // 3 (3 value) positions gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
由于只有 3 个位置,因此唯一可能的索引是 0、1 和 2。因此,如果您在索引缓冲区中放入任何其他值,就会出现该错误。
var indexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf); var indices = [0,1,3]; // ERROR! That 3 is out of range gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); // This will generate an out of bounds error because // the 3 index we put in the index buffer is out of range // as the only valid indices are 0, 1, and 2. gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 0);
您试图绘制太多索引或设置的偏移量超出范围
考虑到上面的设置,如果你这样做了
gl.drawElements(gl.TRIANGLE, 4, gl.UNSIGNED_SHORT, 0);
你会超出范围,因为你只放入了 3 个索引,但你要求绘制 4 个。同样,如果你更改偏移量
gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 1);
同样,您只放入了 3 个索引,但您要求它绘制索引 1,2 和 3 而不是 0、1 和 2。
您将属性设置为访问过多数据
假设我们像上面那样放置了三个 3 值位置。如果我们设置属性像这样拉出3个4值位置
var size = 4; // ERROR! There are only 3 value per position gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
该设置将尝试访问 12 个数据浮点数(假设您的索引正确)但您只输入了 9 个数据浮点数。大小应等于 3
如果您将步幅或偏移量(
gl.vertexAtrribPointer
的最后 2 个参数设置为错误的值,您同样会搞砸。几乎所有 WebGL 程序总是在那里使用 0、0。如果您正在做更花哨的东西确保你设置正确。
您可能没有将数组作为正确的类型传递。很容易忘记将顶点或索引从一般 Javascript 数组转换为 an explicitly typed array.
例如(改编自 gman 的第一个例子):
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
var data = [1,2,3, 4,5,6, 7,8,9, 10,11,12]; // 4 3-D positions
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
// ^^^^^^^^^^^^^^^^
// Failure to explicitly construct a typed array here can give this WebGL error,
// if you bind this array to an attribute:
// GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
var indices = [3,2,1];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
// ^^^^^^^^^^^^^^^
// Failure to explicitly construct a typed array here gives this WebGL error:
// GL_INVALID_OPERATION : glDrawElements: range out of bounds for buffer
gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 0);
在 Javascript、every numeric value is represented by default as an object of type Number 中,这是一个 IEEE 64 位浮点数。因此,例如,indices
数组的第一个元素 3
由以下 64 位表示:
0000 0000 0001 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
如果您将常规 Javascript 数组传递到元素数组缓冲区,那么当 gl.drawElements()
要求将缓冲区解释为无符号短整型(16 位整数)时,它会首先看到那些64位为4组16位,读出如下值:
0000 0000 0001 1000 = 24
0000 0000 0000 0000 = 0
0000 0000 0000 0000 = 0
0000 0000 0000 0000 = 0
当然,24 超出了我们的 4 元素顶点位置数组缓冲区的范围。
出现此错误是因为我正在使用:
gl.drawElements(drawingMode, count, this.gl.UNSIGNED_INT, 0)
而不是:
gl.drawElements(drawingMode, count, this.gl.UNSIGNED_SHORT, 0)
(加载的数据当然是 Uint16Array 而不是 Uint32Array)。