gpt4 book ai didi

javascript - 如何在 three.js 中完全清理上下文和 Canvas

转载 作者:行者123 更新时间:2023-11-29 16:00:13 27 4
gpt4 key购买 nike

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

它有一个“主”和几个“弹出”,每个都有自己的 Canvas 、场景和渲染器。 “主要”也有一个始终显示的场景等。

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

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

在弹出窗口关闭时我们:

  • 处理场景中的一切( Material 等)
  • 配置OrbitControl
  • 处理渲染器
  • forceContextLoss() 渲染器
  • 从 DOM 中移除 Canvas

我怀疑 Canvas 阻止上下文被清理,但也许我错过了什么?那么,我们如何才能完全删除弹出窗口的上下文?

谢谢,威廉

最佳答案

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

(a) 使用单个上下文和剪刀测试来模拟多个 Canvas (推荐)

参见 techniques like this

(b) 使用 virtual webgl context在单个上下文之上模拟多个上下文。

你真的只有 1 个上下文,其他都是虚拟的

据我所知,没有办法强制浏览器释放上下文。即使强制上下文丢失也不能保证摆脱 WebGLRenderingContext 对象,事实上它明确不会。当您遇到上下文丢失事件时,即使在恢复后您也会继续使用相同的上下文对象。

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

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

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

'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>

关于javascript - 如何在 three.js 中完全清理上下文和 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54323838/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com