6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Three.jsでディスプレイによってオブジェクトのスピード感が違うのをなんとかしたい

Last updated at Posted at 2024-10-16

概要

Three.jsでディスプレイによって動きのスピードが早かったり遅かったりといったことが起こると思います。
その対応策を調べました。

問題のコード

公式サイトのコード
  import * as THREE from "three";

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setAnimationLoop(animate); //⭐️
  document.body.appendChild(renderer.domElement);

  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  camera.position.z = 5;

  function animate() {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera);
  }

上記は公式のコードです。
このままの状態だと cubeの動きがディスプレイによって早かったり遅かったりします。

仕組みとしては、⭐️をつけた行の setAnimationLoop関数で animate関数を呼び出しています。
その呼び出し方がディスプレイのリフレッシュレートに基づいているため、ディスプレイごとに早かったり遅かったりします。

対応策

追加編集したコード
  import * as THREE from "three";

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setAnimationLoop(animate);
  document.body.appendChild(renderer.domElement);

  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  camera.position.z = 5;

+ const clock = new THREE.Clock(); //①

  function animate() {
+   const elapsedTime = clock.getElapsedTime(); //②

-   cube.rotation.x += 0.01;
+   cube.rotation.x = elapsedTime; //③
-   cube.rotation.y += 0.01;
+   cube.rotation.y = elapsedTime; //③

    renderer.render(scene, camera);
  }

Clockのインスタンスを作成(①の箇所)し、
そこから getElapsedTime メソッドの値を elapsedTime に代入(②の箇所)、
その値を cubeのrotation に代入(③の箇所)しました。

これで、cubeの動きは時間で制御されるようになったので、
リフレッシュレートに関わらず一定の速さで動くようになりました。

おわりに

すごい細かいこだわりかもしれませんが、何も疑問に思わず requastAnimationFrame で動かしたりしていたので、勉強になりました :baby:

6
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?