【WebGL&Three.js入門】Three.jsの一番シンプルなサンプルコードのチュートリアルの解説

2023年11月11日WebGL & Three.js

WebGL&Three.jsの入門としてThree.jsのチュートリアルに記載されているサンプルコードの基本を解説します。
とっつきにくそうではなりますが、ちょっと中身がわかれば全然そんなことがないと思えるようになります。

まずは、実際にデモを確認しましょう。
以下をクリックしてもらうと、3Dの立方体が表示されます。

これはThree.jsのチュートリアルと同じものです。
もしチュートリアルをみて訳がわからないという場合は、以下を参考にしてみてください。

もしWebGLとThree.jsの違いって何?という場合は、WebGLとThree.jsの違いって何?を参考にしてみてください。

もしThree.jsの基本的な操作の一連の流れを知らないという場合は、Three.jsの基本的な操作の一連の流れがとても短くまとめた記事なので参考にしてみてください。

HTML

<script type="module" src="app.js"></script>

htmlはいたってシンプルで、scriptタグを読み込ませるだけです。
type="module"とすることでimport文を使えるようになります。

Three.jsのインストール

詳しくは、公式サイトのインストール手順に書かれていますが、Node.jsが必要になります。
package.jsonのdependenciesは大体以下のような内容になります。

"dependencies": {
    "@barba/core": "^2.9.7",
    "@parcel/core": "^2.6.2",
    "glsl-easings": "^1.0.0",
    "glsl-hsl2rgb": "^1.1.0",
    "glsl-map": "^1.0.1",
    "glsl-noise": "0.0.0",
    "glsl-rotate": "^1.1.0",
    "glslify": "^7.1.1",
    "gsap": "^3.10.4",
    "lil-gui": "^0.17.0",
    "lodash": "^4.17.21",
    "normalize.css": "^8.0.1",
    "regenerator-runtime": "^0.13.9",
    "smooth-scrollbar": "^8.7.4",
    "stats-js": "^1.0.1",
    "svgo": "3.0.2",
    "three": "^0.152.0"
  },
  "devDependencies": {
    "@parcel/optimizer-htmlnano": "^2.8.3",
    "@parcel/transformer-glsl": "^2.6.2",
    "@parcel/transformer-sass": "^2.6.2",
    "parcel": "^2.6.2",
    "parcel-reporter-static-files-copy": "^1.3.4",
    "rimraf": "^3.0.2"
  },

ここのdependenciesの"three"が入っていればOKです。

JavaScript

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 geometry = new THREE.BoxGeometry();
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 = cube.rotation.x + 0.01;
  cube.rotation.y += 0.01;

  renderer.render(scene, camera);
}

animate();

これも公式サイトのそのままを取ってきています。
意味としては、以下のようになります。

Three.jsをインポート

import * as THREE from "three";

Three.jsのライブラリをインポートしています。

シーンを作成

const scene = new THREE.Scene();

THREE.Sceneオブジェクトを作成しています。これは3D空間の場として機能し、そこに物体や光などの要素を追加します。

カメラの作成

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

THREE.PerspectiveCameraオブジェクトを作成しています。これはユーザーの視点を模倣し、第一引数は視野角、第二引数はアスペクト比、第三と第四引数は描画するオブジェクトの最小距離と最大距離を指定します。

レンダラーを作成し、シーンを描写

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

THREE.WebGLRendererオブジェクトを作成します。これはシーンを描画するために使います。ウィンドウのサイズに合わせてレンダラーのサイズを設定し、生成したDOM要素をHTMLのbodyに追加します。

ジオメトリを作成

const geometry = new THREE.BoxGeometry();

THREE.BoxGeometryオブジェクトを作成しています。これは立方体の形状を定義し、その幅、高さ、奥行きが1です。
ジオメトリのより詳細な情報については、Geometry(ジオメトリ)の種類と変更方法-3Dモデルのデモ付きで紹介を参考にしてみてください。

メッシュを作成し、シーンに追加

const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

THREE.MeshBasicMaterialオブジェクトを作成しています。これは立方体の材質を定義し、色を緑色に指定しています。
マテリアルのより詳細な情報については、Material(マテリアル)の種類と変更方法-3Dモデルのデモ付きで紹介を参考にしてみてください。

THREE.Meshオブジェクトを作成しています。これは形状と材質を組み合わせて3Dオブジェクトを生成し、この場合は緑色の立方体が作成されます。

立方体をシーンに追加します。

カメラ位置を調整

camera.position.z = 5;

カメラの位置を設定しています。ここではz軸方向に5の位置に設定しています。

アニメーションを付与

function animate() {
  requestAnimationFrame(animate);
  cube.rotation.x = cube.rotation.x + 0.01;
  cube.rotation.y += 0.01;

  renderer.render(scene, camera);
}

animate();

animate関数を定義しています。この関数はアニメーションを制御し、requestAnimationFrameメソッドによってanimateをコールバックとして繰り返し呼び出されます。
animateが呼ばれるたびに再度aniamteをコールバックできるので、処理が空いているときに毎度実行してくれる、繰り返してくれるようになります。
立方体はx軸とy軸の周りで連続的に回転します。

renderer.renderメソッドを呼び出して、シーンをカメラの視点から描画します。

animate関数を呼び出して、アニメーションを開始します。

まとめ

WebGL&Three.jsに入門するためには、Three.jsの一番シンプルなサンプルコードのチュートリアルをするのが一番です。