『鬼武者 Way of the Sword』『モンスターハンターワイルズ』のVFXに息吹を与える「VORTEXEL」 [RE:2026 2026年10月2日登壇]

2.2K Views

November 13, 26

スライド概要

2026年10月にカプコンが開催した「CAPCOM オープンカンファレンス RE:2026」の講演資料です。

■ 講演映像(再生リスト)
https://www.youtube.com/watch?v=sHM9kl1e43E&list=PLD_N6X6tKlCM

profile-image

株式会社カプコンが誇るゲームエンジン「RE ENGINE」を開発している技術研究統括によるカプコン公式アカウントです。 これまでの技術カンファレンスなどで行った講演資料を公開しています。 【CAPCOM オープンカンファレンス プロフェッショナル RE:2023】  https://www.capcom-games.com/coc/2023/ 【CAPCOM オープンカンファレンス RE:2022】  https://www.capcom.co.jp/RE2022/ 【CAPCOM オープンカンファレンス RE:2019】  http://www.capcom.co.jp/RE2019/

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

(ダウンロード不可)

関連スライド

各ページのテキスト
1.

『⿁武者 Way of the Sword』 『モンスターハンターワイルズ』の VFXに息吹を与える「VORTEXEL」 米山 哲平 1

2.

『⿁武者 Way of the Sword』 『モンスターハンターワイルズ』の VFXに息吹を与える「VORTEXEL」 米山 哲平 1 それでは只今よりVORTEXELというシステムについてお話をさせていただきます。 よろしくお願いいたします。 1

3.

• 自己紹介 • VORTEXEL └ 概要 └ Geometry └ Turbulence └ Thermal Conductor 当セッションはCEDEC2025で発表した内容に その後の拡張と『⿁武者 Way of the Sword』での 活用事例を追加したものとなっています └ Physics • Extra Content 22 当セッションではこのような構成で進めさせていただきます。 自己紹介から実装の経緯、各機能の解説と使用例等を順番にご説明します。 なお、当セッションはCEDEC2025で発表した内容をベースとしており、 その後の拡張と『⿁武者 Way of the Sword』での活用事例を追加したものとなっています。 CEDEC2025ではかなり高い評価をたくさん頂きありがとうございました。この場を借りて感謝申し上げます。 2

4.

自己紹介 米山 哲平 • 2013年にカプコンに入社 └ 当初RE ENGINEのエフェクトエンジンユニットに所属 • モンスターハンター:ワールド時代 (2015~2019) └ MT FRAMEWORKベースのエンジンで専属エフェクトプログラマとして担当 └ アイスボーンも引き続き担当 • RE ENGINEのエフェクトエンジンユニットに合流 └ しばらくはモンスターハンターワイルズを中心にサポート • 過去の発表 └ MH:W | GPU Particle - モンスターハンター:ワールドにおけるGPU Particleの実装 https://www.docswell.com/s/CAPCOM_RandD/Z7DPJK-2022-07-15-133910 33 まずは簡単な自己紹介をさせてください。 自分は2013年に入社してしばらく、RE ENGINEのエフェクトエンジンユニットに所属していました。 その後、『モンスターハンター:ワールド』チームへ専属のエフェクトエンジンプログラマとして所属することになりました。 そしてRE ENGINEへ再び合流し、エフェクトエンジンユニットのメンバーとしてサポートを行っています。 合流後もしばらくは『モンスターハンターワイルズ』を中心にサポートを行っていました。 で、この自己紹介が結構大事で━━ 3

5.

自己紹介 米山 哲平 • 2013年にカプコンに入社 └ 当初RE ENGINEのエフェクトエンジンユニットに所属 • モンスターハンター:ワールド時代 (2015~2019) └ MT FRAMEWORKベースのエンジンで専属エフェクトプログラマとして担当 └ アイスボーンも引き続き担当 • RE ENGINEのエフェクトエンジンユニットに合流 └ しばらくはモンスターハンターワイルズを中心にサポート • 過去の発表 └ MH:W | GPU Particle - モンスターハンター:ワールドにおけるGPU Particleの実装 https://www.docswell.com/s/CAPCOM_RandD/Z7DPJK-2022-07-15-133910 44 今回制作したシステムはまさしくこの『モンスターハンター:ワールド』でやりたかったことの集大成なためです。 4

6.

モチベーション モンスターハンター:ワールドからのフィードバック • 当時タイトル側に席を置いて密接に連携していた • 次回作でやってみたい事をVFXアーティストと語り合う └ 雑談ベースの妄想話がとても大事 └ いろんなインスピレーションを得た → VORTEXELの開発へ 55 今回ご紹介する技術は『モンスターハンター:ワールド』を作っていく中で出てきたアイディアが発端となっています。 当時は変則的にアーティスト席と非常に近い場所で制作していました。 それもあってアーティストと雑談しながら「もっとスペックがあったら何がしたいか」、「今回なにがめんどくさかったか」、「欲しかった機能は何か」などの情報を収集してました。 おかげでいろんなインスピレーションを得てVORTEXEL構想が立ち上がりました。 そしてこの度 5

7.

モチベーション モンスターハンター:ワールドからのフィードバック • 当時タイトル側に席を置いて密接に連携していた • 次回作でやってみたい事をVFXアーティストと語り合う └ 雑談ベースの妄想話がとても大事 └ いろんなインスピレーションを得た → VORTEXELの開発へ + モンハンワイルズのフィードバックを⿁武者WSに反映・拡張 66 『モンスターハンターワイルズ』からのフィードバックを回収しつつ、『⿁武者WS』に対して反映および拡張を行うまでになりました。 6

8.

77 というわけでここからが本編となります。 ぜひ楽しんでいただければと思います! 7

9.

キャッチコピー 88 VORTEXELにはキャッチコピーがあります。 それが 8

10.

キャッチコピー 次世代の 風 を感じよう ※ 2022.02.24 モンハンワイルズチームに共有した ときに実際に使用したキャッチコピー 99 「次世代の風を感じよう」 です。 これは実際に 2022.02.24『モンスターハンターワイルズ』チームにVORTEXELの情報を共有したときに使ったキャッチコピーです。 この映像はいくつもの重要な要素を示しています。詳しく見ていきましょう。 9

11.

ボルテクセル VORTEXELとは? GPUによる超並列処理を利用した ジオメトリエコシステムの「総称」です 名前の由来 • 3D Texture の要素である Voxel(ボクセル) • 渦・旋風を意味する Vortex(ボルテックス) 名前の通り ボクセル や 3D Texture といった ボリュームデータで各種シミュレーションを行います 10 10 まずVORTEXELとは? GPUによる超並列処理を利用したジオメトリエコシステムの「総称」です。 名前の由来は 3D Texture の要素である ボクセル うず・せんぷうを意味する ボルテックス から来ています。 名前の通り ボクセル や 3D Texture といったボリュームデータで各種シミュレーションを行います。 これによって何ができるか?それがこちらです。 10

12.

何ができるの? 地形に沿って風を吹かせられます! 11 11 地形に沿って風を吹かせられます! このパーティクル群は直接はコリジョンを取っていません。 空間の風に流しているだけです。 つぎに 11

13.

何ができるの? 焼畑出来ます! 12 12 焼畑出来ます! 『モンスターハンターワイルズ』での草原の延焼も当機能によってできた表現です。 風の影響を受けて炎の勢いも変わります。 そして 12

14.

何ができるの? 小石を大量に転がせられます! 13 13 小石を大量に転がせられます 『ワイルズ』をプレイした方はプレイヤー/モンスター問わずあらゆる場面で破片が出ていたことに気づいたかと思います。 これが実現できたのはVORTEXELの恩恵があったからこそです。 13

15.

何ができるの? 大量の髑髏とインタラクション! 14 14 そして新たに『⿁武者WS』では髑髏が大量に転がった印象的なシーンでの戦闘演出にも使用されており、 キャラクターインタラクションによってより迫力のある戦闘となっています。 14

16.

複数の機能? VORTEXELの中に複数のモジュールが存在 → ジオメトリエコシステムとして連携 Geometry 地形解析 Physics 物理演算 Turbulence 風流体 Thermal Conductor 熱伝播 15 15 先ほどの動画を見ると複数の機能を有しているように見えます。 実際にそれぞれの機能を実現するために複数のモジュールがVORTEXELの中に存在しており これがジオメトリエコシステムとして連携しています。 先に述べた「総称である」というのはこのことです。 連携に関してもう少し詳しく見ましょう。 15

17.

各機能との連携 VORTEXEL Geometry 地形解析 Physics 物理演算 Turbulence 風流体 Thermal Conductor 熱伝播 16 16 VORTEXEL内のモジュールはそれぞれ 16

18.

各機能との連携 VORTEXEL Geometry 地形解析 Physics 物理演算 Turbulence 風流体 Thermal Conductor 熱伝播 17 17 片方向でのみ依存するように設計されています。 これは保守コストや処理をスケールしやすくするために気を使った部分でもあります。 例えば 17

19.

各機能との連携 VORTEXEL Geometry 地形解析 Physics 物理演算 Turbulence 風流体 風下でより燃える Thermal Conductor 熱伝播 18 18 熱伝播は風下でより燃えるように風流体を参照し 18

20.

各機能との連携 VORTEXEL Geometry 地形解析 遮蔽情報の参照 Physics 物理演算 Turbulence 風流体 風下でより燃える Thermal Conductor 熱伝播 19 19 風流体は流体シミュレーションのために地形の遮蔽情報を参照 19

21.

各機能との連携 VORTEXEL Geometry 地形解析 地形を参照 Physics 物理演算 遮蔽情報の参照 Turbulence 風流体 風下でより燃える Thermal Conductor 熱伝播 20 20 もちろん物理演算でも地形情報を参照します。 そしてこれらの情報はVORTEXEL内で完結せず 20

22.

各機能との連携 VORTEXEL 遮蔽情報の参照 Geometry 地形解析 小石を転がす Physics 物理演算 2D/3D流体 エフェクト パーティクル Turbulence 風流体 Thermal Conductor 熱伝播 21 21 他システムでも利用されます。 21

23.

