昨今のWebサイトではWebGLを利用した3Dコンテンツをしばしば見かけるようになってきました。WebGLに対応した端末が普及してきていることや、Three.jsなどのライブラリが充実していることもあり、実案件での採用が現実的になってきているからです。

しかし、いざ3Dコンテンツを作ってみると、どこか味気の無いものになってしまう事があります。そんな時はエフェクトの追加をオススメです。エフェクトを追加することで、コンテンツの見栄えが派手になったり、キャラやゲームの状態が伝わりやすくなります。今回エフェクトの例として、RPGのセーブポイントや回復ポイントで使用されそうなデモを制作してみました。

▲ ソースコードはGitHubに公開しておりますので、あわせて参照ください。

※このデモは Three.js(r74)とTypeScript(ver 1.8)によって書かれています。

本記事では、セーブポイント風なエフェクトの作成を通して、Three.jsを使ったエフェクト作成の3つの基本ノウハウを解説します。他のエフェクト作成にも応用できるので是非ご参考ください。

制作の流れ

冒頭のデモは下図のパーツで構成されています。複雑そうに見えますが、分解してみるとシンプルなパーツで構成されている事が分かります。

setting

今回は以下の3つに絞って順に解説していきます。その他のパーツはこの3つの方法の応用で作る事ができます。

  1. 光の柱
  2. パーティクル

ステップ1. 光の柱の作成

step1

円柱を作る

光の柱は縦に伸びる円柱のような形をしています。Three.jsではCylinderGeometryという円柱型のジオメトリが用意されているのでこちらを使用して表現します。

// THREE.CylinderGeometry(上面円の半径, 下面円の半径, 高さ, 縦分割数, 横分割数, 上下面を無くすか否か)
var geometry = new THREE.CylinderGeometry(5, 5, 15, 25, 25, true);

この時、第6引数の上下面を無くすか否かtrueを指定するように注意ください。蓋のある円柱になってしまうのを防ぐためです。

柱を光らせる

円柱に光っているかような質感をもたせます。
発光体を表現する際は、光源に関係なく発色できるMeshBasicMaterialが最適です。

var material = new THREE.MeshBasicMaterial({
  map: texture,           // テクスチャーを指定
  color: 0x007eff,        // 色
  transparent: true,      // 透明の表示許可
  blending: THREE.AdditiveBlending, // ブレンドモード
  side: THREE.DoubleSide, // 表裏の表示設定
  depthWrite: false       // デプスバッファへの書き込み可否
});

設定しているパラメーターを順に解説します。

map

mapパラメーターは使用するテクスチャーを指定できます。テクスチャーはモノクロで作成しておくとcolorパラメーターから白色部分を指定した色に変更できるため、汎用性が高く扱いやすいのでおすすめです。

blending

blendingパラメーターはブレンドモード指定できます。NoBlending(無し)、NormalBlending(半透明合成)、AdditiveBlending(加算合成)、SubtractiveBlending(減算合成)、MultiplyBlending(乗算合成)の5つから選択できますが、今回は重なった部分を白く発光させたいためAdditiveBlendingを指定します。ブレンドモードを使用する場合は、併せてtransparenttrueに設定するように注意ください。

side

sideパラメーターは描画面を指定できます。FrontSide(表のみ)、BackSide(裏のみ)、DoubleSide(表裏両方)の3つから選択できますが、今回は筒の中も表示させたいためDoubleSideを指定します

depthWrite

depthWriteパラメーターは面と面が重なって見える時に、陰に隠れてしまった面を描画させないようにするかどうかを設定できます。今回は光が重なって見える必要があるのでfalseを指定します。

ジオメトリとマテリアルが完成したので、この2つを使用したメッシュを作成すれば光の柱の完成です。

// 光る柱のメッシュを作成
var mesh = new THREE.Mesh(geometry, material);

ステップ2. 渦の作成

step2

渦をつくる

渦は地面にドーナツ型に渦を発生させたいので、TorusGeometryというドーナツ型のジオメトリを使用します。本来は立体のドーナツ型を想定したジオメトリですが、第3引数の分割数の値を2にすることで平面のドーナツ型を作成できます

// THREE.TorusGeometry(半径, 太さ, 放射状の分割数, 管の分割数)
var geometry = new THREE.TorusGeometry(6, 3, 2, 100);

マテリアルは前章の光の柱とほぼ同じ内容で、テクスチャーのみ変更したものを使用します。

var material = new THREE.MeshBasicMaterial({
  color: 0x007eff,
  map: texture,
  transparent: true,
  blending: THREE.AdditiveBlending,
  side: THREE.FrontSide
});

地面に設置する

TorusGeometryはデフォルトで縦に立っているので、90度回転させて地面と平行にします。描画面はFrontSideとしているので、表面が見えるように回転させる向きに注意してください

mesh.rotaition.x = 90 * Math.PI / 180; // 90度回転

地面と平行になりましたが、このままでは地面とエフェクトが重なってしまい下図のようなチラつきが発生してしまいます。

flicker

この問題はメッシュを少しだけ浮かせる事で回避できます。

mesh.position.y = 0.01; // 少しだけ浮かせる

回転させる

渦を巻いているアニメーションをつけます。回転角度をフレーム毎に増やしメッシュを回転させます。

angle++; // 角度をインクリメント
mesh.rotation.y = angle * Math.PI / 180; // 回転

回転させたことで渦を巻いているような見栄えになりました。

ステップ3. パーティクルの作成

step3

粒をつくる

パーティクルにはSpriteというオブジェクトを使用します。Spriteは必ずカメラに正面を向くという特徴のある平面オブジェクトで、パーティクルを表現する場合に、テクスチャーの見え方が均一になるため非常に有効です。このような手法を一般的にビルボードと呼びます。Spriteを生成する場合のマテリアルはSpriteMaterialを使用します。

var material = new THREE.SpriteMaterial({
  color: 0x007eff,
  map: texture,
  transparent: true,
  blending: THREE.AdditiveBlending
});
var sprite = new THREE.Sprite(material);

これで一粒分のパーティクルを作成できました。

湧き出させる

パーティクルが下から湧き出るような演出を作っていきます。下から上へと上がっていく動きと、フェードアウトさせる動きを合わせる事で表現していきます。

// 徐々に上へ
sprite.position.y += 0.1;
// 徐々に薄く
material.opacity -= 0.01;

真上に上がって消えていくアニメーションができました。あとは同じパーティクルを幾つか生成し、時間差をつけてアニメーションさせることで、湧き出るような演出を表現できます。さらに横方向の動きや拡縮を入れるとよりクオリティーが上がります。

まとめ

特別なツールを使用する事なく、JavaScriptのコードのみでセーブポイント風なエフェクトを作成できました。今回紹介した基本ノウハウは、セーブポイントだけでなく、波動や爆発などの様々なエフェクトを作成する際に応用できます

Three.jsとは関係ありませんが、BISHAMONというエフェクトツールの解説書籍『BISHAMON ゲームエフェクトデザイン入門』ではエフェクトの様々な表現方法がわかりやすく解説されているので、あわせて見ておくと良いと思います。本記事以外でもエフェクトに関連した記事をいくつか掲載しているので、こちらもご参考ください。

是非みなさんも色々なエフェクト作成に挑戦してみてください。