如何指定纹理的格式 并异步加载到纹理缓存

请教大家,我面临的问题是这样的。

我有一堆纹理文件,所有的纹理文件都没有后缀名。这些纹理文件包含 png8, etc1_pkm, pvrtc4_pvr 这3种格式

同时我有一个配置文件,告诉我,在什么 device.platform 下应该加载哪些纹理文件。

在 quick-x 中或者 cocos-lua 中 有什么办法可以做到:

  1. 异步加载
  2. 异步加载的同时可以手动指定纹理的目标格式

期望的方法,例如

display.addImageAsync(path_to_image, kCCTexture2DPixelFormat_PVRTC4)

谢谢

下午后来看了一下 cpp 的实现,我想我要的功能,可能还得自己手敲。

android 上是支持 etc1 的,见 ./textures/CCTextureETC.cpp, 然后接口是 Texture2D.initWithETCFile

etc1 可能会遇到 alpha 通道的问题(我还没到这步。。。),常用的方法是用两个 etc1 拼一个图,生产这种 etc1 纹理的工具是 mali 。 渲染的时候要不要改shader 参考这篇文章:http://blog.csdn.net/langresser_king/article/details/9339313

以上结论都是基于 cocos2d-x v2x 的,v3x 的代码没有看过。

PVRTC4 的压缩结果的图片质量问题,我还真花时间研究过。 结论是画面质量可以压到很好,肉眼观察和PNG8位只有细微差别。

要做到这一点的关键是看你用那个压缩工具进行压缩 xcode 的 texture-tool 是不行的。

要用 imgtec 原装货 http://powervr-sdk-pvrtextool.software.informer.com/

然后你可以试试看下面的命令行进行压缩,质量保准顶呱呱

POWERVR_CL_QUALITY = “pvrtcnormal”

execute “#{PATH_TO_POWERVR_CL} -i #{from} -o #{to} -p -l -f PVRTC1_4 -q #{POWERVR_CL_QUALITY} -dither”

如果想追求更好效果的话,还可以试试
POWERVR_CL_QUALITY = “pvrtcbest” , 这个很慢,我在大量的 2048x2048 贴图上跑过,感觉比 normal 没有特别好很多

》》 ps。和你一样,在cocos2dx里面怎么搞我还没有想清楚,先前公司是基于irrlicht的3d引擎,资源加载是无后缀的,所以他是按后缀逐个尝试。

我的看法,不容易出错的处理办法是读文件头来决定使用那种纹理格式。

嗯嗯,我来解释一下把。 我说的不一定对,详细的可以 ./PVRTexToolCL | less 看文档

对于渐变图像: -dither 色彩抖动 开关很重要 ,因为这个纹理是用块压缩算法(block compression) 所以块和块之间的色彩连续性是不保证的。因此要抖动,抖了对连续性要求就低了。

对于底色透明的图像:-l Alpha Bleed 很重要,这个功能会把透明区域划干净,这样让压缩处理的图片的边缘更清晰。

然后:-q pvrtcnormal 和 pvrtcbest 是设定不同的后期补偿程度,后期补偿越大,整体效果越好

另外,使用GPU纹理对运行时的内存利用率有非常大的好处。

位图到GPU需要 内存解压缩 和 密集的CPU计算,表现在产品体验上 就是 卡顿

我们当时分了ALPHA图,是因为我们的建筑窗户部分需要反射环境贴图,而若将alpha与diffuse map放一起,由于alpha本身的0,1比重较大,pvrtc4认为这货很重要,所以拉大了它的比重,导致diffuse精度和质量降低。

新只是GET! 谢谢

另外,在2D游戏中,如果有精确点击的需求,还是需要单独分离出一个png8来做透明检测

Lua 里面支持数据流(stream) 操作吗?如果不支持的话,像素读会非常非常慢哦。

》》 我们有一个makedata_ios.bat makedata_android.bat makedata_win.bat的脚本,根据不同的平台,对资源进行处理。你们是放一起么?

这个问题,我们的做法和你们一样,根据运行平台出素材包

》》你们的UI压缩了么? 我们公司的UI是没有压缩的。完全不敢。。。。。压缩了就无法直视

UI 压缩的。 所有 icon 全部 texture atlas -> gpu texture。 其他素材全部 texture atlas -> png8 quant

》》关于 ect1+png8 和 PNG8+pvrtc4

这里不是很明白,为什么要 gpu 纹理加 上 PNG8呢? 为了在PC调试时候显示吗?

您的文章已被推荐到CocoaChina首页热门文章精选,感谢您的分享。

你们不会打算不改一行c++代码就搞定一个项目吧?。。。

仔细读了 cocos2d-x v3x 的 代码,我发现这个问题已经实现了! v3x 真是好啊!

具体的实现代码在:
https://github.com/chukong/cocos2d-x/blob/csxV3/cocos/platform/CCImage.cpp#L631

这个CCImage 做的很周到,读入素材的二进制后,首先判断是否是ccz或zip 压缩,如果是的话,先解压缩。

然后根据文件头来判断目标的纹理格式。

目前支持的GPU纹理格式分别是 PKM 封装的 etc1 格式 和 PVR 封装的 pvrtc格式

每个人的 标准,和需求不一样, 得目标明确。

你们讨论的结果如何?

具体有一下几个需求:

1.需求加载运行快。
2.需求初始安装包极小(有自动更新)。
3.需求游戏整包小。
4.需求游戏质量极高。
5.需求兼容性

etc1格式你们内存占用多大啊
转成pkm,2048*2048 12M, 太大了,不能接受,大师们怎么解决内存问题呢?

http://gamagama.cn/fetch/4a6SCR8 你下载这个pkm 纹理,载入以后看看使用的内存大小。如果比你现在的纹理小很多的话,那么就是你的 pkm 编译命令有问题了。

–.plist和png一起的打包资源,我们使用如1的方法加载png,然后在回调函数中加载plist。
function LogoScene:loadPlist( file)
cc.Director:getInstance():getTextureCache():addImageAsync(file, handler(self, self.plistImageAsyncCallback,file)) ---------调用此函数就报了,为啥子?

end

–注意回调函数的参数,这是plist异步加载的关键,形参是png纹理。
function LogoScene:plistImageAsyncCallback(texture,file)
string.gsub(file,".png",".plist")
cc.SpriteFrameCache:getInstance():addSpriteFramesWithFile(file, texture);

end

:14:几位大神,想问问,你们的png8是用什么方法和565图片融合的。。我之前查了资料试过用shader把两个图片进行融合。但是发现png8加到内存转换为rgba8888,内存增加太多了。。