您可以丢失对 gl 上下文、所有 gl 对象和画布的所有引用,并从 DOM 中删除画布。不幸的是,因为 JavaScript 是垃圾收集的,所以不知道浏览器何时真正释放内存。有一些一致性测试来尝试测试它们是否正确执行此操作,但如果您不想只是希望和祈祷那么......
通过调用释放您的所有资源gl.deleteXXX
在您创建的所有内容上并取消绑定所有绑定点。这意味着对于每个纹理单元调用gl.bindTexture
在所有目标上null
,与数组、帧缓冲区和渲染缓冲区相同。
var numTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
for (var unit = 0; unit < numTextureUnits; ++unit) {
gl.activeTexture(gl.TEXTURE0 + unit);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
// Delete all your resources
// Note!!!: You'd have to change this code to delete the resources YOU created.
gl.deleteTexture(someTexture);
gl.deleteTexture(someOtherTexture);
gl.deleteBuffer(someBuffer);
gl.deleteBuffer(someOtherBuffer);
gl.deleteRenderbuffer(someRenderbuffer);
gl.deleteFramebuffer(someFramebuffer);
因为你无法绑定null
对于属性,您可以在删除所有缓冲区之前将其大小设置为 1(不允许为零)。要么创建一个新的缓冲区并将其分配给所有属性。
第一个例子
// set a buffer to 1 byte before deleting
// NOTE: You'd need to do this for ALL BUFFERS you created.
gl.bindBuffer(gl.ARRAY_BUFFER, someArrayBuffer);
gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
gl.deleteBuffer(someArrayBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, someElementArrayBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 1, gl.STATIC_DRAW);
gl.deleteBuffer(someElementArrayBuffer);
或者创建一个新的缓冲区并将其分配给所有属性
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
var numAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
for (var attrib = 0; attrib < numAttributes; ++attrib) {
gl.vertexAttribPointer(attrib, 1, gl.FLOAT, false, 0, 0);
}
这将解除旧缓冲区与属性的绑定。
最后将画布大小设置为 1x1 像素。
gl.canvas.width = 1;
gl.canvas.height = 1;
这不是一个完美的解决方案,但它会立即释放除几 k 内存之外的所有内存,无需等待超出您控制的垃圾收集。
至于从头开始重复使用画布,你不能。画布将始终具有您最初要求的相同上下文。
另请参阅@约翰的回答 https://stackoverflow.com/a/38027471/1480391 about loseContext