Search Unity

Weird issue on Texture2D.setPixels, please help

Discussion in '2D' started by jinsediaoying, Nov 28, 2013.

  1. jinsediaoying

    jinsediaoying

    Joined:
    Nov 27, 2013
    Posts:
    13
    So when I trying to make a "worms" style destructible 2d terrain, I changed default sprite shader a bit to let it recieve a alpha map, and then I can edit the alpha map pixel wise at runtime to make part of the original texture transparent.

    The manipulation of the alpha map texture is done by Texture2D.setPixels

    By my understanding, Texture2D.getPixels() will return a color array that in forms like:
    08 09 10 11
    04 05 06 07
    00 01 02 03
    Am I correct?

    The shader is basicly the default Sprite shader except the frag:
    Code (csharp):
    1. fixed4 frag(v2f IN) : COLOR
    2. {
    3.     return tex2D(_MainTex, IN.texcoord) * tex2D(_AlphaMask, IN.texcoord) * IN.color;
    4. }
    This is the code I use to initialize the alpha map texture:
    Code (csharp):
    1.  
    2.     Texture2D t2d;
    3.     Color32[] colorArray;
    4.     int h;
    5.     int w;
    6.     // Use this for initialization
    7.     void Start()
    8.     {
    9.         Texture2D t = GetComponent<SpriteRenderer>().sprite.texture;
    10.         w = t.width;
    11.         h = t.height;
    12.         t2d = new Texture2D(w, h);
    13.         colorArray = new Color32[t.width * t.height];
    14.         for (int i = 0; i < colorArray.Length; i++)
    15.         {
    16.             colorArray[i] = Color.red * 255;
    17.         }
    18.         t2d.SetPixels32(colorArray);
    19.         t2d.Apply();
    20.         renderer.material.SetTexture("_AlphaMask", t2d);
    21.     }
    This the code I use to test setPixels:
    Code (csharp):
    1. public void draw()
    2.     {
    3.         //cut top
    4.         for (int i = colorArray.Length * 3 / 4; i < colorArray.Length; i++)
    5.         {
    6.             colorArray[i].a = 0;
    7.         }
    8.  
    9.         //cut bottom
    10.         for (int i = 0; i < colorArray.Length / 4; i++)
    11.         {
    12.             colorArray[i].a = 0;
    13.         }
    14.         t2d.SetPixels32(colorArray);
    15.         t2d.Apply();
    16.     }
    this is the original texture:
    $original.jpg

    this is the result after start before draw:
    $withalpha.jpg

    this is the result of only run cut top:
    $cuttop.jpg

    this is the result of only run cut bottom:
    $cutbut.jpg

    this is the result of run both cut top and cut bottom:
    $cutboth.jpg

    If you look closely at the result of cut top only and cut bottom only, you will see both of them have a line of pixels remain unchanged, and those lines disappeared in cut both. SInce the line is red, the shader should works correctly, and I have no clue what cause this weird issue, please help.

    Another question:is there a way to change the texture of a Sprite? Sprite.texture is readonly
     
    Last edited: Nov 28, 2013
  2. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    totally guessing here, but check order of operations in your iteration through pixels, like make sure this means what it says:

    Code (csharp):
    1.  
    2. for (int i = colorArray.Length * 3 / 4; i < colorArray.Length; i++)
    3.  
    and not:
    Code (csharp):
    1.  
    2. for (int i = (colorArray.Length * 3) / 4; i < colorArray.Length; i++)
    3.  
    or:
    Code (csharp):
    1.  
    2. for (int i = colorArray.Length * (3 / 4); i < colorArray.Length; i++)
    3.  
    which would have different effects of the value of i.
     
  3. jinsediaoying

    jinsediaoying

    Joined:
    Nov 27, 2013
    Posts:
    13
    Since each post only can have 5 pictures, I opened this new post.

    after running the code below:
    Code (csharp):
    1. int index;
    2.         for (int i = x; i < w-1; i++)
    3.         {
    4.             for (int j = y; j < h-1; j++)
    5.             {
    6.  
    7.                 if (i >= 0  i < w  j >= 0  j < h)
    8.                 {
    9.                     index = i + j * w;
    10.                     colorArray[index].a = 0;
    11.                 }
    12.             }
    13.         }
    I get this:
    $cutcube.jpg

    w and h here are the width and height of the texture, so the code should left the right edge and the top edge unchanged and cut down the rest. But if you look closely to the picture, you will see a rectangular border, which is so weird.

    It seems what happened is that the right and top edges wrap half pixels to the left and bottom edge, don't understand why...


    Edit: x and y are 0 here
     
    Last edited: Nov 28, 2013
  4. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Hmm, what is the "x" in the iteration? Anyway it does seem odd by just looking at your code and this, but I am probably missing something.
     
  5. jinsediaoying

    jinsediaoying

    Joined:
    Nov 27, 2013
    Posts:
    13
    x and y are 0 here, I forget change them
     
  6. jinsediaoying

    jinsediaoying

    Joined:
    Nov 27, 2013
    Posts:
    13
    I find out the reason, it is the default filter mode!, after I change the filter mode to Point, bug get fixed. The bilinear mode somehow draws the opposite edge's pixels...
     
    Last edited: Nov 28, 2013
  7. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Ahh yes - figures, that kinda stuff always kinda sneaks up on you with unity haha