three.jsでふわふわでピカピカなパーティクルを作ってみました!


はじめに

初めての three.js でパーティクルを作ったので、Qiita で初めての記事を投稿してみます。
three.js を学び始めたのはここ1カ月くらいな超ド級の初心者です。

経緯

上記で書いた通り超ド級初心者の私ですが、学び始めて約1カ月が経ったところで、
いままで学んだことのアウトプットとして、自分が大好きなパーティクルを作成しました。

パーティクル自体は専門学生時代に卒業制作の作品で、パーティクルを作るのに特化したとあるライブラリを利用しつつ作った経験があり、モワモワしててフワフワで、時にはシャッキシャキで、とにかく視覚を楽しませてくれるところが大好きです。

成果物

私は英語がまったくもって出来ないので(致命的)、ググって出てきた「fluff(ふわふわ)」と「glitter(ピカピカ)」の単語を合わせて「fluffs-glitters」という名前をこのパーティクルに授けました。

fluffs-glitters

See the Pen fluffs-glitters by Hinano Utsumi (@UtmHnn) on CodePen.


パーティクルのデータ構造

  • mesh (three.js のメッシュ)
  • xDirection (メッシュの横軸方向の制御プロパティ)
  • yDirection (メッシュの縦軸方向の制御プロパティ)
  • xMoveSpeed (メッシュの横軸方向への速度制御プロパティ)
  • yMoveSpeed (メッシュの縦軸方向への速度制御プロパティ)
  • lifeCount (メッシュが画面に表示される寿命)

meshを 500 個生成して、画面中央から上下左右の外枠方向に向かって放射状に拡散します。
メッシュの大きさとスピードはランダムな値で排出され、opacityの値は、画面中央から離れるにつれて低い値になります。

パーティクルの挙動

function updateCircles () {
  for (let i = 0; i < circles.length; i++) {
    circles[i].mesh.material.opacity -= circles[i].lifeCount

    if (circles[i].mesh.material.opacity <= 0) {
      circles[i].mesh.position.x = -0.5 + Math.random() * 1
      circles[i].mesh.position.y = -0.5 + Math.random() * 1
      circles[i].mesh.material.opacity = 1.0
    }

    circles[i].mesh.position.x += circles[i].xMoveSpeed * (circles[i].xDirection ? 1 : -1)
    circles[i].mesh.position.y += circles[i].yMoveSpeed * (circles[i].yDirection ? 1 : -1)
  }
}

描画フレームごとにメッシュを透過していき、opacityの値が 0 になったら、メッシュの座標を初期値にし、opacityを 1 に戻します。このようにメッシュの再利用を行うことで、必要最低限の数の描画で済ませています。

パーティクルの加算合成


opacity: 0.7,
blending: THREE.AdditiveBlending

メッシュにopacityblendingを設定して、透過させ加算合成を行うことで、光っぽさを出しています。

感想

当初の自分は、というか今の自分も、JavaScript の基礎も学びつつ three.js を学習している最中なので、特別キレイなコードを書いたり、機能的な構造になっているプログラムを作ることは、まだとても難しいです。

自分が頭の中でイメージした表現と差分の無いアウトプットが出来るようになることを目指してこれからも学習したことをアウトプットしながら、力をつけていきたいです。