各機能との連携 VORTEXEL Geometry 地形解析 2D/3D流体 Physics 物理演算 エフェクト パーティクル Turbulence 風流体 風で揺れる Thermal Conductor 熱伝播 草燃え検出 Cloth タイトル スクリプト 22 22 最終的にはエフェクトユニットだけではなく他ユニットのシステムからも利用されるまでに至りました。 実装時に他ユニットからの利用のしやすさなどにも気を付けたのも功を奏しました。 その辺の話も後ほど行いたいと思います。 22

24.

23 23 というわけでここからは各モジュールの説明をしていきます。 まずはGeometryです。 23

25.

Geometry GPU上で認識される衝突判定空間の構築および管理を担当 └ VORTEXELの基点となる機能 24 24 GeometryはGPU上で認識するための衝突判定空間を 解析および構築するモジュールです。 この機能はVORTEXELの中でも比較的重要な機能です。 なぜならばまずは空間を認識しないと始まらないためです。 24

26.

構築範囲 • 224x112x224mの範囲をカバー └ MH:Wの古代樹の森が約500x500m →「半分の距離をカバーできればいいだろう」 • 一辺当たり0.5mのボクセル精度 25 25 構築範囲は224x112x224mの範囲をカバーすることを目指して作成を開始しました。 選定理由としては 『モンスターハンター:ワールド』の古代樹の森が一辺約500mなので 「半分の距離をカバーできればいいだろう」 というところから来ています。 その際 25

27.

構築範囲 • 224x112x224mの範囲をカバー └ MH:Wの古代樹の森が約500x500m →「半分の距離をカバーできればいいだろう」 • 一辺当たり0.5mのボクセル精度 26 26 一辺当たり0.5メートルのボクセル精度で地形を解析するので左下の画像のように元オブジェクトにかなり近いフィット率を実現しています。 26

28.

リアルタイム地形解析 元データはCPU側のコリジョン情報を使用 └ 専用アセットの事前準備不要 27 27 この時用いられる衝突判定データはCPU側にあるプレイヤーなどが参照する一般的な地形コリジョンを利用します。 そのためVORTEXEL用にアセットを用意する必要がありません。 しかし地形コリジョンはトライアングルの集合体なのでGPUで都度利用するにはコストが高いです。 そのために「解析処理」を行います。それもリアルタイムで。 一体どのように解析をしていくのか見ていきましょう。 27

29.

SDF (Signed Distance Field) への変換 投入されたトライアングルをSDFへとラスタライズ は内側を示す角 28 28 内部では投入されたトライアングルをSigned Distance Fieldへとラスタライズする処理を行っています。 ラスタライズはトライアングルからAABBを作って、AABB内のボクセルを全走査する単純なものです。 これらの処理はCompute Shaderを使用して1スレッドグループ当たり1トライアングルをラスタライズしています。 ところで急に出てきたSDFですが、皆様ご存じでしょうか? まだ知らない人も多いと思いますので少しだけ解説します。 28

30.

SDF (Signed Distance Field)って? は内側を示す角 29 29 SDFは簡単に言うと 29

31.

SDF (Signed Distance Field)って? • ボクセルの"角"毎に一番近いトライアングルまでの距離が記録されているテクスチャ は内側を示す角 30 30 ボクセルの角毎に、一番近いトライアングルまでの距離が格納されている2次元または3次元テクスチャです。 30

32.

SDF (Signed Distance Field)って? • ボクセルの"角"毎に一番近いトライアングルまでの距離が記録されているテクスチャ └ メッシュの外は正の値、内側は負の値 +0.2 +0.6 +0.1 -0.5 +0.2 -0.8 は内側を示す角 31 31 メッシュの外にいる角は正の値、内側は負の値を持っています。 これの良いところは 31

33.
[beta]
SDF (Signed Distance Field)って?
• ボクセルの"角"毎に一番近いトライアングルまでの距離が記録されているテクスチャ
└ メッシュの外は正の値、内側は負の値
• 周囲の4点(3次元だと8点)をサンプルするだけで
地形にめり込んでいるか判定ができる

+0.2

+0.6

+0.1
-0.5

+0.2

-0.8

float calcDistance(float d[8], float3 uvw) {
float d0 = lerp(d[0], d[1], uvw.x);
float d1 = lerp(d[2], d[3], uvw.x);
float d2 = lerp(d[4], d[5], uvw.x);
float d3 = lerp(d[6], d[7], uvw.x);
d0 = lerp(d0, d1, uvw.y);
d1 = lerp(d2, d3, uvw.y);
return lerp(d0, d1, uvw.z);
}

は内側を示す角

32
32

周囲の4点をサンプルして線形補間するだけで内側かどうかがわかる点です。

32

34.
[beta]
SDF (Signed Distance Field)って?
• ボクセルの"角"毎に一番近いトライアングルまでの距離が記録されているテクスチャ
└ メッシュの外は正の値、内側は負の値
• 周囲の4点(3次元だと8点)をサンプルするだけで
地形にめり込んでいるか判定ができる
└ これが大事
+0.2

+0.6

+0.1
-0.5

+0.2

-0.8

float calcDistance(float d[8], float3 uvw) {
float d0 = lerp(d[0], d[1], uvw.x);
float d1 = lerp(d[2], d[3], uvw.x);
float d2 = lerp(d[4], d[5], uvw.x);
float d3 = lerp(d[6], d[7], uvw.x);
d0 = lerp(d0, d1, uvw.y);
d1 = lerp(d2, d3, uvw.y);
return lerp(d0, d1, uvw.z);
}

は内側を示す角

33
33

VORTEXELではこれを使用して高速な接触判定を行います。

33

35.

ただし・・・ • 完全なSDF構築は非常にコストがかかる └ 全ての角とトライアングルの距離計算 └ 内外判定をする必要がある 34 34 ただし、完全なSDF構築はリアルタイムでやるにはコストがかかりすぎます。 というのも行う場合はすべての角とトライアングルとの距離を計算し、さらに内外判定をする必要があります。 34

36.

ただし・・・ • 完全なSDF構築は非常にコストがかかる └ 全ての角とトライアングルの距離計算 └ 内外判定をする必要がある • VORTEXELでは簡易的なSDF構築 35 35 そのためVORTEXELでは簡易的なSDF構築のみ行っています。 しかし簡易的なのでいろいろ問題があり 35

37.

ただし・・・ • 完全なSDF構築は非常にコストがかかる └ 全ての角とトライアングルの距離計算 └ 内外判定をする必要がある • VORTEXELでは簡易的なSDF構築 └ ダイヤ形状が生成される 36 36 ダイヤ形状が中空に生成される可能性があります。 36

38.

ただし・・・ • 完全なSDF構築は非常にコストがかかる └ 全ての角とトライアングルの距離計算 └ 内外判定をする必要がある • VORTEXELでは簡易的なSDF構築 └ ダイヤ形状が生成される └ トライアングル周囲のボクセルは 有効値が入っているが内側は"空洞"になっている 37 37 他にもトライアングルに隣接した周囲のボクセルにはある程度の有効値が入ってますが 37

39.

ただし・・・ • 完全なSDF構築は非常にコストがかかる └ 全ての角とトライアングルの距離計算 └ 内外判定をする必要がある • VORTEXELでは簡易的なSDF構築 └ ダイヤ形状が生成される └ トライアングル周囲のボクセルは 有効値が入っているが内側は"空洞"になっている ? 38 38 そこから離れたボクセルには触れないので中が空洞になっています。 そうすると当たり抜けやトンネリングといった問題が起きやすくなります が、 38

40.

ただし・・・ • 完全なSDF構築は非常にコストがかかる └ 全ての角とトライアングルの距離計算 └ 内外判定をする必要がある • VORTEXELでは簡易的なSDF構築 └ ダイヤ形状が生成される └ トライアングル周囲のボクセルは 有効値が入っているが内側は"空洞"になっている • 実用上は問題ない └ エフェクトはゲーム性に影響がないので 厳密に判定する必要が無い ? └ ゲーム中コリジョンは 可視化されないので気づかない 39 39 実用上は問題ないのですべて無視します。 というのもあくまでエフェクトで利用されるデータ、つまり見た目だけある程度担保出来ればいいので、ゲーム性に影響がなく厳密に判定する必要が無いためです。 39

41.

厳密に判定する必要が無い 40 40 厳密に判定する必要が無いと思いましたが、すぐに許容できない日がやってきました。 40

42.

薄い屋根 薄い壁 41 41 SDFの宿敵である「薄い板」の参戦です。 41

43.

穴あき対策(⿁武者WS向け拡張) • ⿁武者WSでは薄い板で出来た日本家屋が多い └ SDFの分解能の関係で穴あきになってしまう ※軒下から見た図 42 42 『ワイルズ』の時は問題なかったのですが、『⿁武者WS』では薄い板で出来た日本家屋が多く出てきます。 そうするとSDFの分解能では穴だらけになってしまいます。 42

44.

穴あき対策(⿁武者WS向け拡張) • ⿁武者WSでは薄い板で出来た日本家屋が多い └ SDFの分解能の関係で穴あきになってしまう ※軒下から見た図 43 43 例えばこの屋根では4本の「骨」のようなコリジョンとなってしまっています。 43

45.

穴あき対策(⿁武者WS向け拡張) • ⿁武者WSでは薄い板で出来た日本家屋が多い └ SDFの分解能の関係で穴あきになってしまう └ 雨漏りがひどい! 44 44 こうなると雨が降ったらそれはもう大変なことになります。 幸いなことに元になったコリジョンはOBB等のプリミティブ形状で表現されているので 44

46.

穴あき対策(⿁武者WS向け拡張) • ⿁武者WSでは薄い板で出来た日本家屋が多い └ SDFの分解能の関係で穴あきになってしまう └ 雨漏りがひどい! • SDFではなくキャラクターなどに付いている動的コリジョンに変換 └ OBB形状が扱えるので穴を塞げる ※ワイヤーフレーム表示 45 45 これをコリジョン属性でフィルタして、キャラクター等で使用している動的コリジョン領域にフォールバックすることで低コストで対応できました。 動的コリジョンに関してはPhysicsの章でお話いたしますのでまた後程。 45

47.

46 46 VORTEXELはSDF以外にもデータを提供します。 それが 46

48.

High-Res Occlusion 高解像度遮蔽情報 ボクセル(一辺0.5m)のさらに2x2x2精度 └ つまり25cm単位での精度 47 47 High-Res Occlusionと呼んでいるデータです。 このデータでは 47

49.

