• Unity3d之剥离alpha通道


    unity中, 将图集的 alpha 通道剥离出来可减少包体大小和内存使用大小。

    方法是将原来的一张 rgba 图分成一张 rgb 和一张 alpha 图,android上rgb和alpha图均采用etc压缩格式,ios上采用pvrtc格式。其中alpha通道信息可以存在r中。

    分享 alpha 通道工具的源代码如下: 

      1 using System;
      2 using System.IO;
      3 using UnityEditor;
      4 using UnityEngine;
      5 
      6 public static class TextureAlphaSpliter
      7 {
      8     const string
      9         RGBEndName = "(rgb)",
     10         AlphaEndName = "(a)";
     11 
     12     public static bool WhetherSplit = true;
     13     public static bool AlphaHalfSize;
     14 
     15     static Texture s_rgba;
     16 
     17     public static void SplitAlpha(Texture src, bool alphaHalfSize, out Texture rgb, out Texture alpha)
     18     {
     19         if (src == null)
     20             throw new ArgumentNullException("src");
     21 
     22         // make it readable
     23         string srcAssetPath = AssetDatabase.GetAssetPath(src);
     24         var importer = (TextureImporter)AssetImporter.GetAtPath(srcAssetPath);
     25         {
     26             importer.isReadable = true;
     27             importer.SetPlatformTextureSettings("Standalone", 4096, TextureImporterFormat.ARGB32, 100, true);
     28             importer.SetPlatformTextureSettings("Android", 4096, TextureImporterFormat.ARGB32, 100, true);
     29             importer.SetPlatformTextureSettings("iPhone", 4096, TextureImporterFormat.ARGB32, 100, true);
     30         }
     31         AssetDatabase.ImportAsset(srcAssetPath);
     32 
     33         alpha = CreateAlphaTexture((Texture2D)src, alphaHalfSize);
     34         rgb = CreateRGBTexture(src);
     35     }
     36 
     37     static Texture CreateRGBTexture(Texture src)
     38     {
     39         if (src == null)
     40             throw new ArgumentNullException("src");
     41 
     42         string srcPath = AssetDatabase.GetAssetPath(src);
     43         string rgbPath = GetPath(src, RGBEndName);
     44         int size = Mathf.Max(src.width, src.height, 32);
     45 
     46         AssetDatabase.DeleteAsset(rgbPath);
     47         AssetDatabase.CopyAsset(srcPath, rgbPath);
     48         AssetDatabase.ImportAsset(rgbPath);
     49 
     50         SetSettings(rgbPath, size, TextureImporterFormat.ETC_RGB4, TextureImporterFormat.PVRTC_RGB4);
     51 
     52         return (Texture)AssetDatabase.LoadAssetAtPath(rgbPath, typeof(Texture));
     53     }
     54 
     55     static Texture CreateAlphaTexture(Texture2D src, bool alphaHalfSize)
     56     {
     57         if (src == null)
     58             throw new ArgumentNullException("src");
     59 
     60         // create texture
     61         var srcPixels = src.GetPixels();
     62         var tarPixels = new Color[srcPixels.Length];
     63         for (int i = 0; i < srcPixels.Length; i++)
     64         {
     65             float r = srcPixels[i].a;
     66             tarPixels[i] = new Color(r, r, r);
     67         }
     68 
     69         Texture2D alphaTex = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false);
     70         alphaTex.SetPixels(tarPixels);
     71         alphaTex.Apply();
     72 
     73         // save
     74         string saveAssetPath = GetPath(src, AlphaEndName);
     75         string fullPath = BuildingAssetBundle.GetFullPath(saveAssetPath);
     76         var bytes = alphaTex.EncodeToPNG();
     77         File.WriteAllBytes(fullPath, bytes);
     78 
     79         AssetDatabase.SaveAssets();
     80         AssetDatabase.Refresh();
     81 
     82         // setting
     83         int size = alphaHalfSize ? Mathf.Max(src.width / 2, src.height / 2, 32) : Mathf.Max(src.width, src.height, 32);
     84         SetSettings(saveAssetPath, size, TextureImporterFormat.ETC_RGB4, TextureImporterFormat.PVRTC_RGB4);
     85 
     86         return (Texture)AssetDatabase.LoadAssetAtPath(saveAssetPath, typeof(Texture));
     87     }
     88 
     89     static void SetSettings(string assetPath, int maxSize, TextureImporterFormat androidFormat, TextureImporterFormat iosFormat)
     90     {
     91         var importer = (TextureImporter)AssetImporter.GetAtPath(assetPath);
     92         {
     93             importer.npotScale = TextureImporterNPOTScale.ToNearest;
     94             importer.isReadable = false;
     95             importer.mipmapEnabled = false;
     96             importer.alphaIsTransparency = false;
     97             importer.wrapMode = TextureWrapMode.Clamp;
     98             importer.filterMode = FilterMode.Bilinear;
     99             importer.anisoLevel = 4;
    100             importer.SetPlatformTextureSettings("Android", maxSize, androidFormat, 100, true);
    101             importer.SetPlatformTextureSettings("iPhone", maxSize, iosFormat, 100, true);
    102             importer.SetPlatformTextureSettings("Standalone", maxSize, TextureImporterFormat.ARGB32, 100, true);
    103         }
    104         AssetDatabase.ImportAsset(assetPath);
    105     }
    106 
    107     static string GetPath(Texture src, string endName)
    108     {
    109         if (src == null)
    110             throw new ArgumentNullException("src");
    111 
    112         string srcAssetPath = AssetDatabase.GetAssetPath(src);
    113         if (string.IsNullOrEmpty(srcAssetPath))
    114             return null;
    115 
    116         string dirPath = Path.GetDirectoryName(srcAssetPath);
    117         string ext = Path.GetExtension(srcAssetPath);
    118         string fileName = Path.GetFileNameWithoutExtension(srcAssetPath);
    119 
    120         if (fileName.EndsWith(RGBEndName))
    121             fileName = fileName.Substring(0, fileName.Length - RGBEndName.Length);
    122 
    123         if (fileName.EndsWith(AlphaEndName))
    124             fileName = fileName.Substring(0, fileName.Length - AlphaEndName.Length);
    125 
    126         return string.Format("{0}/{1}{2}{3}", dirPath, fileName, endName ?? "", ext);
    127     }
    128 
    129     public static Texture GetRGBA(Texture src)
    130     {
    131         if (src != null && (s_rgba == null || s_rgba.name != src.name))
    132         {
    133             string path = GetPath(src, "");
    134             if (!string.IsNullOrEmpty(path))
    135                 s_rgba = AssetDatabase.LoadAssetAtPath(path, typeof(Texture)) as Texture;
    136         }
    137 
    138         return s_rgba;
    139     }
    140 }
    SplitAlpha

    然后改造一下 shader,以ngui的shader为例。

    原来要用一张 rgba 图的地方,现在改成用两张图,一张 rgb 和一张 alpha,改造为下:

    Shader "Custom/Alpha Splited Colored"
    {
        Properties
        {
            _MainTex ("RGB", 2D) = "black" {}
            _AlphaTex ("Alpha", 2D) = "black" {}
        }
        
        SubShader
        {
            LOD 200
    
            Tags
            {
                "Queue" = "Transparent"
                "IgnoreProjector" = "True"
                "RenderType" = "Transparent"
            }
            
            Pass
            {
                Cull Off
                Lighting Off
                ZWrite Off
                Fog { Mode Off }
                Offset -1, -1
                Blend SrcAlpha OneMinusSrcAlpha
    
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag            
    
                sampler2D _MainTex;
                sampler2D _AlphaTex;
        
                struct appdata_t
                {
                    float4 vertex : POSITION;
                    float2 texcoord : TEXCOORD0;
                    fixed4 color : COLOR;
                };
        
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    half2 texcoord : TEXCOORD0;
                    fixed4 color : COLOR;
                };
        
                v2f vert (appdata_t v)
                {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.texcoord = v.texcoord;
                    o.color = v.color;
                    return o;
                }
                    
                fixed4 frag (v2f IN) : COLOR
                {
                    // [dev]
                    fixed4 col;
                    col.rgb = tex2D(_MainTex, IN.texcoord).rgb;
                    col.a = tex2D(_AlphaTex, IN.texcoord).r;
    
                    if (IN.color.r < 0.001 && IN.color.g < 0.001 && IN.color.b < 0.001)  
                    {  
                        float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));  
                        col.rgb = float3(grey, grey, grey);  
                    }  
                    else  
                        col = col * IN.color;
                    
                    return col;  
                }
                ENDCG
            }
        }
    
        SubShader
        {
            LOD 100
    
            Tags
            {
                "Queue" = "Transparent"
                "IgnoreProjector" = "True"
                "RenderType" = "Transparent"
            }
            
            Pass
            {
                Cull Off
                Lighting Off
                ZWrite Off
                Fog { Mode Off }
                Offset -1, -1
                ColorMask RGB
                Blend SrcAlpha OneMinusSrcAlpha
                ColorMaterial AmbientAndDiffuse
                
                SetTexture [_MainTex]
                {
                    Combine Texture * Primary
                }
    
                SetTexture [_AlphaTex] 
                {
                    Combine previous, texture * primary 
                }
            }
        }
    }
    shader 

    转载请注明出处:http://www.cnblogs.com/jietian331/p/5167422.html

  • 相关阅读:
    数组(Array)的使用方法
    Django中的事务操作
    什么是事务(Transaction)?事务的四个特性以及事务的隔离级别
    0.2 Django + Uwsgi + Nginx 的生产环境部署之实战篇
    0.1 Django + Uwsgi + Nginx 的生产环境部署之理论篇
    linux 进入编辑文件,保存退出相关命令
    Django--restframework
    使用用户名/邮箱/手机号 + 密码登陆 多形式登陆
    Django中异步任务---django-celery
    Redis 常用命令
  • 原文地址:https://www.cnblogs.com/jietian331/p/5167422.html
Copyright © 2020-2023  润新知