ゲームやビジュアライゼーションのWebコンテンツでは、華やかな3D演出の実装をJavaScriptとWebGLで求められることがあります。この記事のシリーズでは、WebGLのJSライブラリとして有名なThree.jsを利用して、3Dエフェクトの作成手順を解説します。

今回、扱うテーマは「マグマエフェクト」。実は以前、このテーマを3Dエフェクト作成ツールであるEffekseerエフェクシアーで扱ったことがあります(記事「エフェクト作成入門講座 Effekseer編 UVスクロールを使ったマグマエフェクトの作成」)。Effekseerはプログラムを使わないデザインツールなので、今回紹介するThree.jsによるプログラムの作り方とは全く異なります。ですが、表現のエッセンスはどんな作り方でも共通。エフェクトの実装ポイントが理解できていれば、異なった方法でも同じ表現を実装できるのです。

本記事ではシンプルなJavaScriptやGLSLのコードに分解して、身構えることなく学べるようにしています。サンプルコードはGitHubにアップしているので参考にしながら読み進めてください。

※このデモはThree.js(r86)とTypeScript(ver 2.4)とwebpack 3で作成しました。環境構築は記事「最新版TypeScript 2+Webpack 3の環境構築まとめ」を参照ください

エフェクトの構成

Effekseerを使った場合と同様に、6つのオブジェクトの集合で表現できます。それぞれのパーツに施された工夫を順に説明します。

  • マグマ球
  • オーラ球
  • 外側グロー
  • スパーク
  • 内側グロー
  • フレア

マグマ球、オーラ球

magma_and_aura

マグマ球とオーラ球は単純な球状のMeshにテクスチャーを当て、そのテクスチャーをずらすことで流れるマグマや漂うオーラを表現しています。

以下のコードで球を作りテクスチャーを当てます。

// テクスチャーを読み込みます。
var loader = new THREE.TextureLoader();
var map = loader.load('textures/source.png');

// テクスチャーをあてた球のMeshを作成します。
var mesh = new THREE.Mesh(
  new THREE.SphereGeometry(2, 20, 20);
  new THREE.MeshBasicMaterial({ map: map });
);

次にアニメーションをさせた際にテクスチャーがリピートするように設定を追加します。

// 縦横でリピートするように設定します。
map.wrapS = map.wrapT = THREE.RepeatWrapping;

テクスチャーをずらしアニメーションさせるコードを書いてきます。requestAnimationFrame()メソッドなどの毎フレーム実行される関数内に処理を追加します。

// 毎フレーム位置を0.005ずつ動かす。
map.offset.x += 0.005;
map.offset.y += 0.005;

これでテクスチャーのずれて動くアニメーションができます。このようなテクスチャーを動かすアニメーションを「UVアニメーション」と呼びます。

外側グロー

outglow

外側のグローはテクスチャーを貼ったビルボードを表示させます。ビルボードとは必ずカメラに対して正面を向く板の事です。Three.jsでビルボードを実現するにはTHREE.Spriteを使用します。

// テクスチャーを読み込みます。
var loader = new THREE.TextureLoader();
var map = loader.load('textures/source.png');

// マテリアル
var material = new THREE.SpriteMaterial({ 
  map: map,
  color: 0xffffff,
  blending: THREE.AdditiveBlending,
  transparent: true
});

// スプライト
var sprite = new THREE.Sprite(material);

以上でビルボードは作成されますが、デフォルトの大きさが非常に小さいため適切なサイズになるように拡大を忘れないようにしましょう。

sprite.scale.multiplyScalar(10);

スパーク

spark

スパークは板状のMeshを複数作成し、中心に集まるようなアニメーションをさせて再現します
次のコードは一つのスパークを生成するものです。

// テクスチャーを読み込みます。
var loader = new THREE.TextureLoader();
var map = loader.load('textures/source.png');

// 板状のMeshを作成します。
var mesh = new Mesh(
  new THREE.PlaneGeometry(0.15, 2),
  new THREE.MeshBasicMaterial({ map: map });
);

予めスパークのY座標をプラスへずらしておき、中心点(0, 0)に向かって進むアニメーションをつけ、さらに中心点に向かうにつれ透明度を増加させフェードアウトしていくアニメーションを加えます。マグマ球の時と同様に毎フレーム実行される関数に処理を追加します。

// 毎フレーム少しずつ移動し透明に近づける。
mesh.position.y -= 0.5;
mesh.material.opacity -= 0.05;

// 透明度が0以下だったら位置と透明度を初期化する。
if(mesh.material.opacity <= 0) {
  mesh.position.y = 5;
  mesh.material.opacity = 1;
}

ここまでが一つ分のスパークの処理です。あとはスパークを中心点(0, 0)を支点として回転させた物を複製します。スパークの開始位置をランダムで少しずらしておくと、既視感がなくなりクオリティが上がるのでオススメです。

次のページでは内側グローとフレアについての解説します。