日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Unity iOS 使用 ASTC 格式纹理实践

發布時間:2024/8/26 68 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity iOS 使用 ASTC 格式纹理实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


引言

上一篇文章描述了如何在不修改自定義渲染組件的前提下使用 alpha 分離的紋理來提升 iOS 的透明壓縮紋理質量(見這里:上一篇的鏈接)。

在這個方案投入項目開始使用一段時間之后,UI 同學又來找我抱怨了:雖然一些貼圖的不透明部分不會顯得臟了,但是為什么有些紋理的半透明部分表現這么奇怪呀?這就涉及到上次方案中透明通道貼圖格式的選擇問題了。在上一篇文章中,我們的透明通道貼圖在 iOS 上使用了 pvrtc4 的壓縮方式,這樣的做法造成了部分貼圖半透明部分顯示上的效果降低,在一些特定的情況下效果甚至沒法接受。那么如何解決這個問題呢?這一次我們要來說明另一種貼圖質量低下的解決方案:使用 ASTC 格式紋理,并且解釋針對目前部分硬件的限制所作出的調整。

ASTC

關于紋理格式的一些基礎知識可以在上一篇文章中開頭的基礎中看到,在此不做贅述。這里簡單說明一下 ASTC 這種格式。

1. 概述

ASTC(Adaptive Scalable Texture Compression)是一種基于塊的有損紋理壓縮格式,完整細節在 2012 年被提出。這種壓縮格式有多種壓縮率可選,同時有著較高的壓縮率和較好的壓縮質量。

2. 壓縮率
?


在上面的表中展示了從 ASTC 格式從 4x4 到 12x12 每一個像素所占的比特數(bpp),可以看到最大(也就是 4x4)的占用為每個像素一個字節,那么一張 1024x1024 的貼圖,使用 ASTC 4x4 壓縮后,他的大小就是 1MB,這個大小和 ETC2 RGBA 8bpp 格式的大小相同。

3. 紋理質量

從結果來看,在相同的內存占用前提下,ASTC 相較其他傳統壓縮格式的質量更優;而在相同的質量前提下,占用內存更小。關于 ASTC 的壓縮類型選擇和質量相關說明, 可以參考這里:https://developer.nvidia.com/astc-texture-compression-for-game-assets

4. 支持機型

iOS 上,蘋果從 A8 處理器開始支持 ASTC 格式(即從 iphone6,iPad mini 4 開始支持),而以前的 iPhone 5s 和 iPad mini 3 及之前的設備都不支持。

Android 上,未來的壓縮格式正在從 ETC2 轉向 ASTC。但是因為 android 機多樣性,目前的市場普及率我暫不可知。

基本使用

現在在 Unity 中要使用 ASTC 格式非常簡單:選擇紋理導入設置,選擇 ASTC 格式,完成!
?


這就結束了嗎?顯然事情并沒有這么簡單,上面提到過的硬件的限制使得我們無法這么簡單的選擇,因為在不支持的硬件上使用 ASTC 格式,會被軟解為 RGBA,從而數倍的增加其內存占用,讓游戲瞬間被系統殺掉。

針對這些硬件限制,我們基于項目本身的特點一般有以下的考量:
?

  • 在 iOS 上如果項目是個大型游戲,可以放棄低端機器的用戶,那么就直接使用 ASTC;
  • 在 android 上,如果可以得到準確的市場占有率,并確定可以放棄這一部分市場的前提下,可以直接使用 ASTC;
  • 現在立項的移動端游戲,且未來會有開發時長 2 年以上的,可以考慮只使用 ASTC;
  • 否則,如果你想考慮低端用戶,那么還是需要考慮 ASTC 和傳統格式的兼容性問題,我們接下來就會講到這套實現方案:根據硬件條件選擇使用不同的紋理格式。


根據硬件條件選擇使用不同紋理格式

1. 基本思路

首先,對于直接引用打入包內的方式是不適合本方案的。本方案基于通過 AssetBundle 加載資源的項目(包括動態加載和依賴加載)。

基本思路為:在打包時生成一份完整的 AssetBundle 包以后,再針對需要使用 ASTC 的紋理所在的 AssetBundle 包重新打一份 ASTC 版本的;在運行時根據硬件支持情況等信息來選擇加載哪一份 AssetBundle 包(PVRTC/ASTC)。

