繁体   English   中英

如何在three.js中完全清理上下文和画布

[英]How to fully clean up the context and canvas in three.js

我们有一个也可以在iPad上运行的应用程序。 使用three.js r100。

它有一个“主”和几个“弹出窗口”,每个都有自己的画布,场景和渲染器。 “主”也有一个总是显示的场景等。

为避免内存问题,我们在打开弹出窗口时创建所有对象,并在弹出窗口关闭时进行清理。 但是在iPad上,webinfo仍然显示了关闭弹出窗口的画布。

在打开/关闭几个弹出窗口后,我们得到一个关于太多上下文的错误(“此页面上有太多活动的WebGL上下文,最旧的上下文将丢失。”)。 丢失的第一个上下文是“主要”场景。 之后,系统尝试松开“弹出”上下文。 显示第二个错误:“WebGL:INVALID_OPERATION:loseContext:context has lost”。 这似乎是合乎逻辑的,因为我们在关闭弹出窗口时执行了forceContextLoss()。

在弹出窗口关闭我们:

  • 处理场景中的所有内容(材质等)
  • 处理OrbitControl
  • 处理渲染器
  • forceContextLoss()渲染器
  • 从DOM中删除画布

我怀疑画布是在保持上下文不被清理,但也许我想念一些东西? 那么,我们怎样才能完全删除弹出窗口的上下文?

谢谢,威廉

不确定这是一个直接的答案,但我认为你也会有更好的运气

(a)使用单一背景和剪刀测试来模拟多幅画布(推荐)

看到这样的技术

要么

(b)使用虚拟webgl上下文 ,该上下文在单个上下文之上模拟多个上下文。

你真正只有1个上下文而其他人是虚拟的

AFAIK没有办法强制浏览器释放上下文。 即使强制上下文丢失也不能保证摆脱WebGLRenderingContext对象,事实上它显然没有。 当您获得上下文丢失事件时,即使在恢复后仍继续使用相同的上下文对象。

因此,无法保证浏览器不会在创建第9个上下文后立即删除最旧的上下文(或者无论限制是什么)。 唯一的保证是通常在创建新的上下文时,只有旧的上下文丢失了。

无论是最近最少使用的上下文还是最旧的上下文或上下文,最少的资源或没有更多引用的上下文都取决于浏览器。 真的没有简单的方法让浏览器知道要释放哪些上下文。

这是创建和删除上下文的快速测试。 在Chrome桌面上创建第17个上下文时,最旧的上下文会丢失

 'use strict'; /* global THREE */ function makeScene(canvas, color = 0x44aa88, timeout = 0) { const renderer = new THREE.WebGLRenderer({canvas: canvas}); const fov = 75; const aspect = 2; // the canvas default const near = 0.1; const far = 5; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); camera.position.z = 2; const scene = new THREE.Scene(); { const color = 0xFFFFFF; const intensity = 1; const light = new THREE.DirectionalLight(color, intensity); light.position.set(-1, 2, 4); scene.add(light); } const boxWidth = 1; const boxHeight = 1; const boxDepth = 1; const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth); const material = new THREE.MeshPhongMaterial({color}); const cube = new THREE.Mesh(geometry, material); scene.add(cube); let requestId; function render(time) { time *= 0.001; // convert time to seconds cube.rotation.x = time; cube.rotation.y = time; renderer.render(scene, camera); requestId = requestAnimationFrame(render); } requestId = requestAnimationFrame(render); if (timeout) { setTimeout(() => { cancelAnimationFrame(requestId); canvas.parentElement.removeChild(canvas); // manually free all three objects that hold GPU resoucres geometry.dispose(); material.dispose(); renderer.dispose(); }, timeout); } } makeScene(document.querySelector('#c')); let count = 0; setInterval(() => { console.log(++count); const canvas = document.createElement("canvas"); document.body.appendChild(canvas); makeScene(canvas, Math.random() * 0xFFFFFF | 0, 500); }, 1000); 
 <canvas id="c"></canvas> <script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/three.min.js"></script> 

这是与virtual-webgl相同的测试

 'use strict'; /* global THREE */ function makeScene(canvas, color = 0x44aa88, timeout = 0) { const renderer = new THREE.WebGLRenderer({canvas: canvas}); const fov = 75; const aspect = 2; // the canvas default const near = 0.1; const far = 5; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); camera.position.z = 2; const scene = new THREE.Scene(); { const color = 0xFFFFFF; const intensity = 1; const light = new THREE.DirectionalLight(color, intensity); light.position.set(-1, 2, 4); scene.add(light); } const boxWidth = 1; const boxHeight = 1; const boxDepth = 1; const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth); const material = new THREE.MeshPhongMaterial({color}); const cube = new THREE.Mesh(geometry, material); scene.add(cube); let requestId; function render(time) { time *= 0.001; // convert time to seconds cube.rotation.x = time; cube.rotation.y = time; renderer.render(scene, camera); requestId = requestAnimationFrame(render); } requestId = requestAnimationFrame(render); if (timeout) { setTimeout(() => { cancelAnimationFrame(requestId); // take the canvas out of the dom canvas.parentElement.removeChild(canvas); // manually free all three objects that hold GPU resoures geometry.dispose(); material.dispose(); // hold on to the context incase the rendered forgets it const gl = renderer.context; // dispose the rendered in case it has any GPU resources renderer.dispose(); // dispose the virutal context gl.dispose(); // added by virtual-webgl }, timeout); } } makeScene(document.querySelector('#c')); let count = 0; setInterval(() => { console.log(++count); const canvas = document.createElement("canvas"); document.body.appendChild(canvas); makeScene(canvas, Math.random() * 0xFFFFFF | 0, 500); }, 1000); 
 <canvas id="c"></canvas> <script src="https://greggman.github.io/virtual-webgl/src/virtual-webgl.js"></script> <script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/three.min.js"></script> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM