Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 通过setInterval限制WebGL帧速率会严重降低性能_Performance_Three.js_Webgl_Frame Rate - Fatal编程技术网

Performance 通过setInterval限制WebGL帧速率会严重降低性能

Performance 通过setInterval限制WebGL帧速率会严重降低性能,performance,three.js,webgl,frame-rate,Performance,Three.js,Webgl,Frame Rate,我正在创建一个webgl游戏,我对它进行了相当好的优化,但是有一个问题,我的帧速率限制器破坏了性能。我知道你在想什么“嗯,当然是……这是fps限制器”。问题是它没有按预期运行。代码如下: renderTimer = null; function animate() { clearTimeout(renderTimer); renderTimer = setTimeout(function () { _frame = requestAnimationFrame(animate);

我正在创建一个webgl游戏,我对它进行了相当好的优化,但是有一个问题,我的帧速率限制器破坏了性能。我知道你在想什么“嗯,当然是……这是fps限制器”。问题是它没有按预期运行。代码如下:

renderTimer = null;
function animate() {
  clearTimeout(renderTimer);
  renderTimer = setTimeout(function () {
    _frame = requestAnimationFrame(animate);
  }, 33);
  render();
}

function render(){
  // operations for mesh positioning/animation
  handleObjects();
  renderer.render(scene, camera);
}
在我的桌面上,这是预期的工作,游戏是顺利的,并举行在29-30fps

在我的笔记本电脑上,fps下降到22-24,游戏性很差。如果我将间隔延迟改为16毫秒,游戏会相对流畅,保持在35帧/秒左右。如果我删除所有的时间间隔,游戏是完全平滑的,保持在45帧左右

我不完全理解这种行为。如果上限是30fps,为什么我的笔记本电脑性能会降到25fps以下?我希望它在没有间隔的情况下也是25fps,但是速度更快。好奇

我很乐意取消这个间隔,但是我希望我的fps限制在30,球员获得更高的fps将是一个优势


想法?

有几个考虑因素:

  • javascript中的setTimeout不能真正指望非常准确
  • 浏览器可以在任何时候做自己的事情,比如垃圾收集,延迟处理
  • 渲染本身(webgl/three.js+您自己的游戏逻辑)需要时间。即使在主渲染调用之前创建超时,它仍然会引入33毫秒的空闲时间
嗯,现在我想起来了,实际上我不确定最后一点。不管怎样,我观察到了类似的问题,并且我成功地找到了一个非常好的解决方案,如果计算机能够处理这样的帧速率,它将保持帧速率平滑,并且+/-1-2 FPS精确到目标帧速率。不过这是一个黑客

首先,您可以查看Three.js中的requestAnimationFrame实现(对于没有内置该实现的浏览器):

您可以看到,它根据最后一次调用调整setTimeout(目标速度约为60FPS)。所以这是一个你可以尝试的解决方案

我所做的(这项技术似乎很有效)是将超时值作为一个变量,初始值是原始的33或任何期望的帧速率。然后在每一帧上,我记录Date.now(),并将其与前一帧时间进行比较。如果我们错过了预算的帧时间,我们将超时值减少1。如果我们比期望的快,我们将超时时间增加1。因此,代码将持续、平滑地调整超时以匹配所需的帧速率。通过稍微增加/减少,我们避免了不可预知的垃圾收集等问题,完全避免了计算和混乱。它只是工作(tm)


我不会发布代码,因为在我的渲染循环中还有很多事情要做(只有在发生更改时才渲染新帧等),隔离相关的代码示例将是一件乏味的事情。

很有趣。那么在您的示例中,您正在覆盖现有的requestAnimationFrame函数?递增超时解决方案很有趣,我下班后必须试一试。requestAnimationFrame是Three.js中包含的垫片的复制粘贴,以说明浏览器本机不支持它。这似乎是一个自动调整超时值的好例子。我的实现,我描述的,只是稍微扩展了这个想法(我没有覆盖requestAnimationFrame,它都在animate函数和friends中)。啊,好了,我等不及要试一试了=]可变目标速率方法工作得非常好,谢谢@雅库:我试过使用你的方法,如果我想将FPS限制在30以下,效果很好。如果说我想将FPS限制在45,它似乎不起作用。事实上,只需在我的动画中添加一个setTimeout(如下所示),就可以将FPS降低到30。你能分享你的发现吗?
function animate(ts){setTimeout(function(){requestAnimationFrame(animate);},1000/60);//进行渲染}
requestAnimationFrame = function ( callback ) {
  var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
  var id = self.setTimeout( function() { callback( currTime + timeToCall ); }, timeToCall );
  lastTime = currTime + timeToCall;
  return id;
};