2013年11月25日 星期一

[Python] Photoshop 檔案輸出工具 : Export files with each layer set (Python + comtypes + PyQt)

  Photoshop檔案輸出工具試作,以Python 2.7 + comtypes + PyQt 4作成。其中使用comtypes是由於win32com無法處理2維陣列(參考:Python and photoshop- code snippets by Pete Hanshaw)。

  功能是自動的將所有的layers及每個layerSet(group)各別輸出成一個檔案(如下圖),另外還有layerSet的名稱過濾功能以及可自訂的輸出路徑,輸出的檔案名稱依據layerSet的name。


  寫到到目前為止遇到一個奇怪的問題無法解決,就是會無法獲得layerSets的length(app.activeDocument.layerSets.length),會出現NameError: Name length not found的錯誤訊息,另外看到有人使用len(layerSets)獲取length(參考:Photoshop scripting with Python @ Tech Art Tiki),但我用起來一樣會返回錯誤訊息(TypeError: object of type 'Dispatch' has no len()),也許是因為comtypes的關係吧?改天再來繼續完善。

目前完成的code
以下則是最單純的輸出功能的code供參考


參考資料:

2013年11月18日 星期一

[MAXScript] check edge length and face verts count (editable_poly)

檢查邊的長度是否小於輸入值以及面的點數是否大於輸入值,僅適用Editable_Poly。
Help查詢polyOp (Editable_Poly Geometry Methods (polyOp struct))

Code snippet - check editable_poly edge length and face verts count.
on Snipplr

2013年10月31日 星期四

[MAXScript] 利用script快速進行parameter wiring

Help可搜尋關鍵字paramWire
// 進行單向連結
// paramWire.connect [value]fromParam [value]toParam [string]toExpr

