three.jsの基本をおさらいしてみよう!〜基礎の基礎編〜

はっちゃん


three.jsの基本をおさらいしてみよう!〜基礎の基礎編〜

こんにちは、はっちゃんです。

今回は、もはやお馴染み、WebGLを簡単に扱えるライブラリー「three.js」をご紹介します。WebGLを使った3D表現が一般的になってきたとはいえ、実際取り入れられていない方も多いと思います。

そこで今回は、自分の勉強を兼ねて、できるだけ詳しくまとめてみましたので、これから覚えようとしているフロントエンドやデザイナーの方の参考になれば幸いです。

WebGLとは

JavaScriptから利用できるAPIで、ブラウザー上で3DCGプログラミングを実現できる技術です。ブラウザーを通してデバイスのGPUにアクセスすることができます。

下記の記事でもまとめをしているので、気になる方はこちらもあわせてどうぞ。

three.jsとは

threejs

WebGLをそのまま扱おうとすると、APIの扱いに冗長な準備が必要になってしまい、とても高度な技術を要します。

そこで、JavaScriptライブラリーを通して、それらを簡単に取り扱うことができるものが登場しました。それがthree.jsです。

HTMLの準備

それではさっそく使ってみましょう。

最初に3DCGを描画する領域を用意し、その後にライブラリーを読み込みます。zipで落としてきたり、npmでインストールする方法もあるのですが、今回はCDNで読み込みます。

<div id="stage"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>

これで準備は完了です。簡単ですね。
ここからはjsをガンガン書いていきましょう。

ステージを用意

物体(メッシュ)を置くためのステージ(シーン)を用意します。

three.jsを読み込んだことで、THREEというオブジェクトが使えるようなったので、このように記述します。

(function() {
    var scene;
    scene = new THREE.Scene(); // scene ステージ
})();

何もない空間に、これから表示する要素の土台だけがある状態です。

メッシュを用意

次は、メッシュを用意します。また、今回は球体を作ろうと思うので、Mesh関数の引数に、以下の関数を渡します。

  • ジオメトリー(形状)
  • マテリアル(素材)

 

ジオメトリーを示す基本的な関数
BoxGeometry・・・立方体を作る

new THREE.BoxGeometry(幅, 高さ, 奥行き)

SphereGeometry・・・球体を作る

new THREE.SphereGeometry(半径, 経度分割数, 緯度分割数, 開始経度, 経線中心角, 開始緯度, 緯線中心角)

CylinderGeometry・・・円柱を作る

new THREE.CylinderGeometry(上面の半径, 底面の半径, 高さ,円周の分割数, 高さの分割数, フタをしない:true,フタをする:false)
マテリアルを示す基本的な関数
MeshBasicMaterial・・・質感が一番低い。光源の影響を受けないので陰がつかない。
MeshLambertMaterial・・・MeshBasicMaterialより質感が高い。影がつく。
MeshPhongMaterial・・質感が一番高い。影も光も綺麗につく。また、オプションでカラーコードなどを渡せる。

new THREE.MeshLambertMaterial({color: 0xから始まる16進数})

その後、set関数で配置する位置(幅, 高さ, 奥行き)を決め、add関数でシーンに反映させます。

まとめると以下のようなコードになります。

(function() {
    var scene;
    var sphere;

    // scene ステージ
    scene = new THREE.Scene();

    // mesh 物体
    sphere = new THREE.Mesh(
      new THREE.SphereGeometry(100, 20, 20), // geometry 形状
      new THREE.MeshLambertMaterial({color: 0x8dc3ff}) // material 材質、色
    );
    sphere.position.set(0, 0, 0);
    scene.add(sphere);
  })();

カメラを用意

カメラ越しに物体を見るイメージになるので、シーンにカメラを設置します。
PerspectiveCamera関数の引数に、以下の値を渡します。

画角
カメラに写る光景の範囲を角度で表したもの
アスペクト比
画面の長辺対短辺(横対縦)の比率を表したもの
カメラから手前(ニアクリップ面)までの距離
視点から、光景が見え始める面までの距離
カメラから奥(ファークリップ面)までの距離
視点から最も遠い面までの距離
カメラを作る基本的な関数
PerspectiveCamera・・・透視投影。通常生活における物の見え方と同じ。

new THREE.PerspectiveCamera(画角, アスペクト比, ニアークリップ, ファークリップ)

OrthographicCamera・・・正投影。物体の見た目の大きさが視点からの距離によらず、変わらない(どこから見ても物体のサイズは同じ)

new THREE.OrthographicCamera(画角, アスペクト比, ニアークリップ, ファークリップ)

その後、カメラの位置とカメラの向きを設定します。
カメラの向きは、lookAt関数を使用します。シーンの方を向かせたいので、以下のようにしまししょう。

camera.lookAt(scene.position);

まとめると以下のようなコードになります。

