【three.js】で始める【glTF】の世界「初級編」

はじめに

Web技術において、3Dコンテンツはますます重要な役割を果たすようになりました。特に、Webブラウザ上でインタラクティブな3Dモデルやアニメーションを表示できる技術は、ゲーム、教育、プロダクトデザイン、建築ビジュアライゼーションなど幅広い分野で活用されています。
その中でも、three.js はブラウザ上で手軽に3Dシーンを構築できるJavaScriptライブラリとして、開発者に広く支持されています。glTF(GL Transmission Format) は、3Dモデルデータの交換フォーマットとして注目されており、高速なロードや軽量なファイルサイズが特徴です。本記事では、2枚の画像から glTF を作成するサンプルコードと、作成した glTF を表示するためのコード例をもとに、three.js を利用した glTF の基本概念から応用までを解説します。

本記事は、three.js や glTF に初めて触れる方にも理解できるよう、以下の項目について順を追って詳しく解説していきます。

  • three.js の基本構造と3D描画の仕組み
  • glTF の概要とそのメリット
  • 2枚の画像から glTF を作成するサンプルコードの詳細解説
  • 作成した glTF を表示するためのコード解説
  • 実際のプロジェクトへの応用例とカスタマイズのポイント
  • 今後の3D Webコンテンツの展望

それでは、まずは three.js や glTF の基本概念から見ていきましょう。


1. three.jsとは何か

three.js は、WebGL を抽象化してより扱いやすくした JavaScript ライブラリです。WebGL 自体はブラウザ上で3Dグラフィックスを描画するための低レベルAPIですが、three.js を利用することで、面倒な低レベルのコードを記述する必要がなく、シンプルなコードで3Dシーンを構築することが可能となります。

1.1 基本概念:シーン、カメラ、レンダラー

three.js の基本構造は、以下の3つの要素から成り立っています。

  • シーン(Scene)
    3Dオブジェクトやライト、カメラなどをまとめる入れ物です。シーンに追加されたオブジェクトはレンダリング時に描画されます。
  • カメラ(Camera)
    3Dシーン内をどのように捉えるかを決定する視点です。多くの場合、パースペクティブカメラ(PerspectiveCamera)や平行投影カメラ(OrthographicCamera)を使用します。
    サンプルコードでは、パースペクティブカメラを利用しており、視野角、アスペクト比、近接および遠方の描画距離を設定しています。
  • レンダラー(Renderer)
    シーンとカメラから実際の画像を生成する役割を担います。WebGLRenderer を使用することで、ブラウザ上で高速に3Dグラフィックスを描画できます。

1.2 その他の便利なコンポーネント

three.js には他にも、シーン内のオブジェクト操作を補助する以下のようなツールが用意されています。

  • OrbitControls
    ユーザーがマウス操作でカメラの視点を変更できるようにするためのコントローラーです。シーン内のオブジェクトを360度自由に見渡すことができます。
  • ライト(光源)
    シーンに自然な明るさや影を表現するために、環境光(AmbientLight)や平行光(DirectionalLight)などを追加します。これにより、立体感のあるリアルな描画が可能となります。

このように、three.js はシンプルながらも多機能なツールとして、3Dコンテンツ作成の入り口として最適です。


2. glTFフォーマットとは何か

2.1 glTFの概要

glTF は、3Dモデルやシーンデータを効率的に表現するためのオープンなファイルフォーマットです。一般的に「JPEG of 3D」とも呼ばれる理由は、3Dモデルのデータ量を大幅に削減し、高速な読み込みとレンダリングを実現するためです。glTF は以下のような特徴を持っています。

  • 軽量かつ高速な読み込み
    バイナリ形式や JSON 形式で表現され、テクスチャやマテリアル情報が効率的に管理されます。
  • 互換性の高さ
    様々な3Dソフトウェアやゲームエンジン、Webライブラリと連携が可能で、データ交換のスタンダードとなりつつあります。
  • 豊富なメタ情報
    モデルのタイトル、バージョン、作者情報など、カスタムメタデータを追加できるため、プロジェクト管理やモデルの再利用が容易です。

