天天看點

JPG+mask替代透明Png

看到這個标題,有人估計會質疑,這不蛋疼,好好的png幹嘛要分拆成兩個啊!

倘若你有如此質疑,如此憤青的言論,恭喜你來對地方了,同時也小小鄙視你一下,水準太菜了。哈哈 言歸正傳!

為什麼要這麼做?

1、主要目的為了減小包大小,同時圖檔品質損失小。手遊大家都知道,包越小轉化率越高(可玩性相同的前提下)

實作細節:把一張帶alpha通道的導入ps,在ps裡面建立一張大小跟原圖一樣,格式為位圖(為什麼要位圖,alpha值在标記透明的時候 其實就是非黑及白 也就是 0 1),複制原圖的alpha通道到建立的圖層,儲存為png,儲存原圖為JPG 這樣mask和jpg制作好了(這塊用的bmp原圖遭吐槽了,補充一份png的圖)

JPG+mask替代透明Png

前後大小比較:

JPG+mask替代透明Png
JPG+mask替代透明Png

實作原理:

在渲染過程中,把這兩個重新還原回來,緩沖區的rgb為jpg紋理的rgb,a為mask紋理的r或g或b(為什麼是 r/g/b 儲存的mask時三個值是一樣的 不信你試試 反正我試了 好使)

shader源碼:

JPG+mask替代透明Png
Shader "MaskTest" {

    Properties {
        _MainTex ("Base (RGB)", 2D) = "" {}
         _MainMask ("Base (RGB)", 2D) = "" {}
    }
    SubShader {
        Pass
        {
        Blend SrcAlpha OneMinusSrcAlpha  //一定不要忘了這個
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct vert_Input
            {
                fixed4 vertex : POSITION;
                fixed2 texcoord : TEXCOORD0;
            };
            struct vert_Output
            {
                fixed4 pos : SV_POSITION;
                fixed2 texcoord : TEXCOORD0;
            };
            uniform sampler2D _MainTex;
            uniform sampler2D _MainMask;
            vert_Output vert(vert_Input i)
            {
                vert_Output o;
                o.pos = mul(UNITY_MATRIX_MVP,i.vertex);
                o.texcoord = i.texcoord;
                return o;
            }

            fixed4 frag(vert_Output o):COLOR
            {
                fixed4 color1  = tex2D(_MainTex,o.texcoord);
                fixed4 mask = tex2D(_MainMask,o.texcoord);
                color1.a = mask.r;
                return color1;
            }

        ENDCG
        }
    }
}      
JPG+mask替代透明Png

實作效果:

JPG+mask替代透明Png

使用紋理:

JPG+mask替代透明Png

這樣基本實作了功能,但是有點麻煩 還的每次計算兩個紋理,效率有點低,也不夠高大尚

參考别人的說法,是在加載紋理的時候,實作紋理合并,在記憶體中一次生成一個texture,避免在shader中的運算。實作原理就是jpg的rgb拷貝到texture的rgb,把png的r/b/g拷貝到texture的a中

核心代碼如下:

for(int i = 0; i < len; i++)

    {

        dest = pngData[srcIndex];//得到第一個

        outPic[outIndex] = jpgData[srcIndex];

        outPic[outIndex + 1] = jpgData[srcIndex + 1];

        outPic[outIndex + 2] = jpgData[srcIndex+2];

        outPic[outIndex + 3] = dest;

        srcIndex += 3;

        outIndex += 4;

    }

繼續閱讀