這樣在游戲運行過程中,如某個 prefab 引用了一個 sprite,可以通過硬件情況選擇不同的 AssetBundle 包,加載不同包中相同的 Sprite,然后引用到不同壓縮格式的紋理上,就達到了我們的目的。

2. 構建測試工程

基于上面的思路,我們來構建一個測試工程,測試工程需要包含以下內容:
?

  • 打 AssetBundle 包流程
  • 生成 BundleMap,記錄 ASTC 信息,供運行時使用
  • 生成 AtlasBundleMap,記錄需要重新打 ASTC 版本 AssetBundle 包的信息,供打包時使用
  • 運行時資源加載,根據硬件條件來選擇不同的 AssetBundle 包


3. 實現細節

首先是打 AssetBundle 包流程,這塊不會詳細說,因為每個項目的實現都可能不同。在這里,我們的思路是:添加需要動態加載的 AB 包規則,最后計算出它們依賴的資源,按規則打成其他依賴 AB 包。下面的代碼示意了這一過程。
?

var builder = new AssetBundleBuilder();
builder.AddSceneBundle("Assets/Scenes/Test.unity", "scenes_");
builder.AddSceneBundle("Assets/Scenes/Loading.unity", "scenes_");
builder.AddDirBundle("Assets/Textures/Dynamic", "", "textures_");
builder.UpdateSharedAssets();
builder.BuildAssetBundles(abPath, BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);


其中重點在 UpdateSharedAssets() 方法中,其中不僅計算了所有的依賴關系,同時記錄了 AtlasBundleMap 和 BundleMap。

下圖為 BundleMap 的格式,最重要的幾個字段是 BundleName(記錄 AB 包名),AstcVariant(是否有其 ASTC 版本),AstcVariantBundleName(ASTC 版本的 AB 包名)。這個文件會打入最終的 AB 包內,在運行時加載資源時根據 AstcVariant 和 AstcVariantBundleName 來判斷并加載對應的 ASTC 版本的包。
?


下圖為 AtlasBundleMap 的格式。這個文件記錄了需要再打一份 ASTC 版本 AB 包的包名列表,在后續的打包過程中會用到。
?


經過上面的過程,完整的 AB 包已經都打出來了,下面需要重新打一批 ASTC 版本的 AB 包。首先重新打一次圖集:
?

EditorSettings.spritePackerMode = SpritePackerMode.BuildTimeOnly

acker.SelectedPolicy = typeof(CustomSpritePackerPolicy).Name;CustomSpritePackerPolicy.MakeAstc = true;Packer.RebuildAtlasCacheIfNeeded(target, true, Packer.Execution.ForceRegroup);


上面需要注意的是:兩次打圖集需要有一個不同的標志:MakeAstc,第一次為 false,第二次為 true,在自定義的圖集打包規則中才可以判斷出兩次需要打的是不同的圖集。自定義圖集規則中的實現為:
?

if (MakeAstc){
? ? if (IsTransparentCompressed(settings.format))
? ? {
? ?? ???settings.format = Util.ASTC_RGBA_FORMAT;
? ? }
? ? else if (IsOpaqueCompressed(settings.format))
? ? {
? ?? ???settings.format = Util.ASTC_RGB_FORMAT;
? ? }
}


更多的關于自定義圖集規則可以參考官方文檔:https://docs.unity3d.com/Manual/SpritePacker.html

之后使用同樣的 BuildAssetBundleOptions,根據 AtlasBundleMap 中信息對相應資源再打一次 AB 包即可,打完后改名拷貝到之前的文件夾中,現在的 AB 包目錄就像是這樣:
?


其中 astc_ 開頭的都是對應的 AB 包的 ASTC 版本。

接下來我們來到運行時。首先是判斷硬件是否支持 ASTC 格式:
?

public static bool DeviceSupportAstc(){
? ? var support = true;
? ? support = support && SystemInfo.SupportsTextureFormat(ASTC_RGB_FORMAT);
? ? support = support && SystemInfo.SupportsTextureFormat(ASTC_RGBA_FORMAT);
? ? return support;
}


其次是加載資源:
?

