こんにちは、はっちゃんです。
今回は、もはやお馴染み、WebGLを簡単に扱えるライブラリー「three.js」をご紹介します。WebGLを使った3D表現が一般的になってきたとはいえ、実際取り入れられていない方も多いと思います。
そこで今回は、自分の勉強を兼ねて、できるだけ詳しくまとめてみましたので、これから覚えようとしているフロントエンドやデザイナーの方の参考になれば幸いです。
WebGLとは
JavaScriptから利用できるAPIで、ブラウザー上で3DCGプログラミングを実現できる技術です。ブラウザーを通してデバイスのGPUにアクセスすることができます。
下記の記事でもまとめをしているので、気になる方はこちらもあわせてどうぞ。
デザイナー・ノンプログラマにおすすめしたいThree.jsのカンタン3D体験 圧倒的な3D表現にWebの未来を感じるWebGLを使ったサイト・デモ20選
three.jsとは
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.
光のおかげで色と影が見えるようになりました。
まとめ
基本的な流れは、
- 物体を置く場所を作る
- 物体を置く
- カメラを置く
- 光を置く
- レンダリングする
になるのがわかるかと思います。
次回は、物体をマウスや自動で動かしたり、画像を物体に反映させてみようと思います。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。