Three.jsをはじめよう。3D空間の基礎【第1回】

スマートフォンの普及とブラウザ性能の向上により、WEBサイトは「静的な情報の羅列」から「動的で立体的な体験」へと進化を遂げています。
その進化の中心にあるのが、ブラウザ上で3DCGを描画するJavaScriptライブラリ「Three.js」です。

かつては高度なゲーム開発者や、ごく一部のクリエイティブスタジオだけのものだった3D表現が、今や中小企業のブランドサイトや製品プロモーションページでも活用される時代になりました。

この連載では、皆さんと一緒に「3D空間を作る楽しさ」を共有しながら、ビジネスにも役立つ本格的な技術を身につけていくことを目指します。

第1回となる今回は、最小限のセットアップでThree.jsを動かし、3D空間の基本構造を理解することを目指し、最終的なゴールは、ブラウザ上の黒い空間に、鮮やかな緑色の立方体が浮かび、ゆっくりと回転している状態を作ることです。

一見シンプルですが、ここには3D開発のエッセンスがすべて詰まっています。それでは、Three.jsの世界へ一歩踏み出しましょう。

Three.jsを動かす準備

本格的な開発では「Vite(ヴィート)」などの便利なツールを使いますが、今回は一番シンプルな「HTML / CSS / JavaScript」の3つのファイルを用意するところから始めましょう。

3D制作を始めるにあたって、環境構築に時間をかけすぎるのは得策ではありません。
まずは「コードを書いて、すぐに結果が見える」状態を作りましょう。

基本のファイル構成

まずはPC上に作業用フォルダを作成し、以下の3つのファイルを用意します。

  • index.html(表示用の画面)
  • style.css(画面いっぱいに表示するための設定)
  • main.js(Three.jsのメインロジック)

バンドルツールの推奨について

実際の制作現場では、Viteなどのモダンなバンドルツールを使用するのが一般的です。
これにより、最新のJavaScript構文が使えたり、表示を高速化できたりといったメリットがあります。

もしすでにNode.jsなどの環境が整っている方は、npm create vite@latestを利用してセットアップすることをお勧めしますが、まずは仕組みを理解したいという方は、HTMLからCDN経由で読み込む方法でも十分学習を始められます。

Three.jsを構成する「3大要素」の理解

3D空間をブラウザに表示させるためには、現実世界をカメラで撮影するようなイメージを持つことが重要です。Three.jsには、絶対に欠かせない3つの役割が存在します。

Scene(舞台):すべてを包み込む「箱」

Sceneは、3Dオブジェクト、ライト、背景など、すべての要素を配置するための「舞台」です。この箱の中に何もなければ、当然何も表示されません。

Camera(視点):ユーザーの「目」

Cameraは、舞台のどの部分を、どの角度から切り取るかを決定します。WEB制作で最も一般的に使われるのは「PerspectiveCamera(遠近法カメラ)」です。近くのものは大きく、遠くのものは小さく見える、私たちの肉眼に近い表現が可能です。

Renderer(描画):映像を映し出す「映写機」

SceneとCameraが揃っても、それをHTML(Canvas要素)に書き出す処理が必要です。Rendererは、Sceneの内容をCameraの視点から計算し、ピクセルデータとして画面に描画する役割を担います。

実践:立方体を生成する

それでは、実際にコードを書いていきましょう。
以下のステップに沿って記述していきます。

基本の3要素(シーン、カメラ、レンダラー)を作る

まず、土台となる3つの要素を定義します。

      // 1. Three.jsライブラリをインターネットから読み込む
      import * as THREE from "https://unpkg.com/three@0.160.0/build/three.module.js";

      // ------------------------------------------------
      // ステップ1: 基本の3要素(シーン、カメラ、レンダラー)を作る
      // ------------------------------------------------

      // シーン(舞台)を作成
      const scene = new THREE.Scene();
      scene.background = new THREE.Color(0x1a1a1a); // 背景は黒

      // カメラ(視点)を作成
      // new THREE.PerspectiveCamera(画角, アスペクト比, 近くの制限, 遠くの制限)
      const camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      camera.position.z = 5; // カメラを少し手前に引く(そうしないと物体の中に入ってしまう)

      // レンダラー(描画する人)を作成
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight); // 画面いっぱいに広げる
      document.body.appendChild(renderer.domElement); // HTMLにキャンバスを追加

