Alpha Mask – 用 JPG 达到 PNG 效果

发表于2017-03-19
评论0 4.5k浏览
贴图里常用的图片格式是png和jpg,但因为jpg格式因为通道不够,而有的透明图层又需要使用缺失的那个png中的A通道,为此下面就给大家介绍下使用Alpha Mask,达到用jpg也可以实现png效果的方法。

在贴图中有常见的两种格式
PNG:使用 RGBA 四个通道
JPG:使用 RGB 三个通道
当我们需要使用到透明图层时就必须使用 A 通道
 
而 Alpha Mask 的主要功用
就是利用了图片的 RGB 三个通道
来作为额外的遮罩图层
将原本三张 PNG 变换为四张 JPG
使 JPG 也可以达到 PNG 的效果
 
製作原理
读取一至三张不同的 PNG 图片
撷取各自的像素产生出对应的 R、G、B 通道后
将三个通道合併成 Alpha Mask
 
接著则需要利用 Shader 来使用 Alpha Mask 作为遮罩参考来源
赋予相对应的 JPG、Alpha Mask 及 Channel
如此就能够利用 JPG 来达到 PNG 的效果
 
製作流程
这里的范例中使用了 R、G、B 三张不同的 PNG
PS 1:范例中的 JPG 并不是自动产生的,需要另外对 PNG 做处理
PS 2:在使用工具前,必须先勾选 Texture 设定中的 Read/Write Enabled
PS 3:打包图档的长宽必须一致
 
1.点选 Tools/Alpha Mask Maker
2.赋予对应的贴图素材
3.点选 Create Alpha Mask 按钮,并选择储存路径产生出 Alpha Mask

 

4.生成 Alpha Masked 材质球并做相对应设定
Base:赋予 JPG 图片
Alpha:赋予 Alpha Mask 图片
Channel:选择使用的通道
 

5.完成利用JPG来达到PNG效果
工具程式码
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using UnityEngine; 
using UnityEditor; 
using System.Collections; 
using System.IO; 
    