private AssetBundle LoadBundleCore(string bundleName){
? ? if (Util.UseAstc && m_bundleMap != null)
? ? {
? ?? ???BundleMapData bundleMapData = null;
? ?? ???if (m_bundleMap.TryGetValue(bundleName, out bundleMapData))
? ?? ???{
? ?? ?? ?? ?if (bundleMapData.AstcVariant)
? ?? ?? ?? ?{
? ?? ?? ?? ?? ? bundleName = bundleMapData.AstcVariantBundleName;
? ?? ?? ?? ?}
? ?? ???}
? ?? ???else
? ?? ???{
? ?? ?? ?? ?Debug.LogError("Cannot find bundle name in bundle map: " + bundleName);
? ?? ???}
? ? }

? ? var bundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + bundleName);
? ? return bundle;
}


這是所有加載 AB 包時都會調用到的方法(包括動態加載和依賴加載)。其中的過程也很簡單:判斷了硬件情況,根據 BundleMap 找到需要加載的 ASTC 版本的 AB 包名,并去加載。

到這里以后我們的測試工程就已經完成了(詳細的代碼可以看文末的代碼倉庫一節)。我們可以看到在這個 demo 中,我們可以顯示當前動態加載和依賴加載的紋理格式,并切換到另一種紋理,實現了 ASTC 和傳統格式之間的選擇性加載。
?


我們再使用 Profiler 工具來對比一下QQ號碼賣號平臺兩種不同格式的紋理的內存占用:


上圖為 ETC2 格式(為了測試方便,沒有使用 PVRTC,結果是一樣的)的內存占用,64.2KB,即等于 256*256*8/8。
?


上圖為 ASTC 6x6 格式的內存占用,29.1KB,即等于 256*256*3.56/8。



ASTC 6x6 的內存占用比 PVRTC 4bpp 還小了 10%,但是質量卻要好的很多很多。

補充說明

1. 延伸一下,因為上面的方案多生成了一批圖集相關的 AB 包,所以會讓包體有所增大。如果你們項目中有資源更新,那么支持 ASTC 和不支持 ASTC 的設備就需要根據自己的情況來下載不同的資源包。如果要做的好的話這個問題也是需要考慮的。當然這里就不討論了,有需要的同學可以自己研究。

2. 引言中提到的透明通道貼圖 PVRTC RGBA 4bpp 格式造成了貼圖的半透明區域顯示質量差的問題。我之后也嘗試使用 Alpha8 格式來代替,但是實際測試發現所有圖都看不到了,通過看 Unity 的默認 spriterenderer 和 DefaultETC1 的 shader 才知道,他們都使用了 alpha 通道貼圖的 R 通道,而 Alpha8 格式取不到,所以貼圖都不顯示了。要解決這個問題可能需要使用 R8 格式來代替 Alpha8 格式,但是因為我使用的 Unity2017 不支持,所以就沒有繼續嘗試了。

結論

包括前一篇文章,在 iOS 上我們一共使用了 3 種貼圖壓縮格式的方案(android 同理):
?

  • 直接使用 PVRTC
  • 分離透明通道的 PVRTC+PVRTC,或者 PVRTC+Alpha8
  • 根據硬件情況的不同來選擇使用 PVRTC 還是 ASTC


這幾種方案各有優劣和使用場景,我下面就試著總結一下。

1. 方案優缺點對比

PVRTC:
?

  • 優點:開發方便,不需要做額外處理,所有 iOS 設備統一支持
  • 缺點:紋理質量很差


分離透明通道:
?

  • 優點:不受硬件限制
  • 缺點:開發繁瑣(一次性),如果使用 pvrtc+pvrtc 方案,半透明區域質量不好;如果使用 pvrtc+alpha8 方案,內存占用會增加到 12bpp,且可能不支持所有 unity 版本


根據硬件選擇使用 PVRTC 還是 ASTC:
?

  • 優點:內存占用少,紋理質量高
  • 缺點:開發繁瑣(一次性),包體圖集紋理占用存儲空間多一倍


2. 方案適用場景對比

PVRTC:
?

  • 適用于:不那么關注貼圖質量,希望內存占用低,希望開發成本低
  • 不適用于:有品質要求的項目


分離透明通道:
?

  • 適用于:希望透明貼圖的非透明部分不臟,不希望包體增大,2018 以上版本 unity 項目,對于內存占用不那么敏感
  • 不適用于:2018 以下版本 unity 項目,希望內存占用低


根據硬件選擇使用 PVRTC 還是 ASTC:
?

  • 適用于:對包體體積不那么敏感,有開發能力和時間,希望紋理質量高同時內存占用小
  • 不適用于:對包體體積敏感,開發能力和時間有限

總結

以上是生活随笔為你收集整理的Unity iOS 使用 ASTC 格式纹理实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。