【Three.js】パーティクルを作る

JavaScript,Three.js

作ったものは小出しにしていく事にしました。
全部まとめて書こうとすると雑になるから。

パーティクルとは

細かい粒子のこと。これを大量に作れば星空とかを表現することができます。

今さら感はありますが、良いのができたので記事として残しておきます。

作ったもの

こういうの好きだわぁ。動く方向を変えるだけで印象もガラっと変わりますね。

作りかた

Three.jsでパーティクルを作るならSpriteクラスかPointsクラスを使うのが一般的なようです。どちらのクラスを使うか、その使い分けの基準はよく分かりません。好きな方で良いんじゃないでしょうか。今回はSpriteを使いました。

というワケで、まずはSpriteクラスを継承した独自のクラス「Kira」クラスを作ります。

//*************************************************************
// キラキラクラス
//*************************************************************
class Kira extends THREE.Sprite {
  constructor(mat, pos, life, speed) {
    super(mat);
    this.scale.set(0.5, 0.5, 0.5);
    this.startPos = pos;
    this.startLife = life;  
    this.position.copy(pos);
    this.life = life;
    this.speed = speed;
  }

  update() {
    this.position.y += this.speed;
    this.material.opacity -= (1 / this.startLife);
    this.life -= 1;
    if (this.life <= 0) {
      this.position.y = this.startPos.y;
      this.material.opacity = 1;
      this.life = this.startLife;
    }
  }
}

コンストラクタには、親であるSpriteクラスに渡すマテリアルの他に、pos(初期位置)、life(ドラクエでいうHP)、speed(速度)を渡してあげます。

そしてupdateメソッド。こいつを描画ループ内から呼ぶことでパーティクルを動かすことができます。

updateメソッドをざっくり解説

ライフが0になるまで

  • y軸のプラス方向に動かす
  • だんだん透明にする
  • ライフを減らす

ライフが0になったら

  • 初期位置に戻す
  • クッキリさせる
  • ライフを満タンにする

自画自賛ポイント

今日の自画自賛ポイントはコチラ↓。

this.material.opacity -= (1 / this.startLife);

不透明度の設定をしているところですね。不透明度は0~1で設定するので、"1 / this.startLife"分ずつopacityから引いてあげれば、ライフが0になったタイミングで完全に透明にする事ができるという仕組みです。

こういうのを思いつけるかどうかで、モテるかモテないかも決まってきます。

キラキラを作る

先程作ったKiraクラスを使ってキラキラを作っていきます。作ったキラキラは配列に入れておきましょう。そうしないと描画ループ内でupdateメソッドを呼ぶ時に困ってしまいます。

//*************************************************************
// キラキラを作成
//*************************************************************
function createKira() {
  
  for (let i = 0; i < 500; i++) {
    
    // 初期位置
    const x = Math.random() * (20 - -20) + -20;
    const y = 0;
    const z = Math.random() * (20 - -20) + -20;
    const vec = new THREE.Vector3(x, y, z);
    
    // ライフ
    const life = Math.floor(Math.random() * (400 - 40)) + 40;

    // スピード
    const speed = Math.random() * (0.15 - 0.05) + 0.05;

    // マテリアル
    const mat = new THREE.SpriteMaterial({map: particle});

    // キラキラ
    const kira = new Kira(mat, vec, life, speed);

    scene.add(kira);
    kiras.push(kira);
  }
}

今回は500個のキラキラを作っています。初期位置、ライフ、スピードは全てランダムにしてあります。この辺りは好みになると思うので、色々と変えてみると良いでしょう。

描画ループ内でupdateメソッドを呼ぶ

//*****************************************
// 描画
//*****************************************
function renderScene() {
  requestAnimationFrame(renderScene);
  webGLRenderer.render(scene, camera);

  const clock = new THREE.Clock();
  const delta = clock.getDelta();
  trackballControls.update(delta);

  // キラキラを動かす
  for (let i = 0; i < kiras.length; i++) {
    kiras[i].update();
  }
}

配列に入れておいたおかげで、updateメソッドの呼び出しが簡単ですね。

あとがき

こういうの作るの楽しいですね。頑張れば炎みたいなのも作れそうです。今回は以上です。ありがとうございました。

おしゃれ度

★★☆☆☆

Posted by ナカタ