UDN
Search public documentation:

VFXOptimizationResultsJP
English Translation
中国翻译
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 ホーム > パーティクルとエフェクト > パーティクルシステム > 「Unreal Engine 3」における VFX の最適化 > VFX の最適化 : 結果を得る
UE3 ホーム > FX アーティスト > 「Unreal Engine 3」における VFX の最適化 > VFX の最適化 : 結果を得る

VFX の最適化 : 結果を得る


Cascade におけるコアシステム - GPU/ ゲームスレッド / レンダリングスレッド


Cascade (カスケード) は、「Unreal Engine 3」における 3 つの中心的なエンジンシステムに広がる動的なコストを要する堅牢なパーティクルシステムを作成します。その 3 つの中心的なエンジンシステムとは、ゲームスレッド、レンダリングスレッド、GPU のことです。

  • パーティクルシミュレーション時間 (ティック) は、ゲームスレッド (gamethread) 上で計算されます。
  • パーティクルデータのファイナライズ (ジオメトリ、描画コールのパック化) は、レンダリングスレッドで計算されます。
  • パーティクルのビジュアル (シェーダー複雑度、オーバードロー) は、GPU で計算されます。

これらのシステムすべてが、互いと並行して計算を実行します。したがって、どれか 1 つでも速度が遅くなったシステムがあれば、それは、レンダリングプロセス全体のボトルネックとなります。すなわち、フレームレートが低下するということになります。Cascade でパーティクルシステムを作成する際は、これら 3 つのプロセスについて考慮することが重要です。

また、Casucade は、ゲームスレッド上でパーティクルの評価を行いますが、ゲームスレッドはゲームプレイが計算される場所でもあることに注意すべきです。パーティクルの数は、フレームレートを適正な範囲に収めるために非常に重要なものとなります。

オーバードロー - GPU


あなたが経験豊富なエフェクトアーティストであるならば (あるいは、まだ 2 週間しか経験のないエフェクトアーティストであっても)、オーバードローのことは、すでに耳にしたことがあるでしょう。

最も単純化してオーバードローについて説明するならば、次のようになります。

オーバードロー=ピクセルシェーダーのコスト=レイヤー数×レイヤーによって影響を受ける平均ピクセル数×レイヤーのための平均インストラクション (命令) 数

基本的には、マテリアルをスプライトのサーフェスに追加する場合、そのマテリアルのインストラクション数に応じてコストがかかります。(「Unreal Engine 3」では、コンテンツブラウザおよびマテリアルエディタでこれを表示することができます)。透過オブジェクトについては、透過処理が積み重なってオーバードローを作るため、インストラクションによるコストが嵩みます。透過処理のレイヤーが増えるにしたがって、コストが高くなります。このコストは、シェーダー複雑度のビューモードを使って簡単に表示することができます。明るい赤= 300 インストラクション、ピンク= 600 インストラクション、白= 900 インストラクション。PC 上でシェーダー複雑度を表示するには、F5 キーを押します。

シェーダー複雑度のビューモードによって、システムのおよそのコストが算出されますが、このコストはシーンにも依存します。それというのも、透過処理が、やはりコストをもつ不透明なオブジェクトを背景にして計算されるからです。

エフェクトの使用法をチェックすることは、欠かせないことです。通常、任意のシナリオ (武器の衝撃) で呼び出されるエフェクトは、カスタムビルドすることによって、特定のシナリオにマッチさせるようなエフェクトよりも軽くなければなりません。理由は、コストが変動するシナリオで描画されるためです。

オーバードローの影響を制御するために取ることができる処置は、次のようになります。

  1. エミッションのレートを下げる。
  2. マテリアルのインストラクション数を減らす。
  3. パーティクルのスケールを下げる。(スクリーンのより狭い範囲をフィルする)
  4. 近く / 遠くのパーティクルエミッションのための LOD を作成することによって、さまざまな視界距離におけるコストを下げる。
  5. 一列に配置されたエミッタが、互いに重なり合っていないかチェックする。(静的な、配置されたエフェクト)。