2.2 VRMとglTFの関係

VRM は、特にキャラクターアバター向けに最適化された glTF の拡張仕様です。今回のサンプルコードでは、VRM のメタ情報として、タイトル、バージョン、作者情報などを付与している点に注目してください。これにより、glTF ファイルに独自のメタ情報を埋め込むことが可能となり、ユーザーが後からファイルの情報を確認しやすくなります。


3. 2枚の画像からglTFを作成するサンプルコードの詳細解説

ここでは、表と裏の画像を用いて1枚の2Dオブジェクト(板状のメッシュ)を作成し、それを glTF 形式でエクスポートするサンプルコードについて詳しく見ていきます。画像は背景を透過させたPNG画像で正方形で用意します。


表:に「front.png」を、裏:に「rear.png」を指定します。「gltf作成ダウンロード」ボタンでgltfファイルをダウンロードできます。

表:
裏:

3.1 HTMLパート:入力フォームとプレビュー表示

まず、HTML内で以下のような構造が定義されています。

<style>
    .preview {
        display: flex;
    }
    .preview img {
        max-width: 500px;
        max-height: auto;
        margin: 10px;
    }
</style>

表:<input type="file" id="frontImage" accept="image/*"><br>
裏:<input type="file" id="backImage" accept="image/*">
<div class="preview">
    <img id="frontPreview" style="display: none;">
    <img id="backPreview" style="display: none;">
</div>
<button id="createGltf">gltf 作成ダウンロード</button>


ここでは、ユーザーが表面と裏面用の画像ファイルをアップロードできるように、2つのファイル入力フィールドが用意されています。また、アップロードした画像のプレビューを表示するための <img> タグを配置し、CSS で適切なスタイルを指定します。

3.2 画像アップロードとテクスチャ生成

次に、JavaScript部分で、アップロードされた画像ファイルを読み込み、three.js のテクスチャとして利用する処理が実装されています。具体的には、以下の処理が行われます。

  • FileReader を利用して画像をDataURLとして読み込む
    ユーザーがファイルを選択すると、FileReader がそのファイルを読み込み、onload イベントで読み込み結果(DataURL)を取得します。
  • プレビュー画像の表示
    取得した DataURL を、プレビュー用の <img> タグの src 属性に設定し、画像が画面上に表示されるようにしています。
  • three.js の TextureLoader によるテクスチャ生成
    読み込んだ DataURL を元に、THREE.TextureLoader() を使ってテクスチャを生成します。テクスチャ生成時に、sRGBEncoding を指定することで、色の再現性が向上し、実際の表示と一致するよう調整しています。

このようにして、ユーザーがアップロードした画像が three.js 上で利用できるテクスチャデータへと変換されます。

3.3 シーン構築とメッシュの作成

ユーザーが「gltf 作成ダウンロード」ボタンをクリックすると、以下の手順でシーンが構築され、glTF ファイルがエクスポートされます。

3.3.1 シーンの初期化

const scene = new THREE.Scene();

まず、新しいシーンオブジェクトを作成します。ここに後述するメッシュ(画像を貼り付けた平面)が追加されます。

3.3.2 表面用メッシュの作成

const frontMaterial = new THREE.MeshBasicMaterial({ 
  map: frontTexture, 
  side: THREE.FrontSide,
  transparent: true,
  alphaTest: 0.5
});
const frontGeometry = new THREE.PlaneGeometry(1, 1);
const frontMesh = new THREE.Mesh(frontGeometry, frontMaterial);
scene.add(frontMesh);
  • マテリアルの設定
    MeshBasicMaterial を利用して、テクスチャ(frontTexture)を設定。transparent: true および alphaTest: 0.5 の設定により、PNG画像などの透過情報を有効にし、必要な部分だけが描画されるように調整しています。
  • ジオメトリの設定
    PlaneGeometry(1, 1) を利用して、1×1の平面ジオメトリを作成しています。これにより、画像が貼り付けられる平面が定義されます。
  • メッシュの作成とシーンへの追加
    生成したジオメトリとマテリアルを組み合わせて Mesh を作成し、シーンに追加します。

