テクスチャ最適化のテクニック
概要
メモリとディスクスペースをどのように使用するかという問題は、あらゆるゲームを開発する場合に避けて通ることができない問題です。 コンテンツがメモリとディスクスペースを大量に占有する場合は、使用されているテクスチャがその最大の原因となりやすいです。これは、多くの場合、周到な計画を立てることなく、チャンネルパック化を効率的に使用せずにテクスチャをプールに追加したことに起因しています。
本ドキュメントでは、予め (プロジェクトの最後にではなく)、非効率的なテクスチャを排除し、よりスマートで効率的なコンテンツを作成するための秘訣について説明します。
コンテンツの評価
開発中にディスクスペースの問題が起きた場合は、ディスクに乗せてコンテンツの評価を実行することによって、節約が可能となる部分を発見することができる場合があります。通常、大部分が目視による確認に基づくため、すばやく実行することができます。汎用ブラウザでパッケージ内のテクスチャを調べることによって、ただちに、どこでスペースが無駄に使用されているのかわかります。
例
マスターマテリアルのデフォルト
時として不必要に大きいテクスチャがゲームのコンテンツに入るようなエリアがある場合は、マスターマテリアルの使用によります。マスターマテリアル内のテクスチャ サンプル パラメータを使用すると、テクスチャはそのパラメータが適用されなければなりません。しかし、これは多くの場合に見られません。子マテリアルがパラメータをオーバーライドしてそれ固有のニーズに合わせるためです。
表示されている、パッケージ内の T_Test_Mask テクスチャが良い例です。マスターマテリアルを調べることによって、テクスチャ サンプル パラメータに適用されていることが分かります。
このテクスチャは、512x512 のテクスチャであり、マスターマテリアルの中でデフォルトとして適用されること以外に、けっして現実のゲーム内で使用されたり見かけたりすることはありません。問題は、子マテリアルがオーバーライドするか否かにかかわらず、マスターマテリアル内のどんなテクスチャでも子マテリアルに入ってしまうということにあります。この問題は簡単に解決することができます。そのためには、このテクスチャを、シンプルな 8x8 ピクセルの黒いテクスチャに置き換えます。これは、一般のパッケージに保存され、同様な設定をもつあらゆるマスターマテリアルによって再利用されます。さらに次のことにも注意してください。マスターマテリアルが、法線マップのために使用されるテクスチャ サンプル パラメータをもつ場合、別個のプレースホルダーテクスチャを使用する必要があります。これは、法線マップのためのプレースホルダーとして法線マップがつねに必要となるためです。
マテリアルの参照をチェックする
マテリアルをプロファイルする場合は、チャンネルパックの一部ではない (すなわち、RGB イメージにおいて単一のチャンネルではない) エディタのためのテクスチャに注意する必要があります。これらは、浪費の主要な候補であり、簡単に改善することができます。以下にその例を示します。
このエフェクトは、グレイスケール テクスチャのようなものの RGB output を使用しており、テクスチャは明らかにチャンネルパックされたテクスチャの一部にはなっていません。さらに詳しく調べるには、これをブラウザに同期させます。そのためには、テクスチャサンプルの Texture
(テクスチャ) プロパティのための
ボタンをクリックします。このケースではテクスチャが 512x512 のノイズタイルであることが分かります。
つぎの段階として、このテクスチャを使用しているマテリアルが他にないかどうかを調べます。テクスチャを右クリックして、コンテクストメニューから Find All Materials Using This Texture (このテクスチャを使用しているすべてのマテリアルを見つける) を選択します。問題となっているテクスチャを使用するマテリアルからなる集合が作成されるため、このコマンドは非常に役立ちます。初回起動時には時間がかかります。(ゲームのコンテンツのサイズに応じて、インスタンスによっては 5 分ほどもかかることがあります)。ただし、初回以降の起動については、たいてい高速です。
マテリアルの集合が生成されたら、それを選択して、当該のテクスチャを参照しているマテリアルには他に何があるかを調べます。
この例では、多数のマテリアルがあるため、ゲームの多くの部分で使用されている可能性が高い。これを削除することが有益であるということは示されていませんが、今後最適化がさらに必要となる場合に備えておぼえておかなければなりません。
チャンネル パック化と統合
先のパッケージをよく調べてみると、このうち 3 つのテクスチャでスペースを浪費している可能性が目につきます。
これらはどれも 1024x1024 のエミッシブ テクスチャであり、3 つのカラーチャンネルが使用されています。また、各テクスチャのうちほんの少しの部分しか実際には使用されていないことに注目してください。これらの黒いピクセルのすべてがメモリを不必要に占有しているのです。これは二重の問題ですが、解決するのは容易です。すなわち、各テクスチャを単一のチャンネルに置くことによって、これらテクスチャを単一のテクスチャにパックするとともに、トリミングすることによってピクセルの数をできるだけ少なくします。
エミッシブ テクスチャはこの最適化のケースにうってつけです。ソフトであり、簡単にトリミングでき、詳細な部分がそれほど多くありません。マテリアル全体の外見にあまり大きな影響を与えないのが普通です。もちろん、そうでない場合は、そのテクスチャと状況にとって理想的な最適化とは言えなくなるでしょう。
これらのエミッシブ テクスチャをトリミングしてから「チャンネルパック」(channel pack) を実行することによって、スペースとメモリを大幅に節約することができます。まず、すべてのエミッシブをトリミングして 256x256 の領域に合うようにします。特定の状況においては、単純なトリミングでは済まない場合があります。たとえば、水平軸および垂直軸に沿ってトリミングし、さらに残りの軸に沿ってスケーリングしてテクスチャを押しつぶすことが必要となる場合があります。さらに、マテリアルの中で押しつぶしを元に戻して正しく見えるかチェックします。ソフトなエミッシブ テクスチャであれば正常に見えるはずです。ただし、ハードエッジのエミッシブではそれほどうまく機能しません。
ここで、これら 3 個のエミッシブを Photoshop でチャンネルパックします。つまり、まとめられた 3 チャンネル テクスチャのカラーチャンネル内にそれぞれを保存することになります。
テクスチャをチャンネルパックする場合に役立つことがあります。わたしたちが使用している圧縮形式は DXT1 であるため、その圧縮スキームの働きによって、テクスチャの緑のチャンネルに余分なデータが保存されます。したがって、高周波細部に値するエミッシブや精妙なエミッシブの場合は、最高のクオリティのために緑のチャンネルに置きます。
256 にトリミングしても、まだかなり無駄なスペースが含まれている可能性があります。スペースがあり、テクスチャがトリミングされてマテリアルの中でオフセットされている場合は、クオリティを高めてみてはどうでしょうか。テクスチャの高解像度ソースアートをとることによって、エミッシブの高解像度バージョンを下げ、同じ量のスペースを使用しながらそのチャンネルのクオリティを上げることができます。
また、「たとえば 第 4 のエミッシブを含める場合、別のチャンネルをテクスチャに追加してみてはどうだろうか」と、考えている場合も注意すべきです。 その場合問題となるのは、第 4 のチャンネルのテクスチャが DXT1 ではなく DXT5 として圧縮するということです。DXT5 の問題は、圧縮的な観点から見るとアルファチャンネルがフル解像度であるということです。つまり、3 つのカラーチャンネルを合わせたのと同じだけのメモリを使用するということになります! だから DXT5 のコストが高いのです。
この時点で、チャンネルパックされたテクスチャを保存しインポートすることができます。
ここで、マスターマテリアルをセットアップして、エミッシブテクスチャをトリミングおよびオフセットできるようにします。これによってシェーダーの複雑度がやや上がりますが (6 命令)、おそらく、テクスチャプールがすでに嵩んでいるため、この命令分に値するはずです。
マスターシェーダーがテクスチャ遅延されている (つまりピクセセルシェーダーの命令を実行するよりもテクスチャサンプルを処理するのに時間を要する) ことが分かっている場合、命令を数個加えてもパフォーマンスにはまったく影響がありません。このことは、マテリアルの PIX キャプチャをとって、Microsoft のパフォーマンス分析ツールを使用すれば分かります。
最初、シェーダーはこのエミッシブテクスチャをそのままの状態でとります。
このテクスチャをマテリアル上でオフセットし動かすことができるようにする必要があります。そこで、シンプルなシェーダー演算を加えることによって、これらのケースを処理します。その場合、マテリアル インスタンス毎にパラメータを使います。
(フルサイズの表示には画像をクリック)
静的スイッチのパラメータ (Static Switch Parameter) によって、インスタンス単位でトリミングされたエミッシブを使用すべきかどうか決めることができるようになります。 静的スイッチは、バイナリスイッチとして機能します。つまり、チェックを入れると A の input に入るシェーダー文のみ利用します。チェックを外すと、B の中にあるものを使用します。すなわちオプトインするまで、パフォーマンスの負荷が追加されないことになります。
_スイッチについて役に立つことがあります。 スイッチに名前を付ける場合はつねに動詞を使ってください。 つまり、スイッチを切り替えることからアクションを作るのです。これによって、初めてこのマテリアルを見た人でも両方のオプションの意味が分かります。たとえば、CroppedEmissive (トリミングされたエミッシブ) という名前をスイッチにつけていたならば、シェーダーを見ても、どちらのオプションがどちらの状態を意味するか分からなかったでしょう。 UseCroppedEmissive (トリミングされたエミッシブを使用する) という名前が付いているからこそ、だれもが一目で、スイッチにアクションがともない、名前だけでどの状態にあるかが分かり、値がチェックされているか否かも分かるのです。スイッチに名前を付けるときは必ず動詞を使うようにしましょう。
ここにあるパラメータは分かりやすいものです。 Char_Emissive_CropOffset という名前のパラメータは、エミッシブの発光の X 座標と Y 座標を操作するためのものです。また、X および Y のスケールパラメータによって、一方の軸上で個別にテクスチャをスケーリングすることが可能になります。これによって、どのようなエミッシブテクスチャでも押しつぶしを解除することができます。
この演算を改善して、命令を 1 つや 2 つ節約する方法はいくつかあります。ただし、この方法が優れているのは、さまざまなオプションがあることをだれもが分かるからです。
つぎに、パックされたテクスチャの RGB チャンネルのうちどのチャンネルを使用するか選択できるようにしなければなりません。 StaticComponentMaskParameter (静的コンポーネント マスク パラメータ) 式をマテリアルに追加することによって、新たなパックされたテクスチャ内にあるカラーチャンネルのどれであっても選んで使用することができるようになります。そのためには、シェーダーチェーンにおいて 3 つのチャンネルのうち 1 つだけを渡すようにします。
さてこれで、マスターシェーダー上で apply (適用する) をクリックして、親としてマスターを使用するインスタンスの 1 つを開きます。これによって、変更が適切に働いているかテストしてみることができます。
まず、トリミングされたエミッシブを使用するための静的スイッチを有効にします。
つぎに、新たなパックされたテクスチャをエミッシブのスロットに適用します。
使用するカラーチャンネルを選択します。(この場合は赤です)。
スケールパラメータを 2 にセットして、エミッシブがマテリアル上で正しいサイズになるようにします。
あまりよくは見えませんね。なぜでしょうか? テクスチャがクランプ (固定) されていないためです! デフォルトでは、「Unreal Engine 3」にインポートされる新しいテクスチャは、そのテクスチャのプロパティの中で、WRAP (ラップ) にセットされています。すなわち、テクスチャがタイリングする場合、繰り返されることになります。ブラウザの中でテクスチャをダブルクリックして、CLAMP (クランプ) にセットします。
そのまま、次のフラグもセットします。
テクスチャのエッジピクセルがすべて黒であるため、どのミップレベルが表示されているかにかかわらず、つねに黒のままであることになります。これによって、非常に遠く離れた場合にテクスチャが汚れることがなくなります。
良くなりました! つぎに、パラメータを使ってテクスチャをオフセットします。しっかりと見れば通常は充分なのですが、必要であれば、Photoshop において計算をして、ボックスに入れる正確なトリミングの値を出すことができます。この例では、まったくの偶然ですが、オフセットなしで正しく配置できています。
マテリアルインスタンス内でエミッシブカラーを変更して、チェックを入れます。
新たなパックされたテクスチャを使用する他のマテリアルインスタンス上でも同じプロセスを実行します。最終的な結果はつぎのようになりました。
つぎに、使用しないテクスチャを取り除きます。そのためには、Consolidate (統合) コマンドを使用します。
3 つの古いテクスチャと作成した新たなテクスチャを選択します。
右クリックして Consolidate を選択します。 これによってこれら 3 つが削除され、永久に第 4 のテクスチャにリダイレクトされます。これはパッケージをまたいで実行することができますが、安全のために、前もってあらゆるものをチェックしてください。 この操作はやり直すことができませんので、充分気をつけてください!
つぎのダイアログボックスが現れます。
新たなパックされたエミッシブを選択して、
ボタンをクリックします。新たなテクスチャだけが残り、他の 3 つのテクスチャは永久に削除されます。繰り返しますが、 注意してください! 深刻な問題を引き起こす可能性があります! 必ずパッケージを保存するようにしてください。
最後に
- UV をパックする場合は、互いにエミッシブを近づけてパックするようにしてください! それによってトリミングとメモリの節約が容易になります。
- このようなことを最初に準備することによって、最終的には苦労せずに済みます。
- シェーダー複雑度のトレードオフがメモリの節約に見合わない場合があります。かなりまれなことであり、個別的な事象です。 ほとんどの場合、いくらかの節約と釣り合いが取れます。
- エミッシブをトリミングしない場合であっても、チャンネルパック化は有効な考え方であり、クオリティがそのままならば余分なシェーダー計算はまったく行われません。
- Consolidate... および Find All Materials Using This Texture (このテクスチャを使用しているマテリアルをすべて探す) は強力なツールです。
Important!
You are viewing documentation for the Unreal Development Kit (UDK).
If you are looking for the Unreal Engine 4 documentation, please visit the Unreal Engine 4 Documentation site.