游戏中一旦有换装功能,角色可能就会是多个DrawCall了,所以我们可以将部件的贴图动态合并在一张中,本文聊聊PVRTC2bit 和 PVRTC4bit 贴图合并的方法。先看看PVRTC贴图的排列方式。
核心方式是Texture2D.GetRawTextureData()获取贴图的原始数据,运行时使用需要开启贴图的Read/Write,如果出于节省内存的考虑,可以在编辑模式下提前提取贴图的原始数据,运行期在合并。
我们将256和128的贴图合并在一张512的PVRTC贴图中,排列的位置如下。
代码中同时支持PVRTC2bit和PVRTC4bit,注意Apply()的第二个参数是true,表示合并贴图后立即删除内存拷贝,也就是Read/Write了。
using System;
using UnityEngine;
using UnityEngine.UI;
public class PVRTCombine : MonoBehaviour {
public Texture2D texture256;
public Texture2D texture128;
void Start ()
{
GetComponent<RawImage>().texture = Combine(texture256, texture128);;
}
Texture2D Combine(Texture2D tex,Texture2D tex1)
{
int length = 512;
byte[] data = null;
var blcokBytes = 0;
switch (tex.format)
{
case TextureFormat.PVRTC_RGB2:
case TextureFormat.PVRTC_RGBA2:
blcokBytes = 4;
data = new byte[length / 4 * length];
break;
case TextureFormat.PVRTC_RGB4:
case TextureFormat.PVRTC_RGBA4:
blcokBytes = 8;
data = new byte[length / 2 * length];
break;
default:
Debug.Log("Not supported.");
return null;
}
//填充左下角 256
CombineBlocks(tex.GetRawTextureData(), data, tex.width, 4, blcokBytes, 0);
//填充左上角 256
CombineBlocks(tex.GetRawTextureData(), data, tex.width, 4, blcokBytes, BlcokOffset(tex.width,blcokBytes));
//填充右下角 256
CombineBlocks(tex.GetRawTextureData(), data, tex.width, 4, blcokBytes, 2 * BlcokOffset(tex.width,blcokBytes));
//填充右上角区域
//左下角 128
CombineBlocks(tex1.GetRawTextureData(), data, tex1.width, 4, blcokBytes, 3 * BlcokOffset(tex.width,blcokBytes));
//左上角 128
CombineBlocks(tex1.GetRawTextureData(), data, tex1.width, 4, blcokBytes, 3 * BlcokOffset(tex.width,blcokBytes) + BlcokOffset(tex1.width,blcokBytes));
//右下角 128
CombineBlocks(tex1.GetRawTextureData(), data, tex1.width, 4, blcokBytes, 3 * BlcokOffset(tex.width,blcokBytes) + 2 * BlcokOffset(tex1.width, blcokBytes));
//右上角 128
CombineBlocks(tex1.GetRawTextureData(), data, tex1.width, 4, blcokBytes, 3 * BlcokOffset(tex.width,blcokBytes) + 3 * BlcokOffset(tex1.width, blcokBytes));
var combinedTex = new Texture2D(length, length, tex.format, false);
combinedTex.LoadRawTextureData(data);
combinedTex.Apply(false,true);
return combinedTex;
}
int BlcokOffset(int length, int blcokBytes)
{
return length / (16 / blcokBytes) * length;
}
void CombineBlocks(byte[] src, byte[] dst, int length, int block, int bytes, int blockOffest)
{
int cell = length / block;
for (int i = 0; i < cell; i++)
{
for (int j = 0; j < cell; j++)
{
int srcindex = ((i * cell) + j) * bytes;
int dstindex = srcindex + blockOffest;
Buffer.BlockCopy(src, srcindex, dst, dstindex, bytes);
}
}
}
}
iPhone 5SE 真机测试大概合并一张512的贴图需要1毫秒,如果游戏中适合一帧只显示一个角色,如果有建议或者意见欢迎在下面留言。
- 本文固定链接: https://www.xuanyusong.com/archives/4531
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!


两张图叠加形成一张图,其中一张有透明像素,怎么完美叠加。
就用 alpha blend 混合算法就行
雨松大大,请问带mipmap的贴图合并之后怎么保证mipmap还在呢?
Texture2D(length, length, tex.format, false); 最后一个参数就表示是否需要mipmap 你可以试试这个