Unity图片优化神器 - dither算法究极进化方案

在Unity移动平台的游戏开发过程中,贴图资源是往往是占资源量最大的资源。如何在保证视觉效果的同时,尽可能的减少贴图资源,是开发团队会经常遇到的问题。通常来说,对于3D物体的纹理,是可以采用ETC/PVRTC等压缩比很大的算法处理的,但是对于细节要求很高的UI纹理,这样处理造成的失真往往达不到质量要求。对于这类的贴图,我们可以考虑使用失真较小的16位的贴图格式存储。

但是对于颜色数较高的纹理,Unity提供的默认转换方法会呈现明显的色带。针对该问题,keijiro实现了一种dither4444的改进算法。从图1上可以看到,对于画面细节比较平滑的图片,该算法虽然消除了色带现象,同时带来了肉眼可见的噪点。
 

<图1> 左:原始图 右:keijiro的dither4444示意图


笔者在keijiro的算法基础上进行了改进,提供了一个将RGB24bit图dither之后转RGB565的方法,基本消除了肉眼可见的失真,实际效果见图2。
 

<图2> 左:原始图 右:笔者的dither565示意图


实际在我的项目的应用中,对于不适合ETC/PVRTC压缩的图片,二手手机号购买平台都采用了该文章中的RGB565或者RGB565+A8的方式。在肉眼基本无失真的基础上,节省了部分资源。

最后附上OnPostprocessTexture代码

  1. void OnPostprocessTexture (Texture2D texture)
  2. {
  3.                   if(assetPath.Contains ("_dither565"))
  4.                   {
  5.                               var texw = texture.width;
  6.                               var texh = texture.height;
  7.                               var pixels = texture.GetPixels ();
  8.                               var offs = 0;
  9.                               var k1Per31 = 1.0f / 31.0f;
  10.                               var k1Per32 = 1.0f / 32.0f;
  11.                               var k5Per32 = 5.0f / 32.0f;
  12.                               var k11Per32 = 11.0f / 32.0f;
  13.                               var k15Per32 = 15.0f / 32.0f;
  14.                               var k1Per63 = 1.0f / 63.0f;
  15.                               var k3Per64 = 3.0f / 64.0f;
  16.                               var k11Per64 = 11.0f / 64.0f;
  17.                               var k21Per64 = 21.0f / 64.0f;
  18.                               var k29Per64 = 29.0f / 64.0f;
  19.                               var k_r = 32; //R&B压缩到5位,所以取2的5次方
  20.                               var k_g = 64; //G压缩到6位,所以取2的6次方
  21.                               for(var y = 0; y < texh; y++){
  22.                                            for(var x = 0; x < texw; x++){
  23.                                                        float r = pixels [offs].r;
  24.                                                        float g = pixels [offs].g;

复制代码

  1. float b = pixels [offs].b;
  2.                                       var r2 = Mathf.Clamp01 (Mathf.Floor (r * k_r) * k1Per31);
  3.                                       var g2 = Mathf.Clamp01 (Mathf.Floor (g * k_g) * k1Per63);
  4.                                       var b2 = Mathf.Clamp01 (Mathf.Floor (b * k_r) * k1Per31);
  5.                                       var re = r - r2;
  6.                                       var ge = g - g2;
  7.                                       var be = b - b2;
  8.                                       var n1 = offs + 1;
  9.                                       var n2 = offs + texw - 1;
  10.                                       var n3 = offs + texw;
  11.                                       var n4 = offs + texw + 1;
  12.                                       if(x < texw - 1){
  13.                                                 pixels [n1].r += re * k15Per32;
  14.                                                 pixels [n1].g += ge * k29Per64;
  15.                                                 pixels [n1].b += be * k15Per32;
  16.                                       }
  17.                                       if(y < texh - 1){
  18.                                                 pixels [n3].r += re * k11Per32;
  19.                                                 pixels [n3].g += ge * k21Per64;
  20.                                                 pixels [n3].b += be * k11Per32;
  21.                                                 if(x > 0){
  22.                                                           pixels [n2].r += re * k5Per32;
  23.                                                           pixels [n2].g += ge * k11Per64;
  24.                                                           pixels [n2].b += be * k5Per32;
  25.                                                 }
  26.                                                 if(x < texw - 1){
  27.                                                           pixels [n4].r += re * k1Per32;
  28.                                                           pixels [n4].g += ge * k3Per64;
  29.                                                           pixels [n4].b += be * k1Per32;
  30.                                                 }
  31.                                       }
  32.                                       pixels [offs].r = r2;
  33.                                       pixels [offs].g = g2;
  34.                                       pixels [offs].b = b2;
  35.                                       offs++;
  36.                              }
  37.                    }
  38.                    texture.SetPixels (pixels);
  39.                    EditorUtility.CompressTexture (texture, TextureFormat.RGB565, TextureCompressionQuality.Best);
  40.           }
  41. }

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值