LOD -Level of Detail(詳細度)- GPU/ゲームスレッド


Cascade において LOD を使用することによって、プレイヤーからエミッタまでの距離に基づいて、モジュールとビヘイビアを制御することができます。パーティクルシステムのどの属性 (attribute) であっても変更することによって、LOD システムを使用するようにできます。

LOD の設定に関する技術的な詳細については、 Cascade ユーザーガイド の中にある パーティクルシステムの Level of Detail (LOD) のセクションを参照してください。

LOD を作成する場合は、共有されていないモジュールに関連してメモリコストが生じることに留意しなければなりません。複数の LOD にまたがってできるだけ多くのモジュールを共有すると、メモリの使用量を減らすことができます。ユニークなモジュール設定項目を作成するのは、属性を変更する場合にのみ行うようにします。

Cascade のプレビューモードとエディタのパースペクティブ (透視図法) ビューは、さまざまな点でビヘイビアが異なります。Cascade で適切に表示させるには、エディタのプレビューモードが無効になっていることを確認してください。(下図の丸で囲んだ部分)。

lodpreview.jpg

Cascade では、LOD を切り替えて、特定の LOD を表示することができます。Cascade を正しく更新させるためには、エディタの LOD ビューモードを必ず無効にしなければなりません。

エディタのプレビューを有効にして、シーン内をすばやく移動すると、パーティクルシステムがその移動に合わせて複数の LOD を切り替える様子を表示させることができます。(上図の丸で囲んだ部分)。

シーンを測定することによって、適切な状態でエフェクトを表示させるのに必要となる単位数について、実際的な値を得ることが大切です。アンビエントパーティクルシステムの場合は、パーティクルシステムが見えないときに、0.00 のパーティクルをエミットし、ティック時間を減らすことが可能です。距離を測定するには、マウスの中ボタンを押下したまま、いずれかの正投影ビューポート (正面、側面、上面) にドラッグします。

LOD Distance Check Time (LOD 距離チェック時間)

この機能は、プレイヤーからシーン内に配置されたエミッタまでの距離をゲームがチェックする頻度を規定します。(この距離は、使用すべき LOD を決定するために使用されます)。LOD Distance Check Time (LOD 距離チェック時間) は、Automatic (自動) にセットされている場合に有効です。

基本的に、automatic にセットすることによって、LOD がゲームによってプレイ時に決定されます。この LOD Distance Check Time (LOD 距離チェック時間) を大きくすると、チェックの間隔が長くなります。LOD Distance Check Time (LOD 距離チェック時間) は秒で計算されるので、これをセットする場合は、プレイヤーの最大移動速度を考慮する必要があります。LOD Distance Check Time (LOD 距離チェック時間) を 0.00 の値にセットすると、距離が毎フレームごとにチェックされることになり、パフォーマンスは低下します。

LOD のメソッド - ゲームスレッド

パフォーマンスとビジュアルにとって、LOD のメソッドを適切に設定することは不可欠です。

Automatic (自動) - ゲームが、LOD Distance Check Time (LOD 距離チェック時間) を使用して、エフェクト内で定義された距離パラメータに基づく LOD をセットします。通常、ゲームコードによって呼び出されないループするアンビエント (環境) エフェクトで使用されます。

Direct Set (直接設定) - エフェクトが、定められた LOD にスポーンされてとどまっている場合に、(通常はゲームコードによって) LOD が決定されます。普通は、爆発や衝撃などのバースト (破裂的) エフェクトで使用されます。

Activate Automatic (自動のアクティベート) - LOD で定義された距離パラメータに基づき、エフェクトがスポーンされたときに LOD が定義されます。通常、いったんスポーンされると LOD を二度と変更する必要がない、Kismet などによって呼び出される突発的なエフェクトで使用されます。

