所以我要做的是创建一个可以服务于不同用户程序的画布(即,不仅是新的着色器,还有新的对象,转换等)。通过单击程序,应清除当前的WebGL上下文,并将一个全新的程序加载到旧的上下文中。这是我目前的方法,我不确定它是否可行......有任何建议吗?
目前,无论何时选择新程序,javascript都会丢弃旧的program.js并将新的程序添加到DOM中。在用户更改为新程序后,我一直在尝试清理上下文(解除绑定缓冲区和纹理)。但是由于javascript的异步执行,我遇到了副作用:在卸载缓冲区之后仍然存在从旧程序中留下的绘制调用。如果有可能清理旧的制服和属性,我现在也没有意识到。
我想做的是什么?或者我应该在程序更改时创建一个全新的画布和上下文?我的猜测是,这会很快填满内存。你们会说我的想法是最好的方法吗?
编辑:我现在简要介绍一下我的程序如何运作。
只调用一次的初始init()函数:
var select = document.getElementById('program-list');
userProgram = select.options[select.selectedIndex].value;
console.log('Initializing WebGL with user program: ' + userProgram);
canvas = document.getElementById('graphics-surface');
gl = canvas.getContext('webgl'); // create GL context
if (!gl) {
console.log('WebGL not supported, falling back on experimental-webgl');
gl = canvas.getContext('experimental-webgl');
alert('Your browser does not support WegGL.');
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.frontFace(gl.CCW);
gl.cullFace(gl.BACK);
RunDemo(userProgram);
所以实际上一个program.js会被删除,并且一个新的program2.js作为onchange附加在HTML≤select>中。
var changeProgram = function (elem) {
changing = true;
CleanUpDemo();
document.getElementById('program-src').remove();
console.log('program removed');
userProgram = elem.value;
appendSrc(userProgram);
switch (userProgram) {
...
}
changing = false;
RunDemo(userProgram);
};
program.js中的清理功能:
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.deleteTexture(texture);
gl.deleteBuffer(vbo);
gl.deleteBuffer(ibo);
gl.deleteBuffer(normalsBuffer);
gl.deleteRenderbuffer(someRenderbuffer);
gl.deleteFramebuffer(someFramebuffer);
gl.deleteProgram(program);
gl.deleteShader(fragmentShader);
gl.deleteShader(vertexShader);
程序将如下所示:
var InitProgram = function () {
... // meshes, textures and shaders are loaded from file and passed to RunProgram()
RunProgram(vshText, fshText, img, modelObj);
};
var RunProgram = function (vertexShaderText, fragmentShaderText, textureImg, modelFile) {
... // load shaders, meshes, textures, attribs and uniforms to gpu
var loop = function () {
if(!changing) { // added this flag to help with asynchronous calls, doesn't work of course
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
}
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
};