Unity图片优化神器 - Dither算法进阶方案

简介:

在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);
      }
}






原文出处:侑虎科技
本文作者:admin
转载请与作者联系,同时请务必标明文章原始出处和原文链接及本声明。

目录
相关文章
|
4天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
|
4天前
|
人工智能 算法 大数据
Linux内核中的调度算法演变:从O(1)到CFS的优化之旅###
本文深入探讨了Linux操作系统内核中进程调度算法的发展历程,聚焦于O(1)调度器向完全公平调度器(CFS)的转变。不同于传统摘要对研究背景、方法、结果和结论的概述,本文创新性地采用“技术演进时间线”的形式,简明扼要地勾勒出这一转变背后的关键技术里程碑,旨在为读者提供一个清晰的历史脉络,引领其深入了解Linux调度机制的革新之路。 ###
|
14天前
|
人工智能 算法 数据安全/隐私保护
基于遗传优化的SVD水印嵌入提取算法matlab仿真
该算法基于遗传优化的SVD水印嵌入与提取技术,通过遗传算法优化水印嵌入参数,提高水印的鲁棒性和隐蔽性。在MATLAB2022a环境下测试,展示了优化前后的性能对比及不同干扰下的水印提取效果。核心程序实现了SVD分解、遗传算法流程及其参数优化,有效提升了水印技术的应用价值。
|
14天前
|
存储 缓存 算法
优化轮询算法以提高资源分配的效率
【10月更文挑战第13天】通过以上这些优化措施,可以在一定程度上提高轮询算法的资源分配效率,使其更好地适应不同的应用场景和需求。但需要注意的是,优化策略的选择和实施需要根据具体情况进行详细的分析和评估,以确保优化效果的最大化。
|
15天前
|
并行计算 算法 IDE
【灵码助力Cuda算法分析】分析共享内存的矩阵乘法优化
本文介绍了如何利用通义灵码在Visual Studio 2022中对基于CUDA的共享内存矩阵乘法优化代码进行深入分析。文章从整体程序结构入手,逐步深入到线程调度、矩阵分块、循环展开等关键细节,最后通过带入具体值的方式进一步解析复杂循环逻辑,展示了通义灵码在辅助理解和优化CUDA编程中的强大功能。
|
15天前
|
存储 缓存 算法
前端算法:优化与实战技巧的深度探索
【10月更文挑战第21天】前端算法:优化与实战技巧的深度探索
13 1
|
16天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于贝叶斯优化CNN-LSTM网络的数据分类识别算法matlab仿真
本项目展示了基于贝叶斯优化(BO)的CNN-LSTM网络在数据分类中的应用。通过MATLAB 2022a实现,优化前后效果对比明显。核心代码附带中文注释和操作视频,涵盖BO、CNN、LSTM理论,特别是BO优化CNN-LSTM网络的batchsize和学习率,显著提升模型性能。
|
14天前
|
存储 JSON 算法
TDengine 检测数据最佳压缩算法工具,助你一键找出最优压缩方案
在使用 TDengine 存储时序数据时,压缩数据以节省磁盘空间是至关重要的。TDengine 支持用户根据自身数据特性灵活指定压缩算法,从而实现更高效的存储。然而,如何选择最合适的压缩算法,才能最大限度地降低存储开销?为了解决这一问题,我们特别推出了一个实用工具,帮助用户快速判断并选择最适合其数据特征的压缩算法。
26 0
|
16天前
|
数据采集 缓存 算法
算法优化的常见策略有哪些
【10月更文挑战第20天】算法优化的常见策略有哪些
|
16天前
|
缓存 分布式计算 监控
算法优化:提升程序性能的艺术
【10月更文挑战第20天】算法优化:提升程序性能的艺术
下一篇
无影云桌面