固定境界と非固定境界 - ゲームスレッド

境界 (bound) は、エンジンがエフェクトのビジビリティ (表示 / 非表示) を決定できる方法の 1 つです。そのような目には見えない座標によって、エフェクトが表示されるのか表示されないのかを、エンジンが知ることができるのです。境界の隅がビジブル (表示) になっている場合は、エンジンが、必要なエフェクトのあらゆるコンポーネントを計算します。

毎フレームごとにチェックおよび更新される境界は、コストが高くつきます。したがって、境界を固定 (fixed) にセットして、必要な境界の大きさを決定することが重要となります。たとえば、爆発から飛び散った残がいをすべて表示しなければならない場合などでは、境界をかなり大きくする必要があります。コストを抑えるには、境界を中心となるコンポーネントに制限することによって、パフォーマンスを向上させることができます。ただし、その場合、境界が視界領域から外れた場合に、エフェクトが突然非表示になるという欠点があります。

固定境界にすべきか非固定境界にすべきかをを決定するには、考慮しなければならない事項がいくつかあります。

ロケットのトレイル (ロケット雲) や追跡物、発射物に付属するものなどのようなエフェクトを高速で動かす場合は、固定境界をセットすべきではありません。あるいは、大きな固定境界をセットすることによってエミッタが境界の外に飛んで行かないようにすべきです。

境界を設定する場合は、システムで定義されているワールド空間座標とローカル座標について注意を払わなければなりません。エミッタが境界の向きと反対の方向に回転している場合は、エフェクトの要素が、境界の外に飛び出してしまい、要素が、視界領域から突然消えてしまう可能性があります。

描画コール - レンダリングスレッド


パーティクルシステム内の描画コールは、時として追跡が難しいことがあります。描画コールのコストを計算する場合は、複数の要因がからんでいることに留意すべきです。

パーティクルエミッションは、スクリーンの向きにかかわらず、エミッタにつき 1 描画コールにあたります。

メッシュエミッションは、エミットされるメッシュにつき 1 描画コールにあたります。したがって、エフェクト内に 2 つのエミッタがあり、それぞれ 10 個のメッシュをエミットするならば、そのパーティクルシステムに関して合計で 20 描画コールのコストがかかることになります。

マテリアルのパスも描画コールのコストにかかわります。マテリアル内でパスが多くなるにつれて、エフェクト内の描画コールも多くなります。

以下にその例をあげます。

  • パーティクルシステム A が、1 個のパスをもつマテリアルを使用して、12 個のスプライトをスポーンさせる 1 個のエミッタから構成されている場合、パーティクルシステム全体のコストは、1 描画コールということになる。
  • パーティクルシステム B が、2 個のパスをもつマテリアルを使用して、12 個のスプライトをスポーンさせる 1 個のエミッタから構成されている場合、パーティクルシステム全体のコストは、2 描画コールということになる。
  • パーティクルシステム C が、2 個のパスをもつマテリアルを使用して、12 個のメッシュをスポーンさせる 1 個のエミッタから構成されている場合、パーティクルシステム全体のコストは、24 描画コールということになる。(1 コールにつき 2 個のパス × 12 個のメッシュ (各メッシュは 1 描画コールであるため) = 24 描画コール)。
  • パーティクルシステム D が、 2 個のパスをもつマテリアルを使用して、6 個のメッシュをスポーンさせる 1 個のエミッタ、および、1 個のパスをもつ 10 個のスプライトをスポーンさせる 1 個のエミッタから構成されている場合、パーティクルシステム全体のコストは、13 描画コールということになる。(1 コールにつき 2 個のパス × 6 個のメッシュ (各メッシュは 1 描画コールであるため) = 12 描画コール、1 個のパス × 10 個のスプライト = 1 描画コール)。

パスに寄与するマテリアルの属性には、以下のようなものがあります。