High-Res Occlusion 高解像度遮蔽情報 ボクセル(一辺0.5m)のさらに2x2x2精度 └ つまり25cm単位での精度 ボクセル内に壁があるかどうかの2値 1bit情報 48 48 遮蔽されているかどうかの2値が取れます。 1ボクセル1bitなので非常に軽量かつアクセスも高速です。 特に 48

50.

High-Res Occlusion 高解像度遮蔽情報 ボクセル(一辺0.5m)のさらに2x2x2精度 └ つまり25cm単位での精度 ボクセル内に壁があるかどうかの2値 1bit情報 流体シミュレーションでは2値で十分 49 49 流体シミュレーションで利用する場合は遮蔽されているかどうかの2値があれば十分なので相性が非常に良いです。 49

51.

まとめ ボクセルで管理されているのでピンポイントでアクセスできる └ 毎回トライアングル単位でチェックしなくていい! サンプリング座標を渡すだけでアクセス可能 └ GPU Particleと相性最高! SDF特有の穴あき対策も可能 └ 雨漏り等を防ぎましょう! 高速に遮蔽情報が手に入る └ 流体シミュレーションと相性最高! 50 50 ここまでのまとめです ボクセルで管理されているのでピンポイントでアクセスできます。毎回トライアングル単位でチェックしなくていいのです。 サンプリング座標を渡すだけでアクセス可能なためGPU Particleと非常に相性が良いです。 SDF特有の穴あきにもある程度対策が可能となり、ここぞというニーズにこたえられます。 高速に遮蔽情報が手に入るので流体シミュレーションとも相性が良いです。 50

52.

51 51 とてもよさそうな管理システムですがその情報を提供するためにはいろいろな苦労があります。 ということで最適化にも触れていきます。 51

53.

ラスタライズ負荷 52 52 ラスタライズに関しては非常に苦労しました。 52

54.

ラスタライズ負荷 • 3D Textureの広範囲ランダムアクセスは負荷が高い 53 53 そもそも3D Textureに並列で広範囲にランダムアクセスされるので、アクセス効率があまりよくないです。 それでも大抵の場合は特に気にせず動くのですが、時折強烈なスパイクが発生することがありました。 53

55.

ラスタライズ負荷 • 3D Textureの広範囲ランダムアクセスは負荷が高い • 投入されるトライアングル数がまちまち 54 54 これはエリアによって投入されるトライアングル数がまちまちなのもあり、場所によっては平均値の数倍の密度になる場所もあったためです。 54

56.

ラスタライズ負荷 • 3D Textureの広範囲ランダムアクセスは負荷が高い • 投入されるトライアングル数がまちまち • 大きなトライアングルが投入されると⾧大なThread Groupが発生する 55 55 さらに問題なのは非常に大きなトライアングルで、これが投入されると1Thread Groupあたり1トライアングルを処理している都合で非常に⾧く処理するThread Groupが出てきます。 これらをどう対処したのかをご紹介します。 55

57.

フレーム分散 • 1フレームで全領域を処理しない • 1フレームあたり └ 1000区画 └ 1区画あたり1辺3.5m └ 4000トライアングル以下 → 約130フレームで全領域を構築 ※デフォルト設定 • これらの設定で処理負荷を 簡単にスケールできる └ ⿁武者WSではより低負荷で構築 56 56 まず最初に行ったのはフレーム分散です。 これは全領域を1度にラスタライズするのではなく複数フレームに分割します。 デフォルトでは1フレームあたり 1000区画 かつ 4000トライアングル以下としています。 これで130フレームでカバー範囲の全領域を構築できます。 これらの値はタイトル側で設定できるので予算に合わせて処理負荷を簡単にスケールできます。 『⿁武者WS』では「高速な乗り物」は無いのでもっと時間をかけて低負荷で構築しています。 56

58.

トライアングル再分割 1Thread Groupで 1トライアングルを処理 AABB領域のボクセルごとに接触判定 57 57 次にトライアングル再分割です。 先に触れましたが、ラスタライズ時には1Thread Groupで 1トライアングルを処理しています。 比較的単純な実装でAABBを構築した後にそこに被るすべてのボクセルを対象に各Threadで分担して処理するイメージをしていただければ良いです。 57

59.

トライアングル再分割 細⾧かったり大きかったりすると1Thread Groupで処理すべき範囲が増える 図は2次元だが3次元だとより顕著 58 58 しかし細⾧かったり大きかったりすると対象のボクセルが一気に増えていきます。 図では2次元ですが、実際の3次元だと縦・横・奥行の掛け算なので顕著に増えます。 大きなトライアングルが斜めに存在する平らな坂が一番やばいです。 58

60.

トライアングル再分割 図では4つのThread Groupに分離 合計処理ボクセルは増えても処理負荷が偏らないのが重要 59 59 なので閾値サイズを超えたトライアングルは再分割します。 こうすると合計処理ボクセル数は増える場合がありますが、1つのThread Groupが走り続けるということがなくなるので結果的に高速化につながります。 ただ、この図だと流石に余白が気になるので、その場合は適切な稼働数になるまで再分割を繰り返します。 そうすると結果的に合計処理ボクセル数もへります。 59

61.

トライアングル再分割 トライアングルを規則的に分割しバッファに詰めなおす Divide:0 Divide:1 p0 p0 c p2 p1 p2 Divide:2 a b p1 60 60 トライアングルは複雑なことを考えずに4分割してラスタライズ用のバッファに詰めていきます。 60

62.

トライアングル再分割 トライアングルを規則的に分割しバッファに詰めなおす └ 1トライアングルあたりfloat3の3頂点(3*3*4byte=36byte)は重い Divide:0 Divide:1 p0 p0 c p2 p1 p2 Divide:2 a b p1 61 61 が、1トライアングルあたり3次元の3頂点を格納しなおすのは重たいです。 61

63.

トライアングル再分割 トライアングルを規則的に分割しバッファに詰めなおす └ 1トライアングルあたりfloat3の3頂点(3*3*4byte=36byte)は重い └さらに1段階ごとに4倍の容量に増加 Divide:0 Divide:1 p0 p0 c p2 p1 p2 Divide:2 a b p1 62 62 しかも分割するごとに4倍になっていくのでさらに重たいです。 なので保存方法をかえます 62

64.

トライアングル再分割 分割数とインデックスがわかれば分割後のトライアングルが一意に求まる └ 1トライアングルあたり8byteで済む └頂点バッファは元のデータを使用する Divide:0 Divide:1 p0 p0 Divide:2 00 0 c 02 a p2 p1 p2 1 b 01 20 3 2 03 p1 22 23 10 21 12 13 11 ※わかりやすいように4進数(各桁2bit) 63 63 元の頂点データをそのまま使い、 トライアングルのインデックス、分割数、分割後のローカルインデックスさえわかればどのトライアングルかがすぐわかります。 なのでその値をパックすることで、1トライアングルあたり8byteに抑えることができ実行速度が改善されました。 63

65.

容量削減 64 64 最適化はなにも実行速度の高速化だけではありません。 ボクセルを扱うシステムとしては容量とも戦う必要があります。 というわけでSDFを触ります。 64

66.

容量削減 短距離SDF SDF(Signed Distance Field)…に近い情報 VORTEXELでは短距離だけ表現できればいい ? 65 65 VORTEXELでは短距離SDFとしてデータを取り扱います。 一般的な名称ではないですがSDFの低精度版と思っていただければよいと思います。 65

67.

容量削減 短距離SDF SDF(Signed Distance Field)…に近い情報 VORTEXELでは短距離だけ表現できればいい -2.0~+2.0 を 1byte で表現 つまり2.0ボクセル先まで 1ボクセル先までだとカクカクした 見た目が出るので2ボクセル先は必要 ? 66 66 具体的には-2.0~+2.0ボクセル距離でよいので、これを1byte、256段階で表現しても事足ります。 66

68.

容量削減 短距離SDF SDF(Signed Distance Field)…に近い情報 VORTEXELでは短距離だけ表現できればいい -2.0~+2.0 を 1byte で表現 つまり2.0ボクセル先まで 1ボクセル先までだとカクカクした 見た目が出るので2ボクセル先は必要 ? しかし・・・ 全域に詳細なSDFを割り当てるとメモリ量が爆裂 仮に512x512x512解像度のGridを割り当てると 1ボクセル 1byte でも 134MB… 67 67 しかし、全域に詳細なSDFを割り当てるとメモリ量が爆裂します。 仮に512x512x512解像度のGridを割り当てると簡単に134MBいきます。 もちろん精度もカバー領域も足りません。 なので不要なところは刈り取ります。 67

69.

疎なSDF • 大域範囲は均一格子 └ 64x32x64解像度 └ 八分木ではない 68 68 といっても複雑なことを考えずに疎にSDFを管理するだけです。 ただ昨今SDFでよく利用されている八分木ではなく1階層の均一格子で管理しています。 これはできる限り少ない階層アクセスで目的のデータにたどり着きたいという明確な意図があります。 68

70.

疎なSDF • 大域範囲は均一格子 └ 64x32x64解像度 └ 八分木ではない • 各ノードに8x8x8の3D Textureを割り当て 69 69 各ノードには8x8x8の3D Texture相当のデータが割り当てられ、そこにSDF情報が記録されています。 69

71.

疎なSDF • 大域範囲は均一格子 └ 64x32x64解像度 └ 八分木ではない • 各ノードに8x8x8の3D Textureを割り当て └ オリジナルの値は7x7x7範囲に格納 70 70 注意しないといけないのはオリジナルのデータ領域は7x7x7範囲で、 70

72.

疎なSDF • 大域範囲は均一格子 └ 64x32x64解像度 └ 八分木ではない • 各ノードに8x8x8の3D Textureを割り当て └ オリジナルの値は7x7x7範囲に格納 └ 側面は隣接ノードの値を転写 XY Y Z X 71 71 側面は隣接ノードの値を転写します。 こうすることで8点をサンプリングする際に隣接ノードを見に行かなくて済みます 71

73.