物体(メッシュ)を作る

3D空間に表示される物体は、専門用語で「Mesh(メッシュ)」と呼ばれます。このMeshは、以下の2つの要素が組み合わさってできています。

  • Geometry(ジオメトリ)
    物体の「骨格」や「形状」です。頂点情報の集まりを指します。
  • Material(マテリアル)
    物体の「表面」や「質感」です。色、光沢、透明度などを定義します。

この関係性は、よく「粘土細工の形(Geometry)」と、そこに塗る「絵の具(Material)」に例えられます。

      // ------------------------------------------------
      // ステップ2: 物体(メッシュ)を作る
      // ------------------------------------------------

      // ジオメトリ(形状): 箱型(幅, 高さ, 奥行き)
      const geometry = new THREE.BoxGeometry(1, 1, 1);

      // マテリアル(質感): 緑色
      // MeshBasicMaterialは光の影響を受けないため、ライトがなくても色が見える
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
      material.wireframe = true;
      // メッシュ(物体): 形状と材質を組み合わせて作成
      const cube = new THREE.Mesh(geometry, material);

      // シーンに物体を追加
      scene.add(cube);

アニメーションさせる

このままでは、静止した画像が一度描画されるだけです。3Dの醍醐味である「動き」を加えるには、パラパラ漫画のように画面を高速で描き換え続ける必要があります。

アニメーションループの仕組み

JavaScriptの requestAnimationFrame という関数を使います。これはブラウザの描画タイミング(通常1秒間に60回)に合わせて処理を実行してくれる、非常にパフォーマンスに優れた手法です。

      // ------------------------------------------------
      // ステップ3: アニメーションさせる
      // ------------------------------------------------

      function animate() {
        // 次の描画タイミングでこの関数(animate)をまた呼ぶ(無限ループ)
        requestAnimationFrame(animate);

        // 物体を少し回転させる
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.005;

        // 描画を実行
        renderer.render(scene, camera);
      }

      // アニメーション開始
      animate();

画面の中で緑色の立方体がくるくると回り始めましたか?「自分の書いたコードで、3次元の物体が動いている!」とワクワクします。

エンジニアが教える「最初のトラブル」回避策

初心者が最初につまずくポイントがいくつかあります。

画面が真っ暗なときは?

  • カメラの位置
    デフォルトではCameraもMeshも座標(0, 0, 0)に配置されます。カメラを camera.position.z = 5 のように移動させないと、立方体の中にカメラが埋まってしまい、何も見えません。
  • 背景色
    今回は MeshBasicMaterial を使っていますが、他のマテリアルでは「ライト(照明)」がないと真っ黒になります。

コードの順序

Rendererの setSizeappendChild を忘れると、HTML上にCanvasが表示されません。必ず document.body に要素を追加しているか確認してください。

今回のまとめと次回のステップ

お疲れ様でした!ブラウザに緑色の立方体がくるくると回る様子が表示されたでしょうか? 今回学んだことは、どれほど複雑な3Dサイトであっても変わることはありません。

環境構築
環境構築に時間をかけすぎるのは得策ではありませんが、Vite等を使えば表示を高速化できます。
3大要素
Scene(場)、Camera(目)、Renderer(出力)。
Meshの正体
Geometry(形)+ Material(質感)。
ループ処理
requestAnimationFrameで命を吹き込む。

今回は「まずは出してみる」ところまで進みました。でも、まだこの立方体に触ることはできませんし、ブラウザの大きさを変えると表示が崩れてしまいます。

次回、第2回では「カメラワークとレスポンシブ対応」をテーマに、マウスでグリグリ動かせるようにする機能「OrbitControls」の導入や、実務で必須となる画面リサイズ対応に一緒に挑戦しましょう。

もし、今回のステップで「ここがちょっと分からなかった」「自分のサイトならこんな形を出してみたい」といった疑問やアイデアがあれば、ぜひ教えてください。一緒に考えながら、理想の3Dサイトを作っていきましょう!

それでは、次回もお楽しみに…