Unity3D研究院之執行時合併ETC1、ETC2、ASTC、DXT1、DXT5、PVRTC貼圖(一百)
今天是2018年10月24日,祝大家程式員節快樂。
遊戲中一旦有換裝功能,角色可能就會是多個DrawCall了,所以我們可以將部件的貼圖動態合併在一張中。如果想合併PVRTC2或者PVRTC4可以參考我上一篇文章。Unity3D研究院之IOS執行時合併PVRTC貼圖(九十九) ofollow,noindex">https://www.xuanyusong.com/archives/4531
這篇文章討論合併ETC1 ETC2 ASTC4X4 DXT1 DXT5執行時合併方式,為什麼把它們放在一起討論,只是因為它們的合併演算法都是一樣的。DXT1和DXT5一般可用於PC包或者編輯器,ETC1 ETC2用於安卓手機,ASTC4X4用於IOS手機,如下圖所示,畫素排列演算法。
QQ20181023-13145_2.jpg" class="alignCenter"/>
核心方式是Texture2D.GetRawTextureData()獲取貼圖的原始資料,執行時使用需要開啟貼圖的Read/Write,如果出於節省記憶體的考慮,可以在編輯模式下提前提取貼圖的原始資料,執行期在合併。
我們將256和128的貼圖合併在一張512的PVRTC貼圖中,排列的位置如下。(圖片我就不再截取了,和上篇一致,只是換了個壓縮格式)
程式碼中同時支援PVRTC2bit和PVRTC4bit,注意Apply()的第二個引數是true,表示合併貼圖後立即刪除記憶體拷貝,也就是Read/Write了。
using UnityEngine; using UnityEngine.UI; using System; public class TextureCombine : MonoBehaviour { public Texture2D texture256; public Texture2D texture128; void Awake() { GetComponent<RawImage>().texture = Combine(texture256,texture128); } Texture2D Combine(Texture2D tex, Texture2D tex1) { int length = 512; var blcokBytes = 0; byte[] data = null; switch (tex.format) { case TextureFormat.DXT1: case TextureFormat.ETC_RGB4: case TextureFormat.ETC2_RGB: blcokBytes = 8; data = new byte[length / 2 * length]; break; case TextureFormat.DXT5: case TextureFormat.ETC2_RGBA8: case TextureFormat.ASTC_RGB_4x4: case TextureFormat.ASTC_RGBA_4x4: blcokBytes = 16; data = new byte[length * length]; break; default: UnityEngine.Debug.Log("Not supported."); return null; } //填充左下角 256 CombineBlocks(tex.GetRawTextureData(), data, 0, 0, tex.width, 4, blcokBytes, length); //填充左上角 256 CombineBlocks(tex.GetRawTextureData(), data, 0, tex.width, tex.width, 4, blcokBytes, length); //填充右下角 256 CombineBlocks(tex.GetRawTextureData(), data, tex.width, 0, tex.width, 4, blcokBytes, length); //填充右上角區域 //左下角 128 CombineBlocks(tex1.GetRawTextureData(), data, tex.width, tex.width, tex1.width, 4, blcokBytes, length); //左上角 128 CombineBlocks(tex1.GetRawTextureData(), data, tex.width, tex.width + tex1.width, tex1.width, 4, blcokBytes, length); //右下角 128 CombineBlocks(tex1.GetRawTextureData(), data, tex.width + tex1.width, tex.width, tex1.width, 4, blcokBytes, length); //右上角 128 CombineBlocks(tex1.GetRawTextureData(), data, tex.width + tex1.width, tex.width + tex1.width, tex1.width, 4, blcokBytes, length); var combinedTex = new Texture2D(length, length, tex.format, false); combinedTex.LoadRawTextureData(data); combinedTex.Apply(false,true); return combinedTex; } void CombineBlocks(byte[] src, byte[] dst, int dstx, int dsty, int width, int block, int bytes, int length) { var dstbx = dstx / block; var dstby = dsty / block; for (int i = 0; i < width / block; i++) { int dstindex = (dstbx + (dstby + i) * (length / block)) * bytes; int srcindex = i * (width / block) * bytes; Buffer.BlockCopy(src, srcindex, dst, dstindex, width / block * bytes); } } }
ok!如果有建議或者意見歡迎在下面給我留言.
- 本文固定連結: https://www.xuanyusong.com/archives/4535
- 轉載請註明:雨鬆MOMO 於雨鬆MOMO程式研究院 發表
雨鬆MOMO提醒您:親,如果您覺得本文不錯,快快將這篇文章分享出去吧 。另外請點選網站頂部彩色廣告或者捐贈支援本站發展,謝謝!
捐 贈 如果您願意花20塊錢請我喝一杯咖啡的話,請用手機掃描二維碼即可通過支付寶直接向我捐款哦。