必要メモリ Geometryモジュール全体で 約65MB • 224x112x224mの範囲をカバーしながら! • ボクセルを扱うシステムとしては破格の省メモリ └ 4Kテクスチャ1枚分くらいの容量 MH:W時代にメモリ周りで苦労した経験が生きた • 最初から省エネ志向で設計 • メモリ消費量が少ないと結果的に動作も速くなりやすい 72 72 こうして諸々最適化を行なった最終的なGeometryモジュールのメモリ量は約65MBに収まりました。 思い出してほしいのは224x112x224mの範囲をカバーしながらこれです。 4Kテクスチャ1枚分くらいの容量なのでボクセルを扱うシステムとしては破格の省メモリかと思います。 『モンスターハンター:ワールド』時代にメモリ量で非常に苦労した経験があったのでそれが生きた気がします。 今回制作するにあたり最初から省エネ志向かつGPUに適合した構造で組めたのが良かったです。 72

74.

73 73 さて、やっと次のモジュールです。 Turbulenceと呼んでいるモジュール、つまり風に関してです。 73

75.

リアルタイム流体シミュレーション 説得力のある風 • 壁付近は対流 • 岩肌を避ける気流 └ Geometryの当たり判定を利用 GPU/CPU両方で風速が取れる! • 結果はCPU側にリードバック ※画像では一方向の風しか与えてません 74 74 最初に出した動画と合わせてこれらの動画は皆様に対してどれほどのインパクトを与えられたでしょうか? 非常に説得力のある風だと感じていただけていたらうれしいです。 壁付近は対流ができ、岩肌を避け、沿うような気流が見て取れます。 これらは先のGeometryの当たり判定も利用して実際にシミュレーションしています。 そしてこのモジュール、なんと GPUだけではなくCPUでも風情報が取れます。 そのため非常に汎用的で強力な表現力を提供します。 74

76.

リアルタイムで流体シミュレーションする利点 オフラインベイク不要! • 高いイテレーション速度 • リアルタイム即時反映 • 地形修正に追従する必要が無い 追加アセット不要! • 面倒なセットアップが不要 • アセット容量も増えない リアルタイムでもこのくらいの精度が出る 75 75 リアルタイムでシミュレーションする利点は非常に大きく、とにかくオフラインベイクが不要なことが非常に大きいです。 時間帯による風、動的に迫りくる砂嵐による暴風、それによるエフェクトの見た目の変化を即座に確認できますし、エフェクト側から爆風を発生させたり、それらの風圧の 強さなど各種調整がその場で確認できます。 そしてもう一つ。地形修正に追従する必要がなくなります。 制作中は地形が頻繁に修正されますが、そのたびにオフラインでベイク処理をして面倒だった、なんていう経験をした方が皆さんの中にもいらっしゃるかもしれません。 しかし、VORTEXELではそういった負担から解放されます。 それに伴い、追加アセットが不要になります。 これも大きいです。たとえば新規タイトルでとりあえず機能を試してみよう、というときに面倒なセットアップが不要なのです。 検証および導入コストが非常に低いのも魅力となっています。 ベイク済みアセット不要なのでストレージ容量も気にする必要がありません。 75

77.

動的な遮蔽 モンスターのコリジョンにも反応 76 76 実はモンスターなどのコリジョンにも反応しています。 比較的大型の敵と風下で戦う時は威圧感に寄与するはずです。 正直なところ風は可視化されないので、チリや砂煙が周囲に無いとわかりづらいものではあります。 それでも服やアクセサリのはためきとして影響を受けるのでそういった細かい挙動が空気感や威圧感といったものを生み出します。 76

78.

シミュレーション範囲外に関して 77 77 さて、シミュレーション範囲内に関してお話しをしてきました。 が、範囲外はどうなるのか気になるかと思います。 77

79.

シミュレーション範囲外に関して • シミュレーションは比較的狭い範囲 └ デフォルトで128x32x128m └ 範囲外はタイトルのシステムで賄う想定だった 78 78 まず前提としてTurbulenceモジュールはGeometryモジュールと比べ比較的狭い範囲でシミュレーションを行います。 それより外は単にグローバルな風を参照するか、タイトル実装のエリア区切りの古典的な風システムで賄う予定でした。 しかし 78

80.

シミュレーション範囲外に関して • シミュレーションは比較的狭い範囲 └ デフォルトで128x32x128m └ 範囲外はタイトルのシステムで賄う想定だった しかし • タイトル側の管理が煩雑に • タイトル側ではGPU対応が難しい • 毎回タイトルで固有の風システムを実装するのは非効率的 79 79 タイトル側の管理が煩雑になったり、毎回タイトルで固有の風システムを実装するのは非効率です。 なので今回 79

81.

シミュレーション範囲外に関して • シミュレーションは比較的狭い範囲 └ デフォルトで128x32x128m └ 範囲外はタイトルのシステムで賄う想定だった しかし • タイトル側の管理が煩雑に • タイトル側ではGPU対応が難しい • 毎回タイトルで固有の風システムを実装するのは非効率的 → VORTEXEL側で機能を提供するように 80 80 VORTEXEL側で全域をサポートしてしまおうと決心しました。 80

82.

シミュレーション範囲外 • シミュレーションはしない └ 境界部分はブレンドして切れ目が見えないように • 風の発生源は直接参照/デコードする └ 均一格子で分割管理はされている 81 81 と言っても大層な話ではなく範囲外は単にシミュレーションしません。 シミュレーション結果との境界部分はブレンドして切れ目が見えないようにはしていますがそのくらいです。 注目点としては風の発生源に関しては直接参照及びデコードします。 発生源は均一格子で分割管理され高速に探索されます。 これはCPU/GPU共通で行います。 81

83.
[beta]
風の発生源
プロシージャルに生成
• 一つ当たり80byteにパック
• 逆行列が含まれており、サンプリング座標を直接 -1.0 ~ +1.0 空間へ変換
└ -1.0~+1.0空間だと計算が非常に簡単
└ 距離関数をベースとして実装
(+1,+1,+1)

// 形状内距離関数。
// 別途内外判定関数も必要
// さらに別関数で距離とlocationから風速・風向を求められる
float shapeDistance(float3 location, WindInfo info) {
switch(getShapeType(info)){
case PROCEDURAL_SHAPE_BOX:
return max(max(abs(location.x), abs(location.y)), abs(location.z));
case PROCEDURAL_SHAPE_SPHERE:
return length(location);
case PROCEDURAL_SHAPE_CYLINDER:
return length(location.xz); // 上下距離は見ない。
default:
return 0.0;
}
}

(-1,-1,-1)

82
82

風の発生源情報に関してはすべての風形状共通で80byteにパックされており、そこからプロシージャルに風を生成します。
計算に関してもできる限り単純な計算と共通の手順で取得できるように工夫しています。

82

84.

対応している発生源形状 Box, Sphere, Cone, Cylinder • さらに一方向、渦巻き、放射状などの風向きもそれぞれ表現可能 Box+一方向 Cylinder+渦巻 Sphere+放射状 83 83 現在対応されている形状はBox、Sphere、Cone、Cylinderの4つとなっています。 さらにこの形状に対してどのように風を生成するか、距離によってどのように減衰するかといった詳細設定も可能です。 83

85.

直接参照して重くない? 84 84 気になるのは直接参照するには重くないか?という部分ですが、 84

86.

直接参照して重くない? 負荷は限定的 • 風の発生はほぼVFXアーティストが管理 • 遠方はエフェクト自体がカリングされる • 発生しても瞬間的なものが多い 85 85 この負荷は限定的となっています。 というのも風の発生はほぼエフェクトで行われており、エフェクト自体遠方ではカリングされます。 仮に発生しても瞬間的なものが多く、 85

87.

直接参照して重くない? 負荷は限定的 • 風の発生はほぼVFXアーティストが管理 • 遠方はエフェクト自体がカリングされる • 発生しても瞬間的なものが多い → 実際にはほとんど参照・計算されない 86 86 実際にはほとんど参照・計算されないので大きな負荷にはなりませんでした。 86

88.

グローバル風問題 地域全体に吹いてるとして設定される風 87 87 ここまでに風の発生源、つまりローカルな風についてお話してきました。 しかし実際には地域ごとに大域的な風というものが空間を占めています。 87

89.

グローバル風問題 地域全体に吹いてるとして設定される風 88 88 現実世界では言ってしまえばすべてのシミュレーション空間が地続きなので問題ないのですが 88

90.

グローバル風問題 地域全体に吹いてるとして設定される風 現実世界では風は湧き出てくるわけではない・・・ 89 89 VORTEXELでは一部の狭い領域を切り取ったシミュレーションなので範囲外の風が流入してきません。 そうなると大域的な風ってどこから湧き出しているの?となります。 ボクセル空間を真上から見て考えてみましょう。 89

91.

グローバル風問題 90 90 90

92.

グローバル風問題 境界部分に書き込み • 全域に伝わるのに時間がかかる • 精度が低いので隅々まで伝搬しない可能性 91 91 まず最初に考えられるのは境界ボクセルに風を書き込む方法です。 が、こちらは全域に伝わるのに時間がかかってしまいますし、ゲーム内時間で求められる流体シミュレーションの精度では隅々まで伝搬しない可能性が高いです。 さらにちょうど 崖際(がけぎわ) だったり、境界部分に壁があるとそもそも風が発生しないなど問題が出ます。 91

93.

グローバル風問題 全体書き込み • シミュレーションの意味がない • 壁付近も書き込まれてしまう 92 92 次はとりあえず全体にグローバル風を吹かせる方法です。 が、これだとシミュレーションの意味がないですね。 いい感じに元の風とブレンドするなど試行錯誤はできますが、すぐに遷移してしまって求めている結果になりません。 92

94.

グローバル風問題 フィルタして全体書き込み • 地形複雑度 • 圧力値 93 93 ではVORTEXELではどうしているかと言いますと、フィルタしながら全体書き込みしています。 このフィルタで使用しているのは地形複雑度と圧力値です。 93

95.

地形複雑度 High-Res Occlusionのボクセル割り当て数から算出 • 赤いボックスが大きいほど複雑度が高い • つまり壁付近 94 94 Geometryの章でお話ししたHigh-Res Occlusionを覚えていますか? 94

96.

地形複雑度 High-Res Occlusionのボクセル割り当て数から算出 • 赤いボックスが大きいほど複雑度が高い • つまり壁付近 95 95 これを使って各Grid毎に割り当てられたボクセル数をカウントアップすることで簡単に地形の複雑度が手に入ります。 赤い場所ほど割り当て数が多い、つまり複雑度が高い事になります。さらに言うとそこは壁付近であるともいえるわけです。 95

97.

