【UE5】マテリアル最適化Tips

今回は Unreal Engineでのマテリアルを最適化する方法について書きます。

最適化の方針を決める

部分的な最適化は可能ですが、まずはプロジェクト全体で統一した方針を決めておくと、無駄なく効率的な最適化を行えます。

最適化の方針の重要な項目は以下の2つです。

  1. ゲーム内オブジェクトの重要度・優先度をランク付けする
  2. インスタンス(1体)が画面内で占める描画領域を考慮する

これらの指標を基準として、どこに工数をかけるべきか、どの部分を安く済ませるかを明確にしておきます。

ゲーム内オブジェクトの重要度・優先度をランク付けする

「すべてを最優先で見せたい」ができれば理想ですが、ハードウェアの性能には限界があるため、すべてを最高品質にすることは現実的ではありません

例えば、以下の観点でオブジェクトの重要度を分類します。

種類説明優先度
繰り返し大量に見るエフェクト(ヒットエフェクトなど)プレイヤーが高頻度で目にするため、見栄えが重要非常に高い
イベント内で一度きりしか登場しない背景ゲーム体験に影響するが、繰り返し見られない中程度
フレーバー的・探索要素の小物視界の片隅にあることが多く、注目度が低い低い
Information

基本的に重要度や優先度の高いものは時間をかけて作り込み、そうでないものはあまり時間をかけないようにします。

それによって、ゲーム内の表現で大切なものをしっかりとプレイヤーに見せることができる作業時間が確保できるためです。

インスタンス(1体)が画面内で占める描画領域を考慮する

優先度・重要度とは別に、「同時に表示されるインスタンス数」「画面の占有率」を考慮する必要があります。

マテリアルで重くなりやすい処理

優先度が決まったら、実際にマテリアルで重くなる部分を検証します。

対応優先度

マテリアルで重くなりやすく、対処を優先すべきは以下の表のとおりとなります。(対応を優先したい順)

項目概要最適化手法
1. テクスチャサンプリング「高解像度のテクスチャ ✕ サンプリング回数」
最も負荷が大きく、高解像度テクスチャを
複数回参照するとコストが倍増する
Normal / Maskを統合するStaticSwitch / SwitchParameterを使用するサンプラー共有設定を行うMip制御 (レベル) を入れる優先度に基づいて解像度を見直す
2. 半透明・Dither (ディザリング)UEの構造上、かなり重い描画パスとなる必要ないものは極力使わない (StaticSwitchで抑制など)
3. If文とSwitchParam分岐処理は実行順を阻害するのでGPUで重くなるLerpなどに置き換える
4. Noise (ノイズ)ALU計算量が多いので重たい必要ないものは極力使わない (StaticSwitchで抑制など)
事前にTextureにする (ベイク)
5. Pow (指数計算)ALU負荷が高いので、低い指数でも負荷が高い低い指数なら "x * x" で代用する
6. Devuce (除算)割り算は重たい掛け算 (Multiply) に置き換える

1. テクスチャサンプリング

テクスチャサンプリングはメモリアクセスが発生するため、圧倒的に重くなりやすいです。特に、高解像度のテクスチャをサンプリングするほど重くなり、サンプリング回数も影響します。

そのため、画面影響度が高いものは限界まで切り詰めるのをおすすめします。

サンプリング回数を減らす方法はいくつかありますが、簡単に対応しやすい方法を以下に紹介します。

Normal / Mask などのテクスチャを統合 (Packing)

空いているチャンネルに詰め込んでテクスチャを減らすことで、サンプリング回数 (Samleノード数) を減らせます。

Packingの例としては以下のものが考えられます。

  • R: Roughness (ラフネス)
  • G: Metalic (メタリック)
  • B: AO (アンビエントオクリュージョン)
  • A: Mask

StaticSwitch / SwitchParameter を使用する

StaticSwitchノードは、コンパイル段階でつながらない場合に自動で削除され最適化されます。

同じマテリアルを複数の対象に使用したいときはこれを積極的に使うと良いです。

Information

これに対して、Ifノードはランタイムで分岐するため最適化処理されません

サンプラー共有設定を行う

同じテクスチャを2回以上参照している場合は、必ずサンプラー共有設定を行ってください。この設定を行うことで、サンプリング回数が1回で済むようになります。

特にマテリアルファンクション内でサンプリングする場合はこれを行った方がよいです。(使用用途によって調整します)

"Automatic View Mip Bias" (Mipレベルの自動調整) から以下の項目を選びます。

  • Shared Wrap: 共有Wrapサンプラーを使用する
  • Shared Clamp: 共有Clampサンプラーを使用する

Mip制御 (レベル)

遠景メッシュに対して非常に有効です。またUnlit系の場合も効果的。

場合によってはカスタムミップを作るのも有効です。

テクスチャ解像度の見直し

画面占有率の低いオブジェクトに高解像度はあまり意味がないので、低解像度にするのがおすすめです。

2. 半透明 / Dither (ディザリング)

UEでは、「透明処理」だけ別パス (Translucency Pass) で処理されます。また Depth Prepass が効かないため オーバードロー (重複ピクセル描画) が発生し、無駄なピクセルシェーダーが実行されてしまいます。

そのため、必要ないものは極力使わないようにしましょう。(StaticSwitch のON/OFFで抑制するなど)

3. If文や SwitchParam (動的分岐)

GPUは SIMD (同時実行) 構造ですが、分岐処理が発生すると分岐する両方のノードが実行され命令数が増えることがあります。

そのため、置き換え可能であれば “Lerp” ノードを使って補間するようにした方がよいです。

ただし、テクスチャのサンプル数に制限をかける場合、こちらのノードの方が軽い場合があります。高解像度のテクスチャをサンプルする場合はどちらのノードも試してみて、効果の高い方を選択します。

4. Noise (ノイズ)

ノイズは大量の ALU計算(補間・乱数生成)が入るため、テクスチャ1枚のサンプルよりも重くなりやすいです。

対策としては以下のものが考えられます。

  • StaticSwitchで ON/OFF する
  • 事前にTexture にして焼き込む (ベイク)
  • 不要なノイズスクロールは削除する

5. Pow (指数)

指数計算は複数段階の ALU演算が入るため重いです。

そこで、

  • 低い指数ならx*xで掛け算にする
  • 大きい数値はStaticパラメータにする

など極力使わない方針が良いです。

ただ Powでなければできない処理もある(もしくはPowを避けるとノードが複雑になる)場合は、使用して問題ありません。

6. Device (除算)

割り算は重いので基本的には使わず、掛け算 (Multiply) をするようにしたほうがよいです。

(”÷2″ を “*0.5” に置き換えるなど)

おしまい

マテリアルの最適化Tipsでした。

以上、マテリアルの最適化に役立てれば幸いです。

\ 最新情報をチェック /