🐢

とっても簡単、Webサイトに3D表現を取り入れてみた (glTFで始める3Dコンテンツ)

2022/11/17に公開約5,600字

今回作成したもの

https://preview.knockknock.jp/glTF/03/

glTFって何?

Wikipediaによると、

glTF (GL Transmission Format) はJSONによって3Dモデルやシーンを表現するフォーマットである。「3DにおけるJPEG」と表現されることもある。Khronos Group 3D Formats Working Groupによって開発され、APIを問わないランタイムアセット配布フォーマットとしてHTML5DevConf 2016において発表された。glTFは3Dシーンを圧縮し、WebGLなどのAPIを利用するアプリケーションの実行時処理を最小化する、効率的で相互運用可能なアセット配布フォーマットとなることを意図している。glTFはまた、3Dコンテンツ作成ツールやサービスのための共通発行フォーマットを定義している。

3Dモデル形式には、.objや.fbx、.daeといった汎用形式や、.3dsや.blendなどの3Dモデリングツール専用ファイル形式が存在します。しかし、これらは、モデリングツールに強い依存があったり、オフラインでの利用が前提のため、インターネットでの利用を考えると非効率でした。

glTFはこうした問題を解決し、プラットフォームにも依存しない、オープンで誰でも利用でき、インターネットでの配信を前提に作られたファイル形式として、3DおけるPNGやMP4のような立ち位置を目指して作られました。

https://www.codegrid.net/articles/2018-gltf-1/

glTFファイルの作り方

glTFファイルを作るには、既存の3Dモデル(.objや.dae)を、ツールを使ってglTF形式に変換する方法と、3Dモデリングツールを使って、glTF形式で出力する方法があります。後者の方法では、無料で利用できるBlenderを使うと良いかと思います。

Blenderとは、3次元のCGアニメーションを自由に制作できるアプリケーションソフトです。オープンソースのフリーソフトであるため、ダウンロードすれば誰でも簡単に利用できます。価格が無料なのに、有料ソフトにも劣らない機能を持っていることが、このソフトの特徴です。本格的なCGアニメ制作ソフトとして使用できるため、世界中に多くのユーザーがいます。

https://www.blender.org/

https://vook.vc/n/2491

Blenderでモデリングした3DモデルをglTFでエクスポートすることができます。

glTFファイルを無料で探す方法

3Dモデリングソフトの操作は複雑で、慣れが必要になりますので、今回は一から作るのではなく、3Dモデルが配布されているサイトから直接ダウンロードして利用します。glTF形式は、JSON形式のglTFファイルと、テクスチャ画像などの複数のファイルで構成されています。しかし、複数ファイルに分かれてしまっているとファイルの管理は煩雑になってしまいますので、これらをバイナリ形式でまとめたglb形式のファイルを利用します。

https://www.cgtrader.com/

glTFファイルをWebブラウザに表示させてみる

glTFをWebブラウザで表示するには、対応するWebGLライブラリなどを使う必要があります。今回は、デファクトスタンダートとも言える、three.jsを使っていきます。

three.jsとは、手軽に3Dコンテンツを制作できる商用利用可能なJavaScriptライブラリ。WebGLだけで3D表現をするためには、立方体1つ表示するだけでも多くのJavaScriptやGLSLコードを書く必要があり専門知識も必要です。three.jsを使えばJavaScriptの知識だけで簡単に3Dコンテンツが作成できるため、手軽に扱えるようになります。

https://threejs.org/

今回、three.jsの詳細の説明は省かせていただきますが、JavaScriptで以下のコードになります。

import * as THREE from 'https://unpkg.com/three@0.126.1/build/three.module.js';
import {GLTFLoader} from 'https://unpkg.com/three@0.126.1/examples/jsm/loaders/GLTFLoader.js';

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

// カメラの作成
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 4);
camera.lookAt(new THREE.Vector3(0, 1, 0));

// 環境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