圧力値 前回のフレームの流体シミュレーションの過程で手に入る • 緑はマイナスの圧力 • 赤はプラスの圧力 96 96 そしてもう一つの圧力値ですが、これを可視化すると非常に面白いパターンを見ることができます。 これは前回のフレームの流体シミュレーションの過程で手に入る圧力値のことをさします。 動画はマイナスの圧力値を緑色、プラスの圧力値を赤色のボックスで表示しています。 この地域では画面右下に向かって風が吹いています。 そのため風下の壁付近は空気が引っ張られるような状態になっており、 風上の壁付近では空気が壁にぶつかって圧力値が高いような状態になっているわけです。 なのでこの圧力値を使って・・・ 96

98.

マスクマップ 複雑な地形と圧力の「絶対値」が高い場所をマスク • 赤い場所に追加の風を吹かせない 「風の波」 ができた! 97 97 圧力の「絶対値」が高い場所をマスクします。 この赤い場所にはグローバル風を追加しません。 理由としては、風下の壁付近は既に真空のような状態で無風または風が回り込んできている状態、 反対に風上の壁は既に対流した風が出来上がってるとみなし、 その部分の風の形を崩さないようにたもてれば、欲しい見た目になるはずだからです。 ちょうど空白地帯は広くひらけている場所であることがうかがえるかと思います。 結果として非常に有機的な動きを観測でき、 これは結果として「風の波」として作用します。 97

99.

風の吹く場所の自動化 クナファ村では自然と風を避ける場所に 98 98 ここまでの機能の結果、クナファ村のような入り組んだ土地では自然と風を避けるような、なぜその地に村を築いたのかを感じさせるたたずまいとなりました。 これはつまりアーティストが地形ごとに細かい風の調整をしなくても説得力のある風が自動で設定されることを意味しており、工数削減の一助となります。 もちろん、雰囲気付けで風を吹かせたい場合は風の発生源を置くことで要望に応えることも可能です。 98

100.

エフェクト連携 焚火 • 風に合わせてたなびく • 現実的な風速を使うのと すぐ反映チェックできるので 何処に置いても違和感が出にくい └ アセットの再利用性を促進 砂嵐 • 迫力のある演出 • 砂丘の「影」は実際に風が弱い └ シミュレーションの効果 99 99 今回の風の使用例を見ていきますとエフェクトでは焚火の流され方、そして隔ての砂原の砂嵐などで使用されています。 特に砂嵐では迫力のある演出を実現しており砂丘をなぞる強い風を感じられるかと思います。 さらに砂丘の影では風が弱いなどシミュレーションの効果もあります。 もちろん、これだけではなくエフェクトだけでも他にも数多くの場所で使用されています。 99

101.

外部モジュール連携 Cloth • 服の"はためき"でも参照 └ cm単位のシミュレーション ではないのでパタパタする アニメーションは追加で必要 草、木、クナファ村の鳴子 • 一貫した見た目 • 空気感を演出 100 100 ではエフェクト以外ではどうかというと装備や服のはためき等でも参照されています。 といってもcm単位のシミュレーションではないのでパタパタするアニメーションはまだ必要です。 他にも草や木々の揺れ、クナファ村の鳴子(なるこ)などでも使用されており、一貫した見た目かつ説得力のある世界観を生み出しているかと思います。 100

102.

101 101 次に熱伝播処理を司るサーマルコンダクターモジュールです。 101

103.

草燃えで利用 • インタラクション可能 • 一部モンスターは火を避ける └ CPU側へ発火情報をリードバック 102 102 簡単に言えば草燃えを表現しているモジュールになります。 結構毛色が違う機能な気がしますが、これもVORTEXELで管轄している機能になります。 CPU側へ発火情報などをリードバックしているのでそれに反応してモンスターは逃げようとします。 オトモのお尻も燃えます 102

104.

自由な配置 隣接する発火点(球形状)によるリンクを構築 • 2Dヒートマップではない └ 広範囲に発火点が配置できる └ 高低差があっても使用可能 103 103 熱の伝搬処理には 球形状の発火点 を置くことで実現しています。 これが隣接している場合にリンクを構築し相互監視し熱伝播を行います。 配置面積に応じて容量が増える2Dテクスチャヒートマップとは違い、 個数に応じて線形にしか容量が増えないので広範囲に配置できますし、高低差があっても使用可能なので便利です。 103

105.

応用の効くデータ管理 CPUとGPU両方からアクセス可能 • どのくらい炭化しているか0.0~1.0で手に入る • 火が来た方向も手に入る • マテリアルアニメーションで 草束を"削る"表現が可能に 利用場面 • 隔ての砂原の草原 └ 草束単位で仕込んでます • 油涌き谷の油田 └ タール地帯も同じ方式 104 104 熱源の情報はCPUとGPU両方からアクセス可能で、 もちろんシェーダーマテリアルからも直接アクセス可能です。 その際、現在どのくらい燃えたのか、どこから火が来たのかという情報も手に入るので燃え削りアニメーションが実現できます。 これをアーティスト側が利用し、燃え削りの表現を実現しています。 104

106.

説得力のある絵作り • 燃えた草がわかるのでそこから火のエフェクトをだせる • 火の進行方向も持っており風下のほうが火の勢いが強い └ 風流体でより臨場感が増す ※開発当時の検証映像 105 105 そして諸々を合わせて検証したところ非常に説得力のある絵が出来上がりました。 燃えた草はCPUからも手に入るのでそこから炎や煙エフェクトを出すことも可能です。 今回は先にお話しした風流体があるのでそれと合わせると非常に良い感じになりました。 105

107.

パラメータの選定 106 106 燃やせることはわかりましたがどのようなパラメータで管理されているのでしょうか? パラメータの選定に関しても苦労話があります。 106

108.

パラメータの選定 • 当初"温度"を伝搬させる予定だったがコントロールが難しかった 107 107 当初熱伝播という名前にのっとり実際に"温度"を伝搬させる予定でしたがコントロールが難しいことがわかりました。 というのも 107

109.

パラメータの選定 • 当初"温度"を伝搬させる予定だったがコントロールが難しかった └ 燃える速度や延焼範囲の調整が特に難しい └ 基準値やプリセット値の策定が困難 1700℃の火球を出したら 草原が一瞬で消し炭に 草の発火点って何度? 小タル爆弾だと 全然燃えない 108 108 超高温の火球が着弾すると一瞬で全域が燃えたり 草って何度で燃えるの?とか小タル爆弾だと瞬間火力はあるが燃えない、みたいなそれぞれの設定が非常に難しかったためです。 とくに現実的な設定に近づけるほど材質パラメータとかが増えてくるので、それをアーティストに設定してもらうのはよくないなと悩んでました。 108

110.

パラメータの選定 • 最終的に時間指定方式に └ 小さい火種でも着火可能 └ 延焼時間と着火時間で延焼範囲もコントロールできる 109 109 で、ある程度アーティストの要望や出したい絵に関してヒアリングして、最終的には時間指定方式になりました。 つまり2秒あぶられたら着火して、5秒間燃える、みたいな時間指定です。 109

111.

パラメータの選定 • 最終的に時間指定方式に └ 小さい火種でも着火可能 └ 延焼時間と着火時間で延焼範囲もコントロールできる 火球の着弾点から 5秒間延焼させよう 小タル爆弾でも 延焼できる! 草は1秒間火に触れたら着火! 2秒間燃え続ける! 延焼時間と着火時間から 延焼範囲も逆算できる! 110 110 おかげで小さい火種でも着火可能になり、延焼時間と着火時間で燃える範囲もコントロールできるようになりました。 正直今思えばそりゃそうだ、って感じではありますが、燃えるという現象に囚われすぎました。 110

112.

裏話 111 111 このThermal Conductorが開発された発端の裏話を少々。 111

113.

裏話 モンスターハンター:ワールド開発時の頃 • 当時出た「某すごいゲーム」と比較して 「グラフィックすごいのにこっちは草とか燃えないじゃん!」みたいな声があった 112 112 『モンスターハンター:ワールド』開発時に、当時出た「某すごいゲーム」と比較して「グラフィックすごいのにこっちは草とか燃えないじゃん!」みたいなユーザーの声がありま した。 112

114.

裏話 モンスターハンター:ワールド開発時の頃 • 当時出た「某すごいゲーム」と比較して 「グラフィックすごいのにこっちは草とか燃えないじゃん!」みたいな声があった 当時の自分「要望に応えたい! 燃やしたい!」 • しかし断念 └ 他に必須な実装物が多かった └ 既に処理負荷がきつかった └ 当時まだ社会人3年目とかだったのでいっぱいいっぱいだった 113 113 当時の自分としても「要望に応えたい!燃やしたい!」とは思っていましたが諸々の事情で対応が難しかったので一旦お蔵入りに。 113

115.

裏話 モンスターハンター:ワールド開発時の頃 • 当時出た「某すごいゲーム」と比較して 「グラフィックすごいのにこっちは草とか燃えないじゃん!」みたいな声があった 当時の自分「要望に応えたい! 燃やしたい!」 • しかし断念 └ 他に必須な実装物が多かった └ 既に処理負荷がきつかった └ 当時まだ社会人3年目とかだったのでいっぱいいっぱいだった ついに燃やせるように 114 114 そうして今回ついに燃やせるようになりました。 114

116.

裏話 • いろんなエフェクトに仕込まれている • 特にチャージアックスやガンランス └ 動画サイトやSNSなどで話題になって個人的に嬉しかった 115 115 で、仕込めるようになった結果、VFXアーティストの皆さん 芸が細かいのでいろんなものにエフェクトが仕込まれています。 オープンベータ当時にチャージアックスやガンランスによる草燃えを見つけてくれたユーザーを発端に各所で話題になっており個人的にも嬉しかったです。 草原を頑張って燃やし尽くそうとしてくれたユーザーもいて楽しく反応を見させていただきました。 115

117.

裏話 ところで・・・ よく見ると強制鎮火というパラメータが・・・? 116 116 ところで、Heat Sourceには温度上昇、強制発火、強制鎮火の3つのパラメータがあるのですが、この強制鎮火とは何でしょう? 実際に仕込まれているのでぜひ探してみてほしいです。既に見つけている方もいて流石だなと思いました。 116

118.

117 117 さて、お待たせしました。Physicsモジュールです。 117

119.