3.3.3 裏面用メッシュの作成

表面用メッシュと同様に、裏面用にもメッシュが作成されますが、こちらは Y 軸で 180° 回転させることで、裏側が正しく表示されるように工夫しています。

const backMaterial = new THREE.MeshBasicMaterial({ 
  map: backTexture, 
  side: THREE.FrontSide,
  transparent: true,
  alphaTest: 0.5
});
const backGeometry = new THREE.PlaneGeometry(1, 1);
const backMesh = new THREE.Mesh(backGeometry, backMaterial);
backMesh.rotateY(Math.PI);
scene.add(backMesh);
  • 裏面の回転
    backMesh.rotateY(Math.PI) によって、裏面用のメッシュが Y 軸周りに 180° 回転され、裏側の画像が正しい向きで表示されるようにしています。

3.3.4 VRMメタ情報の付加

今回のサンプルコードでは、glTF に VRM のメタ情報を付与するために、以下のようなオブジェクトが作成されています。

vrm = {
  scene: scene,
  userData: {
    vrm: {
      meta: {
        title: '2D VRM',
        version: '1.0',
        author: 'You'
      }
    }
  }
};

ここで、userData プロパティに VRM 固有の情報(タイトル、バージョン、作者)を記載することで、後からファイルを開いた際に、モデルの詳細情報を確認できるようにしています。これにより、プロジェクト管理やモデル共有の際に役立ちます。

3.4 glTFエクスポート処理

シーンが完成した後、three.js の GLTFExporter を利用して、シーン全体を glTF 形式に変換し、ダウンロード可能なファイルとして生成します。

const gltfExporter = new GLTFExporter();
gltfExporter.parse(
  vrm.scene,
  (gltf) => {
    const gltfString = JSON.stringify(gltf);
    const blob = new Blob([gltfString], { type: 'model/gltf+json' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = '2d.gltf';
    link.click();
  },
  (error) => {
    console.error(error);
  }
);
  • GLTFExporter の利用
    GLTFExporter は、three.js のシーンやオブジェクトを glTF 形式に変換するためのモジュールです。ここでは、シーン全体(vrm.scene)を変換対象として指定しています。
  • エクスポートとダウンロード処理
    変換されたデータは JSON 形式の文字列となり、Blob に変換後、URL を作成して <a> タグを動的に生成・クリックすることで、ユーザーのローカルにファイルをダウンロードさせる仕組みとなっています。

この一連の流れにより、ユーザーがアップロードした2枚の画像から、透明度情報を含む2Dオブジェクトが作成され、glTFファイルとしてダウンロードされる仕組みが実現されます。

4. glTF表示コードの詳細解説

次に、作成した glTF ファイルをブラウザ上で表示するためのサンプルコードについて解説します。ここでは、glTFLoader を使用してファイルを読み込み、three.js のシーンに追加して表示しています。

サンプル(右クリックで名前を付けてリンク先を保存)sample.gltf
まわるずんだもん立ち絵素材:坂本アヒル 様

サンプル

4.1 HTMLとUIの設定

まず、HTML 内では以下のように、glTFファイルをアップロードするためのファイル入力フィールドと背景色を変更するためのカラーピッカーが用意されています。

<style>
    #ui {
        position: absolute;
        top: 10px;
        left: 10px;
        z-index: 100;
        background: rgba(255, 255, 255, 0.8);
        padding: 10px;
        border-radius: 4px;
    }
</style>
<div id="ui">
    <div>
        <label for="gltfInput">glTFファイル:</label>
        <input type="file" id="gltfInput" accept=".gltf,.glb">
    </div>
    <div>
        <label for="bgColor">背景色:</label>
        <input type="color" id="bgColor" value="#000000">
    </div>
</div>
<div id="eBody" style="width: 100%;"></div>
  • ユーザーインターフェース(UI)
    UI 部分は、ファイルのアップロードや背景色の変更といった操作を可能にしています。これにより、ユーザーは自身の glTF ファイルを読み込んでシーン上で確認できるようになります。

4.2 シーンとカメラ、レンダラーの初期設定

JavaScript 部分では、まず three.js のシーン、カメラ、レンダラーを初期化します。

scene = new THREE.Scene();
scene.background = new THREE.Color(document.getElementById('bgColor').value);

camera = new THREE.PerspectiveCamera(75, entryBody.clientWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 5);

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(entryBody.clientWidth, window.innerHeight);
entryBody.appendChild(renderer.domElement);
  • シーンの背景色
    UI で選択された背景色(初期値は黒)をシーンの背景に設定します。ユーザーがカラーピッカーを使って色を変更できるように、イベントリスナーも設定されています。
  • カメラの設定
    パースペクティブカメラを利用して、シーン全体を適切な視野で捉えられるようにしています。カメラの位置も調整され、シーン内のモデルが見やすい位置に配置されます。
  • レンダラーの設定
    WebGLRenderer を用いて、シーンをブラウザ上に描画します。antialias オプションにより、エッジの滑らかさも向上させています。

4.3 OrbitControls とライトの追加

シーンをより直感的に操作できるように、OrbitControls を追加し、さらに光源を配置してモデルに立体感を与えています。

controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 7.5);
scene.add(directionalLight);
  • OrbitControls
    ユーザーはマウス操作でカメラの位置や向きを自由に変え、シーン内のオブジェクトを360度どの角度からも観察できます。
  • ライトの役割
    環境光と平行光源を追加することで、モデルに柔らかな明るさとシャドウを与え、3Dとしての存在感を強調しています。

