Art-6: エフェクト・VFX仕様
Rift Survivors の全ビジュアルエフェクト(VFX)の色・形状・持続時間・実装方針を定義する。 シンセウェーブ / サイバーパンクのネオンカラーと、PS1 ローポリの"手触り"を両立させる。
設計原則
- ネオン発光を核に: UnrealBloomPass で映える発光色をエフェクトの主役に据える
- 短く鋭く: 大量の敵を殲滅するゲームなので、個々のエフェクトは 0.2〜0.6 秒で収束
- モバイル 30fps 死守: パーティクル数・ポストプロセスは必要に応じて自動削減
- 手続き生成中心: テクスチャ依存を避け、Points + 頂点色 / シェーダで描画
用語定義
| 用語 | 定義 |
|---|---|
| パーティクル | THREE.Points + BufferGeometry で描画される点群 |
| バースト | 短時間に一斉放射されるパーティクル(攻撃ヒット等) |
| トレイル | 移動体が残す尾状のパーティクル(弾丸等) |
| シェイク | カメラを短時間振動させる演出 |
| フラッシュ | 画面全体 or 部分の瞬間的な明滅 |
| グロウ | 発光体の周囲に広がる光(Bloom 由来) |
共通カラーパレット
VFX で使用する基本色。HEX 表記。
| 用途 | 色名 | HEX | 備考 |
|---|---|---|---|
| ネオン属性 | ネオンピンク | #ff2d75 | 攻撃系の基本 |
| ネオン属性(強) | ホットマゼンタ | #ff6bb5 | 弱点ヒット時 |
| データ属性 | サイバーシアン | #00f0ff | 遠距離攻撃・脱出ポータル |
| データ属性(強) | アイスブルー | #a0f8ff | 弱点ヒット時 |
| グリッチ属性 | エレクトリックパープル | #a855f7 | 敵属性・リベンジ(gameplay/combat.md:192 準拠) |
| グリッチ属性(強) | ネオンバイオレット | #c77dff | 弱点ヒット時 |
| 汎用グロウ | ピュアホワイト | #ffffff | フラッシュ・ヒット芯 |
| クリティカル | ネオンイエロー | #ffd400 | 黄色 + 赤縁取り |
| レア(Common) | グレー | #9ca3af | ドロップ光柱 |
| レア(Rare) | ブルー | #3b82f6 | ドロップ光柱 |
| レア(Epic) | パープル | #a855f7 | ドロップ光柱 |
| レア(Legendary) | ゴールド | #ffcc00 | ドロップ光柱(gameplay/equipment.md:64 準拠) |
パーティクル予算
パフォーマンス制約(PC 60fps / モバイル 30fps)を守るためのグローバル上限。
同時描画パーティクル数の上限
| プラットフォーム | 画面内合計上限 | 新規発生の制限 |
|---|---|---|
| デスクトップ | 300 | 超過時は古い順に削除 |
| モバイル | 100 | 超過時は古い順に削除、発生確率 0.6x |
| ロースペック自動判定 | 60 | パーティクル非必須エフェクトを抑制 |
カテゴリ別の最大パーティクル数(1 エフェクト発生あたり)
| エフェクトカテゴリ | デスクトップ | モバイル | 優先度 |
|---|---|---|---|
| 攻撃ヒット(通常) | 12 | 6 | 高 |
| 攻撃ヒット(クリティカル) | 24 | 10 | 高 |
| 弱点ヒット | 40 | 16 | 高 |
| 武器トレイル(単発) | 20 | 8 | 中 |
| 被弾フラッシュ | 0(ポストプロセスのみ) | 0 | 高 |
| ドロップ光柱 | 30 | 12 | 中 |
| レベルアップ放射 | 80 | 30 | 高 |
| ポータル出現(リフト) | 60 | 24 | 高 |
| ポータルアイドル(ループ) | 30 | 12 | 中 |
| 敵消滅バースト | 15 | 6 | 低 |
| 環境アンビエント | 20 | 0(モバイル無効) | 最低 |
自動削減ルール
// モバイル/低スペック時の削減ロジック(疑似コード)
if (isMobile || gpu.tier < 2) {
particleCount = Math.floor(particleCount * 0.4);
trailLength = Math.floor(trailLength * 0.5);
enableAmbientVFX = false;
}
// 画面内パーティクル上限超過時
if (scene.activeParticles >= MAX_PARTICLES) {
killOldestParticles(scene.activeParticles - MAX_PARTICLES + emitCount);
}攻撃エフェクト(武器カテゴリ別)
通常攻撃・コンボフィニッシュで発生するエフェクト。武器カテゴリによって形状が異なる。 詳細な当たり判定は 戦闘システム を参照。
ソード: 斬撃トレイル
扇形のスラッシュ軌跡。近接の爽快感を演出。
| 項目 | 値 |
|---|---|
| 形状 | 扇形の半透明メッシュ(PlaneGeometry + カスタムシェーダ) |
| 色 | 武器属性色 + 芯 #ffffff |
| 持続時間 | 0.2 秒(コンボ1・2段目)/ 0.35 秒(3段目)/ 0.5 秒(フィニッシュ) |
| 軌跡の幅 | 半径 2.0 units、角度 90° |
| パーティクル | 先端から 12 粒(フィニッシュ時 24 粒)を接線方向に飛散、寿命 0.3 秒 |
| アニメーション | opacity を 1.0 → 0.0 にフェード、scale を 0.8 → 1.1 に拡張 |
| カメラシェイク | フィニッシュ時のみ: 強度 0.15、時間 0.1 秒 |
スピア: 突きエフェクト
前方に伸びる矩形ビーム + 貫通パーティクル。
| 項目 | 値 |
|---|---|
| 形状 | 矩形(幅 0.8 × 長さ 3.5 units)のビームメッシュ |
| 色 | 武器属性色、中心に #ffffff のハイライト |
| 持続時間 | 0.25 秒 |
| パーティクル | 突き抜け時に接触点から 8 粒を垂直方向に飛散、寿命 0.25 秒 |
| アニメーション | ビームを手前から前方へスケール 0.0 → 1.0(0.1 秒)、その後フェードアウト |
| 残像 | 前フレームのビームを opacity 0.3 で 2 フレーム残す |
スタッフ: 魔法弾(ビーム + 着弾)
遠距離の単体弾。発射・飛翔・着弾の3段階。
| 段階 | 形状 | 持続時間 | 備考 |
|---|---|---|---|
| 詠唱(発射予備) | 武器先端に属性色のグロウ球(半径 0.2) | 0.15 秒 | スケール 0.3 → 1.0 |
| 飛翔 | 弾本体(半径 0.3 の球)+ トレイル(20 粒、寿命 0.2 秒) | 距離依存(最長 8.0 units) | 等速直進 |
| 着弾 | 放射状パーティクル 12 粒(弱点時 40 粒)+ リング状衝撃波(半径 0.5 → 1.5) | 0.3 秒 | リングは opacity 1 → 0 |
ガン: マズルフラッシュ + 弾道
高速連射。個々のエフェクトは最小限、弾道は細い光線。
| 項目 | 値 |
|---|---|
| マズルフラッシュ | 銃口に放射状グロウ(半径 0.4、#ffd400 + 属性色)、持続 0.08 秒 |
| 弾道 | 細い矩形(幅 0.2 × 長さ 12.0 units)、opacity 1 → 0 を 0.12 秒 |
| トレイルパーティクル | 弾道上に 6 粒、寿命 0.15 秒(モバイルは省略) |
| カメラシェイク | 連射時は弱シェイク強度 0.05、時間 0.05 秒(累積しないよう制限) |
// ガンマズルフラッシュ実装例
const flash = new THREE.Points(
buildMuzzleGeometry(), // 半径 0.4 の放射状配置
new THREE.PointsMaterial({
size: 0.15,
color: 0xffd400,
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false,
})
);
scene.add(flash);
gsap.to(flash.material, { opacity: 0, duration: 0.08, onComplete: () => scene.remove(flash) });属性エフェクト
武器・スキル・敵・弾丸に属性(ネオン / データ / グリッチ)が付与されている場合の追加演出。 属性ルールは 戦闘システム #属性 を参照。
ネオン(ピンク光)
| 項目 | 値 |
|---|---|
| 基本色 | #ff2d75 |
| 付与演出 | 攻撃判定周囲にピンクのオーラ(半径 +20%)、パーティクルは星型分布 |
| 残光 | ヒット点に opacity 0.6 のピンクグロウが 0.3 秒残る |
| サウンド同期 | 高音の"キラン"系 SE に合わせてフラッシュ |
データ(シアン粒子)
| 項目 | 値 |
|---|---|
| 基本色 | #00f0ff |
| 付与演出 | 直線的な粒子(ドット)が攻撃軌跡上に等間隔で並ぶ(8 粒) |
| 残光 | 矩形の"データストリーム"が 0.4 秒流れる(MeshBasicMaterial + スクロール UV) |
| サウンド同期 | デジタル"ピピッ"系 SE |
グリッチ(紫ノイズ)
| 項目 | 値 |
|---|---|
| 基本色 | #a855f7(gameplay/combat.md:192 準拠) |
| 付与演出 | ヒット時に画面の該当領域のみ RGB 分離ノイズ(3x3 px 程度、持続 0.08 秒) |
| 残光 | ランダムな小矩形のフリッカー(6 個、寿命 0.15 秒) |
| サウンド同期 | 低音の"ザザッ"ノイズ系 SE |
ヒットエフェクト(通常)
敵への攻撃がヒットした瞬間の汎用演出。
| 要素 | 仕様 |
|---|---|
| フラッシュ | 敵モデルに emissive を一瞬 #ffffff に(加算合成、強度 1.5、持続 0.05 秒) |
| パーティクルバースト | 放射状 12 粒(クリティカル 24 粒)、攻撃方向の逆側に散る、寿命 0.25 秒 |
| ヒットストップ | 30ms(通常)/ 60ms(クリティカル)。詳細は 戦闘システム #ヒットストップ |
| ダメージ数字 | 戦闘システム #ダメージ数字の表示 参照。上方 0.8 秒で浮遊消失 |
| カメラシェイク | 通常攻撃は無し。クリティカルのみ強度 0.08、時間 0.08 秒 |
ダメージ数字の追加ビジュアル
| タイプ | 色 | フォントサイズ | 追加演出 |
|---|---|---|---|
| 通常 | #ffffff | 16px | フワッと浮上 |
| クリティカル | #ffd400 + 縁取り #ff2d75 | 24px | 出現時にスケール 0.5 → 1.3 → 1.0 |
| 属性有利 | 属性色(ピンク/シアン/パープル) | 18px | 属性色のグロウ付き |
| 回復 | #4ade80 | 16px | + プレフィックス |
| MISS | #9ca3af | 14px | 小さく揺れてフェード |
弱点ヒットエフェクト
通常ヒットより派手な専用演出。弱点属性が当たった時に発生。 効果倍率は ミッション #弱点の役割 を参照。
| 要素 | 仕様 |
|---|---|
| バースト | 放射状 40 粒(モバイル 16 粒)、属性強色(ネオン #ff6bb5 / データ #a0f8ff / グリッチ #c77dff) |
| リング衝撃波 | 水平リング半径 0.3 → 2.0 units、opacity 1 → 0、持続 0.4 秒 |
| フラッシュ | 画面全体に属性色のビネット、opacity 0.25 → 0、持続 0.15 秒 |
| クリスタルシャード | 属性結晶風の6角形パーティクルが 6 個飛散、重力付き、寿命 0.6 秒 |
| ダメージ数字 | フォントサイズ 28px、属性色の二重グロウ(text-shadow 多段) |
| カメラシェイク | 強度 0.2、時間 0.15 秒 |
| 専用 SE | 「カキィン」系のヒット音を BGM ダッキング 0.1 秒と同期再生 |
| ヒットストップ | 70ms(通常より長め) |
ドロップエフェクト
敵撃破・宝箱からの武器・アイテムドロップ時の演出。レアリティで色・量・持続時間が変化。
光柱(Beam of Light)
ドロップ位置から垂直に立ち上がる光の柱。遠くからでも視認可能。
| レアリティ | 色 | 光柱高さ | パーティクル量 | 持続時間 | Bloom 強度 |
|---|---|---|---|---|---|
| Common | #9ca3af | 2.0 units | 6 粒 | 8 秒 | 0.6x |
| Rare | #3b82f6 | 3.0 units | 14 粒 | 12 秒 | 1.0x |
| Epic | #a855f7 | 3.5 units | 20 粒 | 15 秒 | 1.2x |
| Legendary | #ffcc00 | 4.5 units | 30 粒 | 30 秒 | 1.5x |
| 項目 | 仕様 |
|---|---|
| 光柱形状 | 円柱メッシュ(半径 0.3)+ 加算合成、上に向かってフェード |
| 回転パーティクル | 光柱周囲を螺旋状に上昇(ワールド Y 軸周り、角速度 1.2 rad/s) |
| 下部リング | 足元に半径 0.6 のリング(レアリティ色)、opacity 0.5 で脈動(0.8 秒周期) |
| 出現演出 | スケール Y 軸のみ 0.0 → 1.0 を 0.3 秒、落下位置に小バースト 12 粒 |
| 消滅演出 | 持続時間経過後、opacity 1 → 0 を 0.5 秒でフェード |
Legendary 特別演出
Legendary ドロップ時のみ、出現時に画面全体がゴールドにフラッシュ(#ffcc00、opacity 0.3 → 0、0.4 秒)し、専用 SE を再生する。レアリティ定義は gameplay/equipment.md:61-75(Common/Rare/Epic/Legendary の 4 段階のみ、Uncommon は存在しない)を参照。
レベルアップエフェクト
ダンジョン内レベルアップ時に発生。10 秒のスキル選択 UI 表示中も見え続ける必要がある。
タイムライン
| 時間 | 内容 |
|---|---|
| 0.00s | プレイヤー足元に白フラッシュ(半径 2.0 → 4.0、opacity 1 → 0)、0.2 秒持続 |
| 0.00s | カメラズームインを軽く(FOV 50 → 47、0.3 秒)、ヒットストップ 80ms |
| 0.05s | 放射状パーティクル 80 粒(モバイル 30 粒)が全方位に飛散、寿命 0.8 秒 |
| 0.15s | プレイヤーモデルに全身グロウ(emissive #ffd400、強度 0.8、脈動 0.6 秒周期) |
| 0.30s | 下から上に上昇する光の筋(6 本、#ffd400、高さ 3 units、0.6 秒で消失) |
| 0.50s | リング状衝撃波が水平に広がる(半径 0.5 → 4.0、0.5 秒) |
| 1.00s | パーティクル放射が収束、全身グロウは 継続 |
| 1.00s〜10.00s | プレイヤーの全身グロウが 維持(強度 0.8 で脈動)、周囲に弱パーティクル 10 粒/秒を継続放出 |
| 10.00s | スキル選択完了と同期してグロウがフェード(0.5 秒) |
設計意図
スキル選択 UI(10 秒カウントダウン)が表示されている間、プレイヤーが"強化中"であることを常時可視化する。 スキル選択完了時に UI と同期してエフェクトが収束することで、ゲーム復帰の合図にもなる。
| パラメータ | 値 |
|---|---|
| グロウ脈動周期 | 0.6 秒(sin 波) |
| 継続パーティクル放出レート | 10 粒/秒(モバイル 4 粒/秒) |
| 継続パーティクル色 | #ffd400 + 白芯 |
| サウンド | レベルアップファンファーレ(1.5 秒)+ ループ環境音(10 秒) |
ポータルエフェクト
全ポータル共通の基本仕様と、タイプ別のバリエーション。 ポータルの機能仕様は ミッション #脱出ポータル を参照。
共通: リフトオープン(出現)
Ratchet & Clank 風の次元の裂け目演出。
| 時間 | 内容 |
|---|---|
| 0.00s | ポータル位置に白い光点(半径 0.05、brightness 500%) |
| 0.10s | 光点から垂直に亀裂が走る(高さ 0.5 → 2.5 units)、縁はポータル色に発光 |
| 0.30s | 亀裂の幅が拡大(幅 0.05 → 0.4 units)、パーティクル 30 粒が両側に飛散 |
| 0.50s | 裂け目からリング状衝撃波放出(半径 0.3 → 2.0、0.4 秒で消失) |
| 0.70s | 裂け目内部にエネルギー渦(半透明、回転 1 rad/s)が出現 |
| 1.00s | 最終サイズに到達(幅 1.5 × 高さ 2.5 units)、アイドル状態へ |
共通: ワープトンネル(通過中)
プレイヤーがポータルに入って別シーンへ遷移する瞬間の演出。1 秒のトンネル効果。
| 項目 | 仕様 |
|---|---|
| 形状 | 円筒形のトンネル内部を高速移動するカメラ視点 |
| 色 | ポータルタイプ色のライン流れ(等速 15 units/秒で手前に流れる) |
| 持続時間 | 1.0 秒 |
| クロマティックアベレーション | トンネル中のみ強度 +0.008(デスクトップ) |
| カメラ FOV | 50 → 80 → 50(膨張→収縮) |
| フェード | 開始 0.1 秒で突入フラッシュ(#ffffff、0.2 秒で消失)、終了時に目的地シーンへ 0.15 秒クロスフェード |
共通: 消滅(使用後 or 時間切れ)
| 時間 | 内容 |
|---|---|
| 0.00s | パーティクル放出停止、エネルギー渦が減速 |
| 0.20s | 裂け目の幅が縮小(1.5 → 0.05 units) |
| 0.40s | 光点が残る(brightness 300%) |
| 0.50s | 光点が弾けて消滅(小バースト 8 粒、寿命 0.3 秒) |
ポータルタイプ別バリエーション
| タイプ | メインカラー | アイドル演出 | 備考 |
|---|---|---|---|
| ミッションポータル | #a855f7(バイオレット) | ゆるやかな紫の渦、パーティクル 15 粒常駐 | ロビー定常配置 |
| Vibeverse ポータル | レインボーグラデーション(#ff2d75 → #ffd400 → #00ff88 → #00f0ff → #a855f7 のループ、周期 4 秒) | 多色の渦 + グリッチフリッカー(0.5 秒間隔)、Vibeverse ハブ性を象徴する虹色 | カットイン起動トリガー(詳細色は docs/art/color-script.md と整合) |
| 脱出ポータル | #00f0ff(シアン) | 上昇する光の粒子 30 粒、浮遊感強調 | 60 秒後に不安定化演出追加 |
| リベンジポータル | #ff1744(赤) | 警告パーティクル 20 粒、脈動する赤いリング(0.8 秒周期) | ロビー常設、敗北時のみ出現 |
脱出ポータル: 不安定化演出(60 秒後)
| 時間経過 | 演出 |
|---|---|
| 0〜60s | 通常アイドル |
| 60〜80s | パーティクルが赤みがかり(#00f0ff → #ff5577 に徐々に変化)、画面に弱シェイク(強度 0.05) |
| 80〜90s | 激しくフリッカー、シェイク強度 0.15、警告 SE ループ |
| 90s | 崩壊演出 0.5 秒 → シーン強制終了 |
Vibeverse ポータル: カットイン連携
Vibeverse ポータル使用時は、ワープトンネルの代わりに カットイン演出 が再生される。 ポータル自体の消滅演出はカットイン Phase 1 の「リフトオープン」と同期する。
カットインエフェクト
カットイン演出の全フレーム仕様は カットイン演出 を参照。ここでは VFX 系の補足のみ。
カットイン中の Three.js シーン処理
| 項目 | 対応 |
|---|---|
| ゲーム本体の描画 | renderer.render を停止、最後のフレームを背景に CSS 合成 |
| パーティクルシステム | 全て一時停止(active = false) |
| ポストプロセス | ブルームのみ有効、クロマティックアベレーションは 強度 2.0x に一時増幅 |
| カメラ | 位置固定、回転・追従停止 |
グリッチノイズレイヤー
| 項目 | 値 |
|---|---|
| 発生タイミング | カットイン Phase 1(0.10s〜0.50s)、Phase 4(2.30s〜2.35s) |
| 実装 | <canvas> 2D API でフレーム毎にランダムノイズ生成、mix-blend-mode: screen |
| 強度 | opacity 0.15(Phase 1)/ opacity 0.35(Phase 4) |
| 解像度 | ノイズテクスチャ 128x128(更新 30fps) |
スキャンライン
| 項目 | 値 |
|---|---|
| 実装 | CSS repeating-linear-gradient |
| 色 | rgba(255, 255, 255, 0.04) / transparent の 2px 幅縞 |
| 常時表示 | カットイン全フェーズ |
| モバイル | 省略可(prefers-reduced-motion or 低スペック時) |
スプリットスクリーン境界のグロウ
カットイン Phase 3 の分割線に、ネオンピンクの二重グロウ(filter: drop-shadow 多重)を重ねる。脈動周期は 1.2 秒。
被弾エフェクト(プレイヤー)
プレイヤーが敵攻撃を受けた瞬間の演出。
| 要素 | 仕様 |
|---|---|
| 画面フラッシュ | 画面四辺に赤ビネット(#ff1744、opacity 0.5 → 0、持続 0.2 秒) |
| カメラシェイク | 強度 0.15、時間 0.15 秒 |
| プレイヤーモデル | 赤点滅 8Hz(α値 0.3 ↔ 1.0)、I-Frame の 0.5 秒間 |
| パーティクル | 被弾位置から 10 粒(赤)、寿命 0.3 秒 |
| BGM ダッキング | 音量 -6dB、0.15 秒 |
低 HP 時(HP < 25%)は画面四辺の赤ビネットが 常時表示(opacity 0.3 脈動)。
敵消滅エフェクト
敵を撃破した時の演出。属性によって色が変わる。
| 要素 | 仕様 |
|---|---|
| 破片バースト | 敵カラーの立方体パーティクル 15 粒(モバイル 6 粒)、重力付き、寿命 0.5 秒 |
| フラッシュ | 敵中心に属性色のグロウ球(半径 0.3 → 1.0、opacity 1 → 0、0.2 秒) |
| ボクセル分解 | エリート以上は敵モデルを 20〜40 個のボクセルに分解して散らす(0.6 秒で消失) |
| ボス消滅 | 専用演出(後述) |
ボス消滅演出
| 時間 | 内容 |
|---|---|
| 0.00s | ボスが白くフラッシュ、ヒットストップ 500ms |
| 0.50s | 全身から属性色の光線が放射(12 本、長さ 5 units、0.8 秒) |
| 1.00s | ボスがボクセル分解(100 粒)、同時に画面全体がフラッシュ(#ffffff 0.3 秒) |
| 1.50s | 大型リング衝撃波(半径 0.5 → 8.0 units、0.8 秒) |
| 2.00s | 消滅完了、脱出ポータルのリフトオープン開始 |
ポストプロセス設定
v1 は UnrealBloomPass のみ必須、ChromaticAberration はデスクトップのみ有効。 全体方針は スタイルガイド #ポストプロセス方針 を参照。
UnrealBloomPass
ネオン発光の視覚的な核。全デバイスで有効。
| パラメータ | デスクトップ | モバイル | 備考 |
|---|---|---|---|
threshold | 0.85 | 0.9 | ネオン色だけを発光として拾う |
strength | 0.8 | 0.5 | モバイルはコスト削減 |
radius | 0.6 | 0.4 | |
resolution | 画面解像度 × 0.5 | 画面解像度 × 0.35 | オフスクリーン RT サイズ |
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
const bloomPass = new UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
0.8, // strength
0.6, // radius
0.85 // threshold
);
composer.addPass(bloomPass);
// モバイル判定
if (isMobile) {
bloomPass.strength = 0.5;
bloomPass.radius = 0.4;
bloomPass.threshold = 0.9;
bloomPass.resolution.set(window.innerWidth * 0.35, window.innerHeight * 0.35);
}ChromaticAberration
デスクトップのみ。PS1 感・グリッチ感の演出。
| パラメータ | 値 | 備考 |
|---|---|---|
amount(通常時) | 0.003 | 画面端でわずかに RGB 分離 |
amount(被弾時) | 0.008(0.2 秒) | 被弾演出と同期 |
amount(ワープトンネル) | 0.012 | 1 秒間 |
amount(カットイン Phase 1 最大) | 0.015(0.05 秒) | 裂け目出現時 |
| モバイル | 無効 | パフォーマンス確保 |
// ChromaticAberration の最小シェーダ実装例(断片)
uniform sampler2D tDiffuse;
uniform float amount;
varying vec2 vUv;
void main() {
vec2 offset = (vUv - 0.5) * amount;
float r = texture2D(tDiffuse, vUv + offset).r;
float g = texture2D(tDiffuse, vUv).g;
float b = texture2D(tDiffuse, vUv - offset).b;
gl_FragColor = vec4(r, g, b, 1.0);
}Vignette(任意)
HP 低下時の警告表示などに使用。CSS オーバーレイで実装(ポストプロセスではない)。
| パラメータ | 値 |
|---|---|
| 色 | #000000(通常)/ #ff1744(低 HP 警告) |
| 半径 | 画面対角の 70% |
opacity | 0.2(通常)/ 0.35(被弾時)/ 0.3 脈動(HP < 25%) |
ポストプロセス処理順序
Scene
↓
RenderPass
↓
UnrealBloomPass
↓
ChromaticAberrationPass(デスクトップのみ)
↓
(FilmPass は v2 以降)
↓
OutputThree.js 実装方針
パーティクルの基本構成
THREE.Points + THREE.BufferGeometry + カスタムシェーダマテリアルをベースとする。 Sprite の大量配置は DrawCall が膨らむため避ける。
// パーティクルシステムの基本形
class ParticleBurst {
private mesh: THREE.Points;
private lifetimes: Float32Array;
private velocities: Float32Array;
constructor(count: number, color: THREE.Color, position: THREE.Vector3) {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(count * 3);
const colors = new Float32Array(count * 3);
this.lifetimes = new Float32Array(count);
this.velocities = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
positions[i * 3] = position.x;
positions[i * 3 + 1] = position.y;
positions[i * 3 + 2] = position.z;
const dir = randomDirection();
this.velocities[i * 3] = dir.x * 3;
this.velocities[i * 3 + 1] = dir.y * 3;
this.velocities[i * 3 + 2] = dir.z * 3;
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
this.lifetimes[i] = 0.25 + Math.random() * 0.1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.08,
vertexColors: true,
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false,
sizeAttenuation: true,
});
this.mesh = new THREE.Points(geometry, material);
}
update(dt: number): boolean {
const positions = this.mesh.geometry.attributes.position.array as Float32Array;
let alive = 0;
for (let i = 0; i < this.lifetimes.length; i++) {
if (this.lifetimes[i] <= 0) continue;
this.lifetimes[i] -= dt;
positions[i * 3] += this.velocities[i * 3] * dt;
positions[i * 3 + 1] += this.velocities[i * 3 + 1] * dt;
positions[i * 3 + 2] += this.velocities[i * 3 + 2] * dt;
this.velocities[i * 3 + 1] -= 5.0 * dt; // 重力
alive++;
}
this.mesh.geometry.attributes.position.needsUpdate = true;
(this.mesh.material as THREE.PointsMaterial).opacity = Math.max(0, alive / this.lifetimes.length);
return alive > 0;
}
dispose(): void {
this.mesh.geometry.dispose();
(this.mesh.material as THREE.Material).dispose();
}
}オブジェクトプール
発生頻度の高いエフェクト(ヒット・マズルフラッシュ・ダメージ数字)は Pool で再利用し、GC 負荷を削減。
class ParticlePool {
private available: ParticleBurst[] = [];
private active: Set<ParticleBurst> = new Set();
acquire(count: number, color: THREE.Color, pos: THREE.Vector3): ParticleBurst {
const p = this.available.pop() ?? new ParticleBurst(count, color, pos);
p.reset(count, color, pos);
this.active.add(p);
return p;
}
release(p: ParticleBurst): void {
this.active.delete(p);
this.available.push(p);
}
}シェーダマテリアル(必要な場合のみ)
ポータルのエネルギー渦など、頂点アニメーション or UV スクロールが必要な場合は ShaderMaterial を使用。 ただし v1 ではコンパイル時間短縮のため、シェーダ数は 最大 5 種類 までに抑える。
| シェーダ名 | 用途 | 頂点数目安 |
|---|---|---|
vortexShader | ポータル渦 | 64 |
beamShader | 光柱・ビーム | 8〜16 |
trailShader | 武器トレイル | 可変(最大 32) |
glitchShader | グリッチノイズレイヤー | フルスクリーンクアッド |
chromaticShader | ChromaticAberration | フルスクリーンクアッド |
メモリ・DrawCall 節約
| 項目 | 対応 |
|---|---|
| 敵消滅のボクセル破片 | InstancedMesh でまとめて 1 DrawCall |
| ダメージ数字 | DOM 要素(CSS transform)で Three.js 外に逃がす |
| ドロップ光柱 | 同種の光柱は InstancedMesh + インスタンス色で 1 DrawCall |
| パーティクルバースト | テクスチャなし、PointsMaterial sizeAttenuation のみ |
モバイル対応サマリー
モバイル 30fps 維持のための削減ルール総覧。
| カテゴリ | デスクトップ | モバイル | 削減根拠 |
|---|---|---|---|
| 画面内パーティクル上限 | 300 | 100 | CPU/GPU 両方を削減 |
| Bloom strength | 0.8 | 0.5 | フィルレート削減 |
| Bloom resolution | 0.5x | 0.35x | オフスクリーン RT サイズ |
| ChromaticAberration | 有効 | 無効 | シェーダ 1 パス削減 |
| カメラシェイク | 有効 | 強度 0.6x | 酔い軽減も兼ねる |
| 環境アンビエントパーティクル | 20 | 0 | 存在感不要な粒を削除 |
| 武器トレイル | 20 粒 | 8 粒 | |
| レベルアップ放射 | 80 粒 | 30 粒 | |
| ボス消滅ボクセル | 100 粒 | 40 粒 | |
| スキャンライン(カットイン) | 有効 | 有効(CSS のみ) | コストほぼゼロ |
| グリッチノイズキャンバス | 128x128 @30fps | 64x64 @15fps | 更新頻度・解像度両方削減 |
prefers-reduced-motion
ユーザー設定で prefers-reduced-motion: reduce が指定されている場合:
- カメラシェイク 全て無効
- スプリットスクリーン / グリッチ系エフェクトはフェードのみに差し替え
- レベルアップ放射はフラッシュのみに簡略化
チェックリスト(完了条件)
- [x] 全エフェクトの色(HEX)・形状・持続時間(秒)・パーティクル数が定義されている
- [x] 武器カテゴリ別(ソード / スピア / スタッフ / ガン)の攻撃エフェクトを定義
- [x] 属性(ネオン / データ / グリッチ)別の追加演出を定義
- [x] ヒット・弱点ヒット・ドロップ・レベルアップ・被弾・敵消滅を定義
- [x] ポータル 4 タイプ(ミッション / Vibeverse / 脱出 / リベンジ)の演出を定義
- [x] カットインと Three.js シーンの連携方針を定義
- [x] ポストプロセス(Bloom / ChromaticAberration)のパラメータを定義
- [x] パーティクル予算(PC 300 / モバイル 100)を定義
- [x] Three.js 実装方針(Points + BufferGeometry, Pool, Shader)を定義
- [x] モバイル削減ルールを定義
次のステップ
- Art-2: カラースクリプト(進行中)で定義されるシーン別パレットと VFX 色を整合させる
- Art-7: アニメーション でキャラクターモーションと VFX のタイミングを同期
- 実装フェーズ:
ParticlePool・VFXDirectorクラスの設計着手