Physics 一番やりたかったやつ 制作フローの関係で実装時期としては一番最後に 飛び散る破片! ばらまかれる薬莢! 118 118 今回のVORTEXELの構想で一番やりたかった機能です。 動画を見ているだけで楽しいです。 ただしタイトル制作フローの関係で実装時期としては一番最後の実装となりました。 118

120.

コンセプト 119 119 VORTEXELのPhysicsモジュールに関しては別途重要なコンセプトを設けていました。 それが 119

121.

コンセプト エフェクトのための物理 120 120 「エフェクトのための物理」です。 120

122.

物理演算エンジンの再開発? 既存の物理演算エンジン • メリット └ 高い精度 └ 複雑な形状に対応 121 121 実を言うとRE ENGINEには以前から信頼と実績のある物理演算エンジンが完備されています。 こちらは高い精度と安定性、複雑な形状に対応しており重要な機能としてRE ENGINEに息づいています。 ただし 121

123.

物理演算エンジンの再開発? 既存の物理演算エンジン • メリット └ 高い精度 └ 複雑な形状に対応 • デメリット └ 嘘がつきづらい 物理法則に従わないほうが問題 └ 処理タイミングの都合で エフェクトのGPU Particleとの 協調動作が難しい 122 122 動きに嘘がつきづらく、エフェクトのGPU Particleと協調動作が難しいため、エフェクトで利用するには難がありました。 誤解しないでほしいのはこれは既存のエンジンが悪いという話ではなくそもそもコンセプトが違うという話です。 122

124.

物理演算エンジンの再開発? 既存の物理演算エンジン • メリット └ 高い精度 └ 複雑な形状に対応 • デメリット └ 嘘がつきづらい 物理法則に従わないほうが問題 └ 処理タイミングの都合で エフェクトのGPU Particleとの 協調動作が難しい VORTEXEL Physics • メリット └ エフェクト側の好きな タイミングで実行可能 └ 精度を犠牲に超高速 • デメリット └ 雑な精度 └ 比較的小さな物体でのみ使用可能 └ 上方向に積むことはできない 123 123 なのでVORTEXELではエフェクトに特化した物理演算エンジンを提供することにしました。 エフェクトで完全管理された実行タイミング、嘘物理、GPU Particleで大量に扱える、そういった要望をかなえます。 そのために意図的に精度を犠牲にするという、既存の物理演算エンジンとは対照的なコンセプトとなっています。 123

125.

物理演算エンジンの再開発? 既存の物理演算エンジン • メリット └ 高い精度 └ 複雑な形状に対応 • デメリット └ 嘘がつきづらい 物理法則に従わないほうが問題 └ 処理タイミングの都合で エフェクトのGPU Particleとの 協調動作が難しい VORTEXEL Physics • メリット └ エフェクト側の好きな タイミングで実行可能 └ 精度を犠牲に超高速 • デメリット └ 雑な精度 └ 比較的小さな物体でのみ使用可能 └ 上方向に積むことはできない 124 124 さて、デメリットの中に「比較的小さな物体でのみ使用可能」とあります。 これはなんでしょうか? 124

126.

Tiny Physics (と呼んでる概念) 125 125 これはTiny Physicsと個人的に呼んでいる概念で、 125

127.

Tiny Physics (と呼んでる概念) 比較的小さな物体でのみ使用可能 • 具体的には半径が「短距離SDFの1ボクセルサイズ」以下 └ つまりモンハンワイルズ環境なら半径0.5m以下 126 126 Geometryの章でお話しした短距離SDFの1ボクセルサイズ以下の形状の場合に使えるテクニック群となります。 126

128.

Tiny Physics (と呼んでる概念) 比較的小さな物体でのみ使用可能 • 具体的には半径が「短距離SDFの1ボクセルサイズ」以下 └ つまりモンハンワイルズ環境なら半径0.5m以下 • 小さい物体だからバレないことが多々ある └ バレない範囲で精度を落として高速化 127 127 瞬間的に発生するエフェクトにおいては小さい物体だからばれないことが多々あるので、ばれない範囲で精度を落として高速化します。 127

129.

サポートされている剛体形状 • Sphere Box Tetrahedron • Box • Card • Capsule • Tetrahedron 128 128 説明に移る前にサポートされている形状を軽くお話ししておきます。 剛体形状としては比較的よくつかわれる形状をサポートしています。 128

130.

サポートされている剛体形状 • Sphere Box Tetrahedron • Box • Card • Capsule • Tetrahedron Mesh • 16頂点以下のMesh 129 129 さらにおまけで16頂点以下のMeshもサポートされてたりします。 パーティクルだからSphereだけ、ということはないです。 大事なのは地面に自立可能な多面体が使用できるという点です。 129

131.

地面との接触 130 130 さて、そんな多面体と地面の接触に関して想像しましょう。 130

132.

地面との接触 131 131 131

133.

地面との接触 132 132 通常地面と接触する場合は角、辺、面などをそれぞれ見ていく必要があります。 が、 132

134.

地面との接触 133 133 すでに重すぎます。 VORTEXELではこれを 133

135.

地面との接触 134 134 角とPlaneの交差にまで落とし込みます。 134

136.

地面との接触 中心点がいるボクセルの短距離SDF情報を参照 凸凹があるとめり込む事はもちろんある 135 135 このPlaneはパーティクルの中心点のいるボクセルのSDFから構築されます。 隣接するボクセルがデコボコしてたらもちろんめり込みます。 が、小さい物体のめり込みなんてまず気になりません。 135

137.

接触と法線 接触の検出は簡単 136 136 SDFから衝突情報を算出する場合は注意点があります。 接触の検出自体は非常に簡単です 136

138.

接触と法線 接触の検出は簡単 • SDFから1点だけ距離をサンプル • (距離 – 外接球の半径)が0.0以下なら接触 └ 外接球は後述します 137 137 SDFから一点だけ距離をサンプルして、距離 - 外接球の半径が0以下なら接触とみなせます。 ここで出てきた外接球に関してはまた後程 しかし 137

139.

接触と法線 接触の検出は簡単 • SDFから1点だけ距離をサンプル • (距離 – 外接球の半径)が0.0以下なら接触 └ 外接球は後述します 法線の算出は難しい • Marching Cubes法でトライアングルを構築 └ トライアングルを構築して判定は流石に重い Marching Cubes法では 1ボクセルで最大5枚のトライアングルを生成 138 138 法線の算出は難しいです。 SDFを可視化するときに用いられるMarching Cubes法ですがこれでトライアングルに展開して全トライアングルと接触判定は流石につらいです。 もう一つ 138

140.

接触と法線 接触の検出は簡単 • SDFから1点だけ距離をサンプル • (距離 – 外接球の半径)が0.0以下なら接触 └ 外接球は後述します 法線の算出は難しい • Marching Cubes法でトライアングルを構築 └ トライアングルを構築して判定は流石に重い • ごくわずかに離れた位置で数回 サンプリングして計算 └ 複数回サンプリングしたくない Marching Cubes法では 1ボクセルで最大5枚のトライアングルを生成 139 139 ごくわずかに離れた位置を再サンプリングして計算する方法がありますが、正直複数回サンプルもしたくないです。 ではどうするか 139

141.
[beta]
代表法線
ボクセル毎にただ一つの法線を決定する
• とても軽い!

float3 calcOcclusionNormal(float corner[8]) {
float3 v = float3(0, 0, 0);
v += float3(-1, -1, -1) * corner[0];
v += float3(+1, -1, -1) * corner[1];
v += float3(-1, +1, -1) * corner[2];
v += float3(+1, +1, -1) * corner[3];
v += float3(-1, -1, +1) * corner[4];
v += float3(+1, -1, +1) * corner[5];
v += float3(-1, +1, +1) * corner[6];
v += float3(+1, +1, +1) * corner[7];
// 0割りを回避しながら normalize
return v / max(length(v), 0.00001);
}

法線

サーフェス

法線は「normalize( ∑(中心点から角までのベクトル * 距離) )」で求める

140
140

代表法線と個人的に呼んでいるものを求めます。
SDFをサンプリングするときにボクセルの角8点を既にロードしているのでこれを再利用します。
角8点に向かう方向に距離値をかけてすべて合算し、最後にNormalizeすると代表法線が求まります。
ただし、

140

142.
[beta]
代表法線
ボクセル毎にただ一つの法線を決定する
• とても軽い!
• 正確ではない法線が発生する

float3 calcOcclusionNormal(float corner[8]) {
float3 v = float3(0, 0, 0);
v += float3(-1, -1, -1) * corner[0];
v += float3(+1, -1, -1) * corner[1];
v += float3(-1, +1, -1) * corner[2];
v += float3(+1, +1, -1) * corner[3];
v += float3(-1, -1, +1) * corner[4];
v += float3(+1, -1, +1) * corner[5];
v += float3(-1, +1, +1) * corner[6];
v += float3(+1, +1, +1) * corner[7];
// 0割りを回避しながら normalize
return v / max(length(v), 0.00001);
}

法線

サーフェス

同じ距離に向き合うように2つの
サーフェスが生成される場合は0法線

法線は「normalize( ∑(中心点から角までのベクトル * 距離) )」で求める

141
141

これはあくまで簡易的な計算なので必ずしも正しい法線が得られるわけではありません。
特にMarching Cubes法において複数のトライアングルを生成するようなボクセルで一本しか法線が取れないことになります。

141

143.
[beta]
代表法線
ボクセル毎にただ一つの法線を決定する
• とても軽い!
• 正確ではない法線が発生する
└ 軽さ最優先

float3 calcOcclusionNormal(float corner[8]) {
float3 v = float3(0, 0, 0);
v += float3(-1, -1, -1) * corner[0];
v += float3(+1, -1, -1) * corner[1];
v += float3(-1, +1, -1) * corner[2];
v += float3(+1, +1, -1) * corner[3];
v += float3(-1, -1, +1) * corner[4];
v += float3(+1, -1, +1) * corner[5];
v += float3(-1, +1, +1) * corner[6];
v += float3(+1, +1, +1) * corner[7];
// 0割りを回避しながら normalize
return v / max(length(v), 0.00001);
}

法線

同じ距離に向き合うように2つの
サーフェスが生成される場合は0法線

サーフェス

法線は「normalize( ∑(中心点から角までのベクトル * 距離) )」で求める

142
142

しかしそれを許容してでも軽さを優先しています。

142

144.

代表法線 143 143 実際に可視化するとこんな感じ。 ちゃんと壁の外側に矢印が向いていることがわかるかと思います。 143

