Skip to content
Go back

要約「MH:W | GPU Particle - モンスターハンター:ワールドにおけるGPU Particleの実装」

· Updated:

[Yoneyama 2018Yoneyama, T. 2018. MH:W | GPU Particle - モンスターハンター:ワールドにおけるGPU Particleの実装. Game Creators Conference. https://www.docswell.com/s/CAPCOM_RandD/Z7DPJK-2022-07-15-133910.]

slides

方針#

  • 可読性は最重要
  • CPUに余裕がないので、Dispatchを少なく
  • GPUの並列性を阻害したくないので、アトミックをなしに

要素#

  • エフェクトは任意の数のエミッタを持つ
  • エミッタは任意の数のアイテムを持つ
    • 速度、寿命、座標変換、などの種類がある

構造#

  • Emitter Table (CPU→GPU):
    • 有効なエフェクトの配列
    • Emitter Headerへのインデックスを持つ
  • Emitter Header (CPU→GPU):
    • 間接参照のための値の配列
    • EmtBinHead:Emitter Binaryへのオフセット
    • PtBinHead:Particle Binaryへのオフセット
    • PtIdxHead:Particle Index Listへのオフセット
    • PtSize:Particle Binaryでの1要素のサイズ
  • Emitter Binary (CPU→GPU):
    • エミッタごとに、共通データをヘッダに持ち、その下にアイテムの配列を持つ
    • 共通データは、どのアイテムが有効かのビットセット、などを持つ
  • Particle Header:
    • Alive:パーティクルが生存中かのフラグ
    • EmitterID:エミッタの番号
    • Index:パーティクルの番号
    • Depth:深度値
  • Particle Index List:
    • Particle Headerへのインデックスの配列
    • 生存中、消失中、未使用、の順で連続する
  • Particle Binary:
  • Emitter Range:
    • エミッタごとのParticle Headerのスパンを持つ配列
    • 生存と非生存の2つ分
  • Emitter Data:
    • エミッタごとの、発生するパーティクルのParticle Headerへのスパン、生存中の数、を持つ

処理#

  • 初期化(GPU):初回のみ一度だけ行う
    • パーティクル総数を0クリアする
    • Particle HeaderをInvalidにする
  • エフェクトの生成(CPU):
    • Emitter Tableに要素を追加して、指定のEmitter Headerの要素を確保
    • Emitter Binaryの末尾に割り当てた領域をEmitter Headerに記録
    • Particle Binaryの末尾に割り当てた領域をEmitter Headerに記録
  • エフェクトの更新(CPU):
    • エミッタを更新
      • 親の移動値の反映、など
    • アイテムを更新
      • パーティクルを出す数の決定、外部パラメータの反映、タイムライン制御、など
    • エミッタ用データの更新
      • Emitter Headerを介して、Emitter Binaryの指定の領域にアイテムを書き込む
  • エフェクトの更新(GPU):
    • Begin Update
      • パーティクルの総数を、前フレームの総数と現フレームの予定数の総和として、指定の最大数でクランプしてから書き出す
    • Fill Unused Index
      • 新規のエミッタが割り当てたParticle Index Listの末尾領域をInvalidで埋める
    • Spawn Particles
      • 新しく発生(spawn)するパーティクル数を決め、Particle Headerの末尾に割り当てる
      • Emitter Rangeをゼロ初期化
    • Initialize Particles
      • Particle Index Listに新しく発生したパーティクルの分を追記
      • Particle Headerにデータを書き込む
      • Dispatch(エミッタ数, 1, 1)
    • Update Particle
      • Particle Headerを辿って、パーティクルをアイテムに沿って動かす
      • 1スレッド、1パーティクル
      • シェーダはuber
    • Bitonic Sort
      • 生存フラグ(1bit)、エミッタID(13bits)、深度値(32bits)をキーとしてParticle Headerをソートする
      • 深度値は透明物の前後関係を正しく描画するために必要
      • Bitonic Sortなのは著者都合
    • Range Particles
      • Emitter Rangeを構築する
      • スレッドごとに要素2つ取り出してEmitterIDや生存フラグを比較する
      • 0スタートと1スタートで2回行う
    • Terminate Particles
      • 消滅したパーティクルのParticle Index Listを無効化する
    • Build Emitter Draw Args
      • 実際のパーティクル数でEmitter Dataを更新
      • Draw Indirect用引数をエミッタごとに構築
    • Build Primitive
      • パーティクルから頂点データを構築する
      • 1スレッド、1パーティクル
      • ビルボードとリボンに対応