清理 Threejs WebGl 上下文

Posted

技术标签:

【中文标题】清理 Threejs WebGl 上下文【英文标题】:Clean up Threejs WebGl contexts 【发布时间】:2014-02-04 09:17:33 【问题描述】:

我在清理 WebGl 场景时遇到问题。我将 Three.js 与 WebGlRenderer 一起使用。在我的应用程序中,我必须经常更改视图,因此需要一直渲染新场景。到目前为止,我销毁并重新初始化了整个 Threejs 场景。切换场景大约 15 - 20 次后,我收到以下警告:

WARNING: Too many active WebGL contexts. Oldest context will be lost.

多次切换后,上下文完全丢失,应用程序崩溃。

有没有办法在清理时销毁当前的 WebGl 上下文?还是 WebGlRenderer 在实例化时总是创建一个新的 WebGl 上下文?

我正在使用 Three.js R64。

【问题讨论】:

除非您有用于渲染的分屏系统,否则一个上下文就足够了。它并不打算频繁地丢弃和创建上下文。 好的,这对我有用。谢谢。 【参考方案1】:

我也有同样的问题,但由于要求,我无法使用 SPA 解决它。

WebGLRenderer 中有 .forceContextLoss() 方法(rev 71,可能是早期的)用于这种情况。

所以,我在 'deallocate' 方法中的代码有点像

_self.renderer.forceContextLoss();
_self.renderer.context = null;
_self.renderer.domElement = null;
_self.renderer = null;

【讨论】:

这行得通。虽然它在 r74 中没有记录,但它在那里 github.com/mrdoob/three.js/blob/r74/src/renderers/… 这也适用于我。同时,值得一提的是,扩展“WEBGL_lose_context”模拟了webgl上下文丢失,这并不意味着浏览器实际上释放了webgl上下文分配的GPU上的资源,而可能只是假装它确实做到了。 Kronos 上有一个讨论帖。 IE11 不支持此功能。我的 SPA 在 Chrome 上运行得很好,但在 IE11 上我开始看到快速的性能退化。对于 IE,我想唯一的选择是拥有单例 WebGL 上下文(在 ThreeJS 的情况下是 WebGLRenderer)并在整个会话中重用它。 在 2020 年仍然有用(THREE.js Release 113)。【参考方案2】:

您可以为不同的场景保留相同的渲染器。渲染器并不关心它将渲染什么场景。如果您愿意,可以在每次致电 render() 时提供不同的 Scene

// instantiate only once and keep it
var renderer = new THREE.WebGLRenderer();

// current scene and camera. Switch whenever you like
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(...);
fillScene(scene);

// rendering always uses current scene
function render() 
    renderer.render(scene, camera);
    requestAnimationFrame(render);


/* ... 
 *   somewhere in your application
 * ...
 */
if(condition) 
  // switch scene
  scene = new THREE.Scene();
  fillOtherScene(scene);

【讨论】:

谢谢,这也是我的方法。使用一个渲染并在需要时交换场景。 :) 使用 Threejs r98,可以结合调用 renderer.dispose() 来释放内存。【参考方案3】:

您应该只创建和使用一个 WebGlRenderer。在我的 SPA(单页应用程序)中,经过几次重定向后,THREE.js 中的相机/场景出现了奇怪的问题。这是因为每次呈现一个特定页面时都会创建 WebGlRenderer。控制台日志中没有错误(只有您写的警告)。 错误表现为相机位置的变化和渲染问题。

【讨论】:

嘿! kraag,我正在使用角度指令开发threejs,当我重定向它时出现内存泄漏问题,你设法解决你的问题吗?怎么清理threejs? 正如我所写。只使用一个 WebGlRenderer 是的,但我需要将threejs渲染到其他视图(使用d3)的视图,然后我需要重新初始化threejs,所以我需要一种干净的方法来删除它们,或者我应该持有渲染一次初始化?并保留以备将来使用?

以上是关于清理 Threejs WebGl 上下文的主要内容,如果未能解决你的问题,请参考以下文章

在测试WebGL上下文后删除WebGL上下文

WebGL入门(四十四)-WebGL上下文丢失事件与上下文恢复事件处理

webgl丢失上下文

如何确定活动WebGL上下文的数量?

Autodesk Forge 上的 WebGL 上下文丢失错误

<canvas>:从内存中删除 2d 上下文而不从内存中删除 webgl 上下文