_CameraDepthTextureに関する疑問

今回の主な話題:_CameraDepthTextureに関する疑問、テクスチャAlphaチャネルが画像サイズへの影響、URPがGrabPass効果を達成する方法、AssetDatabaseロードに失敗したAssetのInstance IDの取得方法、Bundleファイルがメモリにロードするタイミングの判断方法。


Rending

_CameraDepthTextureに関する1つの疑問があります。

_CameraDepthTextureをオンにさせると、深度マップを実現するために、Cameraがシーン内のShadowCasterを使用しているすべての可視オブジェクトをレンダリングする必要があります。

ただし、シーン内のオブジェクトは、ZWriteがオンになっているときに、深度をDepth Bufferに書き込みます。このDepth Bufferを直接取得する方が、DrawCallに比べたらほぼ2倍効率的じゃないですか?それとも、Unityはこの方面で何か考えがありますか?

また、より実際的な質問をします。

私達のプロジェクトにはシーン内の湖の深度効果をレンダリング する必要があります。すべての不透明シーンオブジェクトのマテリアルは、ShadowCasterのある同じShaderに関連しています。ただし、まだ水に入っている個別のオブジェクトがShadowCasterのPassをレンダリングする必要があります。何かShaderを増えず状況で水に入っているオブジェクトがShadow Caster Passをレンダリングしない方法ありませんか?私達はBuilt-inのレンダリングパイプラインを使用しています。

1つ目の質問は、この質問にあるUnity公式スタッフの回答を参照できます。

ここでは2つの原因が述べってあります。1つは、非フルスクリーンレンダリングの場合、元々カメラレンダリングに対応する深度を取得したかったのですが、Depth Bufferはフルスクリーンであります。2番目の原因は。多くのプラットフォームがDepth Bufferのデータを直接取得することをサポートしていないためです。

リファレンスページ:

https://forum.unity.com/threads/poor-performance-of-updatedepthtexture-why-is-it-even-needed.197455/

そして、FrameBufferFetch関連の質問を確認したところ、Unityフォーラムの別の投稿内の回答を見ました。UnityはFrameBufferFetchをサポートしていますが、DepthBufferの取得はサポートしていないと書かれています。

リファレンスページ:

https://forum.unity.com/threads/pixel-local-storage-and-frame-buffer-fetch-on-mobile-devices.604186/

2つ目の質問に対して、Shaderを増加しなければ、現時点では他の良い方法はまたありません。

Shaderを増加できる場合には、元のShaderを1つコピーし、ShadowCaster部分のみに

1つの「NeedDepth」タグを添付します。水中オブジェクトのShaderをこのShaderに置き換え、別にShadowCasterのみのあり、「NeedDepth」タグが付けているShaderを作成してReplace操作を行います。もう1つのCamaraを追加し、メインカメラに従い、またはメインカメラの子ノードとします。1つのRTを作成し、このカメラをRTまでレンダリングします。UpdateにReplaceShaderを使用して描画すると、そのタグを持つShadowCasterのみが深度レンダリングを行います。後でこのRTに対してエンコードなどの操作を行うことができ、このRTが記録するのは水中オブジェクトの深度です。プロセス全体に多くの余分な作業がないようですから、試してみることができると思います(テストしたことはありませんが、理論的には行えます)。


Texture

UWAの別の記事から、画像のAlphaチャネルがメモリに影響があることがわかりました。

下記のアセット配置でテストします

Tga_Alpha - Alphaあり

Tga_NoAlpha - Alphaなし

Png_Trans - 透明画像含む

Unity内のFormatに入って、すべてのコードをTextureImporterFormat.ASTC_6x6に設定します

テスト結果

Unityで、3つ画像のFormatはすべて下図のようです。

3つ画像が表示するメモリサイズはすべて同じです。

Texture ImporterのAlpha SourceをNoneに設置しても、テスト結果に影響はありません。

同じFormat形式に対して、画像にAlphaチャンネルが含まれているかどうかは、メモリサイズは同じですか?

Tex.7z

A1:原文の最適化提案は、意味のないAlphaチャネルを削除することです(原文にAlpha値がすべて1のテクスチャとして定義されています)、これは確かにメモリの最適化に役に立ちます。

問題主のテスト例に、png形式であろうとtga形式であろうと、エンジンに入った後、エンジンによって内部形式(RGBA、ETC、ASTCなど)に変換されます。ETC2を例として、Alphaチャネルがない場合、圧縮品質が許容範囲内であれば、RGB_Compressed_ETC2_4bitsを使用できます。そして、この無意味なAlphaチャンネルが追加された場合、バッチインポートするときにRGBA_Compressed_ETC2_8bitsを自動的に選択されます。これで、メモリは倍になります。

