一部のプロジェクトでは、60fpsが完全に必要なわけではないと思っていました。そのフレームレートでスムーズに実行できれば、30fpsで実行されるオブジェクトや物をもっと増やすことができると思いました。 three.js内でrequestAnimationFrameシムを編集した場合、その方法で30に制限できると考えました。しかし、提供されているthree.js自体を使用してこれを行うより良い方法があるかどうか疑問に思っていました。また、これは私が考えているようなパフォーマンスの向上をもたらしますか? 60fpsの2倍のオブジェクトを30fpsでレンダリングできますか? 30と60での実行の違いを知っていますが、スムーズな一定の30fpsで実行できるようになりますか?
私は通常WebGLRendererを使用し、特定のものをターゲットにしているプロジェクトを除いて、必要に応じてCanvasにフォールバックします。通常、これらはwebglシェーダープロジェクトです。
このようなものはどうですか?
function animate() {
setTimeout( function() {
requestAnimationFrame( animate );
}, 1000 / 30 );
renderer.render();
}
CPUとGPUが実行する必要のある作業量はワークロードによって異なり、スムーズなフレームレートの上限を設定します。
GPUはほぼ線形に動作し、常に同じ数のポリゴンを画面にプッシュできます。
ただし、オブジェクトの数を2倍にした場合、CPUはこれらすべてのオブジェクト(行列変換など)をアニメーション化するためにさらに努力する必要があります。それはあなたの世界モデルとJavascriptがどれだけの余分なオーバーヘッドが与えられるかを行う他の仕事に依存します。 visibleオブジェクトの数などの条件も重要です。
すべてのポリゴンが常に画面上にある単純なモデルの場合は、「フレームレートの半分、オブジェクトを2倍にする」という規則に従う必要があります。シーンのような3Dシューティングゲームの場合、これは間違いなく当てはまりません。
カスタムフレームレートの問題を解決する2つの方法を提供するこの記事に出くわしました。
http://codetheory.in/controlling-the-frame-rate-with-requestanimationframe/
この方法は、60 fpsで一貫してキャンバスをレンダリングしないコンピューターでも安定したアニメーション速度になるため、より堅牢だと思います。以下は例です
var now,delta,then = Date.now();
var interval = 1000/30;
function animate() {
requestAnimationFrame (animate);
now = Date.now();
delta = now - then;
//update time dependent animations here at 30 fps
if (delta > interval) {
sphereMesh.quaternion.multiplyQuaternions(autoRotationQuaternion, sphereMesh.quaternion);
then = now - (delta % interval);
}
render();
}
このアプローチは、THREE.Clockを使用してデルタを測定することでも機能します。
let clock = new THREE.Clock();
let delta = 0;
// 30 fps
let interval = 1 / 30;
function update() {
requestAnimationFrame(update);
delta += clock.getDelta();
if (delta > interval) {
// The draw or time dependent code are here
render();
delta = delta % interval;
}
}
一般的な回答には問題があり、fpsを制限しない場合と比較して、低速のコンピューターでは最大-10fpsになります。たとえば、36pfsを制限せずに、受け入れられているソリューションは26fpsです。
代わりにこれを行うことができます:
var dt=1000/60;
var timeTarget=0;
function render(){
if(Date.now()>=timeTarget){
gameLogic();
renderer.render();
timeTarget+=dt;
if(Date.now()>=timeTarget){
timeTarget=Date.now();
}
}
requestAnimationFrame(render);
}
その方法は、すでに遅れている場合は待つつもりはありません。