4.4 glTFLoader によるファイル読み込み

ユーザーがファイル入力フィールドから glTF ファイルを選択すると、以下の処理が行われます。

document.getElementById('gltfInput').addEventListener('change', function(event) {
    const file = event.target.files[0];
    if (!file) return;
    const url = URL.createObjectURL(file);
    loadGLTF(url);
});

function loadGLTF(url) {
    const loader = new GLTFLoader();
    loader.load(url, function(gltf) {
        // 必要に応じて既存のモデルを削除する処理を追加可能
        scene.add(gltf.scene);
    }, undefined, function(error) {
        console.error('glTF読み込みエラー:', error);
    });
}
  • ファイル読み込みの流れ
    ユーザーがファイルを選択すると、そのファイルから一時的な URL を生成し、GLTFLoader を用いて非同期にファイル内容を読み込みます。読み込みが完了すると glTF 内に含まれるシーン(gltf.scene)が three.js のシーンに追加され、ブラウザ上に表示されます。

4.5 ウィンドウリサイズへの対応とアニメーションループ

表示領域のサイズが変わった際に、レンダラーとカメラのアスペクト比を自動で更新するための処理と、シーンを継続的に再描画するためのアニメーションループが実装されています。

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}

window.addEventListener('resize', onWindowResize, false);

function animate() {
    requestAnimationFrame(animate);
    controls.update();
    renderer.render(scene, camera);
}
animate();
  • リサイズ対応
    ユーザーがウィンドウサイズを変更した際に、カメラのアスペクト比やレンダラーのサイズを再設定することで、常に正しい表示状態を維持します。
  • アニメーションループ
    requestAnimationFrame を用いることで、スムーズな再描画を実現。OrbitControls の更新処理も含め、ユーザー操作に対するリアルタイムな反映が行われます。

5. three.js と glTF を活用した3D表現の応用

これまで、基本的な glTF の生成と表示方法を学んできましたが、ここではさらに応用的な視点から、three.js と glTF を利用する際のポイントやカスタマイズの方法について解説します。

5.1 モデルのカスタマイズとアニメーション