145.

形状とPlaneの衝突 144 144 これで法線と接触点が取れたのでこの二つでPlaneを生成します。 そのあと各形状との衝突を行うのですがこれはすべての形状で同じ処理、 144

146.

形状とPlaneの衝突 全頂点 to Planeでの衝突判定 • 頂点はシェーダーに焼きこまれている └ グローバルメモリアクセスが無い! └ 形状ごとのシェーダーバリエーション による最適化 145 145 つまり全頂点とPlaneの衝突で判定します。 ただし各頂点はシェーダーに直接焼きこまれているため、グローバルメモリのアクセスは発生しません。 形状ごとにシェーダーバリエーションが生成されるようになっており、ついでに各形状で出来る古典的な最適化も入ってます。 145

147.

形状とPlaneの衝突 全頂点 to Planeでの衝突判定 • 頂点はシェーダーに焼きこまれている └ グローバルメモリアクセスが無い! └ 形状ごとのシェーダーバリエーション による最適化 Meshの場合のみ、グローバルメモリからロード 146 146 ただしMeshに関してはグローバルメモリからロードしています。 そのためこちらは多少コストはかかりますが、明確な形をもった状態から崩す場合に便利です。 146

148.

形状とPlaneの衝突 全頂点 to Planeでの衝突判定 • 頂点はシェーダーに焼きこまれている └ グローバルメモリアクセスが無い! └ 形状ごとのシェーダーバリエーション による最適化 Meshの場合のみ、グローバルメモリからロード • 利便性向上のため重複座標の 刈り取りもリアルタイムで初回だけ行っている 147 147 便利ついでに初回利用時は重複位置にいる頂点は刈り取るような機能も入れています。 後からわかった事ですがDCCツールで事前に色々設定しないと位置は重複しているが法線が違うから別頂点扱いになる場合が多く アーティストのトラブルシューティングが大変になりそうだったのでいれています。 147

149.

外接球と内接球 形状を完全に内包する球 ▼ 外接球 148 148 次に先ほど少し触れた外接球、ついでに内接球について。 これは幾何学用語に出てくるものと大体一緒で、ここでは形状を完全に覆う球というニュアンスです。 この球の半径を用いて、SDFで構築される壁との接触判定を行います。 ただし、この後さらに各頂点と先ほど構築したPlaneの接触判定を行う必要があることは忘れないでください。 さてそれに対して、 148

150.

外接球と内接球 形状を完全に内包する球 ▼ 外接球 形状に完全に内包される球 ▼ 内接球 149 149 こちらが内接球です。 外接球とは反対に形状に完全に内包「される」球です。 なぜ触れたかと言えば、こちらが次につながる重要な要素だからです。 149

151.

パーティクル同士の衝突 150 150 というわけでパーティクル同士の衝突についてお話いたします。 VORTEXELでは壁とパーティクルだけではなく、パーティクル同士の相互干渉もサポートしています。 しかしパーティクル同士の衝突も地面の時と同じく角、辺、面などをそれぞれ見ていく必要があります。 が、 150

152.

パーティクル同士の衝突 151 151 もちろんこちらもそんなことやってられないので 151

153.

パーティクル同士の衝突 152 152 パーティクル同士の衝突は完全に球同士のみの判定にします。 ここで先ほどの内接球が使用されます。形状は一切見ません。 そのため 152

154.

パーティクル同士の衝突 153 153 横⾧の物は見かけ上すごくめり込みますがやはりエフェクトという特性上そこまで気になりません。 153

155.

パーティクル同士の衝突 154 154 そしてこれがその結果です。 154

156.

パーティクル同士の衝突 155 155 いかがでしょう? パーティクル同士は本当に球形状同士でしか行っていません。 ボックス同士のめり込みは気になりますか? この時点で個人的に求めていたクオリティが達成できました。 155

157.

動的なコリジョン 地形更新は1フレームに 実行できる範囲が限られている • 武器やモンスターのコリジョンも取りたい • 扉や動的に動くものにも反応したい 動的コリジョン • プロシージャルな形状限定 • 風の遮蔽も有効 156 156 地形とパーティクルの衝突が取れますが、まだ必要な衝突があります。 それは武器やモンスター等の衝突です。 小石は敵の体で跳ねてほしいし、大剣の切り上げで小石もつき上げたいです。 しかし先にも話した通り、コリジョンのラスタライズは1フレームに1回で範囲も限られているので難しいです。 そのために動的コリジョンも実装されています。 こちらはプロシージャルな形状限定となりますが毎フレーム更新が可能です。 風の遮蔽としても機能します。 156

158.

パフォーマンス PlayStation5 での10,000 パーティクル のコスト • 相互干渉有り:+0.06ms • 相互干渉無し:+0.03ms ゲーム中に10,000も パーティクルは出ない • 攻撃から出る破片は100パーティクル弱 • つまりほぼノーコストで常用可能 →「気軽に使っていいよ」 ※開発当時の検証映像 157 157 気になるパフォーマンスに関してもお話ししておきましょう。 10,000パーティクルを PlayStation5 で出した時、物理演算シミュレーション有りと無しの差は 相互干渉有りで+0.06ms 相互干渉無しで+0.03ms この密度感、この量でです。 しかしゲーム中に10,000パーティクルも出すことはないです。出ても攻撃から100個破片が出るくらい。 つまりほぼノーコストで常用可能と言えます。 なのでアーティストには「気軽に使っていいよ」とアナウンスを出しました。 157

159.

結果、あらゆる物に使ってもらえた! • 大量の髑髏 • 叩きつけで出る小石 • ライトボウガン等の薬莢 • etc… 158 158 結果、あらゆる物に使ってもらえました。 『⿁武者WS』では大量の髑髏による演出、 『モンスターハンターワイルズ』では叩きつけによる小石、そしてライトボウガン等の薬莢。 あらゆる場所で利用されています。 158

160.

利用例 あまりにも気軽に使えるのでガンランスのパイル分離にも使われている • 大量に出せるGPU Particleとしてのアドバンテージはないが開発工数を大幅に低減 159 159 あまりにも気軽に使えるのでガンランスのパイル分離なんかにも使われてます。 正直パーツが少ないのでGPU Particleとしてのアドバンテージはないのですが、代わりに開発工数の低減に一役買っています。 159

161.

利用例 焚火料理のハーブにも! • 肉に動的コリジョンが仕込まれている 一瞬コリジョンが見える 160 160 焚火料理のハーブなんかにも使われてます。 小回りが利きますし実装もしやすいので実装工数の低減ができ、大量の物量をさばく一助となったと伺っています。 160

162.

葉っぱの嘘物理 風 風 風 161 161 さて、もう一つ、エフェクトのための嘘物理についても触れておきます。 VORTEXELの風シミュレーション精度は1m単位なので、 葉っぱのような場合は風が葉っぱの下に潜り込んでひっくり返す、ということはできません。 出来ても 回転せず真横にスライド移動するだけです。 161

163.

Wakeup Over Reaction 安定状態から外力が働いたら"オーバーなリアクション"を取るように • エフェクト向けに作られてるからできる"嘘挙動" 162 162 なので葉っぱのような薄いものに舞ってもらうためにWakeup Over Reactionという機能を入れています。 これを有効にすると安定状態から外力が働いたら"オーバーなリアクション"を取るようになります。 どうですかこの風圧! これこそエフェクト向けに作られてるからこそできる嘘挙動という感じです。 162

164.

最終形態 • Turbulenceと組み合わせると めちゃめちゃすごい! • チームへの共有時に かなり評判が良かった うれしい! ※開発当時の検証映像 163 163 さて、ここまでの機能を組み合わせたらどうなるのか、 開発当時の検証時の動画がこちらとなっています。 これです!これが見たかった! これを初めてアーティストに見せてもらった時、安っぽい表現ですが私は「次世代感」を感じました。 ああ、ついにここまでできる時代が来たんだなと。 とにかく、Turbulenceと組み合わせるとめちゃくちゃすごいです。 最後の飾りのプロペラで葉っぱを掃く表現も非常にユニークです。 そして何より空気感や風をしっかり感じられるのが素晴らしいです。 アーティスト側でチームへ共有したときもかなり評判が良かったとうかがっており個人的にも非常に嬉しかったです。 163

165.

SNSでの反応 • チャタカブラの叩きつけの小石の一個一個物理演算かかってる!(PVの反応) • ガンランスの薬莢が体に当たって弾かれる! • レ・ダウの巣の大量の小石が蹴れる!? ゲーム性とは関係ないエフェクト単体で面白さが提供できたのは個人的には満足 164 164 ベータテストや製品版ではSNSで楽しんでもらえていたところを見させていただきました。とても嬉しかったです。 ゲーム性とは関係ないエフェクト単体で面白さが提供できたので個人的には非常に満足しております。 164

166.

165 165 使いやすさについて工夫した点もお話しさせてください。 165

167.

アーティストフレンドリーな設計 166 166 VORTEXEL周りの使いやすさとして自分の中の理想が一つあって それが 166

168.

アーティストフレンドリーな設計 Click to Go 167 167 Click To Goという考えです。 と言っても何か既にある言葉というわけではなく自分が頭の中で考えた用語で、たぶん既に似た概念はあるはずです。 167

169.

アーティストフレンドリーな設計 Click to Go 1クリックですぐに使用できる状態にする 168 168 とにかく1クリックあるいは1アクションしたらすぐに使用できる状態にしたいと考えていろいろと工夫しました。 168

170.

アーティストフレンドリーな設計 Click to Go 1クリックですぐに使用できる状態にする 少なくとも試用検証が非常に簡単! 169 169 そうすることで試用検証が非常に簡単になり、導入コストや参入障壁が取り払われます。 169

171.

アーティストフレンドリーな設計 Click to Go 1クリックですぐに使用できる状態にする 少なくとも試用検証が非常に簡単! 流石に製品仕様では調整したほうが良い 170 170 といっても流石にそのまま最後まで行くのは難しいのでちゃんと調整できるようにもしています。 170

172.

