Unity3D + NGUIでのテクスチャ圧縮の使用

こんにちはKhabrovchane!



これが私の最初ですが、Habrに関する最後の投稿ではないことを願っていますので、厳密に判断しないでください。



Heyworksで実装に成功し、Pocket Troopsプロジェクト(The Expendables)で使用した開発を共有したいと思います。 すべての開発者が遭遇し、直面している問題は、NGUIとUnity3dだけでなく、他のエンジンとパッケージでも動作しますが、ゲームインターフェースの品質と重量の中間点を見つけることです(ただし、これはインターフェースだけではありません)。 この記事では、1つの石で2羽の鳥を殺すのを手伝います。



まず第一に、 レオポタム同志に、彼が記事の議論で私たちに提出したというアイデアをありがとうございます。それは彼のせいです。 私たちはこのアイデアを開発し、NGUIシェーダーに代わるものを作成し、生活を簡素化するユーティリティをいくつか作成しました。 ビルドサイズで獲得したバイト数、より複雑なシェーダーを使用して失われたナノ秒数の測定は開始しません。実行したすべての作業に価値があると言うだけです-アートとしての勝利は肉眼で見える また、この記事はNGUIに関連付けられているという事実にもかかわらず、ここで説明するアプローチはUIだけでなく、任意のテクスチャで正常に使用できることに注意してください。 対応するシェーダーを記述するだけで十分です。 しかし、私は急いでいます。他から始めたいと思ったからです。



私たちのプロジェクトには多くの地図があります。 つまり、視覚的な品質とビルドサイズの選択は、特にiOSの100MBの寸前で、私たちにとって非常に鋭いものでした。



ここに、たとえば、すべてのスキルアイコンと一般的なグラフィックスを含むメインアトラスがあります







また、ストアアイコンが付いたストアアトラスと、改善アイコンが付いた2つの改善アトラスもあります。 合計4つのアトラス2048x2048。 そして、これは制限ではありません、アート部門は最近私たちを喜ばせるように...



まさにそこに疑いの余地はありません-アトラスを刈り取る必要があります。 そしてここで最初の問題が浮かび上がります-PVRTCは自信を持ってiOSのみをサポートしますが、一部のAndroidはそれを保持しますが、一部はサポートしないため、デバイスの1つがPVRTCを理解せず、非圧縮テクスチャで動作し始めた場合、メモリからのクラッシュに備えてください。 実際、最初はこの状況に耐えなければなりませんでした。 圧縮サポートの問題に加えて、PVRTCはグラデーションの透明度と透明度への移行を視覚的に提供します。 ただし、このために小さなハックがありました。 テクスチャを取得し、Photoshopで開いて、グレーで塗りつぶされた新しいレイヤーを配置し、その上にノイズを適用します(ノイズを追加12.5%)、ブレンド方法を設定します-柔らかな光、レイヤーのほとんど目立たない透明度(通常20-40%)、およびマスクを適用します透明な領域にノイズが適用されないように、アルファテクスチャ。 ( 別のHeyworks従業員による記事の写真について詳しく読むことができます)しかし、これはノイズを100%除去しませんでした。特に、透明性への移行時にアーティファクトが見られました。 特に「ノイズの多い」スプライトは、非圧縮のアトラスに割り当てる必要がありました。 要するに、彼らができる限り最高の回転。



それで、私たちは今の所に来た、あるいはむしろ、急に跳ね上がりました。 そしてそれについてさらに詳しく。



Leopotamが提案する方法の本質は、アトラスのテクスチャからアルファチャネルを選択し、RGBテクスチャに既に圧縮を適用することです。 これは、まず第一に、ノイズから私たちを救い、また、アルファチャンネルを持つテクスチャでは利用できなかったアンドロイドでETC圧縮を使用することを可能にします。



しかし、アルファをどうするか? 最初のオプションは、Alpha8テクスチャの使用を示唆しています(ただし、すべてのiOSデバイスが適切に動作するわけではありませんが、かなり前のようで、真実ではないようです)。 2番目のオプション-プロジェクトに1〜4個のアトラスがある場合、 r、g、bから個別のテクスチャを使用できます。 そのチャネルは各アトラスのスプライトの透明度に関する情報を取得します(アトラスが3つ未満の場合、このテクスチャはRGBになります) 。



4つのアトラスのアルファチャネルを1つのテクスチャに配置すると、このようなサイケデリックが得られます。