three.js では、glTF 形式で読み込んだモデルに対して以下のようなカスタマイズが可能です。

  • マテリアルやシェーダーの変更
    glTF 内のマテリアル設定は基本的に PBR(物理ベースレンダリング)に対応していますが、必要に応じて独自のシェーダーを適用し、エフェクトやライティング効果を強化できます。
  • アニメーションの制御
    glTF にはアニメーション情報が含まれている場合があり、three.js の AnimationMixer を利用することで、再生、停止、ブレンドといった操作が可能です。これにより、キャラクターの動きやインタラクションのあるシーンを実現できます。

5.2 インタラクティブなシーン作成

実際のプロジェクトでは、ユーザーとのインタラクションを取り入れることで、より魅力的な3D体験を提供できます。

  • クリックイベントやマウス操作の利用
    three.js では Raycaster を利用することで、オブジェクトのクリック検出やホバー時のエフェクトを実装できます。これにより、ユーザーがシーン内の特定のモデルに対して情報を得られるような仕組みを構築可能です。
  • GUIツールの統合
    dat.GUI や ControlKit といったライブラリを組み合わせることで、シーン内のオブジェクトやライティング、カメラ設定をリアルタイムに調整できるパネルを実装できます。これにより、開発者だけでなく、ユーザー自身がカスタマイズを体験できるインターフェースを提供できます。

5.3 複雑なシーン構築のための設計思想

three.js を使った大規模なプロジェクトでは、コードのモジュール化やシーン管理が重要になります。以下のような点に注意しましょう。

  • モジュール分割
    複数のシーンやオブジェクト、エフェクトを管理する場合、各コンポーネントごとにファイルを分割し、管理しやすい構造にすることが推奨されます。
  • パフォーマンス最適化
    モデルのポリゴン数やテクスチャサイズ、ライティングの数など、パフォーマンスに影響を与える要素を事前に検討し、適切な最適化を行うことで、スムーズな描画体験を提供できます。LOD(Level of Detail)の技法や、不要なオブジェクトの削除処理なども有効です。
  • 非同期処理とローディング管理
    大量のモデルやテクスチャを読み込む際には、プログレスバーやローディング画面を実装して、ユーザーに処理の進捗状況を伝える工夫も重要です。

5.4 今後の展開と拡張性

glTF と three.js の組み合わせは、今後のWeb3Dコンテンツの発展においても重要な役割を果たすと考えられます。

  • WebXRとの連携
    VR(バーチャルリアリティ)や AR(拡張現実)の分野において、glTF はその軽量さと高速読み込みの特性から、今後さらに需要が高まると予測されます。three.js も WebXR API に対応しており、これらの技術と組み合わせることで、没入感のある体験を実現できます。
  • リアルタイムレンダリングの進化
    ブラウザ自体の性能向上や、WebGL 2.0 の普及により、よりリアルなライティングやシェーダー効果、ポストプロセスエフェクトを取り入れたシーン作成が可能になります。これにより、ゲームやシミュレーション、デジタルツインといった分野での応用がさらに広がるでしょう。
  • コミュニティとオープンソースの力
    three.js や glTF は、世界中の開発者コミュニティによって支えられており、新しい機能の追加や最適化、バグ修正が日々行われています。最新情報や実践例をキャッチアップしながら、自分自身のプロジェクトに取り入れていくことで、常に最新の技術トレンドを反映した3Dコンテンツを作成できるようになります。

6. まとめと今後の展望

本記事では、two つのサンプルコードを通して、three.js を利用した glTF の作成と表示方法について、初心者でも理解しやすいよう詳細に解説してきました。以下に、本記事の主要ポイントをまとめます。

