【学習記録】Three.jsを始めてみた!3Dプログラミング初心者が理解したWebGLの基本
JavaScriptの3Dライブラリ「Three.js」を使って、回転する立方体を画面に表示する基本的な3Dシーンの作成方法を解説します。

Web上でリッチな3D表現を見て、「自分もやってみたい!」と思ったのが、Three.jsを触り始めたきっかけです。複雑そうに見えましたが、基本的なコードを書いてみると、意外とシンプルな「お作法」があることがわかりました。
私が初めて動かした「回転する立方体」のコードを例に、3Dシーンを作るために必要な、核となる要素の役割と構造をまとめてみます。これは、同じようにThree.jsを学び始めた方への、私自身の備忘録も兼ねています。
実際のコード
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
const container = document.getElementById('app');
// レンダラー
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
// シーン
const scene = new THREE.Scene();
scene.background = new THREE.Color('#FAFAFA');
// カメラ
const camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000000);
camera.position.set(2, 2, 3);
// ライト
const hemi = new THREE.HemisphereLight(0xffffff, 0x444444, 0.8);
hemi.position.set(0, 20, 0);
scene.add(hemi);
const dir = new THREE.DirectionalLight(0xffffff, 0.8);
dir.position.set(5, 10, 7.5);
scene.add(dir);
// ジオメトリ
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0xeeeeee });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// グリッドヘルパー
const grid = new THREE.GridHelper(10, 10, 0x888888, 0x222222);
scene.add(grid);
// コントロール
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
// リサイズ
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener('resize', onWindowResize, false);
// アニメーション
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const t = clock.getElapsedTime();
mesh.rotation.x = t * 0.6;
mesh.rotation.y = t * 0.9;
controls.update();
renderer.render(scene, camera);
}
animate();3Dシーンを構築する5つの基本要素
Three.jsの基本的な要素の役割をまとめました。
1. シーン (Scene)=オブジェクトを置く「舞台」
役割
3Dオブジェクト、ライト、カメラといった全ての要素を格納しておくコンテナ、つまり「舞台」そのものです。
コードでの処理
new THREE.Scene()で作成し、scene.add(mesh)のように、作成したものをここに配置していきます。
2. カメラ (Camera)=視点を決める「撮影機材」
役割:
舞台(シーン)をどこから、どのような視野角で見せるかを決めます。
コードでの処理:
THREE.PerspectiveCamera(透視投影)を使うと、遠くのものが小さく見える、人間が見るのと近い自然な表現ができます。
camera.position.set(2, 2, 3)で、カメラをどこに配置するかを決定します。
3. メッシュ (Mesh)=形と素材を持つ「俳優」
役割
シーン内に存在する具体的な「物」です。これは形状(ジオメトリ)と材質(マテリアル)の2つで構成されます。
- ジオメトリ (Geometry):形状データ(立方体、球体など)を定義します。
- マテリアル (Material):物の質感、色、光の反射の仕方を定義します
コードでの処理
new THREE.Mesh(geometry, material)として作成し、scene.add(mesh)で舞台に登場させます。
4. ライト (Light)=物を照らす「照明」
役割
オブジェクトに陰影をつけ、立体感を出すために必須です。ライトがないと、オブジェクトは真っ黒になって見えません。
コードでの処理
全体をぼんやりと照らすHemisphereLight(半球ライト)と、特定の方向から当たるDirectionalLight(指向性ライト)を組み合わせています。
5. レンダラー (Renderer)=すべてを画面に描く「映写機」
役割
シーンをカメラを通して見て、その結果をブラウザの画面に描き出す(レンダリングする)のが仕事です。
コードでの処理
new THREE.WebGLRenderer()で描画機能を使い、アニメーションループ内のrenderer.render(scene, camera)で画面を更新します。
Three.jsの土台となる「WebGL」とは?
ここで、Three.jsの心臓部とも言えるレンダラーについて、少し深掘りします。
私たちが書いたコードでTHREE.WebGLRendererというものを使っていますが、この「WebGL」こそが、Webブラウザで3Dを描画するための土台となっている技術です。
WebGLの役割
WebGLは、JavaScriptから直接、PCやスマートフォンの**GPU(グラフィックス処理ユニット)**の能力を引き出すためのAPI(プログラミングの規約)です。
- GPU:高速な画像処理に特化した計算機です。通常のCPUよりも3Dグラフィックスの計算を圧倒的に速く処理できます。
- WebGLの機能:WebGLは、複雑な3Dの計算(頂点の座標変換や色の計算など)をGPUに任せるための「通訳」のような役割を果たします。これにより、Three.jsのようなライブラリは、高速でスムーズな3D表現をブラウザ上で実現できるのです。
Three.jsは、この扱いの難しいWebGLの操作を「シーン」「カメラ」「メッシュ」といったわかりやすい概念で抽象化(隠蔽)してくれているため、私たちは複雑な計算を意識せずに3Dプログラミングに集中できるというわけです。
オブジェクトを動かすアニメーションの仕組み
コードの最後の部分で、立方体がクルクルと回り続けているのは、アニメーションの部分のおかげです。
requestAnimationFrame(animate)
ブラウザに「次の描画タイミングでanimate関数をもう一度実行してね」とお願いする命令です。これにより関数が繰り返し実行され、動きが生まれます。
mesh.rotation.x = t * 0.6;
経過時間(t)に応じてメッシュの回転角度(rotation)を少しずつ変えていくことで、滑らかな回転が実現しています。
まとめと次のステップ
Three.jsは、裏側で強力なWebGLの力を借りながら、「舞台(シーン)」に「俳優(メッシュ)」を配置し、「カメラ」を通して「映写機(レンダラー)」で描く、というシンプルな構造で3Dの世界を作り上げています。
この基本を理解できたので、次のステップとして、マテリアルを変えて光沢を出したり、自分で作った3Dモデルを読み込んでみたりすることに挑戦したいと思っています。