質問にあるASTCについては、UnityエディターのソースコードでのTextureインポート形式の定義には次のコメントがあります。

// ASTC uses 128bit block of varying sizes (we use only square blocks). It does not distinguish RGB/RGBA.

つまり、Alphaチャネルが含まれているかどうかとは関係ありません。ASTC形式の紹介については、GithubにあるASTC Format Overviewを読むことをお勧めします。

Unity新しいバージョンの問題については、Unityフォーラムのこの問題を確認できます。

プロジェクトのテクスチャ形式がすべてASTCであり、Alphaを削除する意味はあまりないと考える人もいるかもしれませんが、実には一言で言えません。サイズが同じですけど、Alphaがあるかどうかは、ある程度圧縮品質に影響しますから、プロジェクトで合理的に使用する必要があります。

 

A2:ゲーム実行中に、TextureのAlphaチャネルは、ソースファイルの状況ではなく、インポート後の状況で確認できます。UWAローカルアセット検出は、インポート後の結果としてTextureのAlphaチャネルを検出します。

画像ソースファイルの形式はグラフィックハードウェアでサポートされておらず、Unityも直接引き継ぐことはありません。画像をインポートした後、Import Settingsにある設置によって画像を処理して、ハードウェアがサポートする形式(エンジンの形式)にインポートされ、操作で使用されるアセットもインポートされた後のものです。

問題主がAlpha SourceをNoneに設定しましたから、インポートする時に元Alphaチャネルはインポートされません。圧縮形式は、Alphaチャネルを含むASTC_6x6であります。インポート後、3つのアセットはデフォルトですべて1であるAlphaチャネルを生成します。メモリサイズは当然同じです。


Rending

URPがGrabPass効果を達成する方法はありますか?URPパイプラインはもう元のGrabPass機能を削除しました。現在には、熱擾乱のような1つの歪み特殊効果の機能があります。URPは実体画像を直接取得して歪み効果を作成できますが、半透明オブジェクト(水、他の特殊効果など)を歪みたい場合には取得できません。

問題主がGrabPassを完全に実現したいことは無理だと思いますが、代わり方法は存在しています。

GrabPassとは、最初にオブジェクトAを描画し、次にオブジェクトBを描画する時にAを影響し、オブジェクトCを描画する時にBを影響するということです。注意すべきなのは、ここで最も重要なのは、オブジェクトBはオブジェクトCより早く描画されたから、BはCに影響をあげられなくいことです。

しかし、オブジェクトBとオブジェクトCがABC全体に影響があることを納得できる場合、簡単になります。まずには1つのRTを使って歪み情報を保存し、Uber Shaderでこの歪みを画面に体現させ、これですべてのオブジェクト(不透明または半透明)は歪み情報に影響を受けました。

URPがどのように実現されているかはわかりませんが、私たち自身のSRPはこのように変更して実現されています。


Editor

現在、ScriptableObjectから継承する1つのAssetがあります。何かの原因で、引用スクリプトのGUIDが間違いました。では、特定のエディタースクリプトを使用してこのAssetのPathを見つけることができますが、ProjectView内でどうやって選択できますか?

テストしたところ、Selection.instanceIDを使用すると選択できますが、Instance IDは一般的にObjectを介して取得します。しかし、スクリプト引用が間違っているため、AssetDatabaseはこのObjectをロードできません。このInstance IDを取得する方法またはAPIはありますか?

オープンソースコードを見て、1つ可能性のある方法を見つけました。

//assetPath : 対応するスクリプトが見つからないAssetインスタンスのパス
HierarchyProperty property = new HierarchyProperty(assetPath);
Selection.activeInstanceID = property.GetInstanceIDIfImported();

こうすればProjectView内で選択できます。


Addressable

すべてのアセットをダウンロードした後、テストスクリプトでLoadAssetAsync関数をコールすれば、下図のようになります。

AssetBundleProviderでは1つ目の疑問があります。

Addressablesはすべてキャッシュメカニズムを使用してAssetBundleパッケージを保存するため、ここのFile.Existsは常にFalseではありませんか?

2番目の疑問は次のとおりです。

WebRequestのダウンロードを完了した後、AddressablesがBundleをメモリにロードするタイミングを把握するにはどうすればよいですか?私の考えに問題があるかもしれませんが、後のスタックトレースでLoadFromFileのようなコールは見つかりませんでした。

ここでのFile.Existsは、キャッシュをチェックするのではなく、ファイルがStreamingAssetsにあるかどうかをチェックするためのものです。また、ダウンロードされたすべてのアセットはキャッシュを介して取得され、キャッシュにアセットがない場合はダウンロードします。Loadの部分はもうUnityWebRequestAssetBundle内にパッケージ化されました。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意)https://answer.uwa4d.com