6.1 本記事の主要ポイント

  • three.js の基本概念
    シーン、カメラ、レンダラーといった基本要素を理解することで、3Dシーンの基盤が整います。また、OrbitControls やライトの追加といった操作により、インタラクティブでリアルな描画が可能です。
  • glTF のメリットと応用
    glTF は、軽量かつ高速に3Dデータを扱えるフォーマットとして、特に Web 上での利用に適しています。VRM 拡張により、キャラクターアバターとしての利用も進んでいます。
  • 画像からの glTF 作成プロセス
    サンプルコードでは、2枚の画像をアップロードし、テクスチャとして読み込んだ後、平面ジオメトリに貼り付ける手法で glTF ファイルを生成しました。これにより、ユーザー自身がオリジナルの2Dモデルを簡単に作成・エクスポートできる仕組みが実現されています。
  • glTF の表示と操作
    別サンプルコードでは、glTFLoader を用いてファイルを読み込み、three.js のシーンに追加することで、簡単に3Dモデルを表示する方法を紹介しました。ウィンドウリサイズへの対応やアニメーションループの実装も重要なポイントです。
  • 今後の応用例と展望
    WebXR やリアルタイムレンダリング技術の進化により、three.js と glTF の組み合わせは、今後さらに多くの分野で活用されることが期待されます。インタラクティブなシーンの構築や、ユーザー体験の向上を目指すプロジェクトにおいて、その可能性は無限大です。

6.2 最後に

three.js と glTF を使った3D表現は、初心者でも比較的容易に始めることができ、また高度なカスタマイズも可能な非常にパワフルな技術です。今回のサンプルコードを通して、基本的な使い方から応用技術まで一通りご紹介しましたが、実際に手を動かして試してみることで、より深い理解と発見が得られるでしょう。
ぜひ、この記事を参考にしながら、あなた自身のアイデアを形にする3D Webコンテンツの開発にチャレンジしてみてください。

今後も、three.js や glTF の最新情報、ベストプラクティスについてはコミュニティや公式リポジトリ、各種チュートリアルなどで情報収集を続け、日々進化するWeb技術の恩恵を最大限に活用していただければと思います。

付録:実践Tipsと参考リソース

付録1: デバッグとパフォーマンス改善のヒント

  • コンソール出力の活用
    JavaScript の console.logconsole.error を使って、エラー発生箇所や処理の流れを確認しましょう。特に glTF のエクスポートやロード時には、エラーハンドリングが重要です。
  • stats.js の利用
    three.js のシーン描画中のフレームレートやレンダリング時間を可視化するために、stats.js を利用すると、パフォーマンスのボトルネックを特定できます。
  • 不要なオブジェクトの削除
    glTF ファイルを何度も読み込む際は、古いモデルをシーンから削除してメモリリークを防ぐようにしましょう。

付録2: 参考リソースと公式ドキュメント

  • three.js 公式サイト
    最新のリリース情報やデモ、サンプルコードが多数掲載されています。
    three.js GitHub
  • glTF 公式サイト
    glTF の仕様書や、各種実装例、最適化のテクニックなど、glTF に関する情報がまとまっています。
    https://www.khronos.org/gltf/
  • コミュニティフォーラムやブログ記事
    Stack Overflow、Qiita、各種ブログなど、実践的なTipsやトラブルシューティングの情報も充実しています。

付録3: 今後の技術動向

  • WebXR の普及
    VR や AR コンテンツの需要が高まる中、three.js と glTF の組み合わせは、よりインタラクティブな体験を提供するための標準的な手法となるでしょう。
  • リアルタイムシェーダーと物理シミュレーション
    GPU の進化に伴い、よりリアルなシェーダー表現や物理シミュレーションの実装が容易になってきています。これにより、ゲームやシミュレーション、教育コンテンツにおける表現の幅が広がります。

終わりに

本記事では、2枚の画像から glTF を生成するコードと、生成した glTF をブラウザ上で表示するコードを例に、three.js を利用した3Dモデリングおよび表示の基本から応用までを網羅的に解説しました。初心者の方がまずは基本概念を理解し、実際のコードを読み解くことで、3Dコンテンツ作成の一歩を踏み出すための助けとなれば幸いです。
また、three.js と glTF の組み合わせは、その軽量性と高い拡張性から、今後さらに多くの Web プロジェクトで利用されることが予想されます。自分自身のアイデアを形にし、インタラクティブで魅力的な3D体験を創出するための技術として、ぜひ積極的に取り入れてみてください。

著作
VOICEVOX:ずんだもん
まわるずんだもん立ち絵素材:坂本アヒル 様

PR広告

楽天ブックスでthree.jsの本を探す
楽天でずんだもんを探す