透過マテリアル=1 パスベース

  • 歪み (distortion) は、+2
  • bUseLitTranslucencyDepthPass (光源処理透過デプスパスを使用する) は、+1
  • bUseLitTranslucencyPostRenderDepthPass (光源処理透過性ポストレンダリングデプスパスの使用) は、+1
  • bUsedWithFogVolumes (フォグボリュームとともに使用) は、+2

不透明 / マスク化マテリアル=2 パスベース

特定のシーンのための描画コールを表示するには、 DumpParticleFrameRenderingStats (パーティクルフレームレンダリング統計のダンプ) コマンドを使用します。このコマンドは、描画コールのコストを詳細にリスト表示したスプレッドシートを出力します。

描画コールによる影響は、レンダリングされているビューの数に比例して強まります。つまり、分割スクリーンでは、その影響が倍になるということです。分割スクリーンのためのエフェクトの最適化に関する詳細については、 VFX の最適化 : 分割スクリーン のページを参照してください。

エフェクトを作成する場合、および、エフェクトを最適化する場合は、以上にあげたコストに留意することが大切です。レンダリングスレッドのコストが描画コールのために高くなり、なおかつ、背景がコスト配分内にある場合は、このことから検討してみる必要があります。

メッシュエミッション = ゲームスレッド / レンダリングスレッド


メッシュエミッション (mesh emission) は、Cascade がもつ非常に強力な機能のうちの 1 つですが、誤って使用する可能性のある機能でもあります。メッシュを使用する場合は、描画コールに関連する上記数値に留意しなければなりません。エミッションのレートは、描画コールの数に合致します。メッシュ上にある頂点の数を多くしないことも、有効です。

場合によっては、単一のメッシュエミッションを使用することによって、インスタンスのために大量の残がいを作成するのに必要となるスプライトすべての位置を計算するというコストをかけずに、多量のオブジェクトをフェイクすること可能となります。

コリジョン - ゲームスレッド


パーティクルコリジョンは、通常「Unreal Engine 3」において高いコストがかかるため、必要な場合に限って使用するようにしなければなりません。

ただし、Collision Actor (コリジョンアクタ) モジュールを使用してワールド内の衝突すべきオブジェクトを指定することによって、コリジョンのコストを抑えることができる場合もあります。これは、通常、Kismet のアクションを通じて行われます。あるいは、エミッタアクタがワールド内に配置されるとともに、アクタのインスタンスパラメータによって衝突すべきシーン内の特定のオブジェクトを定義することが可能なスクリプトを通じて行われます。このタイプのコリジョンを設定する方法については、 アクタ単位のパーティクルコリジョン のページを参照してください。

コリジョンのコストを最小に抑えるために使用できる設定項目には、次のようなものがあります。

  1. MaxCollisions (最大コリジョン): この値をできるだけ小さくします。
  2. Collision Completion Option (コリジョン完了オプション): これを HaltCollisions/Freeze (コリジョン停止 / フリーズ) に設定することによって、MaxCollisions (最大コリジョン) に達したときにシーンのコリジョンチェックを中止させます。
  3. Damping Factor (減衰係数) によって、コリジョンに続いて起きるオブジェクトの跳ね返り (bounce) が決定されます。この値が低くなるほど、オブジェクトの静止が早くなります。(MaxCollisions の値を低めます)。

Spawn Per Unit (単位当たりのスポーン) - GPU/ ゲームスレッド


Spawn Per Unit (単位当たりのスポーン) は、パーティクルシステムが動いているときにギャップをフィル (fill) するのに役立つ Cascade の機能です。Spawn Per Unit (単位当たりのスポーン) は、見栄えがするパーティクルのトレイル (trail) を作るのに便利ですが、この機能を使用する場合は、パフォーマンス上の制限とビジュアルのバランスを取る必要があります。

