Не уверен, что это прямой ответ, но, думаю, вам повезет больше либо
(а) с использованием одного контекста и теста ножниц для эмуляции нескольких полотен (рекомендуется)
См. методов, подобных этой
или
(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>