babylon.js を覚えようシリーズ ステップ14はパーティクル表現です。

Three.jsでは自作で頑張るわけですが、babylon.jsではパーティクルシステムが備わっていますので、簡単にパーティクル表現が可能です

いきましょう!

f:id:hollywis:20200709105939p:plain

パーティクルの作り方

パーティクルシステム

パーティクルシステムを用いたパーティクル表現の例はこちらです。

コード中に説明を追加していますので順番にみていきましょう

コード例は以下です。

var createScene = function () {
var scene = new BABYLON.Scene(engine);
// ライトやカメラなど環境セッティング
var light0 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(-10, 7, -10), scene);
var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 20, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
// パーティクルの吹き出し口のオブジェクト作成
var fountain = BABYLON.Mesh.CreateBox("foutain", 1.0, scene);
// 地面作成
var ground = BABYLON.Mesh.CreatePlane("ground", 50.0, scene);
ground.position = new BABYLON.Vector3(0, -15, 0);
ground.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);
ground.material = new BABYLON.StandardMaterial("groundMat", scene);
ground.material.backFaceCulling = false;
ground.material.diffuseColor = new BABYLON.Color3(0.3, 0.3, 1);
// パーティクルシステムの作成
var particleSystem = new BABYLON.ParticleSystem("particles", 2000, scene);
//パーティクルに貼るテクスチャ定義
particleSystem.particleTexture = new BABYLON.Texture("textures/flare.png", scene);
// パーティクルの出る(emit:放出)ポイントをVector3で定義 mn~maxで定義可能
particleSystem.emitter = fountain; // the starting object, the emitter
particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0); // Starting all from
particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0); // To...
// パーティクルの色 2種類と消えゆくときの色
particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);
// パーティクル ランダムで min〜maxに
particleSystem.minSize = 0.1;
particleSystem.maxSize = 0.5;
// パーティクルのライフタイム設定 ランダムでmin~max
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5;
// 放出(emit)率
particleSystem.emitRate = 1500;
// ブレンドモード : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;
// 重力設定
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);
// エミット(放出)後のパーティクルの方向
particleSystem.direction1 = new BABYLON.Vector3(-7, 8, 3);
particleSystem.direction2 = new BABYLON.Vector3(7, 8, -3);
// 角速度(ラジアン)
particleSystem.minAngularSpeed = 0;
particleSystem.maxAngularSpeed = Math.PI;
// スピード
particleSystem.minEmitPower = 1;
particleSystem.maxEmitPower = 3;
particleSystem.updateSpeed = 0.005;
// Particle Systemをスタート
particleSystem.start();
// 吹き出すアニメーション
var keys = [];
var animation = new BABYLON.Animation("animation", "rotation.x", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
// アニメーション設定 フレーム0, valueは拡大率 "1"
keys.push({
frame: 0,
value: 0
});
// フレーム50, 拡大率 "0.2"
keys.push({
frame: 50,
value: Math.PI
});
// フレーム 100, 拡大率 "1"
keys.push({
frame: 100,
value: 0
});
// アニメーションスタート
animation.setKeys(keys);
fountain.animations.push(animation);
scene.beginAnimation(fountain, 0, 100, true);
return scene;
}

動いている例はこちら
www.babylonjs-playground.com

解説

この部分で パーティクルシステム(Particle System)を作成しています

    // パーティクルシステムの作成
var particleSystem = new BABYLON.ParticleSystem("particles", 2000, scene);
//パーティクルに貼るテクスチャ定義
particleSystem.particleTexture = new BABYLON.Texture("textures/flare.png", scene);
// パーティクルの出るポイントをVector3で定義 mn~maxで定義可能
particleSystem.emitter = fountain; // the starting object, the emitter
particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0); // Starting all from
particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0); // To...

2000というのは、表示可能な最大数の設定値です。

さらに、パーティクルシステムには、パーティクルが見えるようにするためのテクスチャと、開始点からのパーティクルの位置と広がりを設定する「エミッタ(emitter)」も必要です。

パーティクルのスタート

particleSystem.start();

パーティクルの停止

particleSystem.stop();

リセット方法

particleSystem.reset()

もし遅延起動させたい場合には