エミッションをコントロールするには、いくつかこつがあります。

  1. Unit Scalar (単位スカラー) をできるだけ高い値に保つとともに、この値とエミッションレートとのバランスを取ることによって、エフェクトを重くしすぎずに、必要なフィルが得られるようにする。
  2. Spawn Per Unit (単位当たりのスポーン) を使用して高いエミッションレートになることが分かっている場合は、なるべく少ないインストラクションのマテリアルを使用する。
  3. Max Frame Distance (最大フレーム間隔) を調整して、エミット可能なパーティクルの数を制限する。エミッタがこの Max Frame Distance (最大フレーム間隔) を超えた場合は、その間隔を下回るようになるまで、Spawn Per Unit (単位当たりのスポーン) がミッションを中止します。これによって、エミッタが大量のスプライトをシーンにダンプしないようになります。

メモリコスト


Cascade には、パーティクルシステムの作成にかかわる貴重な情報を大量に表示できる機能が備わっています。この表示機能を有効にすることによって、システムで割り当てられているパーティクルの数およびシステムがエミットしているパーティクルの数について適切に把握できるため、役立つことが多いです。

Particle Allocation (パーティクルの割り当て) によって、エミッタが任意の時間にワールド内に配置できるパーティクルの数が決まります。これは、パーティクルシステムによって消費されるメモリを計算するのに大いに役立ちます。メモリの概算を見るには、Cascade 内の [View] (ビュー) ドロップダウンメニューで、パーティクルのメモリオーバーレイ表示を有効にします。

設定値を調整することによって、メモリコストの増減を確認することができます。

メモリ使用量を減らす方法には、次のようなものがあります。

  1. システム内にあるモジュールの数を、当該ビヘイビアのために必要不可欠なモジュールまで減らす。
  2. ループエフェクトについては、Loop Time/Duration (ループ時間 / 期間) を減らす。(ループ当たりのパーティクル割り当て数を減らす)。
  3. ライフタイムを減らす。(全体としてのパーティクル数を減らす)。
  4. できるかぎり多くのモジュールを共有する。

Cascade の特徴として、あるエミッタから別のエミッタへとモジュールを共有させる機能があります。この機能には 2 つの利点があります。 第一に、複数のエミッタにまたがって値を編集したい場合に、1 個のモジュールを編集して残り全部のモジュールは更新させることができます。第二に、モジュールを共有化することによってメモリ使用量が減ります。これは、クック済みバージョンが、モジュールのコストをモジュールの 1 個のインスタンスとして見なすためです。

より最近になってクッカに追加された機能を使用すると、パーティクルシステム内のモジュールをすべて評価して同一モジュールを判定し、さらに、自動的にモジュールを共有化することによって、メモリ使用量をクック時に減らすことができます。

ティック時間 - ゲームスレッド


Tick Time (ティック時間) は、シーン内でパーティクルシステムを更新するのに費やされた時間です。Tick Time は stat particles (統計パーティクル) コマンドを使用して見ることができます。このコマンドは、パーティクルの評価コストに必要な関連情報をすべてリスト表示するものです。

Tick のコストを減らすためには、多数の方法があります。

Tick Time は、シーン内のアクティブなエミッタアクタの数から直接影響を受けます。シーン内にアクティブなエミッタが増えるほど、Tick Time は大きくなります。エミッタは、レベルがスタートしてループしなければならない場合、必ず autoActivate (自動アクティベート) にセットされるべきです。

大量のスプライト / 爆発 / バーストエフェクトが、エディタ内でレベルロード時にビジブル (可視的) になっているならば、これらのエフェクトは自動的に実行時に評価されて、レベルがロードされると処理落ちが目につく場合があります。

エフェクト内で パーティクルパラメータ (Particle Parameter) を使用することによって、エフェクトがワールド内に配置されると、位置のオフセットが可能になります。パーティクルパラメータを使って、エミッタの数を減らすことができるため、Tick の全体的なコストを下げることができます。パーティクルパラメータは、個々の設定項目のためのモジュール内にある [desitribution] (分布) リストから Particle Parameter を選択することによって設定できます。

