はじめに
「ブラウザで3Dグラフィックスって、なんか敷居高そう」と思っていませんか。正直なところ、WebGLを直接触ろうとすると確かにそうなんですよね。でも、Three.jsを使えば話は別です。
Three.jsは、WebGLのややこしい部分をうまく隠蔽してくれる3Dライブラリです。GitHub星110,000以上、月間1,200万ダウンロードという数字が示すように、ブラウザ3Dの世界ではデファクトスタンダード的な存在になっています。
個人的にはWebGL周りのライブラリの中では、学習コストとできることのバランスが一番良いと感じています。
特徴・メリット
WebGLの複雑さを抽象化
WebGLを直接書こうとすると、シェーダー言語(GLSL)の知識が必要になったり、行列計算を自分で書いたりと、なかなかハードルが高いんですよね。Three.jsはこのあたりを綺麗に抽象化してくれます。
「シーン」「カメラ」「メッシュ」といった直感的な概念でコードを書けるので、3Dプログラミング初心者でも入りやすいです。
豊富なエコシステム
16年の歴史があるプロジェクトなので、サンプルコードやチュートリアルが豊富です。公式サイトだけでも数百のサンプルがあり、やりたいことに近い実装を見つけやすい。これ、意外と重要なポイントだと思います。
WebGPU対応
最新のr181バージョンではWebGPUレンダラーにも対応しています。WebGPUはWebGLの次世代規格で、より高いパフォーマンスが期待できます。将来性という意味でも安心感がありますね。
主な特徴まとめ
- 直感的なAPI設計
- クロスブラウザ対応
- WebGL/WebGPUの両対応
- MITライセンス
- アクティブなメンテナンス(2,000人以上のコントリビューター)
インストール方法
npmでインストールするのが一般的です。
npm install three
または、CDNから直接読み込むこともできます。
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.181/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.181/examples/jsm/"
}
}
</script>
プロジェクトにES Modulesで組み込む場合は、importmapを使うとパス解決が楽になります。
基本的な使い方
Three.jsの基本構成は「シーン」「カメラ」「レンダラー」の3つです。これに「オブジェクト」と「ライト」を追加していく形になります。
回転するキューブを表示する
まずは定番の、回転するキューブを表示してみましょう。
import * as THREE from 'three';
// シーンを作成
const scene = new THREE.Scene();
// カメラを作成(視野角、アスペクト比、near、far)
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// レンダラーを作成
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
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() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
これだけで緑色のキューブが回転するシーンが完成します。30行程度のコードでここまでできるのは、なかなかコスパが良いですよね。
ライティングを追加する
よりリアルな見た目にするには、ライティングが必要です。
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);
document.body.appendChild(renderer.domElement);
// ライトを追加
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);
// MeshStandardMaterialでライティングに対応
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({
color: 0x0088ff,
metalness: 0.3,
roughness: 0.4
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
MeshBasicMaterialをMeshStandardMaterialに変えて、ライトを追加するだけでリアルな陰影がつきます。
3Dモデルの読み込み
GLTFLoader を使えば、BlenderなどのツールでエクスポートしたGLTFファイルを読み込めます。
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// OrbitControlsでマウス操作を有効に
const controls = new OrbitControls(camera, renderer.domElement);
// ライト設定
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 10, 5);
scene.add(directionalLight);
// GLTFモデルの読み込み
const loader = new GLTFLoader();
loader.load(
'/models/your-model.glb',
(gltf) => {
scene.add(gltf.scene);
},
(progress) => {
console.log('Loading...', (progress.loaded / progress.total * 100) + '%');
},
(error) => {
console.error('Error loading model:', error);
}
);
camera.position.set(0, 2, 5);
controls.update();
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
実践的なユースケース
Three.jsは様々な用途で活用されています。
製品の3Dビューワー
ECサイトで製品を360度回転させて見せるビューワーは、Three.jsの得意分野です。実際、多くの企業サイトで採用されています。
データビジュアライゼーション
地理データや統計データを3D空間で可視化するケースも増えています。NASAのSolar Systemプロジェクトなど、科学分野での活用例も多いです。
ブラウザゲーム
Krunker(FPSゲーム)やCrossy Roadのようなブラウザゲームも、Three.jsで作られています。Unityほどの本格的なゲームエンジンは不要だけど、ある程度の3D表現が欲しいという場合に適しています。
ポートフォリオサイト
クリエイターのポートフォリオサイトで、インタラクティブな3D演出を入れるケースも多いです。差別化要素としてはかなり効果的だと思います。
AR/VR コンテンツ
WebXR APIと組み合わせれば、ブラウザでAR/VRコンテンツも作れます。専用アプリのインストール不要でXRコンテンツを提供できるのは大きなメリットです。
パフォーマンスのTips
Three.jsで開発する際、いくつか気をつけておきたいポイントがあります。
ジオメトリの使い回し
同じ形状のオブジェクトを複数配置する場合、ジオメトリは使い回しましょう。
const geometry = new THREE.BoxGeometry(1, 1, 1);
for (let i = 0; i < 100; i++) {
const material = new THREE.MeshStandardMaterial({ color: Math.random() * 0xffffff });
const mesh = new THREE.Mesh(geometry, material); // geometryは共有
mesh.position.set(Math.random() * 10, Math.random() * 10, Math.random() * 10);
scene.add(mesh);
}
レンダラーの設定
アンチエイリアスやピクセル比の設定で、品質とパフォーマンスのバランスを調整できます。
const renderer = new THREE.WebGLRenderer({
antialias: true,
powerPreference: 'high-performance'
});
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
まとめ
Three.jsは、ブラウザで3Dグラフィックスを扱うなら一択と言っていいライブラリです。
- WebGLの複雑さを隠蔽してくれる
- 豊富なサンプルとドキュメント
- アクティブなメンテナンスで将来性も安心
- WebGPU対応で次世代にも対応
30代になって思うのは、技術選定では「枯れた技術」の価値ってあるんですよね。Three.jsは16年の歴史があり、2,000人以上のコントリビューターがいて、毎月1,200万回ダウンロードされている。これだけのエコシステムがあれば、困ったときに情報が見つからないということはまずないです。
ブラウザで3D表現に挑戦してみたい方は、まず公式サイトのサンプルを眺めてみることをおすすめします。「こんなことができるのか」という発見があるはずです。