3Dグラフィックでの表現を用いたウェブサイトが増えてきたなあ、と思う方も多いのではないでしょうか。このグラフィックの表現は、もちろんHTMLとCSSだけでは不可能です。WebGL(Webグラフィックライブラリ)という、ブラウザ上で3次元・2次元のオブジェクトやグラフィックをレンダリングするために使用されるJavaScriptAPIが使われています。
そんなWebGLを簡単に扱うことができるライブラリ「three.js」というものがあるので、本記事ではthree.jsを用いた3Dグラフィックの作成について紹介しようと思います。
JavaScriptをある程度触ったことのある方であれば、比較的簡単に導入することができると思うので、ぜひ一読してみてください。この記事を通して、以下のようなオブジェクトをブラウザに表示できるようになります。
目次
WebGLとは
3DグラフィックをHTML5のCanvas要素に描画できるJavaScript APIです。
ほかの3Dグラフィックに対応しているFlash PlayerやUnity Web Playerといったものは、プラグインをインストールしないと表示することが不可能でしたが、WebGLはプラグインが必要ないため、プラグイン未搭載のパソコンやスマートフォンでも対応可能になっています。
WebGLの対応ブラウザ
2021年現在、iOSやAndroidを含めた主要ブラウザ全てで対応可能となっています。
WebGL – 3D Canvas graphics(Can I use ___?)
WebGLのライブラリ「three.js」
three.jsはWebGLをJavaScriptで扱うことができ、3Dオブジェクトをブラウザに表示できるライブラリです。three.jsを用いることで、本格的な3Dをプラグイン無しで簡単に作ることができます。
Three.js – JavaScript 3D Library(three.js公式サイト)
公式サイトにはサンプルが載っています。
three.js examples(three.js公式ドキュメント)
3Dオブジェクトを表示しよう
それでは実際に、three.jsを用いて3Dオブジェクトを作成してみましょう。
HTMLファイルを用意する
1 2 3 4 5 6 7 8 9 10 11 | <html> <head> <meta charset="utf-8"> <title>three.js</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script src="js/common.js"></script> </head> <body> <canvas id="canvas"></canvas> </body> </html> |
three.jsはHTMLのcanvas要素が必要になります。canvas要素は図形やアニメーションを描くために使われるHTML要素です。three.js側で呼び出すために必要なので、canvas要素には任意のid(今回は”canvas”)を指定しておきます。
また、three.jsを表示させるためにjsの読み込みが必要ですが、今回はCDNを使っています。こちらは公式サイトの左メニューCode>Downloadからダウンロードできます。
Three.js – JavaScript 3D Library(three.js公式サイト)
three.jsの公式JavaScriptとは別に、今回のはcommon.jsというファイルにthree.js動作用のJavaScriptを書いていきます。
作業用JavaScriptファイルの準備
先ほど作成したcommon.jsを開き、以下を記述してください。
1 2 3 4 5 6 7 8 9 10 | // ページの読み込みを待つ window.addEventListener('load', init); // canvasのサイズを指定 const width = window.innerWidth; //ブラウザの横の長さ const height = window.innerHeight; //ブラウザの縦の長さ function init() { //ここに描画処理を書きます } |
widthとheightにて、canvas要素のブラウザの横・縦の長さを指定しています。
pxでの指定も可能ですが、今回はブラウザ内いっぱいになるようにしています。
three.jsで3Dオブジェクトをブラウザに表示させるためには、シーン・カメラ・レンダラーといったものが必要になります。流れは以下のような感じですが、必要な要素さえあれば順番通りにやらなくても問題はありません。
1シーンを作る
1 | const scene = new THREE.Scene(); |
3D空間になる「シーン」を作ります。
2カメラを作る
1 2 | const camera = new THREE.PerspectiveCamera(45, width / height); camera.position.set(0, 0, 1000); // x,y,z座標でカメラの場所を指定 |
シーン内にあるオブジェクトを投影するための「カメラ」を作り、位置を指定します。
3レンダラーを作る
1 2 3 | const canvasElement = document.querySelector('#canvas') //HTMLのcanvasのid const renderer = new THREE.WebGLRenderer({ canvas: canvasElement }); renderer.setSize(width, height); |
WebGLを生成(レンダリング)するための「レンダラー」を作ります。
4ライトを作る
1 2 3 | const light = new THREE.AmbientLight(0xFFFFFF, 1.0); //色、光の強さ light.position.set(50, 50, 50); // x,y,z座標でライトの場所を指定 scene.add(light); |
ライトが無いと3D空間が真っ暗になるため、光源を置いてあげます。今回指定しているAmbientLightは空間全体に均等に光を当てるので、一律に明るくなるライトです。
他のライトについての詳細は、記事の下の方にまとめました。
53Dオブジェクトを作る
3Dオブジェクトには、
- 形や大きさなど形状を表す「ジオメトリ」
- 色や質感をつけるための「マテリアル」
- ジオメトリを受け取りマテリアルに適用する「メッシュ」
という概念があります。以下のように記載し、各要素を指定していきます。
1 2 3 4 | const geometry = new THREE.SphereGeometry(200, 300, 300); //ジオメトリ const material = new THREE.MeshNormalMaterial(); //マテリアル const mesh = new THREE.Mesh( geometry, material ); //メッシュ scene.add( mesh ); |
ジオメトリとマテリアルについては記事の下のほうにまとめています。
63D空間を描画する
1 2 3 4 | function start() { renderer.render(scene, camera); } start(); |
最後に、シーンとカメラをレンダリングすることで、ブラウザ上に3Dオブジェクトを描画できます。
こちらがブラウザに表示されたら成功です。
今回、ライトは「DirectionalLight(平行光源)」、ジオメトリは「SphereGeometry(球体)」、マテリアルは「MeshNormalMaterial(RGBカラー)」にしています。
全体のソース
全体のソースはこちらです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // ページの読み込みを待つ window.addEventListener('load', init); // canvasのサイズを指定 const width = window.innerWidth; //ブラウザの横の長さ const height = window.innerHeight; //ブラウザの縦の長さ function init() { // シーンを作る const scene = new THREE.Scene(); // カメラを作る const camera = new THREE.PerspectiveCamera(45, width / height); camera.position.set(0, 0, 1000); // x,y,z座標でカメラの場所を指定 // レンダラーを作る const canvasElement = document.querySelector('#canvas') //HTMLのcanvasのid const renderer = new THREE.WebGLRenderer({ canvas: canvasElement }); renderer.setSize(width, height); // ライトを作る const light = new THREE.DirectionalLight(0xFFFFFF, 1); //平行光源(色、光の強さ) light.position.set( 0, 0, 1000 ); scene.add(light); // 3Dオブジェクトを作る const geometry = new THREE.SphereGeometry(200, 300, 300); //球体(半径、水平セグメント、垂直セグメント) const material = new THREE.MeshNormalMaterial(); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); //アニメ―ション function start() { renderer.render(scene, camera); } start(); } |
ライト一覧
three.jsで使えるライトについて、以下にまとめました。
- 空間全体へ均等に光を当て、一律に明るくなる
- 光が直接当たっていない箇所も照らされる
1 | const light = new THREE.AmbientLight(0xFFFFFF, 1.0); //環境光源(色、光の強さ) |
- 特定の方向に放射される光が平行になる
- 照らされる面や影の方向は一定になる
1 2 | const light = new THREE.DirectionalLight(0xFFFFFF, 1); //平行光源(色、光の強さ) light.position.set(0,0,1000); //光の位置(x、y、z) |
- 上からと下からの色を分けて光を当てられる
1 2 | const light = new THREE.HemisphereLight(0x93C54B, 0x0000FF, 1.0); light.position.set(500,500,1000); //光の位置(x、y、z)、わかりやすいよう位置を少しずらしています |
上からは黄緑(0x93C54B)、下からは紺(0x0000FF)というライトにして、X・Y軸はそれぞれ500ずつ移動しています。
- 単一点から全方向へ光るライト
1 2 | const light = new THREE.PointLight(0xFFFFFF, 1, 1500, 1.0); //点光源(色、光の強さ、光の届く距離、光の減衰値) light.position.set( 0, 0, 1000 ); |
- 特定の方向(点座標)に向けて光を当てられる
1 2 | const light = new THREE.SpotLight(0x93C54B, 4, 1000, Math.PI / 2, 1, 0.5); //スポットライト光源(色、光の強さ、光の届く距離、角度、ターゲットからの光の減衰値、光源からの光の減衰値) light.position.set( 200, 200, 1000 ); //わかりやすいよう位置を少しずらしています |
ジオメトリ一覧
three.jsで使えるジオメトリについて、以下にまとめました。
1 const geometry = new THREE.SphereGeometry(200, 300, 300); //球体(半径、水平セグメント、垂直セグメント)
1 const geometry = new THREE.BoxGeometry(300, 300, 300); //立方体(半径、水平セグメント、垂直セグメント)
※わかりやすいように少し回転させています
1 const geometry = new THREE.PlaneGeometry(300, 300, 1, 1); //平面(幅、高さ、横の分割数、縦の分割数)
※わかりやすいように少し回転させています
1 const geometry = new THREE.ConeGeometry(200, 400, 400); //三角錐(半径、水平セグメント、垂直セグメント)
1 const geometry = new THREE.CylinderGeometry(100,100,400,12); //円柱(上部の円柱の半径、下部の円柱の半径、高さ、面数)
1 const geometry = new THREE.DodecahedronGeometry(200, 0); //正十二面体(半径、詳細)
※詳細(detail)のデフォルトは0ですが、0より大きい値に設定すると頂点が追加され、十二面体ではなくなります。
1 const geometry = new THREE.IcosahedronGeometry(200, 0); //正十二面体(半径、詳細)
※詳細(detail)のデフォルトは0ですが、0より大きい値に設定すると頂点が追加され、二十面体ではなくなります。
1 const geometry = new THREE.TorusGeometry(100,50,100,100); //ドーナツ(トーラス(円環)の半径、チューブの半径、トーラスの面数、チューブの面数)
マテリアル一覧
three.jsで使えるマテリアルについて、以下にまとめました。
- RGBカラーにする
- このマテリアルのみ、ライトがなくても目視できる
1 | const material = new THREE.MeshNormalMaterial() |
- 塗りつぶし(色指定がないと白になる)
1 | const material = new THREE.MeshBasicMaterial({color: 0x93C54B}); |
- 光沢のない質感
1 | const material = new THREE.MeshLambertMaterial({color: 0x93C54B}); |
- 光沢のある質感
1 | const material = new THREE.MeshPhongMaterial({color: 0x93C54B}); |
- アニメ(カートゥーン)調の質感
1 | const material = new THREE.MeshPhongMaterial({color: 0x93C54B}); |
- 光の反射などを現実の物理ベースでレンダリングする
1 | const material = new THREE.MeshStandardMaterial({color: 0x93C54B}); |
まとめ
本記事ではthree.jsの触りの部分を紹介しました。
より高度な開発ができるようになれば、以下のサイトのように部屋の中の各要素などさまざまなオブジェクトをつくることができます。それにより、ウェブサイトの表現の幅が広がったり、オリジナルのゲームを作れたりするようになったり、できること広がると思うので、この機会にぜひthree.jsに挑戦してみてはいかがでしょうか。
The ultimate Three.js course(three.js journey)
参考サイト
シーンの作成 – three.js docs(three.js公式ドキュメント)
簡単なThree.jsのサンプルを試そう(ics.media)
最新版で学ぶThree.js入門 手軽にWebGLを扱える3Dライブラリ(ics.media)
Three.jsをかじる本(Zenn)
初心者でも絶対わかる、WebGLプログラミング<three.js最初の一歩>(HTML5 Experts.jp)