Search Unity

build size optimization - jpg + separate alpha in png format possible?

Discussion in 'Editor & General Support' started by Andrej-Vojtas, Apr 28, 2013.

  1. Andrej-Vojtas

    Andrej-Vojtas

    Joined:
    Jan 12, 2009
    Posts:
    67
    Hello,

    I have a game with hundreds of full screen character sprites (resulting in hundreds of MB to download). It's really important for me to reduce this without breaking the art. The art doesn't look good with DXT compression. I believe the ideal way to go is to have the color image in a jpg and the alpha information in a separate 8-bit png. Is this possible in a 2D framework/etc. out there, or in Unity in general?

    I am aware, this is not how Unity works (you import the texture into a format, Unity compresses the asset package at build time etc.)
    Still, I found out I can load jpg and png trough Texture2D.LoadImage, but I have no idea how to put them together. I guess a shader could do that, but I have no clue how to set them up in Unity and even less how to use them in code to call something like Finale = Merge(jpg, png).

    I think I found slightly related answer here a 10 lines of code that should do the trick, but I miss the context, I don't know how to use it: http://forum.unity3d.com/threads/1309-combining-textures-and-alpha

    I am open to any ideas, and hope someone solved this already.
    Thank you for your time.
     
  2. Andrej-Vojtas

    Andrej-Vojtas

    Joined:
    Jan 12, 2009
    Posts:
    67
    Ok,

    so I figured out a shader that does what I need, see below. If there are some errors or unnecessary stuff, please let me know. It takes one RGB 24 bit Unity texture and one Alpha 8 Unity Texture (with Alpha from Greyscale ON). I tested it in the editor with a simple scene. I created a material, changed the shader to the custom one, added the textures. Then I added the material onto a plane and it works.

    I also figured out how to avoid Unity importing my .jpg and .png as textures once I add them in the Resource folder, as I want them added to the build in their compressed form. I change the extension to .bytes and then use Resource.Load("name") as TextAsset and then create a texture and add the image data from the TextAsset.bytes with Texture2D.LoadImage.

    So I have a shader and the two textures loaded from the image files in code. I can create a plane, but I am not sure how to scale and position it so that the image is displayed pixel perfect. Is there an easy way how to do it? Or is there a way how to use the shader without a plane/mesh?

    Code (csharp):
    1. Shader "RGBplusA" {
    2.     Properties {
    3.         _MainTex ("Main Texture", 2D) = "white" {}
    4.         _Mask ("Mask Texture", 2D) = "white" {}
    5.     }
    6.     SubShader {
    7.         Blend SrcAlpha OneMinusSrcAlpha
    8.        
    9.         Pass
    10.         {
    11.             SetTexture [_Mask] {combine texture}
    12.             SetTexture [_MainTex] {combine texture, previous}
    13.         }
    14.     }
    15. }
    16.  
     
    Last edited: Apr 30, 2013
  3. deram_scholzara

    deram_scholzara

    Joined:
    Aug 26, 2005
    Posts:
    1,043
    Code (csharp):
    1. planeTransform.localScale = (Vector3.right * (myTexture.width/myTexture.height) + Vector3.forward) * theHeightOfYourCameraFrustum + Vector3.up;
    theHeightOfYourCameraFrustum is just Camera.size on the viewing camera if it's in orthographic mode. If not, you need to do some math to figure out the height based on the distance the plane is from the camera.

    Then just position and rotate as needed.
     
  4. Andrej-Vojtas

    Andrej-Vojtas

    Joined:
    Jan 12, 2009
    Posts:
    67