【UNITY填坑日记】unity图片资源优化神器dither4444

用过UNITY的朋友们都应该知道,unity为了在运行时提升装载资源的速度,采用了单独的图片压缩方式。而并不是我们平时所接触的JPG、PNP等。

简单来说,UNITY资源最后打包出来的图片基本上会大大超出我们原文件大小。简而言之,图片资源大小和以下几点相关

  • 图片长宽大小
  • 图片是否是2的幂次方
  • 图片是否是正方形
  • 图片的压缩格式

我们以IOS平台为例子,unity提供了 DXT(4位和8位)、16BIT、32BIT(true color)几种压缩格式。经过实测,不带alpha(透明通道)的图片,使用DXT压缩可以达到理想效果。但若图片带alpha,使用DXT压缩则会在透明边缘出现非常模糊的现象,图片基本不可用。

这时候我们需要采用16BIT或者32BIT的压缩存储方式,但显而易见,存储开销和运行游戏时的内存开销将大大增加。

另外,unity提供的16色压缩算法还很“独特”的对颜色进行了“分层”,效果效果那是非常的渐变分明。。

(以下图片来自dither4444:https://github.com/keijiro/unity-dither4444

这里写图片描述
这里写图片描述

下图是转了16色的,在很多游戏场景里基本不可用。

下面我们的神器dither4444出场了,
这里写图片描述
这个是使用dither4444处理成16色的图片,能看得出来差别在哪吗?

其实原理很好理解,使用点阵的疏密来替代颜色的变化(在90年代的PC游戏里经常使用的效果)

这样我们能以损失较小图片品质的情况下,大大降低我们的资源大小。所以我们在不得已需要使用非DXT压缩格式时,可以考虑使用本工具对图片进行压缩。


附代码(以下代码是我改过dither4444的,将自动对指定目录的导入图片进行16BIT转换)

using UnityEngine;
using UnityEditor;
using System.Collections;

class TextureModifier : AssetPostprocessor
{

    bool Fit(string assetPath){
        string[] dirs = new string[] { "/BattleSprites/", "/Character/", "/HeadAvata/", "/Items/", "/TileRes/models/", "/TileRes/tilemap/"};

        foreach(var dir in dirs){
            if(assetPath.Contains(dir)) return true;
        }
        return false;
    }

    void OnPreprocessTexture()
    {
        var importer = (assetImporter as TextureImporter);

        importer.textureType = TextureImporterType.Sprite;
        importer.spritePixelsPerUnit = 1;
        importer.generateMipsInLinearSpace = false;


        if (Fit(assetPath)) {
            //importer.textureFormat = TextureImporterFormat.RGBA32;
        }
    }

    void OnPostprocessTexture (Texture2D texture)
    {
        if (!Fit(assetPath)) {
            return;
        }

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

猜你喜欢

转载自blog.csdn.net/rcfalcon/article/details/51432070