エミッタアクタは、視界に入っていない場合や、モメリにもはやロードされていないレベルの部分に関係する場合に、ストリームアウトして無効にすることができます。レベルジオメトリとともにエミッタアクタをストリームすることによって、Tick のオーバーヘッド減らすのは、有効なやり方です。大気に関する (atmospheric) エフェクトが重い場合には、Kismet のアクションを使用して、戦闘中に大気 (atmosphere) の on/off を切り替えることによって、Tick Time とオーバードローを抑えることができます。

パーティクルシステムがメモリにロードされているものの、視界から外れている場合 (たとえば、上の階にあるなどの場合) は、Kismet のアクションとボリュームのストリーミングでそのパーティクルシステムを切り替えることによって、評価のコストを減らすことができます。

メッシュエフェクトをパーティクルシステムの代わりにすることができる場合があります。配置された静的メッシュは、ゲームスレッド上で評価のコストがかかりません。静的メッシュをパーティクルシステムの代わりに配置した方が多くの場合においてより得になります。 これには、眺望 (vista) エフェクトやフォグ (fog) エフェクトなどが含まれます。

パーティクルの数は評価コストに直接影響します。シーン内でパーティクルの数が増えれば、また、パーティクルが長く生き続ければ、その分だけ一層評価が必要となります。ライフスパンを、エフェクトに必要となる期間だけに限定することは、あらゆる点で効果的です。

パーティクルシステム内で LOD を有効にすることによって、システムが最適な視界の範囲から外れている場合に、パーティクルエミッションを下げることができます。主人公の視点からエフェクトを検討するとともに、視点が遠くにある場合に容認できるクオリティ低下のレベルについて考えることによって、役立つ場合があります。LOD を、必要とされている距離に厳格に合わせるならば、シーン内で評価コストを下げるのに役立ち、ビジュアルのクオリティが劇的に低下することもありません。

下げることができる高負荷な評価コスト (たとえば、コリジョン、非固定境界、高すぎるコストの単位当たりのスポーンなど) について、エフェクトを点検してみましょう。境界を固定した状態にセットすることによって、パフォーマンスを著しく向上させることができます。可能な場合はいつでもこれを利用すべきです。

非平行光源のコスト - ゲームスレッド


非平行光源を使用すると、ワールド内でトレースを実行してシーンにスポーンしたエミッタ周囲の光源情報を判定することによって、パーティクルエフェクトに深みとリアリティをもたらすことができます。非平行光源は、ゲームスレッドの評価コストがかかります。非平行光源の用途としては、武器のエフェクト、衝撃のエフェクト、キャラクターのエフェクト、アンビエントフォグエフェクト、Bink シネマティックエフェクトである場合が多いです。

パーティクルのカラーをライト環境に適合させる別の方法しとしては、 パーティクルパラメータ (Particle Parameter) を使用して、アクタ単位にカラーとアルファを調整するというやり方があります。配置されたアンビエントエフェクトが決して動くことがない場合は、その上でパーティクルパラメータを使用することによって、コストをいくらか削減することができます。

  1. メモリ内にエフェクトのユニークなカラー種を保存するためのコスト
  2. 実行時にユニークなカラー種をロードするためのコスト
  3. Cascade 内で各カラー種を作成するためのコスト
  4. エフェクトを光源処理して、ゲームスレッド上で非平行光源と環境をマッチさせるのにかかるコスト

パフォーマンスが許す場合は、なるべく非平行光源を使用するのがよいでしょう。パフォーマンス上の制約によって、この方法を取らざるを得ない場合には、パーティクルパラメータを使用することによってエフェクトを設定すると、役に立つことがあります。

「Unreal Engine 3」における VFX の最適化 に戻る。