particleSystem.startDelay = 3000;

なんてこともできます。

タイマーを設定して、自動的に勝手に止めることもできます

particleSystem.targetStopDuration = 5; //自動停止
particleSystem.disposeOnStop = true; //パーティクルシステムを破棄し、メモリを開放

パーティクルのテクスチャマスク

f:id:hollywis:20200709121020p:plain

particleSystem.textureMask = new BABYLON.Color4(0.1, 0.8, 0.8, 1.0);

テクスチャにマスクを適用して、一部の色をフィルタリングしたり、アルファチャネルの一部をフィルタリングしたりすることもできます。

パーティクルエミッタ

パーティクルエミッタはメッシュだけでなく、任意のVector3でもOKです。

particleSystem.emitter = new BABYLON.Vector3(-1, 2, 3);

これで任意の点から、パーティクルを放出できます。

ローカル空間

エミッタがメッシュのとき、isLocal設定で、パーティクルをメッシュの座標系に依存させることができます。

particleSystem.isLocal = true

例はこちら
https://www.babylonjs-playground.com/#LNRAI3

場所と広がり

f:id:hollywis:20200709122843p:plain

minEmit maxEmitを設定することで、放出場所を設定します。

particleSystem.minEmitBox = new BABYLON.Vector3(-2, -3, 4);
particleSystem.maxEmitBox = new BABYLON.Vector3(4, 2, 3);

シンプルな例がこちら

ただテクスチャを貼ったパーティクルを数個だし、漂流して消えます。

 var createScene = function () {
var scene = new BABYLON.Scene(engine);
// Setup environment
var light0 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 2, 8), scene);
var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 20, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
// Create a particle system
var particleSystem = new BABYLON.ParticleSystem("particles", 2000, scene);
//Texture of each particle
particleSystem.particleTexture = new BABYLON.Texture("textures/flare.png", scene);
// Where the particles come from
particleSystem.emitter = new BABYLON.Vector3(0, 0, 0); // the starting object, the emitter
particleSystem.minEmitBox = new BABYLON.Vector3(-0.5, -0.5, -0.5); // Starting all from
particleSystem.maxEmitBox = new BABYLON.Vector3(0.5, 0.5, 0.5); // To...
// Start the particle system
particleSystem.start();
return scene;
}

ライフタイム

パーティクルの生存期間を設定できます

// Life time of each particle (random between...)
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5;

また、高度な設定方法もあります。

system.targetStopDuration = 0.5など停止が決まっているとき

particleSystem.addLifeTimeGradient(0, 0.5); //初期のパーティクルはLife time 0.5
particleSystem.addLifeTimeGradient(1, 0); // 最後のパーティクルはLife time 0

第一引数の0は、最初。1は終わりの時を意味します。

乱数をとりたい場合

particleSystem.addLifeTimeGradient(0, 0.5, 0.8);
particleSystem.addLifeTimeGradient(1.0, 0, 0.1);

このように,第二引数と第三引数の間で乱数をとります

サイズ

// Size of each particle (random between...)
particleSystem.minSize = 0.1;
particleSystem.maxSize = 0.5;

このような書き方もできる

// Scale of each particle (random between...)
particleSystem.minScaleX = 0.1;
particleSystem.maxScaleX = 0.5;
particleSystem.minScaleY = 0.2;
particleSystem.maxScaleY = 0.4;

時間経過を反映した場合(要:targetStopDuration)

particleSystem.addStartSizeGradient(0, 10);
particleSystem.addStartSizeGradient(1.0, 500);

例はこちら
https://www.babylonjs-playground.com/#3NM14X#14

particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);

グラデーションもできます

particleSystem.addColorGradient(0, new BABYLON.Color4(1, 1, 1, 0));
||>
開始時、終了時設定あり
>||
particleSystem.addColorGradient(0, new BABYLON.Color4(1, 1, 1, 0));
particleSystem.addColorGradient(1.0, new BABYLON.Color4(1, 1, 1, 1));

ブレンドモード