paramWire.connect $foo.baseObject[#radius] $baz.bend[#angle] "radius / 2"

// 進行雙向連結
// paramWire.connect2Way [value]leftParam [value]rightParam [string]leftExpr [string]rightExpr

2013年10月7日 星期一

[Unity] Particle System使用Mesh時,在畫面外不會Render的解決方式

  近日在幫忙解決一個Particle System(Shuriken)的particle消失的問題,遇到的情況是當Particle System的Render Mode使用Mesh,且Particle System的pivot是在畫面外時,mesh不會被render。這是Particle System本身的一個bug,理應要有個Always Render之類的選項來避免off-screen的時候被cull掉。(舊版的particle系統中則是沒有這個問題)

  在經過測試之後,得出兩種解決方式:
  1. Simulation Space - World
    在Particle System的基本設定中,把Simulation Space設定為World。而必須使用Local Space的particle就可使用第二種方式。
  2. Sub Emitters
    啟用Sub Emitters Module,在Birth新增一個sub emitter,這個sub emitter可以是deactive的。



2013年9月27日 星期五

[SAI] 如何使用正式版

  在成功購買Sai之後,Systemax會寄給你一份認證資訊,其中包含

  • Softoware License Number
  • Certificate Download Password
  • Password Character Type

  再來到Systemax的Download Software License Certificate File網頁,輸入你的Softoware License Number跟Certificate Download Password,下面則是要輸入自己的System ID,System ID每台電腦皆不相同,可從Sai執行指令獲得(Others>System ID),輸入完成後即可下載認證檔案,放置到Sai的目錄中即可。


2013年9月10日 星期二

[UVLayout] 基本教學

  今天用起多年未開過的UVLayout發現幾乎快忘光了,所以就在這記錄一下UVLayout要怎麼使用吧~免的下次再打開又忘光光了。因為UVLayout這款軟體極度不人性化、介面極度簡陋的特色,記不記得熱鍵是操作此軟體的最重要重點...下面附上官方的文件,以及一些重點操作的說明(UVLayout 2.06):


基本操作
  • 3D視角操作:
    • 旋轉(水平)
      • 以高度軸為基準 - LMB + 滑鼠水平移動
      • 以攝影機軸為基準 - Ctrl + LMB + 滑鼠水平移動
        (若發生基準軸錯誤問題,用Ctrl操作之後會恢復正常)
    • 透視切換 - O
    • Focus View - Home
  • 3D視窗:
    • Texture顯示
      • 切換Texture - T
      • 變換Texture尺寸 - +/-
    • 選取Shells
      • 選取 - Shift + LMB
      • 範圍框選 - Shift + Drag LMB
      • 清除所有選取 - Shift + LMB空白位置
  • UV操作:
    • Drop UV(3D編輯視窗) - D
    • 復原UV Drop(UV視窗) - Shift + D
    • UV切分 - C
    • UV黏合 - W
    • 將Shell對齊到要黏合的另一個邊上 - M
    • Shell的編輯
      • 放大 - Space + RMB
      • 旋轉 - Space + LMB
      • 移動 - Space + CMB 
    • UV Vertex編輯
      • 移動 - Ctrrl + RMB
    • 對稱
      • 尋找對稱 
        1. Menu>Symmerty Find
        2. 左鍵選UV Border
        3. 中鍵選對稱的UV Border
        4. Enter結束
      • 交換對稱 - Shift + S
      • 對齊對稱的Shell - S(在Shell上)
    • COPY UVs
      • 可用於對稱UV或相同Shell的堆疊
        1. Menu>Copy UVs 開啟Copy UVs的功能
        2. 第一下LMB選擇來源Shell上的一邊
        3. 第二下以後可依序選擇其他Shells上對應的邊
        4. 按下Space執行

參考文章

2013年9月6日 星期五

[Unity][Mecanim] 角色處理注意事項


以下為作業上的一些紀錄。

角色輸出與輸入


  • 3ds Max的單位設置為 1 Unit = 1 Centimeters
    • 如此在不改變Asset的Scale Factor狀況下(在Asset的Import Settings中,預設為0.01),Max中的一公尺會與Unity的一公尺相等,這是最符合物理的單位設定,可避免物理運算出現奇怪的現象。
  • 讓角色在DCC Tool中面向Front View(從Front View看到的是角色的正面),如此匯入Unity後,角色的正面會與GameObject的Forward方向一致。
  • 輸出骨架模型FBX檔案時,雖然不會勾選Animation項目,但是其子項目Skins必須要是被勾選著的,否則不會帶出Skin資料(3dsMax 9)。
  • 非Biped-based角色(只由Bone/Dummy...組成的Rig)在輸出動作檔案時,需保留一個Skinned mesh一同輸出,否則會發生輸出的FBX檔沒有Root Node的狀況。
  • 骨架請勿帶有negative scale,因為目前的mechanim並不支援negative scale的blending。
  • 當你的角色的root node不是skeleton而是dummy之類的物件時,在Unity的FBX Import Settings需將Animation設置為Store in Nodes,原因尚未探究(參考
  • 物件的命名不要跟輸出的FBX檔名相同(不是Child的物件),否則會出現flagsCount >= mask.m_Count錯誤訊息,而Rig的Root Node若取名與檔名相同則會出現Look rotation viewing vector is zero錯誤訊息(參考)。
  • Twist bone的父物件必須為該部位的主要骨頭
Mechanim系統
  • 在進行FBX Import Setting的設定時,在Animation的部份要注意Root Transform的設定,勾選的項目將不會對角色產生實際的位移旋轉效果(成為假動作的狀態)。
  • 當角色的動作本身有做位移時,如果動作與動作間的Blending設定吃掉了部份的時間區段,將會喪失那個時間區段內的位移距離,可能會導致位移效果有誤差的狀況。

相關文章

[Unity] 效能上需要注意的事項


在此整理一些有關效能上需要注意的問題,主要資訊來源是Unity的Manual,其中可能有許多地方理解錯誤,請多包涵與指正。
  • Mesh

    • Mesh的渲染是由Renderer Component擔當,一個Renderer會消耗一次運算,當一個角色被拆分成N個Meshes,也就會有N次的運算,因此要儘可能的減少Mesh的數量。
    • GameObject上被Deactive的Renderer Component,依舊會佔用記憶體,只是不會被呈像出來。
    • Mesh的Hard Edge上的點,因為Vert的Normal不一致,所以會被視為多個Verts,而UV Border Edge上的Vert也是一樣,在渲染流程上會被視為多個點。在Unity中所顯示的Verts、Tris就是這個真實的數量(送給OpenGLES的點的數量),所以才會有與DCC Tool中所顯示的數據不同的現象。
參考資料


  • Compression Assets
    • Unity在匯入資源時,會自動進行壓縮,而你可以在Preference中取消這項設定讓編輯時可以省下壓縮的等待時間,但在建立遊戲時是一定會進行壓縮的,不受該項設定影響。
  • Mesh Import Settings
    • Mesh Compression可以減少檔案所佔容量,但不能減少運算時的記憶體消耗。
    • Mesh Optimization會優化點的順序增進GPU運算效能。
  • Textures
    • Normals、Tangents:
      若物件沒有使用到Normal map及Real-time Lighting的話,可以取消Normals。而物件沒有使用到Normal map的話,可以取消Tangents。
    • Anisotropic Filtering:
      是針對當Mesh的面與視角的夾角相當小時會獲得較好的貼圖品質(通常用於地板),但也會增加GPU的運算消耗,在Quality Settings中可以針對所有的貼圖進行設定。
    • 在Unity中貼圖必須為二的冪次方,非二的冪次方貼圖通常只用於GUI。
    • Unity沒有限制貼圖必須為正方形,然而在iOS平台有這項要求,因此製作貼圖時須遵守正方貼圖原則。
參考資料




  • Materials:
    • 在一個GameObject、Renderer上使用的Material是越少越好,最好只使用一個,每個Material都會增加一個Draw call。
  • Skinned Mesh:
    • Unity使用1、2、4根骨頭來計算控制一個頂點,因此在DCC Tool中進行綁定時,一個頂點的權重最多包含4根骨頭即可,在遊戲中實際使用幾根骨頭做運算是依據Quality Settings中的設定。
參考資料




  • Bones:
    • PC遊戲通常的骨頭數量是介議於15~60根間,而行動平台建低於30根。(Blade&Soul的玩家角色使用約130根左右,其中包含臉部、附加骨頭)若人物有使用IK,在匯入Unity後因已經過Bake程序,應把IK清除掉必免占用運算。
  • Animation Compression:
    • Keyframe Reduction
      在匯入時減少Keyframs數量,能夠減少檔案尺寸及記憶體消耗,而Compression只能減少檔案尺寸
  • Combine Children:
    • Combine Children這個Script可以進行combine meshes的動作,而要combine的物件得使用同一張圖,這個處理可以有效降低draw calls(將多個使用同一張貼圖同一個材質的Meshes合併為一個Mesh)。

//

Manual中有優化圖像效能的指引

CPU: optimizing Draw call count
GPU: optimizing Model geometry

http://docs.unity3d.com/Documentation/Manual/OptimizingGraphicsPerformance.html

[Unity] Scroll and Turbulence Shader (流動加擾動效果)

這是我的第二個Fragment Shader,在此作紀錄供參考。
參考文章


此Shader的表現效果:


Inputs
MainTex為一張transparent texture,OffsetTex則是一張noise texture,Shader會以OffsetTex擾動MainTex,擾動的程度由Distortion控制,速度則由TurbulenceSpd控制。另外MainTex本身也會做流動,流動速度由ScrollSpd控制。
Inputs
Fragment Shader (without normals)

 Properties 
 {
  _MainTex("_MainTex", 2D) = "black" {}
  _OffsetTex("_Offset", 2D) = "black" {}
  _Distortion("_Distortion", Float ) = 0.1
  _TurbulenceSpd("_TurbulenceSpd", Float) = -50  
  _ScrollSpd("_ScrollSpd", Float) = 30
 }
 
 SubShader 
 {
  Tags
  {
   "Queue"="Transparent"
   "IgnoreProjector"="True"
   "RenderType"="Transparent"
  }
  
  Cull Off
  ZWrite Off
  Blend SrcAlpha OneMinusSrcAlpha

  Pass {
   CGPROGRAM
   #pragma vertex vert
   #pragma fragment frag
   #include "UnityCG.cginc"
   
   struct appdata {
    fixed4 vertex : POSITION;
    fixed2 texcoord : TEXCOORD0;
   };
   
   struct v2f {
    fixed4 pos : SV_POSITION;
    fixed2 uv : TEXCOORD0;
    fixed2 uv2 : TEXCOORD1;
   };
   
   fixed4 _MainTex_ST;
   fixed4 _OffsetTex_ST;
   fixed _Distortion;
   fixed _TurbulenceSpd;
   fixed _ScrollSpd;
   
   v2f vert (appdata_base v) {
    v2f o;
    
    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    
    // Offset _MainTex uv
    fixed mainTexOffset = _Time * _ScrollSpd;
    //o.uv.x = v.texcoord.x * _MainTex_ST.x + _MainTex_ST.z;
    //o.uv.y = v.texcoord.y * _MainTex_ST.y + _MainTex_ST.w + mainTexOffset;
    o.uv.x = v.texcoord.x;
    o.uv.y = v.texcoord.y + mainTexOffset;
    
    // Offset _OffsetTex uv
    fixed offsetTexOffset = _Time * _TurbulenceSpd;
    //o.uv2.x = v.texcoord.x * _OffsetTex_ST.x + _OffsetTex_ST.z + offsetTexOffset;
    //o.uv2.y = v.texcoord.y * _OffsetTex_ST.y + _OffsetTex_ST.w;
    o.uv2.x = v.texcoord.x + offsetTexOffset;
    o.uv2.y = v.texcoord.y;
    
    return o;
   }
   
   sampler2D _MainTex;
   sampler2D _OffsetTex;
   
   fixed4 frag(v2f i) : COLOR {
    // convert OffsetTex's color to luminance to distort MainTex's uv
    fixed4 offsetTexColor = tex2D(_OffsetTex, i.uv2);
    fixed lum = Luminance(offsetTexColor);
    fixed2 texCord = ( lum, lum );
    
    fixed4 mainTexColor = tex2D( _MainTex, i.uv + texCord * _Distortion );
    
    return mainTexColor;
   }
   
   ENDCG
  }
 }

  • tex2D返回的是color值(r, g, b, a)


Surface Shader ( Need Normals)

  CGPROGRAM
  #pragma surface surf NoLighting 
  #pragma target 2.0
  
  sampler2D _MainTex;
  sampler2D _OffsetTex;
  float _Distortion;
  float _Speed;
  float _MoveSpeed;

  struct EditorSurfaceOutput {
   half3 Albedo;
   half3 Normal;
   half3 Emission;
   half3 Gloss;
   half Specular;
   half Alpha;
  };
  
  fixed4 LightingNoLighting(EditorSurfaceOutput s, fixed3 lightDir, fixed atten)
     {
         fixed4 c;
         c.rgb = s.Albedo; 
         c.a = s.Alpha;
         return c;
     }
   
  struct Input {
   float2 uv_MainTex;
   float2 uv_OffsetTex;
  };

  void surf (Input IN, inout EditorSurfaceOutput o) {
   
   // pan OffsetTex
   fixed time = _Time * _Speed;
   fixed2 UV_PanY = fixed2( IN.uv_OffsetTex.x + time, IN.uv_OffsetTex.y );
   
   // pan MainTex
   fixed moveTime = _Time * _MoveSpeed;
   fixed2 UV_PanMove = fixed2( IN.uv_OffsetTex.x, IN.uv_OffsetTex.y + moveTime );
   
   fixed2 OffsetTex2D = tex2D( _OffsetTex, UV_PanY.xy );
   fixed2 distorted = OffsetTex2D * _Distortion;
   fixed2 Add1 = UV_PanMove + distorted;
   
   fixed4 MainTex2D = tex2D( _MainTex, Add1.xy );
   
   o.Albedo = MainTex2D;
   o.Alpha = MainTex2D.a;
  }
  ENDCG

2013年9月5日 星期四

[Unity] Read/Write Enabled

Unity匯入的Asset中,Texture與Model的Import Settings裡都會有Read/Write Enabled的選項,這個選項的作用是:
  • Texture:
    • Select this to enable access to the texture data from scripts (GetPixels, SetPixels and other Texture2D functions). Note however that a copy of the texture data will be made, doubling the amount of memory required for texture asset. Use only if absolutely necessary. This is only valid for uncompressed and DTX compressed textures, other types of compressed textures cannot be read from. Disabled by default.
    • 當有scripts會從Texture存取texture data時,會需要勾選Read/Write Enabled,但這個選項會使Unity需要一份額外的copy,增加記憶體的消耗。此選項預設是關閉的,也只適用於未壓縮或DXT貼圖格式的貼圖。
  • Model:
    • Enables the mesh to be written at runtime so you can modify the data; it makes a copy in memory. When this option is turned off, it saves memory since Unity can unload a copy of mesh data in the game. However, if you are scaling or instantiating meshes at runtime with a non-uniform scale, you may have to enable "Read/Write Enabled" in their import settings. The reason is that non-uniform scaling requires the mesh data to be kept in memory. Normally this is detected at build time, but when meshes are scaled or instantiated at runtime you need to set this manually. Otherwise they might not be rendered in game builds correctly.
    • 當你需要Runtime修改Model資料時,會需要開啟Read/Write Enabled,同樣會需要一份額外的記憶體消耗,而值得注意的是當Model在Runtime有被做非等比縮放時,也會需要開啟此選項。
    • 使用Mesh Combine...功能時需要開啟Read/Write Enabled。
參考資料
參考文章

2013年9月4日 星期三

[Unity][Mecanim] flagsCount >= mask.m_Count 錯誤訊息的解決方法



  在處理Mecanim的角色時,有時候會遇到上面的錯誤訊息,經過一番搜尋在Unity Answers上找到了錯誤的原因:


  FBX檔案內的物件命名跟FBX檔名命名相同。另外也發現如果Rig Root Node的命名跟FBX檔名相同的話會產生以下的錯誤:


  因此在DCC端處理物件的時候,要注意物件的命名都不可以跟FBX檔名重複,雖然child物件並不會造成這個問題,但還是應該嚴謹一點依照此原則做命名。


  而當要修正此問題時,似乎要把原有有問題的檔案先刪除之後再Import修正過的檔案才能正確運作,若是直接覆蓋錯誤訊息依然會存在。

2013年9月3日 星期二

[Unity] Collider的Physics效能比較

  最近專案在進行效能調校時,為了要減少Physics的效能消耗,查到了freshcut在Unity Community中發表的實驗數據

在只考量Physics效能的時候,Static的Collider無論是哪一類型的Collider消耗都是非常低的,但在dynamic的狀況下,三種Collider對效能的消耗量則有相當的差距:
Box Collider > Capsule Collider >> Sphere Collider
Box Collider稍稍大於Capsule Collider的消耗,而Sphere Collider的消耗則是明顯的少了很多,因此在許可的狀況之下應盡量使用Sphere Collider。

參考文章


2013年8月29日 星期四

[Unity] 更改Asset的Import Settings後,執行ImportAsset以正確更新

  當利用script進行批次的Import Settings設定時,需注意設定參數完成之後得要重新Import Asset才能夠讓Unity成功判讀到你的更改,不然會發生在Inspector中的資訊是對的,但執行Save Project後卻還是沒有正確寫入到Prefab或meta檔案之中。

舉例:
// 設定貼圖檔案的圖片壓縮格式
textureImporter.textureFormat = TextureImporterFormat.PVRTC_RGBA4;
// 設定了Import Settings之後再使用AssetDatabase.ImportAsset進行asset的更新
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate );

參考資料

2013年8月26日 星期一

[Photoshop] 預覽 16bit color 的效果

  如果想在Photoshop中即時模擬圖檔轉存為16bit color格式後所呈現的效果,用色調分離就能簡單的模擬出頗為相近的效果。


  方法是在圖層中添加色調分離調整圖層(Posterise adjustment layer),而分離的色階要輸入的是“2^bits數”。譬如說:想要模擬ARGB4444格式的效果,在色調分離調整圖層中要輸入的色階數就會是二的四次方,也就是16。


  那如果是RGB565這種不均等的格式,就需要對各顏色Channel個別加上不同的色調分離調整圖層,方法是開啟色調分離調整圖層的圖層樣式,其中的進階混合可以指定要作用在哪個色板上。


  補充說明一下色彩深度(Color depth),ARGB4444代表的是一張16bits數的圖檔格式(4bit * 4,4位元 * 4個Channel),數字代表的是各自對應Channel中所擁有的color數,1 bit就是2色(2^1),能存有黑與白,而4 bit就是16色(2^4),而ARGB4444的色彩數就是65535色(16色^4個Channel)。


參考資料

2013年8月1日 星期四

[Unity] Shader試作 可調整Rim Light效果的Fragment Shader

嘗試撰寫Shader的紀錄。
這是一個帶有類似Rim Light效果及Tint Color,並且可以與原始的Texture做Blending的不受光Fragment Shader,用於角色受擊效果。

Shader "Custom/Unlit Transparent Cutout With Color" {
 Properties {
  _Color ("Color (RGB) Blending (A)", Color) = (1,0,0,0)
  _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
  _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
 }
 
 // Fragment shader by Janus Huang
 SubShader {
 
  Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
  Blend SrcAlpha OneMinusSrcAlpha
  Lighting Off
  
  Pass {
   CGPROGRAM
   #pragma vertex vert
   #pragma fragment frag
   #include "UnityCG.cginc"
   
   struct appdata {
    fixed4 vertex : POSITION;
    fixed3 normal : NORMAL;
    fixed2 texcoord : TEXCOORD0;
   };
   
   struct v2f {
    fixed4 pos : SV_POSITION;
    fixed2 uv : TEXCOORD0;
    fixed4 color : COLOR;
   };
   
   fixed4 _MainTex_ST;
   fixed4 _Color;
   fixed _Cutoff;
   
   v2f vert (appdata_base v) {
    v2f o;
    
    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    fixed3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
    // 越是面向camera的vertex在dot計算後會獲得越大的計算結果
    fixed dotProduct = dot(v.normal, viewDir);
    // smoothstep用法同lerp, 但其曲線在頭尾都會趨緩
    o.color = smoothstep(0.5, 1, dotProduct);
    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    
    return o;
   }
   
   sampler2D _MainTex;
   
   fixed4 frag(v2f i) : COLOR {
    fixed4 texcol = tex2D(_MainTex, i.uv);
    // clip同AlphaTest
    clip( texcol.a - _Cutoff );
    // 受擊時的color計算 - 將貼圖加亮1.5倍後乘上dot計算後的黑白色(外黑內白)再加上_Color
    fixed3 hitColor = texcol.rgb * 1.5 * i.color.rgb + _Color.rgb;
    // 以_Color的alpha控制貼圖與受擊時的混合程度
    texcol.rgb = lerp( texcol.rgb, hitColor, _Color.a);

    return texcol;
   }   
   ENDCG
  }
 }
}


參考文章

2013年7月30日 星期二

[Unity] Assign Texture and Material (Editor Script)

複製已存在材質並該改貼圖後賦予至模型

// create material
Material newMaterial = new Material( Shader.Find("Diffuse"));
// assign shader
newMaterial.shader = sourceMaterial.shader;
// copy properties from existing material
newMaterial.CopyPropertiesFromMaterial(sourceMaterial);
// create texture from asset(asset path)
Texture texture = (Texture)AssetDatabase.LoadAssetAtPath( textureRelativePath, typeof(Texture));
// assign texture to material
newMaterial.SetTexture("_MainTex", texture);
// create material asset
AssetDatabase.CreateAsset(newMaterial, newMaterialAssetRelativePath);
// assign material to gameObject
AssignMaterial( gameObject, newMaterial );

在建立texture時需注意,在editor部份可以使用AssetDatabase.LoadAssetAtPath,而runtime則需使用Resource.Load

2013年7月10日 星期三

[Unity] Soft Particles

Soft Particle是能淡化Particle與其他Object交錯的痕跡的技術。

Unity在使用Soft Particle前必須要先設定Quality中的Soft Particles選項,且平台需支援Depth Textures(似乎無法在iOS上運作)。另外也必須使用Deferred Lighting rendering path或是以Script讓Camera去render Depth Textures


相關文章

2013年6月27日 星期四

[Unity] 使用 Mecanim 需要注意的事情

此處紀錄我在使用Mecanim過程中所發現需要注意的一些地方,有些可能不正確或解說錯誤,僅供參考!

  • 骨架檔的root的x,y需要對正至原點
骨架檔的root的x,y需要對正至原點,否則動作blending時會有位移的誤差。
  • (Humanoid Rig)如果想要動作在blending前後不會移動到collider,除了在Import Settings裡把動作位移鎖住之外,要注意若是進行blending的時間區段中有較大的位移會容易造成collider的移動,因為blending時會吃掉一部分的位移量導致發生誤差。
  • Any State可以立即執行動作
想要立刻執行的動作(例如死亡)可以利用Any State,Any State代表任何時機點且在任何State之上,所以只要觸發條件成立就會立即執行,但其conditions必須是一次性的命令發送。詳細內容:[Unity] Mecanim 強制進入某個State的方法
Any State的觸發時機是任何時候,只要觸發條件成立就會立刻執行
  • 骨架由無實體物件組成時,需要給骨架的root綁定一個mesh
如果骨架是由bone, dummy等無實體的物件組成,且採取骨架、動態分離的檔案規則時,骨架的root需要綁定一個mesh,且動態檔內也必須要留著這個mesh,如此骨架檔才能成功套用到動態。
  • Humanoid Rig會消耗較多的效能
角色的Rig選擇Humanoid會比起Generic消耗更多的效能,而Legacy則是依據開發者所撰寫的controller,當角色越簡單時,使用Legacy會比較省效能。詳細內容:Mecanim Performance and Optimization
  • 當不使用IK功能時,Rig選擇Generic可以避免一些問題
角色需求較單純時使用Generic可以避免一些因為Humanoid的IK所造成的表現性上的誤差(如transition時的位移誤差)。當Rig選擇Generic時可看到Clip設定中的Root Transform Position(XZ)的Based Upon可選項目除了Original(依照動作檔中原始所key的位置)外就是Root Node Position,選擇Root Node Position時會以骨架的root對正(0,0),而Humanoid則是Center of Mass,以骨架體積中心點對正(0,0),因此當角色的腳挪動時僅管hip沒有移動仍然會使角色的位置偏移。
  • Humanoid Rig最好只使用在人類角色上
Humanoid是針對人類型骨架角色設計的,例如因Foot IK是針對單關節(人類的膝蓋)所設計,所以當腿部結構有雙關節時(如羊人的腳),就會發生一些不正常的現象(如滑步明顯、腳步抖動...)。
  • Transition的conditions為bool時,無法調整blending timing
當條件為bool時,代表該transition可以在任何時間發生,所以就只能調整duration而無法調整timing,如果去調整它會發現重新點選該transition時,會被自動歸回中央點。
當conditions為bool時是無法設定transition timing的
  • 承上,transition的conditions可以不只一個
譬如已有一個bool的條件再加上一個exit time條件,可以使transition依照bool判斷觸發,但transition發生的timing會是固定的,也就是你在transition的timeline中所調整的timing。 參考文章:


bool搭配exit time可以指定transition的timing

延伸閱讀:

[Unity] 清除Console的Log - Clear Console

參考文章:

如果直接
using System

會造成UnityEnging.Object與object的衝突

using sys = System;

static void clearConsoleLog ()
{
 Assembly assembly = Assembly.GetAssembly(typeof(SceneView));
    sys.Type type = assembly.GetType("UnityEditorInternal.LogEntries");
    MethodInfo method = type.GetMethod ("Clear");
    method.Invoke (new object (), null);
}

2013年6月21日 星期五

[Unity] 以ARGB4444搭配Dithering進行貼圖減量

  之前一直受ARGB Texture所困擾,在Mobile平台沒有合適的壓縮格式能在品質與容量之間取得較好的平衡,下面列出幾個格式的缺點
  • RGBA PVRTC 4 bits - iOS推薦的壓縮格式,但是4bits對於圖像品質的破壞太大
  • ARGB 32 bit - 雖能保有圖片品質,但所消耗的容量實在太龐大
  • ARGB 16 bit - 雖能降低貼圖容量,但是顏色有明顯的帶狀瑕疵(color banding)
  Android平台由於各家GPU所支援的壓縮格式各有不同,因此ARGB 16 bit也就是降低texture容量最適合的選項,但16 bit所造成的帶狀瑕疵十分明顯,若真的要使用也不太可能,正好前一陣子看到Unity IN上有Cytus開發者之一的syyang所發表的文章



  • 使用 RGBA4444 搭配 Dithering 減少記憶體用量 by syyang @ UNITYIN

  •   這篇文章正好解決了這個問題,利用Dithering在16bit color depth獲得較佳的圖像呈現,消除帶狀瑕疵。進行Dither處理之後,圖片的顏色資訊會被重新處理,檢視圖片可發現變的有顆粒狀感(抖色),當圖片在眼中的呈現越小時,就會發現看起來跟truecolor的圖片品質頗接近。由於是對顏色資訊做了重新的演算,所以並不受到Unity的轉檔所影響,只要在Import Settings中設定Format為16 bit的壓縮,即可省下容量又能保有還能接受的圖片品質。

      此外需要注意的是經過dither處理的texture若又被Unity重新壓縮到不同尺寸的圖片時,會加重顆粒感使圖片品質降低(因為顏色訊息被重新處理過了),因此輸出給Unity的texture asset必須要輸出成遊戲主要使用的texture size。此外,若處理過的貼圖是用於3D模型的話,經過UV的拉扯也會使圖片失真更加明顯。目前Unity本身並不支援dithering,在網上也還沒看到有人做出支援dither處理的script/plug-in,因此得要自行預先處理這些textures。

    經過UV拉扯、尺寸放大後失真變的相當明顯
    但dithering還是有其諸多限制,而最原始的作法當然就是使用RGB444的安全色系來繪製texture,及在各個channel中只使用:0, 15, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, 255。但除了顏色數便少之外,還得少用漸層表現,要犧牲的也是相當多,也許能在不影響美術風格的前提下選擇性使用。

      在以Gimp進行dithering處理時,須先將貼圖縮成最終使用的尺寸,在縮小圖片時三種內插法看起來效果幾乎相同,然後再執行Dither to ARGB,此時會多出一個圖檔視窗就是dithering後的圖檔,進行匯出之後即可。匯出PNG的設定所有選項皆可取消,但當texture需要再alpha邊緣作細緻的過度時,透明像素的色彩是必須要被儲存的。Compression Level 0跟9在色系較單純的圖片上是幾乎沒有差別。


    Gimp在安裝script之後可進行dithering處理
    Gimp匯出PNG時的設定

    參考資料


    延伸閱讀

    2013年6月6日 星期四

    [Unity] Dynamic Camera FOV

    遭遇情境

      今天想達成一個攝影機的效果,就是當有特定的物體越來越接近畫面邊緣時,就要動態的增減Camera的FOV,讓該特定物體不要跑出畫面。

    解法

      大致上很簡單,只有兩個步驟:

    1. 求出物件距離畫面邊緣的距離
    2. 利用Mathf.Lerp達成相對應的FOV調整

      先利用Camera.WorldToViewportPoint( Vector3 )求出物件在畫面上的位置,返回的是normalized value(0至1之間),如此就能得知物件相對於畫面邊緣的距離,0代表是在畫面左方邊緣,1則是在畫面右方邊緣。

      再來則是利用Mathf.Lerp來調整FOV,Lerp實際上的運作是
    public static float Lerp(float start, float end, float value)
    {
        return ((1.0f - value) * start) + (value * end);
    }
    
    在其3個arguments中,value是一種類似權重的概念,當他為0時返回的值會是start,為1時返回的即是end,為中間的數值時就是返回按照比例計算後的結果。

      因此我只要把WorldToViewportPoint求得的值,以想要的數值範圍作normalize後,讓距離變成0至1之間的數值,傳入Lerp之中就可達成動態FOV的效果。範例如下:

    // amount : Value between 0 and 1 indicating the weight of value2.
    // 為距離螢幕邊緣比重的值
    Camera.fieldOfView = Mathf.Lerp( float CameraMinFOV, float CameraMaxFOV , float amount );
    


    參考資料


    延伸閱讀

    2013年6月5日 星期三

    [Unity] Mecanim Animator .controller 文件結構紀錄

    此文章紀錄Mecanim Animator Controller檔案的內容結構,當角色數量龐大時,眾多的Animator Controller會造成極大的管理上的困擾,因此若能直接解析內部的訊息的話,即可利用Script做外部的直接修改,做出更方便的管理工具。

    而在初次看過其內容後,獲得了一個重點即是,各地方的命名十分重要,Controller內部的目標來源都是以fileID的形式運作,但同時有些東西也可以在Unity中做命名,雖然會需要多一個命名規則的訂制與管理的工,但是直接利用Name做修改會比用fileID方便許多,譬如說Transition的命名。

    參考文件
    在開始看文件內容之前,先說明fileID的運作方式,fileID實際上是由兩組數字組成,首先是該物件的Class ID Number,然後是一組五位數物件在所在檔案內的序號(偶數),舉個例子,現在有一個帶有3個Animation Clip的FBX檔案,則這3個Clip的fileID就是:( 7400000, 7400001, 7400002 ),74為Animation Clip的ID Number。

    以下開始文件內容:
    在每個區段(term,代表一個object)的一開始,都會先有一串的數據資訊
    • --- !u!91 &9100000
      !u!後代表的是物件類型
      &(ampersand)後的數字是該區段資訊獨有的fileID
    AnimatorController此部份包含了Animator的基本屬性,如:
    • m_Name
      Animator的名稱
    • m_AnimatorEvents
      Flags
    • m_Layers
      Layers
    在來是各個Transition的參數(State與State間的Transition),
    • m_Name
      Transition的命名,預設狀況下是無命名的。
      如果想要手動修改.controller文件的話,對所有的Transition做命名會方便非常多,可快速的知道各個Transition資訊的位置。
    • m_SrcState / m_DstState
      來源跟目的State,填入的資訊為fileID。
    • m_TransitionDuration
      Transition的時間長度,應該是以SrcState的Motion的時間長度為基準的趴數。
      例如來源動作的長度為2秒,而m_TransitionDuration的值為0.5時就是使用1杪做過渡。
    • m_TransitionOffset
      DstState相對於TransitionDuration起始點的offset。
      當DstState的起始點與TransitionDuration的起始點相同時,則m_TransitionOffset的值為0。
      當DstState的結束點與TransitionDuration的起始點相同時,則m_TransitionOffset的值為1。
    • m_Conditions
      進行Transition的條件,以下的參數皆為Condition的條件式
      • m_ConditionMode
        條件判斷的模式
        • 1,Bool的True
        • 2,Bool的False
        • 3,Float/Int的Greater
        • 4,Float/Int的Less
        • 5,ExitTime
        • 6,Int的Equals
        • 7,Int的NotEqual
      •  m_ConditionEvent
        要參照的Flag,m_ConditionMode為ExitTime時此欄位為空
      • m_EventTreshold
        條件式的參考值,Bool時不管是True或False值都填0
      • m_ExitTime
        ExitTime的float值
    再來是State的資訊

    最後是StateMachine的資訊


    [Unity] Mecanim 強制進入某個State的方法(ex立刻執行死亡動作)

    How to change to a specific state immediately.

    參考資料
      在Mecanim Animator Controller中有個叫做Any State的State,是一個一直處在作用中的State,只能連接給其他的State,其他的State是不能連接給他的。

    Animator - Any State

      假使想要有一個在任何State規則之上的動作流程時(即條件成立時能立即進入該流程),譬如說人物的死亡動作,當程式下達死亡指令時,你會想要死亡動作是立刻表演,不希望這個流程會被其他的State卡住。
      這時候Any State就能達到這個效果,在這裡以一個範例作解說:在Animator Parameters中新增一個IsDead的Bool,並新增一個接收Any State的死亡動作State,且Transition Conditions為IsDead == true,如此當死亡時程式下達指令給Animator(animator.SetBool("dead",true)),就會讓dead這個State立刻執行。
      但是因為Any State是一直在作用狀態中的,所以並不能一直讓觸發條件成立,必須要是一次性的命令,否則就會發生一直反覆進入dead State的狀況,舉例來說:IsDead被設為true且Animator已經進入dead State的時候,就必須要把IsDead設回false。

    防止重複觸發Any State的範例Code如下:
    static int deadState = Animator.StringToHash("Base Layer.dead");
    if ( animator.GetCurrentAnimatorStateInfo(0).nameHash == deadState )
    {
        animator.SetBool("IsDead", false);
    }
    
    補充說明,animator.GetCurrentAnimatorStateInfo(int IDX)所返回的是Hash,且Hash並不能轉回String,因此得要先把你所知道的State名稱轉成Hash(.StringToHash())再做比對。
      在這樣的需求之下代表State的命名必須是有規則的、固定的,為了方便作業流程,動作片段的取名與State相同也可以省去某些操作上的步驟(直接將動作片段拉入Animator生成state時會自動以動作片段名稱為state命名)。
      另外直接從Any State做一個Transition到預設動作上,也能用來跳出任何的State。

    Unity 4.3 更新

    在Unity 4.3中新增了一個新的Parameter類型:Trigger,其作用是達成一次性的判斷條件,非常實用。其功能就是當Animator.SetTrigger("ParameterName")命令下達之後,該parameter會被設為True,並在transition完成時會被設為False,以往都需要自己撰寫設回False的程序,現在利用Trigger這個Parameter就會方便很多。
    另外在4.3中Mecanim有大幅的優化,譬如Mecanim已幾乎適用所有的component、property...,可以利用Mecanim控制你的相機FOV、控制你的Script的參數...,再配上新支援的Event(以往ImportedAnimation不支援Event)以及優化過的Animation Window(Dope Sheet + Curves),Mecanim的實用程度已大幅提高。


    參考文章
    延伸




    2013年5月27日 星期一

    [Unity] Shader - ShaderLab


    參考資料:
    相關資料:
    參考範例:


    人生第一次的shader撰寫XD,超陽春Unlit受擊變色用shader,透過shaderLab簡單的功能只要少少幾行就能完成!呈現的效果為,不受光影響,單一貼圖表現,可以透過Color property的alpha來控制貼圖與color間的混合

    ● Opaque版本
    Shader "Custom/Unlit Opaque With Color" {
    	Properties {
    		_Color ("Color (RGB) Blending (A)", Color) = (1,0,0,0)
    		_MainTex ("Base (RGB)", 2D) = "white" {}
    	}
    	SubShader {
    		Tags {"RenderType"="Opaque" "IgnoreProjector"="True"}
    		Lighting Off
    		Cull back
    		ZWrite On
    		
    		Pass {
    			SetTexture [_MainTex] {
    				ConstantColor [_Color]
    				combine constant lerp(constant) texture
    			}
    		}
    		
    	}
    	FallBack "Unlit/Diffuse"
    }
    

    ● Transparent Cutout版本
    Shader "Custom/Unlit Transparent Cutout With Color" {
    	Properties {
    		_Color ("Color (RGB) Blending (A)", Color) = (1,0,0,0)
    		_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    		_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    	}
    	SubShader {
    		Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    		Lighting Off
    		Cull back
    		ZWrite On
    		Blend SrcAlpha OneMinusSrcAlpha
    		
    		Pass {
    			Alphatest Greater [_Cutoff]
    			SetTexture [_MainTex] {
    				ConstantColor [_Color]
    				combine constant lerp(constant) texture, texture
    			}
    		}
    		
    	}
    	FallBack "Unlit/TransparentCutout"
    }
    
    

    2013年5月23日 星期四

    2013年5月9日 星期四

    [Unity] Prefab 不會 update 的問題

    近日在作業時遇到一個嚴重的問題!
    當我把一個fbx檔案包成prefab時,就會造成部分內容無法與原始的fbx檔案同步更新。

    目前只知道單純變動fbx檔案內的geometry, uv是會同步更新的,
    而hierarchy完全不會更新,
    skin資訊雖會更新,但是看起來只有更新了權重值,所以依然會有問題發生,
    若fbx檔案變動了material,也不會更新,
    此外相信不會更新的內容有非常多...
    而目前對於此問題沒有找到較好的解決方式...


    相關文章:

    2013年4月2日 星期二

    Unity - Editor Script Coding - 編寫Editor Script之參考資料

    入門站:
    資料:

    參考文章蒐集:
    • http://forum.unity3d.com/threads/92148-need-help-with-texture-import-setting-script

    零散紀錄:
    • 取得Type
      GameObject.GetType().Name
    • 取得某個選擇中的Asset的路徑(亦可作用於目錄)
      AssetDatabase.GetAssetPath(OBJECT)
    • 取得 某個Asset檔案 內的所有元件
      AssetDatabase.LoadAllAssetsAtPath("AssetPath")

    2013年3月21日 星期四

    3dsMax - 請小心FBX Export Preset的設定

    今天遇到了一個超奇妙的問題,當我輸出FBX要Bake Animation的時候,我的時間區段一直只能設定0到100之間,但昨天明明還是正常的,查了將近一整天一直無法解決,後來請高手支援一下才發現原來是個愚蠢的問題!

    那就是FBX Export Preset中可以設定Start跟End的最大最小值,而這該死的被設定成了0到100,至於為何突然會被設定成0至100之間,這還是一個謎!不過我猜是因為我用了MAXScript的FbxExporterSetParam的關係‧‧‧

    設定FBX Export Preset的步驟

    1. 在FBX Exporter dialog中按下Edit按鈕並選擇Edit preset
    2. 會跳出上圖左方的Tree List找到Bake Animation的Start/End項目並右鍵點擊選擇Edit min max
    3. 輸入Minimum及Maximum數值
    但目前還不知道要怎麼將他回復成預設狀態‧‧‧

    另外要用MAXScript設定Start/End的話可以使用

    FBXExporterSetParam "BakeFrameStart" [Integer value]
    
    FBXExporterSetParam "BakeFrameEnd" [Integer value]
    
    FBXExporterSetParam "BakeFrameStep" [Integer value]

    2013年3月19日 星期二

    [AE] Camera Mapping

    想用一張2D照片做出3D空間的效果,所使用的技術為Camera Mapping或Camera Projection。


    教學:
    1. 較陽春的作法,適合構圖簡單和沒這麼多時間生小孩的時候用XD,將元素切分成幾個圖層,拉出前後距離即可。
      How To Make Virtual 3D Photos In After Effects by AndrewKramer
    2. 使用AE的Light shadow做出投影的效果,只需用幾片板子即可做出簡單的3D空間效果。
      而在實際用過之後發現有幾點需要注意。在結構較複雜的場景中,板子的對位非常重要,否則會有很大的破綻。另一點則是,投影出來的圖像解析度跟原圖差距相當大,因為通常原圖是被投影到更大的面積上,且有角度造成的失真,儘管把Shadow Map Resolution調到最大也還是達不到可用的水準,目前還不知道較佳解決的方法,若解析度不佳,那這種方法也就沒路用了。
      教學:
      Camera Mapping in After Effects by Creative Cow
      2D footage to stereo 3D using camera projection mapping
      Camera Projection technique Tutorial
      其他範例:峽谷
    3. 利用建模做出更真實的3D效果。
      Discover projection mapping to animate photos in 3D
    4. 另外我有試出一種偷吃步的方式:傾斜大法!
      在AE中利用Effect/Corner pin做出Skew,再把與後方景物位差明顯的物件拆出來,不做傾斜並跟著會傾斜的底圖移動,就能有空間感的錯覺。但目前只試過水平運鏡的狀況,也許垂直運鏡跟深度運鏡會較難表現。
    延伸閱讀:
    [Wiki] 3D Projection 

    [MAXScript] Path處理

    以前在處理檔案路徑時,有些功能都自己寫Function來用,例如將兩段路徑結合成一個完整路徑等等。今天看MAXScript Reference時才發現,MAXScript自己就有許多Methods可以對路徑做各種的處理,非常方便。

    MAXScript Reference - PathConfig Struct
    以下從中節錄出較常用的項目

    pathConfig.appendPath 
    將路徑片段合併
    pathConfig.appendPath "c:\\temp" "test.txt"
    "c:\temp\test.txt"

    pathConfig.convertPathToLowerCase
    - 將路徑轉為小寫並將反斜槓統一

    pathConfig.convertPathToLowerCase "C:\\Temp\Test/pATH"
    "c:\temp\test\path"


    pathConfig.pathsResolveEquivalent
    - 比對兩個路徑是否相同

    pathConfig.pathsResolveEquivalent "scenes\\test.txt" "./scenes/test.txt"
    true


    pathConfig.removePathLeaf
    - 取得上一層的目錄路徑

    pathConfig.removePathLeaf "c:\\temp\\test"
    "c:\temp"



    pathConfig.stripPathToTopParent 
    - 取得最上層的路徑

    pathConfig.stripPathToTopParent "C:\\temp\\test\\test.tga"
    "C:\"
    pathConfig.stripPathToTopParent "\\\\SomeServer\\Projects\\Test"
    "\\SomeServer"



    pathConfig.removePathTopParent
    - 去除最上層的路徑

    pathConfig.removePathLeaf "c:\\temp\\test"
    "temp\test"


    pathConfig.stripPathToLeaf
    - 取得最深一層的路徑,與filenameFromPath作用相同

    pathConfig.stripPathToLeaf "C:\\temp\\test"
    "test"
    pathConfig.stripPathToLeaf "C:\\temp\\test\\"
    ""
    pathConfig.stripPathToLeaf "C:\\temp\\test\\somefile.tga"
    "somefile.tga"


    pathConfig.isAbsolutePath
    - 檢驗是否是絕對路徑(但不檢驗該路徑是否存在)

    pathConfig.isLegalPath
    - 檢驗是否是合法的路徑(但不檢驗該路徑是否存在)

    pathConfig.GetDir <#directory_type>
    - 傳回系統預設目錄路徑

    #font | #Scene | #export | #import | #help | #expression | #preview | #image | #Sound | #plugcfg | #maxstart | #vpost | #drivers | #autoback | #matlib | #scripts | #startupScripts | #defaults | #renderPresets | #ui | #maxroot | #renderoutput | #animations | #archives | #Photometric | #renderassets | #userScripts | #userMacros | #userStartupScripts | #temp | #userIcons | #maxData | #downloads | #proxies


    pathConfig.isPathRootedAtBackslash
    - 檢驗路徑是否是以斜槓為開頭

    要取得Max的一些預設路徑則從此查找
    MAXScript Reference - 3ds Max System Directories

    2013年3月12日 星期二

    如何不影響Scale的數值對Bone做到縮放尺寸的效果

    如何不影響Scale的數值對Bone做到縮放尺寸的效果

    例,在對原本Scale值為[1,1,1]的Bone,進行Scale 2倍的動作後,Scale值變為[2,2,2],若想在保持現有尺寸的狀態下把Bone的Scale值歸回[1,1,1],可利用Animation>Bone Tools,方法如下:
    1. 開啟Bone Tools視窗。
    2. 選擇要修改的Bone,執行Reset Scale,此時Scale值已被修正為1,但Bone的顯示有問題,用以下步驟進行修正。
    3. 將Bone On關掉再打開,做個Refresh動作。
    4. 執行Reset Stretch。
    5. 執行Realign。

    另外可用Max Script進行這個手續:
    for o in selection do
    (
        resetScale o
        o.setBoneEnable false currenttime
        o.setBoneEnable true currenttime
        o.resetBoneStretch()
        o.realignBoneToChild()
    )
    

    2013年3月7日 星期四

    Unity3D輸出之圖檔壓縮格式(行動平台)

    要對圖檔壓縮進行優化時,須先了解各圖檔之規格,Unity Manual中有提到各平台可支援的各種圖檔格式,請參考在本文結尾的參考文章中的[1]以及Wiki中的資訊。

    iOS:
    PVRCT
      貼圖尺寸須為二的冪次方之正方貼圖
    Android:
    RGB Compressed ETC 4 bits (ETC1)
     (Ericsson Texture Compression, supported by all OpenGL ES 2.0 GPUs)
     4bits / pixel,無Alpha,Android 2.2(Froyo)以上支援
    RGBA 16bit
     有Alpha,容量是ETC的四倍(請看參考[1])。

    若要減少Alpha對資源的佔用,有一些技巧可以解決(請看參考[3][4])。
     方法1,將Alpha Channel抽出,與Color Map連接拼成一張貼圖。
      優點:一張貼圖、Shader改動較小。
      缺點:貼圖只能二方連續(one direction wrap),提高shader效能消耗
     方法2,將Alpha Channel抽出,單獨存成一個檔案,再從shader進行結合。
      優點:貼圖可四方連續,運用上靈活性較高。
      缺點:shader需要額外多出一個sampler。
    當硬體不支援輸出之壓縮格式時,Unity會將資源以RGBA的方式做Decompress,如此會提高渲染時間、記憶體消耗和Decompress時間(增加讀取階段的時間)。

    下表是檔案容量對照(含MipMaps)

    尺寸 ETC 4bits RGBA 16bit RGBA 32bit
    2048
    2.7 mb
    10.7 mb
    21.3mb
    1024 682.8
    2.7 mb
    5.3mb
    512 170.8 682.7
    1.3mb
    256 42.8 170.7 341.3
    128 10.7 42.8 85.3
    64 2.7 10.7 21.3


    參考文章:
    [1]http://docs.unity3d.com/Documentation/Manual/Textures.html
    [2]http://docs.unity3d.com/Documentation/Manual/android-GettingStarted.html
    [3]http://forum.unity3d.com/threads/73998-DXT-or-PVRTC
    [4]http://malideveloper.arm.com/develop-for-mali/sample-code/etcv1-texture-compression-and-alpha-channels/
    http://gamedev.stackexchange.com/questions/44134/unity-android-truecolor-texture-performance-hit-and-alternatives-for-truecolor
    http://stackoverflow.com/questions/9148795/android-opengl-texture-compression

    http://zh.wikipedia.org/wiki/RGB
    http://en.wikipedia.org/wiki/Ericsson_Texture_Compression
    http://en.wikipedia.org/wiki/PVRTC