// 光源
const spotLight = new THREE.SpotLight(0xffffff, 0.7);
spotLight.position.set(-10, 10, 10);
scene.add(spotLight);

// レンダラー
const renderer = new THREE.WebGLRenderer({
    alpha: true,
    antialias: true
});
renderer.setClearColor(0x000000, 0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);

// GLTFファイルの読み込み
const model
const loader = new GLTFLoader();
loader.load('ice-cream.glb', (gltf)=> {
    model = gltf.scene;
    scene.add(model);
}, undefined, function (e) {
    console.error(e);
});

document.getElementById('webgl').appendChild(renderer.domElement);
tick();
function tick() {
    requestAnimationFrame(tick);
    if (model) {
        model.rotation.y += 0.01;
    }
    renderer.render(scene, camera);
}

three.jsでglTFファイルをロードするには、GLTFローダーを使います。成功すれば、このように表示されることが確認できたかと思います。

ScrollTriggerを使ってパララックス化する

ScrollTriggerとはWebページのスクロールに応じて、任意の操作を簡単に行うためのJavaScriptライブラリです。このScrollTriggerを使って、読み込んだglTFをパララックス化してみます。

https://greensock.com/scrolltrigger/

ます、GSAP本体とScrollTrigger.jsの2つを読み込みます。CDNから読む込む場合は以下を書きます。

<script src="//cdn.jsdelivr.net/npm/gsap@3.7.0/dist/gsap.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/gsap@3.7.0/dist/ScrollTrigger.min.js"></script>

パララックス化するJavaScriptは、今回はこれだけです。

gsap.to('.js_ice-cream', {
    scrollTrigger: {
        trigger: '.js_box',
        start: 'top start',
        end: 'bottom end',
        pin: true,
    }
});

簡単に説明すると、.js_box要素の上部が、ブラウザの上部と重なると、.js_ice-cream要素が固定され、.js_box要素の下部がブラウザの下部と重なると、.js_ice-cream要素の固定が解除される、という内容です。ScrollTriggerについての詳細は今回は省きますが、以下の記事がとてもわかりやすく解説しています。

https://yumegori.com/gsap-scrolltrigger

3Dモデルといえど、ブラウザに表示されれば、他のDOM要素と同様に扱えるので、重ね順を変更して、前面にも、背面にも、テキストや画像をのせることができ、パララックス対象の要素として、JavaScriptでアニメーションさせる事も可能です。

これでも良いように思えますが、より臨場感を出すために、カメラを移動させてみます。

let scrollProgress = 0;    // ←追記

gsap.to('.js_ice-cream', {
    scrollTrigger: {
        trigger: '.js_box',
        start: 'top start',
        end: 'bottom end',
        pin: true,

        // ↓追記
        onUpdate: (e)=> {
            scrollProgress = e.progress;
        },

    }
});
tick();
function tick() {
    requestAnimationFrame(tick);
    if (model) {
        model.rotation.y += 0.01;
    }

    // ↓追記
    if (camera) {
        camera.position.set(0, Math.floor((4 - (6 * scrollProgress)) * 100) / 100, 4);
        camera.lookAt(new THREE.Vector3(0, 1, 0));
    }

    renderer.render(scene, camera);
}

カメラの位置をスクロールに合わせて移動させることで、よりダイナミックな表現を実現できました。

まとめ

いかがでしたでしょうか?2017年に発表されたglTF 2.0は、発表当時とても話題になり、一時期Facebookでも採用されるなど、注目度が上がりましたが、ここ最近、めっきり話題に登らなくなり、忘れかけてた人もいるかもしれません。ただ、Blenderやthree.jsなど、サポートも増えており、次世代3Dフォーマットとして、定着してくる可能性はあります。

今回のコンテンツ制作において、glTFが必須というわけではありませんが、バイナリ化されたglbは特に扱いが楽でした。glTF自体はJSONですので、変更が容易にできるという点は、何かのサービスに活用できるのではと思います。

Discussion

ログインするとコメントできます