BLENDMODE_ONEONEがデフォルトであり、blendMode指定されていない場合に使用されます。

  • BLENDMODE_ONEONE -色は結果に影響を与えるアルファなしで追加されます
  • BLENDMODE_STANDARD- カラーは、パーティクルのアルファを使用して追加されます(つまり、カラー(1-アルファ)+パーティクルカラーアルファ)
  • BLENDMODE_ADD -色が追加されますが、粒子の色のみが粒子のアルファを使用します(つまり、色+ particleColor *アルファ)

例はこちら
https://www.babylonjs-playground.com/#MX2Z99#8

  • BLENDMODE_MULTIPLY-色が乗算され、(1-アルファ)に追加されます(つまり、色*パーティクルカラー+ 1-アルファ)

例はこちら
https://playground.babylonjs.com/#KUDH9F#1

  • BLENDMODE_MULTIPLYADD- BLENDMODE_MULTIPLY後に BLENDMODE_ADD

例はこちら(スペースキーを押すと爆発表現のパーティクルが放出されます)
https://www.babylonjs-playground.com/#VS5XS7#0

rate

rateは1秒あたりのパーティクルの放出数を設定します

f:id:hollywis:20200709125218p:plain

後ほど、設定値を手動設定もできます

particleSystem.manualEmitCount = 300;

時間経過を考慮したGradient設定もできます

particleSystem.addEmitRateGradient(0, 10);
particleSystem.addEmitRateGradient(1.0, 500);

例はこちら
https://www.babylonjs-playground.com/#3NM14X#0

放出方向

2つの方向を指定できます。

一方向のみを指定した場合、パーティクルは指定された一般的な方向にランダムに放出されます。

2つ指定されている場合、パーティクルは2つの方向の間を移動します。

particleSystem.direction1 = new BABYLON.Vector3(-7, 8, 3);
particleSystem.direction2 = new BABYLON.Vector3(7, 8, -3);

重力

//Set the gravity of all particles (not necessarily down)
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);

回転

パーティクルのZ軸を中心として、角速度の範囲をラジアン/秒で定義できます。

particleSystem.minAngularSpeed = 0;
particleSystem.maxAngularSpeed = Math.PI;

次のように初期回転角度も定義できます

particleSystem.minInitialRotation = 0;
particleSystem.maxInitialRotation = Math.PI;

速度

放出するパーティクルのパワーと全体的なモーション速度の範囲を定義できます

0.01がデフォルト。(更新が速い=アニメーションが速い)

particleSystem.minEmitPower = 1;
particleSystem.maxEmitPower = 3;
particleSystem.updateSpeed = 0.005;

Gradient設定で徐々に速度を変えることもできます

詳しくは例をどうぞ
https://www.babylonjs-playground.com/#3W04PW#0は

速度リミット

時間の経過に伴う速度の制限を定義できます。

制限に達した場合、速度に係数が適用されます。

particleSystem.addLimitVelocityGradient(0, 0.5);
particleSystem.addLimitVelocityGradient(1.0, 3);

例はこちら

https://www.babylonjs-playground.com/#9GBBPM#2

抗力係数

空気摩擦をシミュレートするために使用されます。

たとえば、ドラッグ係数が0.8に設定されている場合、粒子の方向の20%だけが粒子の位置に追加されます。

particleSystem.addDragGradient(0, 0.5);
particleSystem.addDragGradient(1.0, 3);

例はこちら

https://www.babylonjs-playground.com/#BDW3BF#0

整列

例はこちら
https://www.babylonjs-playground.com/#EV0SEQ

このようんy軸を揃えて整列させると

system.billboardMode = BABYLON.ParticleSystem.BILLBOARDMODE_Y;

こんな感じで湯気を表現できる
https://www.babylonjs-playground.com/#B9HKG0#0

ノイズテクスチャ

なんかいろいろできるっぽいです

https://www.babylonjs-playground.com/#R1JWLA#3

まとめ

パーティクルシステムを用いて、様々なパーティクル表現を学びました。

パーティクルのエミッタ(放出元)の設定や、パーティクルの放出方向、色、ブレンドモード、速度、数、重力設定などなど、事細かに設定できることがわかりました。

ここでは紹介しませんでしたがパフォーマンスに問題がある際には、WebGL2を用いたパーティクル作成機能などもあるので、ドキュメントを読んでみてください。

次回は、環境設定に入ります

Receive the latest news in your email
Table of content
Related articles