關於_CameraDepthTexture的疑惑


1)關於_CameraDepthTexture的疑惑
​2)貼圖Alpha通道對圖片大小的影響
3)URP要怎么實現GrabPass的效果
4)如何獲取AssetDatabase加載失敗的Asset的Instance ID
5)如何判斷Bundle文件加載進內存的時機


這是第226篇UWA技術知識分享的推送。今天我們繼續為大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鍾,認真讀完必有收獲。

UWA 問答社區:answer.uwa4d.com
UWA QQ群2:793972859(原群已滿員)

Rendering

Q:一個關於_CameraDepthTexture的疑問。

如果開啟_CameraDepthTexture,Camera就需要渲染一遍場景內所有帶有ShadowCaster的可見物體的Pass來實現深度圖。

但是場景中的物體在開啟ZWrite的時候就把深度寫進了Depth Buffer中了,直接獲得這個Depth Buffer是不是比近乎DrawCall翻倍的方式更有效率呢?還是Unity在這方面有什么考慮?

另外,問一個更實際的問題:
我們的項目需要渲染場景的中湖水的深度效果,所有不透明的場景物體的材質都是關聯同樣一個Shader,這個Shader是帶有ShadowCaster的。但是只有個別插入水中的物體需要去渲染ShadowCaster的Pass,有沒有方法在不增加Shader的情況下,讓沒有插入水里的物體不渲染Shadow Caster Pass呢?我們用的是Built-in的渲染管線。

A:第一個問題,可以參考這個問題中Unity官方人員的回復。
里面講了兩個原因,第一是對於非全屏渲染的情況,本來是想拿對應相機渲染的深度,但是Depth Buffer是全屏的。第二個原因是因為很多平台不支持直接拿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/

 

第二個問題,如果不增加Shader,目前沒想到其他好的方法。
如果可以增加Shader,可以將原來的Shader復制一份,只在ShadowCaster的部分加一個“NeedDepth”這樣的Tag,將水下的物體的材質球換成這個Shader,另外做一個只有ShadowCaster並帶有“NeedDepth”這個Tag的Shader,這個Shader用來做Replace操作。

額外增加一個Camera,這個Camera跟隨主相機,或者作為主相機的子節點,創建一個RT,讓這個Camera渲染到這個RT,在Update里面使用ReplaceShader去畫一下,那么只有有那個Tag的ShadowCaster會進行深度渲染,后續可以對這個RT進行編碼等操作,這個RT記錄的就是水下物體的深度。整個過程看上去沒有特別多的額外工作,覺得可以一試(我沒有做過測試,但理論上是可行的)。

感謝Xuan@UWA問答社區提供了回答


Texture

Q:在UWA的《紋理優化:不僅僅是一張圖片那么簡單》這篇文章中,描述了圖片含有Alpha通道會對內存有影響。

通過以下的測試資源配置:

  • Tga_Alpha - 含有Alpha通道
  • Tga_NoAlpha - 不含有Alpha通道
  • Png_Trans - 含有透明的圖片
  • 進入到Unity中的Format,全部代碼設置為TextureImporterFormat.ASTC_6x6

測試結果:

  • 三張圖片Unity全部Format為下圖格式
  • 三張圖片顯示的內存大小全部一樣
  • Texture Importer的Alpha Source設置為None,對測試結果無影響

    問題:圖片是否含有Alpha通道,對於同一個Format格式,內存大小都是一樣的嗎?
    Tex.7z

A:原文中的優化建議是去除無意義的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的意義不是很大,其實不能一概而論,雖然大小相同,但根據(https://zhuanlan.zhihu.com/p/158740249)中的測試,是否有Alpha通道會一定程度上影響壓縮質量。所以還是要在項目中合理使用。

感謝范君@UWA問答社區提供了回答

A2:游戲運行時Texture的Alpha通道要看導入后的情況,不能看源文件的情況。UWA本地資源檢測對於Texture的Alpha通道檢測的就是導入后的結果。

圖片源文件的格式,圖形硬件是不支持的,Unity也不直接接管。導入圖片后,會按照Import Settings中的設置對圖片進行處理,將圖片導入成硬件支持的格式(在引擎中的格式),而在運行中使用的資源也是導入后的。

題主將Alpha Source設置為None,那么導入時就不對源文件的Alpha通道進行導入,而壓縮格式為ASTC_6x6,這個格式是包含Alpha通道的。這樣導入后三個資源都會默認生成一個全為1的Alpha通道。占用內存大小自然一樣。

感謝Prin@UWA問答社區提供了回答


Rendering

Q:URP如何實現GrabPass的效果?URP管線已經去掉了原先GrabPass的功能,現在有一個扭曲特效的功能,類似熱擾動那種。雖然URP能夠直接獲取到實體圖做扭曲效果,但是像是半透明物體(比如:水、其他特效等)也需要被扭曲就做不到。

A:題主想要完全實現GrabPass估計不行,但是可以有替代方案:

GrabPass的意思就是先繪制a物件,然后繪制b物件的時候影響a,繪制c物件的時候影響ab。注意,這最重要的是b物件的擾動影響不了c物件,因為b物件是比c物件先繪制的。

但是如果你能夠接受b物件和c物件的擾動同時影響abc,那么就簡單了,先用一個RT將扭曲的信息存下來(其實就是UV偏移),然后在Uber Shader中將偏移應用在畫面上。這樣扭曲信息就擾動了所有物件(不管是不透明還是半透明)。

雖然不知道URP怎么實現的,但是我們自己改的SRP,就是這么實現的。

感謝王爍@UWA問答社區提供了回答


Editor

Q:現在有一個繼承於ScriptableObject的Asset,無論出於什么原因,引用腳本的GUID錯了。那么通過一定的編輯器腳本能找到這個Asset的Path,但是如何在ProjectView內選中它?

經測試,使用Selection.instanceID是可以選中的,而Instance ID一般需要通過Object來獲取,但是因為腳本引用錯誤了,所以AssetDatabase是無法載入這個Object的。有什么辦法或者API能獲取到這個Instance ID呢?

A:通過查看公開源碼,找到了一個可用的方法:

//assetPath : 某個找不到對應腳本的Asset實例路徑
HierarchyProperty property = new HierarchyProperty(assetPath);
Selection.activeInstanceID = property.GetInstanceIDIfImported();

這樣可以在ProjectView內正確選中了。

感謝題主黃程@UWA問答社區提供了回答


Addressable

Q:當下載好所有的資源后,在一個測試腳本中調用LoadAssetAsync函數,如下圖:


在AssetBundleProvider這里是第一個疑惑:
既然Addressables全部采用緩存機制來存放AssetBundle包,那此處的File.Exists不是總會為False嗎?

第二個疑惑在於:
Addressables在WebRequest完成下載后,如何把握把Bundle加載進內存的時機?也可能是我的思路有問題,但是在后面的堆棧追蹤里面沒有發現有類似於LoadFromFile這樣的調用。

A:這兒的File.Exists並不是檢查緩存,而是檢查文件在不在StreamingAssets里面。而所有下載的資源則是通過緩存來獲取的,若緩存里沒有則下載。而Load這部分已經被封裝在了UnityWebRequestAssetBundle內了。

感謝黃程@UWA問答社區提供了回答

 

封面圖來源於網絡


今天的分享就到這里。當然,生有涯而知無涯。在漫漫的開發周期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站上准備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ群:793972859(原群已滿員)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM