Unity图片优化神器 - Dither算法进阶方案
2017-08-25 13:50
295 查看
原文链接:https://blog.uwa4d.com/archives/2001.html
这是侑虎科技第288篇原创文章,感谢作者喵小逗供稿,欢迎转发分享,未经作者授权请勿转载。当然,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)
作者知乎专栏:https://zhuanlan.zhihu.com/p/28624490
在Unity移动平台的游戏开发过程中,贴图资源是往往是占资源量最大的资源。如何在保证视觉效果的同时,尽可能地减少贴图资源,是开发团队会经常遇到的问题。通常来说,对于3D物体的纹理,是可以采用ETC/PVRTC等压缩比很大的算法处理,但是对于细节要求很高的UI纹理,这样处理造成的失真往往达不到质量要求。对于这类的贴图,我们可以考虑使用失真较小的16位贴图格式存储。
但是对于颜色数较高的纹理,Unity提供的默认转换方法会呈现明显的色阶。针对该问题,keijiro实现了一种Dither4444的改进算法。从下图1上可以看到,对于画面细节比较平滑的图片,该算法虽然消除了色阶现象,同时带来了肉眼可见的噪点。
<图1> 左:原始图 右:keijiro的 Dither4444示意图
笔者在keijiro的算法基础上进行了改进,提供了一个将RGB24 Bit图Dither之后转RGB565的方法,基本消除了肉眼可见的失真,实际效果见下图2。
<图2> 左:原始图 右:笔者的 Dither565示意图
实际在我的项目的应用中,对于不适合ETC/PVRTC压缩的图片,都采用了该文章中的RGB565或者RGB565+A8的方式。在肉眼基本无失真的基础上,节省了部分资源。
最后附上OnPostprocessTexture代码:
文末,感谢喵小逗的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)。
也欢迎大家来积极参与U Sparkle开发者计划,简称"US",代表你和我,代表UWA和开发者在一起!
这是侑虎科技第288篇原创文章,感谢作者喵小逗供稿,欢迎转发分享,未经作者授权请勿转载。当然,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)
作者知乎专栏:https://zhuanlan.zhihu.com/p/28624490
在Unity移动平台的游戏开发过程中,贴图资源是往往是占资源量最大的资源。如何在保证视觉效果的同时,尽可能地减少贴图资源,是开发团队会经常遇到的问题。通常来说,对于3D物体的纹理,是可以采用ETC/PVRTC等压缩比很大的算法处理,但是对于细节要求很高的UI纹理,这样处理造成的失真往往达不到质量要求。对于这类的贴图,我们可以考虑使用失真较小的16位贴图格式存储。
但是对于颜色数较高的纹理,Unity提供的默认转换方法会呈现明显的色阶。针对该问题,keijiro实现了一种Dither4444的改进算法。从下图1上可以看到,对于画面细节比较平滑的图片,该算法虽然消除了色阶现象,同时带来了肉眼可见的噪点。
<图1> 左:原始图 右:keijiro的 Dither4444示意图
笔者在keijiro的算法基础上进行了改进,提供了一个将RGB24 Bit图Dither之后转RGB565的方法,基本消除了肉眼可见的失真,实际效果见下图2。
<图2> 左:原始图 右:笔者的 Dither565示意图
实际在我的项目的应用中,对于不适合ETC/PVRTC压缩的图片,都采用了该文章中的RGB565或者RGB565+A8的方式。在肉眼基本无失真的基础上,节省了部分资源。
最后附上OnPostprocessTexture代码:
void OnPostprocessTexture (Texture2D texture) { if(assetPath.Contains ("_dither565")) { var texw = texture.width; var texh = texture.height; var pixels = texture.GetPixels (); var offs = 0; var k1Per31 = 1.0f / 31.0f; var k1Per32 = 1.0f / 32.0f; var k5Per32 = 5.0f / 32.0f; var k11Per32 = 11.0f / 32.0f; var k15Per32 = 15.0f / 32.0f; var k1Per63 = 1.0f / 63.0f; var k3Per64 = 3.0f / 64.0f; var k11Per64 = 11.0f / 64.0f; var k21Per64 = 21.0f / 64.0f; var k29Per64 = 29.0f / 64.0f; var k_r = 32; //R&B压缩到5位,所以取2的5次方 var k_g = 64; //G压缩到6位,所以取2的6次方 for(var y = 0; y < texh; y++){ for(var x = 0; x < texw; x++){ float r = pixels [offs].r; float g = pixels [offs].g; float b = pixels [offs].b; var r2 = Mathf.Clamp01 (Mathf.Floor (r * k_r) * k1Per31); var g2 = Mathf.Clamp01 (Mathf.Floor (g * k_g) * k1Per63); var b2 = Mathf.Clamp01 (Mathf.Floor (b * k_r) * k1Per31); var re = r - r2; var ge = g - g2; var be = b - b2; var n1 = offs + 1; var n2 = offs + texw - 1; var n3 = offs + texw; var n4 = offs + texw + 1; if(x < texw - 1){ pixels [n1].r += re * k15Per32; pixels [n1].g += ge * k29Per64; pixels [n1].b += be * k15Per32; } if(y < texh - 1){ pixels [n3].r += re * k11Per32; pixels [n3].g += ge * k21Per64; pixels [n3].b += be * k11Per32; if(x > 0){ pixels [n2].r += re * k5Per32; pixels [n2].g += ge * k11Per64; pixels [n2].b += be * k5Per32; } if(x < texw - 1){ pixels [n4].r += re * k1Per32; pixels [n4].g += ge * k3Per64; pixels [n4].b += be * k1Per32; } } pixels [offs].r = r2; pixels [offs].g = g2; pixels [offs].b = b2; offs++; } } texture.SetPixels (pixels); EditorUtility.CompressTexture (texture, TextureFormat.RGB565, TextureCompressionQuality.Best); } }
文末,感谢喵小逗的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)。
也欢迎大家来积极参与U Sparkle开发者计划,简称"US",代表你和我,代表UWA和开发者在一起!
相关文章推荐
- Unity图片优化神器 - Dither算法进阶方案
- 【UNITY填坑日记】unity图片资源优化神器dither4444
- [Unity优化]图片纹理压缩方案
- Unity项目图片纹理优化方案
- 百度没出新算法之前这样的最好的的优化方案
- 海量数据库的查询优化及分页算法方案
- 海量数据库的查询优化及分页算法方案
- Unity开发安卓游戏(2):基于安卓游戏的优化方案总结!
- 海量数据库的查询优化及分页算法方案
- 海量数据库的查询优化及分页算法方案
- FW: 海量数据库的查询优化及分页算法方案
- 海量数据库的查询优化及分页算法方案
- 海量数据库的查询优化及分页算法方案
- 海量数据库的查询优化及分页算法方案
- STL堆算法性能分析与优化方法(GCC4.4.2 stl_heap.h源代码分析与改进方案)
- 海量数据库的查询优化及分页算法方案[转帖]
- PHP服务端如何通过程序将图上传到指定的图片服务器与图片服务器的优化方案
- 海量数据库的查询优化及分页算法方案
- 海量数据库的查询优化及分页算法方案(转)
- 海量数据库的查询优化及分页算法方案