public class AlphaMaskWindow : EditorWindow 
    private Texture2D m_textureR; 
    private Texture2D m_textureG; 
    private Texture2D m_textureB; 
    
    private int m_arrayLength; 
    private int m_width; 
    private int m_height; 
    private Texture2D m_alphaMask; 
    
    [MenuItem("Tools/Alpha Mask Maker")] 
    private static void OpenWindow() 
    
        EditorWindow.GetWindow ().Show (); 
    
    
    
    void OnGUI() 
    
        GUILayout.BeginVertical (); 
        m_textureR = EditorGUILayout.ObjectField("Reference Texture R", m_textureR,typeof(object), false)asTexture2D; 
        m_textureG = EditorGUILayout.ObjectField("Reference Texture G", m_textureG,typeof(object), false)asTexture2D; 
        m_textureB = EditorGUILayout.ObjectField("Reference Texture B", m_textureB,typeof(object), false)asTexture2D; 
    
        if (m_textureR != null || m_textureG != null || m_textureB != null
        
            if(CheckSize()) 
                DisplayButtons(); 
            else
                EditorGUILayout.LabelField("Textures should have the same size."); 
        
    
        EditorGUILayout.EndVertical (); 
    
    
    
    private void DisplayButtons() 
    
        if (GUILayout.Button ("Create Alpha Mask")) 
            CreateAlphaMask (); 
    
        
        
    private void CreateAlphaMask() 
    {         
        m_alphaMask = null
        m_arrayLength = 0; 
    
        Initialize (m_textureR); 
        Initialize (m_textureG); 
        Initialize (m_textureB); 
    
        Color[] channelR = GetChannel (m_textureR, Color.red); 
        Color[] channelG = GetChannel (m_textureG, Color.green); 
        Color[] channelB = GetChannel (m_textureB, Color.blue); 
    
        Color[] finalColor = new Color[m_arrayLength]; 
        for(int cnt = 0; cnt < finalColor.Length; cnt++) 
        
            finalColor[cnt] = new Color(channelR[cnt].r, channelG[cnt].g, channelB[cnt].b); 
        
    
        m_alphaMask.SetPixels (0, 0, m_width, m_height, finalColor); 
    
        SaveAlphaMask (); 
    
    
    
    private void Initialize(Texture2D texture) 
    
        if (m_alphaMask != null
            return
    
        if (texture != null
        
            m_arrayLength = texture.GetPixels().Length; 
            m_alphaMask = new Texture2D (texture.width, texture.height, TextureFormat.RGBA32, false); 
        
    
    
    
    private Color[] GetChannel(Texture2D texture, Color color) 
    
        Color[] channel = new Color[m_arrayLength]; 
    
        if(texture != null
        
            channel = texture.GetPixels(); 
            for(int cnt = 0; cnt < m_arrayLength; cnt++) 
            
                if(channel[cnt].a != 0) 
                    channel[cnt] = color; 
                else
                    channel[cnt] = new Color(0, 0, 0, 0); 
            
        
        else
        
            for(int cnt = 0; cnt < m_arrayLength; cnt++) 
            
                channel[cnt] = new Color(0, 0, 0, 0); 
            
        
    
        return channel; 
    
    
    
    private bool CheckSize() 
    
        m_width = 0; 
        m_height = 0; 
    
        SetSize (m_textureR); 
        SetSize (m_textureG); 
        SetSize (m_textureB); 
    
        bool result = true
    
        result &= CheckTextureSize (m_textureR); 
        result &= CheckTextureSize (m_textureG); 
        result &= CheckTextureSize (m_textureB); 
    
        return result; 
    
    
    
    private void SetSize(Texture2D texture) 
    
        if (texture == null
            return
    
        m_width = texture.width; 
        m_height = texture.height; 
    
    
    
    private bool CheckTextureSize(Texture2D texture) 
    
        if (texture != null
            return m_width == texture.width && m_height == texture.height; 
        else
            return true
    
    
    
    private void SaveAlphaMask() 
    
        string path = EditorUtility.SaveFilePanelInProject ("Save Alpha Mask", "", "jpg","Select folder and choose file name."); 
    
        byte[] bytes = m_alphaMask.EncodeToJPG(); 
            
        File.WriteAllBytes(path, bytes); 
    
        AssetDatabase.Refresh (); 
    
}

Shader 程式码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
Shader "Unlit/Transparent Colored Alpha Masked"
{
    Properties
    {
        _MainTex ("Base (RGB)", 2D) = "black" {}
        _MaskTex ("Alpha (RGB)", 2D) = "white" {}
        _Channel ("Channel", Vector) = (1, 0, 0, 0)
    }
    SubShader
    {
        LOD 100
        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
        }
        Cull Off
        Lighting Off
        ZWrite Off
        Fog { Mode Off }
        Offset -1, -1
        Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma only_renderers opengl d3d9 gles gles3 metal
                #include "UnityCG.cginc"
                struct appdata_t
                {
                    float4 vertex : POSITION;
                    float2 texcoord : TEXCOORD0;
                    fixed4 color : COLOR;
                };
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float2 texcoord : TEXCOORD0;
                    fixed4 color : COLOR;
                };
                uniform sampler2D _MainTex;
                uniform sampler2D _MaskTex;
                float4 _MainTex_ST;
                fixed4 _Channel;
                v2f vert (appdata_t v)
                {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                    o.color = v.color;
                    return o;
                }
                fixed4 frag (v2f i) : COLOR
                {
                    fixed4 mask = tex2D(_MaskTex, i.texcoord) * _Channel;
                    fixed alpha = mask.x  + mask.y + mask.z;
                    fixed4 col = fixed4(tex2D(_MainTex, i.texcoord).rgb * i.color.rgb,  alpha * i.color.a);
                    return col;
                }
            ENDCG
        }
    }
}



如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论