R.Aokiをフォローする

【Three.js】3Dアニメーションを実装してみよう

フロントエンド

はじめに

今回はちょっとしたWebGL回です。

「3D面白そうだな~」と思っていたところ、簡単に遊べることが分かったため遊んでみました。

使用技術

・Three.js

使用技術解説

そもそもWebGL(Web Graphics Library)って?

簡単に言うと「ウェブブラウザ上でプラグインを使用せずに2D・3Dのグラフィックをレンダリングする技術」です。

WebGLのプログラムは制御コードとシェーダーコードの2つで構成されており、制御コードをJavaScriptで記述、シェーダーコードをGPUで実行することで3D表現やアニメーションといった重い処理も描画可能としています。

基本的にすべてのブラウザに対応しているため、ブラウザ内で特別なプラグインを導入する必要なくグラフィックを描画することができます。

Three.jsとは?

WebGLを利用して3D表現を行うことができるJavaScriptライブラリです。

WebGLだけでは複雑な記述が必要になるところ、Three.jsを用いることでカメラやテクスチャ、光源などを容易に扱うことができます。

3Dモデルの表示やアニメーションのみならず、3Dゲームやブラウザ向けのVRを作成することも可能で、Three.jsの公式サイトでも活用事例が紹介されています。
公式サイト

使用例

以下のコードが実装内容です。

早速ですが実際に作成した動画がこちらになります。
サンプル動画

<html>
  <head>
    <meta charset="utf-8" />
    <script type="importmap">
      {
        "imports": {
          "three": "https://cdn.jsdelivr.net/npm/three@0.167.0/build/three.module.js",
          "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.167.0/examples/jsm/"
        }
      }
    </script>
    <script type="module">
      import * as THREE from "three";
      import { OrbitControls } from "three/addons/controls/OrbitControls.js";

      // サイズ指定
      const width = window.innerWidth;
      const height = window.innerHeight;

      // レンダラー作成
      const canvasElement = document.querySelector("#target");
      const renderer = new THREE.WebGLRenderer({
        canvas: canvasElement,
      });
      renderer.setClearColor(new THREE.Color("rgb(51, 51, 51)"));
      renderer.setSize(width, height);

      // シーン作成
      const scene = new THREE.Scene();

      // カメラ作成
      const camera = new THREE.PerspectiveCamera(45, width / height);
      camera.position.set(0, 0, 1000);

      // コントローラー作成
      const controls = new OrbitControls(camera, canvasElement);

      // 球体作成
      const geometry = new THREE.SphereGeometry(300, 30, 30);
      // 画像読み込み
      const loader = new THREE.TextureLoader();
      const texture = loader.load('img/cs.png');
      texture.colorSpace = THREE.SRGBColorSpace;
      // マテリアル編集
      const material = new THREE.MeshStandardMaterial({
        map: texture
      });
      // メッシュ
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);

      // 環境光源
      const ambient = new THREE.AmbientLight(0xFFFFFF, 1);
      scene.add(ambient);

      // 平行光源
      const directionalLight = new THREE.DirectionalLight(0xFFFFFF);
      directionalLight.position.set(1, 1, 1);
      scene.add(directionalLight);

      tick();

      function tick() {
        // レンダリング
        renderer.render(scene, camera);
        requestAnimationFrame(tick);
      }
    </script>
  </head>
  <body style="margin:0;">
    <canvas id="target"></canvas>
  </body>
</html>

解説

①レンダラーの作成
作成したオブジェクトを描画(レンダリング)するために使用される機能がレンダラーです。
今回はあらかじめ設定していた<canvas>に描画させています。

②カメラの作成
Three.jsで描画に必要になってくるもう一つの要素です。
レンダラーで描画空間を指定しましたが、描画する風景はここで設定したカメラを通した形で描画されます。

③コントローラーの作成
描画しているオブジェクトの動かすために使用しています。
今回は複雑な設定はせず、対象のカメラとキャンバスを指定した以外はデフォルトのままです。

④シーンの作成
シーンは簡単に言うと世界を描画するための箱のようなものです。
作成した3Dオブジェクトや光源(ライト)をシーンに設置していくことで、立体的な表現を作り込んでいきます。

⑤オブジェクトの作成、設置
three.jsでは、オブジェクトは「メッシュ」と呼ばれています。メッシュは「ジオメトリ」と「マテリアル」で構成されています。
今回の例では球体のジオメトリに用意していた画像のマテリアルを張り付けたメッシュを作成し、シーンに加えています。

⑥光源の設置
今回は環境光源と平行光源の2種類を設置しました。
環境光源は空間全体に均等に光を当てるため、描画空間自体の明るさを上げることができます。一方で平行光源は一方向への光となり、光と影が生まれます。

⑦完成
最後にレンダリングを行うループイベントを設定すれば完成です。

おわりに

以上Three.jsのご紹介でした。

今回はThree.js内で3Dオブジェクトを作成し、上から画像を張り付けるといった手法でしたが、Blenderで作成した3Dモデルを読み込んで動かすことも可能なため、人体や建造物といった複雑なものを動かすこともできます。

所感として、Three.jsのみで複雑な3Dアニメーションを行うことは難しく、基本的には3Dモデルをインポートして使用するのがメインのように感じました。
とはいえ3D文字や立方体、球体をアクセントで使用したい等であれば手軽に扱えると思います。
(某大阪テーマパークの地球儀など)

少しでも興味を持った方がいればぜひ触ってみてください!

クレジット

https://developer.mozilla.org/ja/docs/Web/API/WebGL_API
https://threejs.org/examples/