日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unity iOS 使用 ASTC 格式纹理实践

發(fā)布時(shí)間:2024/8/26 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity iOS 使用 ASTC 格式纹理实践 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


引言

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

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

ASTC

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

1. 概述

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

2. 壓縮率
?


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

3. 紋理質(zhì)量

從結(jié)果來看,在相同的內(nèi)存占用前提下,ASTC 相較其他傳統(tǒng)壓縮格式的質(zhì)量更優(yōu);而在相同的質(zhì)量前提下,占用內(nèi)存更小。關(guān)于 ASTC 的壓縮類型選擇和質(zhì)量相關(guān)說明, 可以參考這里:https://developer.nvidia.com/astc-texture-compression-for-game-assets

4. 支持機(jī)型

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

Android 上,未來的壓縮格式正在從 ETC2 轉(zhuǎn)向 ASTC。但是因?yàn)?android 機(jī)多樣性,目前的市場(chǎng)普及率我暫不可知。

基本使用

現(xiàn)在在 Unity 中要使用 ASTC 格式非常簡單:選擇紋理導(dǎo)入設(shè)置,選擇 ASTC 格式,完成!
?


這就結(jié)束了嗎?顯然事情并沒有這么簡單,上面提到過的硬件的限制使得我們無法這么簡單的選擇,因?yàn)樵诓恢С值挠布鲜褂?ASTC 格式,會(huì)被軟解為 RGBA,從而數(shù)倍的增加其內(nèi)存占用,讓游戲瞬間被系統(tǒng)殺掉。

針對(duì)這些硬件限制,我們基于項(xiàng)目本身的特點(diǎn)一般有以下的考量:
?

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


根據(jù)硬件條件選擇使用不同紋理格式

1. 基本思路

首先,對(duì)于直接引用打入包內(nèi)的方式是不適合本方案的。本方案基于通過 AssetBundle 加載資源的項(xiàng)目(包括動(dòng)態(tài)加載和依賴加載)。

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

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

2. 構(gòu)建測(cè)試工程

基于上面的思路,我們來構(gòu)建一個(gè)測(cè)試工程,測(cè)試工程需要包含以下內(nèi)容:
?

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


3. 實(shí)現(xiàn)細(xì)節(jié)

首先是打 AssetBundle 包流程,這塊不會(huì)詳細(xì)說,因?yàn)槊總€(gè)項(xiàng)目的實(shí)現(xiàn)都可能不同。在這里,我們的思路是:添加需要?jiǎng)討B(tài)加載的 AB 包規(guī)則,最后計(jì)算出它們依賴的資源,按規(guī)則打成其他依賴 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);


其中重點(diǎn)在 UpdateSharedAssets() 方法中,其中不僅計(jì)算了所有的依賴關(guān)系,同時(shí)記錄了 AtlasBundleMap 和 BundleMap。

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


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


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

EditorSettings.spritePackerMode = SpritePackerMode.BuildTimeOnly

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


上面需要注意的是:兩次打圖集需要有一個(gè)不同的標(biāo)志:MakeAstc,第一次為 false,第二次為 true,在自定義的圖集打包規(guī)則中才可以判斷出兩次需要打的是不同的圖集。自定義圖集規(guī)則中的實(shí)現(xiàn)為:
?

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


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

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


其中 astc_ 開頭的都是對(duì)應(yīng)的 AB 包的 ASTC 版本。

接下來我們來到運(yùn)行時(shí)。首先是判斷硬件是否支持 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 包時(shí)都會(huì)調(diào)用到的方法(包括動(dòng)態(tài)加載和依賴加載)。其中的過程也很簡單:判斷了硬件情況,根據(jù) BundleMap 找到需要加載的 ASTC 版本的 AB 包名,并去加載。

到這里以后我們的測(cè)試工程就已經(jīng)完成了(詳細(xì)的代碼可以看文末的代碼倉庫一節(jié))。我們可以看到在這個(gè) demo 中,我們可以顯示當(dāng)前動(dòng)態(tài)加載和依賴加載的紋理格式,并切換到另一種紋理,實(shí)現(xiàn)了 ASTC 和傳統(tǒng)格式之間的選擇性加載。
?


我們?cè)偈褂?Profiler 工具來對(duì)比一下QQ號(hào)碼賣號(hào)平臺(tái)兩種不同格式的紋理的內(nèi)存占用:


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


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



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

補(bǔ)充說明

1. 延伸一下,因?yàn)樯厦娴姆桨付嗌闪艘慌鷪D集相關(guān)的 AB 包,所以會(huì)讓包體有所增大。如果你們項(xiàng)目中有資源更新,那么支持 ASTC 和不支持 ASTC 的設(shè)備就需要根據(jù)自己的情況來下載不同的資源包。如果要做的好的話這個(gè)問題也是需要考慮的。當(dāng)然這里就不討論了,有需要的同學(xué)可以自己研究。

2. 引言中提到的透明通道貼圖 PVRTC RGBA 4bpp 格式造成了貼圖的半透明區(qū)域顯示質(zhì)量差的問題。我之后也嘗試使用 Alpha8 格式來代替,但是實(shí)際測(cè)試發(fā)現(xiàn)所有圖都看不到了,通過看 Unity 的默認(rèn) spriterenderer 和 DefaultETC1 的 shader 才知道,他們都使用了 alpha 通道貼圖的 R 通道,而 Alpha8 格式取不到,所以貼圖都不顯示了。要解決這個(gè)問題可能需要使用 R8 格式來代替 Alpha8 格式,但是因?yàn)槲沂褂玫?Unity2017 不支持,所以就沒有繼續(xù)嘗試了。

結(jié)論

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

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


這幾種方案各有優(yōu)劣和使用場(chǎng)景,我下面就試著總結(jié)一下。

1. 方案優(yōu)缺點(diǎn)對(duì)比

PVRTC:
?

  • 優(yōu)點(diǎn):開發(fā)方便,不需要做額外處理,所有 iOS 設(shè)備統(tǒng)一支持
  • 缺點(diǎn):紋理質(zhì)量很差


分離透明通道:
?

  • 優(yōu)點(diǎn):不受硬件限制
  • 缺點(diǎn):開發(fā)繁瑣(一次性),如果使用 pvrtc+pvrtc 方案,半透明區(qū)域質(zhì)量不好;如果使用 pvrtc+alpha8 方案,內(nèi)存占用會(huì)增加到 12bpp,且可能不支持所有 unity 版本


根據(jù)硬件選擇使用 PVRTC 還是 ASTC:
?

  • 優(yōu)點(diǎn):內(nèi)存占用少,紋理質(zhì)量高
  • 缺點(diǎn):開發(fā)繁瑣(一次性),包體圖集紋理占用存儲(chǔ)空間多一倍


2. 方案適用場(chǎng)景對(duì)比

PVRTC:
?

  • 適用于:不那么關(guān)注貼圖質(zhì)量,希望內(nèi)存占用低,希望開發(fā)成本低
  • 不適用于:有品質(zhì)要求的項(xiàng)目


分離透明通道:
?

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


根據(jù)硬件選擇使用 PVRTC 還是 ASTC:
?

  • 適用于:對(duì)包體體積不那么敏感,有開發(fā)能力和時(shí)間,希望紋理質(zhì)量高同時(shí)內(nèi)存占用小
  • 不適用于:對(duì)包體體積敏感,開發(fā)能力和時(shí)間有限

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。