[原]JPG+mask替代透明Png
本人水平有限,不正之处还往大拿狂喷!
看到这个标题,有人估计会质疑,这不蛋疼,好好的png干嘛要分拆成两个啊!
倘若你有如此质疑,如此愤青的言论,恭喜你来对地方了,同时也小小鄙视你一下,水平太菜了。哈哈 言归正传!
为什么要这么做?
1、主要目的为了减小包大小,同时图片质量损失小。手游大家都知道,包越小转化率越高(可玩性相同的前提下)
实现细节:把一张带alpha通道的导入ps,在ps里面新建一张大小跟原图一样,格式为位图(为什么要位图,alpha值在标记透明的时候 其实就是非黑及白 也就是 0 1),复制原图的alpha通道到新建的图层,保存为png,保存原图为JPG 这样mask和jpg制作好了(这块用的bmp原图遭吐槽了,补充一份png的图)
前后大小比较:
实现原理:
在渲染过程中,把这两个重新还原回来,缓冲区的rgb为jpg纹理的rgb,a为mask纹理的r或g或b(为什么是 r/g/b 保存的mask时三个值是一样的 不信你试试 反正我试了 好使)
shader源码:
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 } } }
实现效果:
使用纹理:
这样基本实现了功能,但是有点麻烦 还的每次计算两个纹理,效率有点低,也不够高大尚
参考别人的说法,是在加载纹理的时候,实现纹理合并,在内存中一次生成一个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;
}