(function() {
    var scene;
    var sphere;
    var camera;
    var width = 500;
    var height = 250;

    // scene ステージ
    scene = new THREE.Scene();

    // mesh 物体
    sphere = new THREE.Mesh(
      new THREE.SphereGeometry(100, 20, 20), // geometry 形状
      new THREE.MeshLambertMaterial({color: 0x8dc3ff}) // material 材質、色
    );
    sphere.position.set(0, 0, 0);
    scene.add(sphere);

    // camera
    camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
    camera.position.set(200, 100, 300);
    camera.lookAt(scene.position);
  })();

レンダラーを用意

いよいよレンダリングです。今まで設定したものをHTMLと紐付けます。
今回レンダラーにはWebGLRendererを使用します。

基本的なレンダラー関数
WebGLRenderer・・・WebGLを扱うレンダラー。GPUで演算を行うため、3Dグラフィックス処理において実行速度が早い。Three.jsの全機能が使える。モダンブラウザでのみ対応。
オプションでアンチエイリアスの設定も可能です。

new THREE.WebGLRenderer({ antialias: true})

CanvasRenderer・・・一般的に2Dグラフィックスを描画するときに使用するCanvas2Dで、3Dグラフィックスを実現する。CPUで演算を行うため3Dグラフィックス処理において実行速度が遅い。Three.jsの一部の機能しか使えないが、対応しているブラウザが多い。

次にsetSize関数とsetClearColor関数とで、

<div id="stage"></div>

にセットするサイズと背景色を指定します。

色は0xから始まる16進数で記述します。その後、idからDOMオブジェクトを取得し、appendChildでcanvasタグをdiv内にセットします。

最後にrender関数の引数にsceneとcameraを渡し、レンダリング完了です。まとめると以下のようなコードになります。

(function() {
    var scene;
    var sphere;
    var camera;
    var renderer;
    var width = 500;
    var height = 250;

    // scene ステージ
    scene = new THREE.Scene();

    // mesh 物体
    sphere = new THREE.Mesh(
      new THREE.SphereGeometry(100, 20, 20), // geometry 形状
      new THREE.MeshLambertMaterial({color: 0x8dc3ff}) // material 材質、色
    );
    sphere.position.set(0, 0, 0);
    scene.add(sphere);

    // camera
    camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
    camera.position.set(200, 100, 300);
    camera.lookAt(scene.position);

    // renderer
    renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setSize(width, height);
    renderer.setClearColor(0xeeeeee);
    document.getElementById('stage').appendChild(renderer.domElement);
    renderer.render(scene, camera);
})();

codepenにも同じコードを用意したので、実際に見てみましょう。

See the Pen three.js sample1 by k_hatsushi (@hatsushi_kazuya) on CodePen.

球体は表示できていますが、真っ暗ですね。

光源を用意

私たちの住んでる世界も同じですが、物体は光が当たらないと目には見えませんよね? WebGLを扱う場合も光が必要で、光源を設置してあげなければいけません。
 

光を作る基本的な関数
DirectionalLight・・・平方光源。三次元空間全体に無限遠にある平行な光源。その為影は物体の位置に影響されない。

new THREE.DirectionalLight(0xから始まる16進数, 光の強さ)

PointLight・・・点光源。1点から放射状に光を放つ光源。その為影は物体の位置に影響され、地面と物体の距離が離れるほど影は大きくなる。

AmbientLight・・・環境光自然光の乱反射をシュミレートする光源。全方向に光が当たる。よりリアルな光や影を演出するための補足として使用。

光源の設定をしたら、位置を設定し、シーンに追加します。

(function() {
    var scene;
    var sphere;
    var camera;
    var light;
    var renderer;
    var width = 500;
    var height = 250;

    // scene ステージ
    scene = new THREE.Scene();

    // mesh 物体
    sphere = new THREE.Mesh(
      new THREE.SphereGeometry(100, 20, 20), // geometry 形状
      new THREE.MeshLambertMaterial({color: 0x8dc3ff}) // material 材質、色
    );
    sphere.position.set(0, 0, 0);
    scene.add(sphere);

    // light
    light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, 100, 30);
    scene.add(light);

    // camera
    camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
    camera.position.set(200, 100, 300);
    camera.lookAt(scene.position);

    // renderer
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(width, height);
    renderer.setClearColor(0xeeeeee);
    document.getElementById('stage').appendChild(renderer.domElement);
    renderer.render(scene, camera);
})();

それではどんな風に表示されたか実際に見てみましょう。

See the Pen three.js sample2 by k_hatsushi (@hatsushi_kazuya) on CodePen.


光のおかげで色と影が見えるようになりました。

まとめ

基本的な流れは、

  1. 物体を置く場所を作る
  2. 物体を置く
  3. カメラを置く
  4. 光を置く
  5. レンダリングする

になるのがわかるかと思います。

次回は、物体をマウスや自動で動かしたり、画像を物体に反映させてみようと思います。

はっちゃん
この記事を書いた人
はっちゃん

フロントエンドエンジニア

関連記事