Unity图片优化-Dither算法(RGBA16优化)

在unity开发过程中,游戏图片占用了很大一部分的手机内存。所以在游戏开发中,对图片的优化也至关重要。

在Unity中常用的的图片格式有RGBA32,RGBA16,ETC,PVRTC等。这里我们主要讨论带透明通道的RGBA32和RGBA16这两种格式的图片在Unity占用的内存空间已经优化方案。

我们知道,RGBA32是R,G,B,A四个通道每个通道用8位来表示,RGBA16则是用4位。所以RGBA32能够带来更好的显示效果。同时也会带来更大的内存消耗。下面给两张RGBA16和RGBA32的对比图。

RGBA32


RGBA32.png

RGBA16


RGBA16.png

从上面两个图可以看得出,RGBA32能够带来更好的显示效果。而RGBA16在有些地方的色阶太明显,导致显示效果不尽人意。由此keijiro(Github地址)写了一个dither算法来消除这种色阶,以达到高于RGBA16低于RGBA32的显示效果。

下图为Dither优化之后的RGBA16

RGBA16-Dither.png

通过对比能明显看出优化后的RGBA16能够消除色阶,如果不是放大特意看,和RGBA32几乎差别不同。通过这种方式将内存降低一半确认带来更好的效果。

万事总会存在利弊,这个算法在消除了色阶的同事,带来的是更多的噪点。所以这个方法不适用于图片需要放大来显示的。总体来说,该方案在一定程度上还是能够带来很好的效果。
最后把算法的核心代码贴出来 。


public class TextureImportSetting : AssetPostprocessor {

    string[] assetTexturePath = new string[]{"Assets/Resources/TextureVN/"}; //放置需要优化的路径
    void OnPreprocessTexture(){
        foreach (var str in assetTexturePath)
        {
            if (this.assetPath.StartsWith(str) )
            {
                TextureImporter textureImporter = this.assetImporter as TextureImporter;
                textureImporter.textureType = TextureImporterType.Advanced;
                textureImporter.npotScale = TextureImporterNPOTScale.ToNearest;
                textureImporter.mipmapEnabled = false;
                textureImporter.isReadable = false;
                if ( textureImporter.DoesSourceTextureHaveAlpha())
                {
                    textureImporter.textureFormat = TextureImporterFormat.RGBA32;
                }
            }
        }
    }
    public static void OnPostprocessRGB16 (Texture2D texture)
    {
        
        var texw = texture.width;
        var texh = texture.height;

        var pixels = texture.GetPixels ();
        var offs = 0;

        var k1Per15 = 1.0f / 15.0f;
        var k1Per16 = 1.0f / 16.0f;
        var k3Per16 = 3.0f / 16.0f;
        var k5Per16 = 5.0f / 16.0f;
        var k7Per16 = 7.0f / 16.0f;

        for (var y = 0; y < texh; y++) {
            for (var x = 0; x < texw; x++) {
                float a = pixels [offs].a;
                float r = pixels [offs].r;
                float g = pixels [offs].g;
                float b = pixels [offs].b;

                var a2 = Mathf.Clamp01 (Mathf.Floor (a * 16) * k1Per15);
                var r2 = Mathf.Clamp01 (Mathf.Floor (r * 16) * k1Per15);
                var g2 = Mathf.Clamp01 (Mathf.Floor (g * 16) * k1Per15);
                var b2 = Mathf.Clamp01 (Mathf.Floor (b * 16) * k1Per15);

                var ae = a - a2;
                var re = r - r2;
                var ge = g - g2;
                var be = b - b2;

                pixels [offs].a = a2;
                pixels [offs].r = r2;
                pixels [offs].g = g2;
                pixels [offs].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].a += ae * k7Per16;
                    pixels [n1].r += re * k7Per16;
                    pixels [n1].g += ge * k7Per16;
                    pixels [n1].b += be * k7Per16;
                }

                if (y < texh - 1) {
                    pixels [n3].a += ae * k5Per16;
                    pixels [n3].r += re * k5Per16;
                    pixels [n3].g += ge * k5Per16;
                    pixels [n3].b += be * k5Per16;

                    if (x > 0) {
                        pixels [n2].a += ae * k3Per16;
                        pixels [n2].r += re * k3Per16;
                        pixels [n2].g += ge * k3Per16;
                        pixels [n2].b += be * k3Per16;
                    }

                    if (x < texw - 1) {
                        pixels [n4].a += ae * k1Per16;
                        pixels [n4].r += re * k1Per16;
                        pixels [n4].g += ge * k1Per16;
                        pixels [n4].b += be * k1Per16;
                    }
                }

                offs++;
            }
        }

        texture.SetPixels (pixels);
        EditorUtility.CompressTexture (texture, TextureFormat.RGBA4444, TextureCompressionQuality.Best);
    }
    void OnPostprocessTexture(Texture2D texture){

        foreach (var str in assetTexturePath)
        {
            if (this.assetPath.StartsWith(str) )
            {
                TextureImporter textureImporter = this.assetImporter as TextureImporter;
                if ( textureImporter.DoesSourceTextureHaveAlpha())
                {
                    OnPostprocessRGB16(texture);
                }
            }
        }
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容

  • 001发现的问题 下午,复习资料到了,自己做题。 发现无论视频还是书籍,对初学者来说都是有不足的。 视频的老师教学...
    河马先森阅读 175评论 0 0
  • 我们没必要去讨好身边的同龄人,说白你去讨好只是为了显摆自己朋友多。讨好和真心是不同的,当你讨好她做朋友的时候,或许...
    杜杜_鹃阅读 139评论 0 0
  • 2017年6月22日5时04分50秒,杭州119指挥中心接到报警称,望江路和之江路交叉口附近发生火灾;5时05分5...
    西克觅阅读 534评论 0 0
  • 画符 作者:散人 有一个大户人家,五短身材,又有钱,又情人多。其中一个情人生了一个儿子,一岁时突乱到夜里就哭啼,找...
    闻思修1965阅读 482评论 0 1
  • 郑州哪里可以苹果手机扩容,2018年7月iPhone 升级内存价格表 6/6plus 到32G 1...
    小松修机阅读 1,674评论 0 0