"GL_INVALID_OPERATION: Insufficient buffer size." 在可变数量的渲染调用之后
"GL_INVALID_OPERATION: Insufficient buffer size." after variable number of render calls
我正在使用 MapboxGL 将 geojson 作为多边形渲染到地图上。页面正确加载和呈现,但是当我四处移动地图时,在一定数量(通常在 ~30-100 之间)的呈现调用和多边形消失后出现此错误。
GL_INVALID_OPERATION: 缓冲区大小不足。 (Chrome)
WebGL 警告:drawElementsInstanced:索引缓冲区太小。 (FF)
我已经设法(我认为)将其缩小到
的问题
gl.drawElements(gl.TRIANGLES, tResult.triangleIndices.length, gl.UNSIGNED_SHORT, 0);
使用 Spector.js 扩展,我看到 drawElements 方法中的第二个参数(计数)在每次调用时都不同(tResult.triangleIndices.length 在我登录时 而不是 它)。这可能是个误会,因为它适用于 30-100 次渲染。
我在 bufferData() 和 drawElements() 中尝试了缓冲区类型的各种数据类型组合,但没有成功。
我试过使用较低的多边形网格。
我尝试在每个渲染过程中调用各种 gl.clear 方法。
这可能不相关,但 fwiw 它是一个 vue-cli 应用程序,所以它正在从 npm 加载库。
相关代码如下:
初始化:
[...setting up shaders and stuff]
// link the two shaders into a WebGL program
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
this.aPos = gl.getAttribLocation(this.program, 'a_pos');
gl.clearColor(1.0, 1.0, 1.0, 1.0); // Clear to black, fully opaque
// create and initialize a WebGLBuffer to store vertex and color data
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(tResult.triangleLocations), gl.STATIC_DRAW);
this.verticesIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(tResult.triangleIndices), gl.STATIC_DRAW);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.enable(gl.CULL_FACE);
gl.cullFace(gl.BACK);
渲染:
render: function (gl, matrix) {
gl.useProgram(this.program);
gl.uniformMatrix4fv(
gl.getUniformLocation(this.program, 'u_matrix'),
false,
matrix
);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.enableVertexAttribArray(this.aPos);
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
gl.drawElements(gl.TRIANGLES, tResult.triangleIndices.length, gl.UNSIGNED_SHORT, 0);
}
这个问题在我看来就像你在渲染时没有设置 ELEMENT_ARRAY_BUFFER
。
如果您没有使用顶点数组(您没有),那么属性和缓冲区绑定是全局状态。因此,如果在您初始化事物和渲染事物(例如 mapbox 渲染它的东西)之间改变了状态,那么当您渲染时,您将使用与您在 init 中设置的不同的缓冲区。
尝试添加
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer);
调用前drawElements
类似地,如果在相同的 webgl 上下文中发生任何其他事情,您设置的其他状态(如面部剔除)可能会或可能不会持续到渲染时间。
如果不行你也可以试试webgl-lint for slightly informative error. Especially if you label your buffers
我正在使用 MapboxGL 将 geojson 作为多边形渲染到地图上。页面正确加载和呈现,但是当我四处移动地图时,在一定数量(通常在 ~30-100 之间)的呈现调用和多边形消失后出现此错误。
GL_INVALID_OPERATION: 缓冲区大小不足。 (Chrome)
WebGL 警告:drawElementsInstanced:索引缓冲区太小。 (FF)
我已经设法(我认为)将其缩小到
的问题gl.drawElements(gl.TRIANGLES, tResult.triangleIndices.length, gl.UNSIGNED_SHORT, 0);
使用 Spector.js 扩展,我看到 drawElements 方法中的第二个参数(计数)在每次调用时都不同(tResult.triangleIndices.length 在我登录时 而不是 它)。这可能是个误会,因为它适用于 30-100 次渲染。
我在 bufferData() 和 drawElements() 中尝试了缓冲区类型的各种数据类型组合,但没有成功。
我试过使用较低的多边形网格。
我尝试在每个渲染过程中调用各种 gl.clear 方法。
这可能不相关,但 fwiw 它是一个 vue-cli 应用程序,所以它正在从 npm 加载库。
相关代码如下:
初始化:
[...setting up shaders and stuff]
// link the two shaders into a WebGL program
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
this.aPos = gl.getAttribLocation(this.program, 'a_pos');
gl.clearColor(1.0, 1.0, 1.0, 1.0); // Clear to black, fully opaque
// create and initialize a WebGLBuffer to store vertex and color data
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(tResult.triangleLocations), gl.STATIC_DRAW);
this.verticesIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(tResult.triangleIndices), gl.STATIC_DRAW);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.enable(gl.CULL_FACE);
gl.cullFace(gl.BACK);
渲染:
render: function (gl, matrix) {
gl.useProgram(this.program);
gl.uniformMatrix4fv(
gl.getUniformLocation(this.program, 'u_matrix'),
false,
matrix
);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.enableVertexAttribArray(this.aPos);
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
gl.drawElements(gl.TRIANGLES, tResult.triangleIndices.length, gl.UNSIGNED_SHORT, 0);
}
这个问题在我看来就像你在渲染时没有设置 ELEMENT_ARRAY_BUFFER
。
如果您没有使用顶点数组(您没有),那么属性和缓冲区绑定是全局状态。因此,如果在您初始化事物和渲染事物(例如 mapbox 渲染它的东西)之间改变了状态,那么当您渲染时,您将使用与您在 init 中设置的不同的缓冲区。
尝试添加
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer);
调用前drawElements
类似地,如果在相同的 webgl 上下文中发生任何其他事情,您设置的其他状态(如面部剔除)可能会或可能不会持续到渲染时间。
如果不行你也可以试试webgl-lint for slightly informative error. Especially if you label your buffers