ただし、結果のテクスチャの合計サイズを測定すると、少し失われます。 品質の顕著な改善が魂を温めるので、怖くない。 しかし、私たちはそこで止まりません。 最初に、アルファチャネルを持つテクスチャを取得し、16ビットにします。 この容量は必要な情報を送信するのに十分であり、視覚的に違いに気付くことはありません。 次に、対応するアトラスの半分のサイズ(つまり、2kアトラスの場合は1k)のアルファテクスチャを使用した場合、視覚的には目立ちませんが、ボリュームのゲインは次のようになります。 4回!



合理的な質問-アトラスの場合の対処方法-5つ以上? このためのリソースもあります。 結局、アルファテクスチャを4倍に削減しました。つまり、4x4 = 16アトラスだけを正方形に広げることができます。 もちろん、アトラスの1つを変更するたびにこのような巨人的な作業を手動で行うことは、ありがたい仕事です。 これを行うために、アトラスからアルファチャネルを収集し、それをアルファテクスチャに分解し、マテリアルをセットアップするスクリプトを作成しました-アルファチャネル選択マスクと各マテリアルのテクスチャ座標のシフト。 ただし、NGUIがアトラスと連携する方法には、微妙な点が1つあります。 実際、たとえば、アトラスが変更されると、新しいスプライトが追加されます。スプライトをシャッフルするときのNGUIは、元のテクスチャでは機能せず、そのコピーがアトラスでベイク処理されます。 ただし、アトラスはRGBとしてマークされているため、NGUIがアトラスからスプライトを読み取ると、すべての透明度情報が失われます。 ここでは、NGUIを掘り下げる必要がありますが、これは私が本当に望んでいないことです。 そして、2つの方法を実行しました。 最初は、アトラス内の何かを変更する前に呼び出されます。 彼はリストのすべてのアトラスをRGBAとしてマークし、NGUIが適切に機能するようにします。 2番目の方法は、アトラスからアルファチャンネルを「取得」し、それらを個別のテクスチャに分解し、必要に応じてそれとアトラスマテリアルの両方を設定し、アトラスをRGBで再度返します。



はい、マテリアル、またはシェーダーについて少し説明します。 NGUIシェーダーを取り、それを少し書き直して、アトラステクスチャのアルファチャネルからではなく、マスクで選択された特定のアルファテクスチャチャネルからアルファを読み取るようにしました。







ここで、NGUIを操作するもう1つの微妙さが私たちを苦しめました。 実際には、同じUIをレンダリングするために、同じシェーダーのいくつかの変更が使用されているように見えます。 ClippingPanelを使用する場合-内部でUIを切り取る方法は、置き換えられるシェーダーの変更を設定するだけです。 そして、これはSoftClipまたはAlphaClip(シェーダーの変更に応じて名前が付けられます)であるため、これらのシェーダーも微調整する必要があります。 最初の実験ではこの瞬間を考慮せず、機能しないスクロール可能なリストを受け取りました。 さらに、新しいバージョンのNGUIでは、すべてが一般的に異なる動作をします。シェーダーには、これまで掘り下げていない原則に従って番号が付けられています。



これは何のためですか?



-現在、UIはPVRTCおよびETC圧縮の影響を受けていないように見えます。圧縮アーティファクトは可能な限り排除されました

-圧縮サイズのアトラスを使用したバージョンと比較しても、ビルドサイズが大幅に減少しました。それらを取得しないとどうなるかはわかりません

-アトラスを使用するプロセスは少し複雑ですが、その日が来て、私たちは完全自動化に来ると信じています

-シェーダーでの不必要な操作により、ビデオカードの計算サイクルが追加されたと確信していますが、これまでのところ誰も違いを見ていません



参照により、私は愛と好意をお願いします:



-アトラスを処理し、アルファテクスチャを収集するスクリプト

-記事に記載されているすべてのシェーダー

-システムを構成する資産-処理するアトラス資料を配布する必要があります。



このシステム全体で、私たちは常に作業、テスト、修正を行い、すべての変更が常にビットパックに収まるようにします(感謝しないで構いません)。 スクリプトはもちろんプロダクション品質のものではありません。特にアルファテクスチャへのパスなど、いくつかの定数を微調整する必要がありますが、これには困難があるとは思いません。



この資料が誰かにとって非常に役立つことを本当に願っています。 コメント、改善の提案、建設的な批判を楽しみにしています。



よろしくお願いします!



All Articles