アーティストフレンドリーな設計 チェックボックスを入れるだけ • 冒頭で述べた通りCPU側の既存の当たり判定を利用 • 事前ベイクなども不要 └ あとは処理負荷と相談して構築範囲などの調整をするだけ 171 171 まずはVORTEXEL自体の機能を有効化する方法です。 動画中のマウスカーソルをご覧ください。チェックボックスを入れるだけです。 初期検証するだけならプログラマ対応も必要ありません。 冒頭で述べた通りCPU側の既存の当たり判定を利用しているので事前ベイクなども不要です。 あとはアーティストは普段通りエフェクトエディタをつかってコリジョンアイテムを入れるだけです。 171

173.

アーティストフレンドリーな設計 エフェクトではアイテムを入れるだけ • とりあえず跳ねるようになる 172 172 エフェクトで実際に使用する場合もアイテムを一個入れるだけで転がって跳ねるようになっています。 この時に設定されるデフォルトパラメータもちょうどよい値が最初から設定されています。 172

174.

高度な物理パラメータをマスク 質量すらマスク対象 • Advanced Settingsを有効にすると出る 旧来のエフェクトのパラメータ調整で「重さの表現」ができる • 基本的に同じエミッター内の同一質量の物体としか接触しないので 質量で「重さの表現」はあまりできない 173 173 さらにパラメータのうち、高度と考えてる一部物理パラメータをマスクしています。 というのも複雑で多様な物理パラメータは正直物理挙動の利用においては障壁になりうると個人的に考えているためです。 何だったら質量ですら初期状態ではマスクしています。 形状の変化しない剛体物理において、同じ質量同士の物体では質量を上げても動作は変わらないですし、 エフェクトにおける重さの表現はVelocityアイテムの減衰率で表現することがとても多いのでそちらを制御したほうが直感的だと考えています。 つまるところアーティストは慣れ親しんだ今まで通りのエフェクトのパラメータ調整を行うだけでそれっぽい物理挙動を設定できるというわけです。 173

175.

174 174 さてここからは、より幅広い環境で動かすための拡張に関してご紹介します。 174

176.

より幅広い環境で動かすために 必要VRAM • 全部合わせても100MB未満 └ Geometryで65MB └ Turbulenceで20MB └ 残りは他モジュール ※いずれもデフォルト値での計測であり、タイトルごとに調整されてます 175 175 先にも述べましたが導入コストはできるだけ安く設計しているつもりです。 特に必要VRAMは全部合わせても100MB未満です。およそ4Kテクスチャ2枚分以下です。 175

177.

より幅広い環境で動かすために 必要VRAM • 全部合わせても100MB未満 └ Geometryで65MB └ Turbulenceで20MB └ 残りは他モジュール 処理時間 • TurbulenceはVORTEXELの中では"比較的"コストがお高め └ 風の3次元流体計算が原因 └ PlayStation5では0.6ms程 └ Async Computeによって裏で動作 ※いずれもデフォルト値での計測であり、タイトルごとに調整されてます 176 176 しかし処理時間に限っていえば、これらの中でもTurbulenceは比較的重い部類になります。 3次元の流体計算は処理する要素数と反復回数が多いのでやはり重くなりがちです。 176

178.

重要度の考察 エフェクト自体が削減対象に挙がりやすい… 177 177 そして残念なことにVORTEXEL関係なく、そもそもエフェクト自体が削減対象に挙がりやすいという悲しい背景があります。 現実は厳しいです。ならばいっそ 177

179.

重要度の考察 エフェクト自体が削減対象に挙がりやすい… • いっそのことシミュレーション自体を無効化できるようにしよう! → 品質は落ちるが選択肢があるということが大事 178 178 エフェクトがほとんど表示されなくなるなら開き直ってシミュレーション自体を無効化できるようにしよう!となりました。 かなり本末転倒に聞こえますが、選択肢があるという事が大事なのです。 178

180.

重要度の考察 エフェクト自体が削減対象に挙がりやすい… • いっそのことシミュレーション自体を無効化できるようにしよう! → 品質は落ちるが選択肢があるということが大事 • あとからシミュレーション消して大丈夫…? 179 179 しかし、削減を迫られるのは決まって開発終盤です。 開発終盤にいきなりシミュレーションを無くすとかなり見た目が変わってしまいます。 流石にそれは良くないのである程度見た目を担保出来るように手を加えています。 179

181.

Turbulenceの風シミュレーションのオミット対応 範囲外風のシステムを拡張 • 常にWind Emitterを直接サンプルするように └ 爆風とかはちゃんとインタラクションできる • 遮蔽率も常にチェック └ シミュレーション無しでも壁付近は風が吹かない 180 180 まず出発点としてシミュレーション範囲外を管理しているシステムを拡張して全域で常に直接参照できるようにしました。 小手先の調整機能として微妙な減衰、微妙な範囲の拡張用係数も利用可能です。 遮蔽率も常にチェックされるので壁付近で風が吹かない機能も引き続き利用可能です。 180

182.

Turbulenceの風シミュレーションのオミット対応 範囲外風のシステムを拡張 • 常にWind Emitterを直接サンプルするように └ 爆風とかはちゃんとインタラクションできる • 遮蔽率も常にチェック └ シミュレーション無しでも壁付近は風が吹かない Indoor Mask • 遮蔽率の低い広い屋内でも風を吹かないようにする機能 • 元々3D Textureにキャッシュしていた └ 全域で直接サンプルできるように拡張 181 181 他にもIndoor Maskという機能にも手が入っています。 これは遮蔽率が低い「広い屋内」で風が吹かないように屋内としてマークする機能で、 実は前から入っていたのですが、こちらも全域で参照できるようにしました。 シミュレーション有りと比べれば差異がいろいろ出てきますが、 今回はエフェクト自体が削減されているという事情と勘案して妥当な見た目に抑えられるだけの機能がはいったと思います。 181

183.

Geometryの局所利用 容量的にも削減したい… • Geometryの65MBを何とか減らしたい └ 分散実行されているがそのわずかな処理時間も減らせる 182 182 その次は、想像以上にメモリ環境が厳しくなった昨今、Geometryのメモリも削減検討がなされました。 基本戦術としては構築範囲を狭めることである程度のメモリ削減が図れますが、 182

184.

Geometryの局所利用 容量的にも削減したい… • Geometryの65MBを何とか減らしたい └ 分散実行されているがそのわずかな処理時間も減らせる Geometryの構築範囲を手動制御可能に • 導入のしやすさのために自動構築がデフォルト動作だった → 特定エリアをピンポイントで処理できるように 183 183 より突き詰めたい場合のために局所的に手動構築できるようにしました。 もともとは導入のしやすさを重視して自動で構築処理が走るようにしていましたが、 これをOFFにするフラグを用意し、タイトル側でAABBをクエリするとその範囲だけを構築してくれます。 コリジョン頼みで配置されていたエフェクトや、印象的なパーティクルコリジョンのあるステージなどのためにGeometry自体を後からOFFにするのは難しいですが、 逆にそういった場所のみピンポイントで構築してしまえば他は妥協できるわけです。 183

185.

Geometryの局所利用 ⿁武者WSでは一部ボス部屋は常に構築 • そのほかのエリアはターゲットスペックによる 184 184 『⿁武者WS』では一部ボス部屋は常に構築するように手が入れられています。 そのほかのエリアはターゲットスペックによって構築するか無効化するかを切り替えています。 184

186.

185 185 ここまでがVORTEXELの内容に関する説明でした。 この後はおまけ話です。 185

187.

2025年 大阪・関西万博で公開されていた 体験型コンテンツのモンスターハンター関連作品 186 186 じつは、2025年に大阪・関西万博で公開されていた体験型コンテンツである『モンスターハンターブリッジ』でもVORTEXELが利用されていました。 186

188.

開発終盤にエフェクトの クオリティアップで必要に • モンスターの動きに合わせて 岩の破片を動かしたり煙を風圧で流したり • 自分は使われているのを知らなかった └ ほぼノーサポートで導入できたということに 187 187 開発終盤にエフェクトのクオリティアップで必要になったとのことで、モンスターの動きに合わせて岩の破片を動かしたり煙を風圧で流したりする際に利用されているとのことで す。 正直自分は使われているのを知らず、後から聞いて驚きました。 つまるところほぼノーサポートで導入できた事例となりました。 現在は公開が終了していますが、今後移設展示されることが公表されていますので、 もし行く際はエフェクトの動きなんかを気にするのも楽しみ方の一つになるかもしれません。 187

189.

初期構想 実はMHW:IBの開発開始頃に思い付きで実装 • といっても開発フロー的にこのタイミングで載せてもあまり効果が無いのでお蔵入りに ※2018年MHW:IB開発環境で撮影 188 188 最初期の構想に関しても少しだけ。 実は『モンスターハンター:ワールド アイスボーン』の開発開始頃に思い付きで実装してたりします。 といっても開発フロー的に今から載せても活用しきれない、となったのでお蔵入りに。 映像は古代樹の森での検証動画となっています。 なのでだいぶ前から構想されていたことが伝わるかと思います。 188

190.

初期構想 当初はメモリ量を恐れて1ボクセルあたり1bitのSDFをCPUで構築 • 驚いた事に1bit単位ならPlayStation4環境のCPUでも1秒かからず全域を構築できる! • かわりに勾配が45度単位でカクカクしてる ※2018年MHW:IB開発環境で撮影 189 189 当初はメモリ量を恐れて1ボクセルあたり1bitのSDFをCPUで構築していました。 驚いた事に1bit単位ならPlayStation4のCPUでも1秒かからず全域を構築できました。 かわりに勾配が45度単位でカクカクしていますが、それでもパーティクルは地形に沿って流すことができました。 この頃から非常に可能性を感じていましたね。 そんな感じの思い出話でした。 189

191.

最後に この数年間VORTEXELについてずっと語りたかった! 個人的にも非常に満足のいくプロダクトが作れた 素晴らしいエフェクトを作ってくれたアーティストの皆様にも感謝 皆様に何かしらの刺激になれば幸いです! 190 190 というわけでVORTEXELについての講演でした。 正直もっとたくさん語りたいことがあるのですが残念ながらここまでです。 この数年間ずっとずっと語りたくて仕方がなかった内容であり、CEDEC発表時も非常に多くの好評をいただきましたので、今回再び皆様にお話しする機会ができて良かっ たです。 個人的にも非常に満足のいくプロダクトが作れたと思っています。 そしてこのVORTEXELを使って数々のすばらしいエフェクトを作ってくれたアーティストの皆様にも感謝しています。 今回の講演が皆様にとって何かしらの刺激になれば幸いです! 190