ThreeJS停止渲染

8
我正在一个基本的3D场景上使用ThreeJS,其中包含OrbitControls。一切都很好,但是即使用户没有查看它,它也在循环自身,导致整个网站变得非常缓慢。我想要一个函数,在满足某些条件时(在这种情况下,用户不查看画布),可以调用该函数来启动和停止渲染。我有一个起始函数,它工作得很好,但停止函数似乎不起作用,因为在ThreeJS初始化后,我的网站变得无法忍受地缓慢。
我已经寻找并尝试了几个“解决方案”,但由于某种原因它们不能与我的应用程序一起使用。我的假设是这些解决方案来自旧版本的ThreeJS。
以下是我在main.js文件中的代码:
var scene, 
    camera, 
    controls,
    render,
    requestId = undefined;


function init() {
    scene = new THREE.Scene();
    var threeJSCanvas = document.getElementById("threeJS");
    camera = new THREE.PerspectiveCamera( 75, threeJSCanvas.width / threeJSCanvas.height, 0.1, 1000 );

    controls = new THREE.OrbitControls( camera );

    // Controls and Camera settings

    // Create Geometry.

}

function render() {
    requestId =  requestAnimationFrame(render);
    renderer.render(scene, camera);

}

function start() {
    render();
}

function stop() {
   window.cancelAnimationFrame(requestId);
   requestId = undefined;


}

在我的另一个JavaScript文件中,我的pageChange函数(这是一个多页面应用程序)内部有一个条件语句,如下所示:

if (page == 5) { // The page with the canvas on it
    if (!locationsRendered) {
    init();
    locationsRendered = true;
}
} else { // If the page is not the page with the canvas on it
    if (locationsRendered) {
        stop();
    }
}

locationsRendered 在第二个 JavaScript 文件中的本地作用域内较早地进行了初始化。

任何帮助都将不胜感激,因为我不能让这个简单的 3D 场景在加载后拖慢我的整个应用程序。这是不现实的。


你的场景似乎是静态的。没错吧?如果是这样的话,你不需要每秒重新渲染它60次。 - WestLangley
非常正确,除了控件之外没有任何动画。由于某种原因,我认为为了使控件平稳运行,需要以60fps渲染。我将修复它并会回报! - Bjornir
只需添加 controls.addEventListener( 'change', render ); - WestLangley
那真的非常有助于性能。非常感谢!现在我只需要修改一些东西来隐藏画布,或者至少在不需要时禁用它的控件。您能否将您的回复转换为答案,以便我可以选择它作为最佳答案? - Bjornir
3个回答

13

如果你的场景是静态的,那么就没有必要使用动画循环。只需要在摄像机因鼠标或触摸事件移动时重新渲染即可。

只需要使用以下模式:

controls = new THREE.OrbitControls( camera, renderer.domElement );

controls.addEventListener( 'change', render );

function render() {

    renderer.render( scene, camera );

}

three.js r.67


我在OrbitControls.js文件中添加了一个return语句,如果event.target.id != "threeJS",我的应用程序运行更快、更高效。非常感谢您的帮助! - Bjornir

2

我在场景中使用了轨迹球控件,因此无法使用上述解决方案(因为轨迹球控件会在鼠标事件触发后继续更新)。

为了解决这个问题,我使用了:

function animate() {
  renderer.render(scene, camera);
  controls.update();
}
renderer.setAnimationLoop(animate);

这将无限运行动画循环。要暂停动画,可以指定null作为动画循环:

renderer.setAnimationLoop(null);        // pause the animation

要恢复动画,只需再次传递动画循环即可:

renderer.setAnimationLoop(animate);     // resume the animation

1

完全停止渲染循环的另一种解决方案是降低每秒帧数,从而减少资源消耗。

如果您需要对场景进行响应式更新,但不一定需要动画效果,并且需要在需要时恢复正常速度,则此方法特别有用。

使用简单的setTimout()函数可以很好地实现这一点。

var fps 10;

function render() {

   //reduce framerate
   setTimeout(()=>{

        requestAnimationFrame(render);

        //must be called to enable rotating
        controls.update();
        renderer.render(scene, camera);


   }, 1000/fps)

};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接