Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Some pixels wrong using SetPixels()

Discussion in 'Scripting' started by er0d, Apr 8, 2020.

  1. er0d

    er0d

    Joined:
    Nov 8, 2017
    Posts:
    20
    Hello,

    I'm trying to generate a 2D tilemap. But some pixels at the borders of the tiles are not at the right location :

    upload_2020-4-8_15-20-22.png
    If you look carefully at the screenshot above, you can see that some pixels on the left border are brown, bit should be green. And it seems that it's the case only for the pixels that are brown on the right border.
    Same with some pixels on the top border.

    The way I generate this texture is by loading 32x32 pixels png files, then copying them into a texture using Texture2D.SetPixels() function :

    Code (CSharp):
    1. public void GenerateChunk(ChunkModel chunkModel)
    2.     {
    3.         byte[] grassFileData = File.ReadAllBytes("Assets/Tilemap/Tiles/grass32_2.png");
    4.         Texture2D grassTexture = new Texture2D(/* ... */);
    5.         grassTexture.LoadImage(grassFileData);
    6.  
    7.         byte[] mudFileData = /* ... */
    8.  
    9.         Texture2D chunkTexture = new Texture2D(ChunkSidePixelSize, ChunkSidePixelSize);
    10.         for (int i = 0; i < ChunkModel.ChunkSideSize; ++i)
    11.         {
    12.             for (int j = 0; j < ChunkModel.ChunkSideSize; ++j)
    13.             {
    14.                 switch (chunkModel.GetTile(i, j))
    15.                 {
    16.                     case TileType.GRASS:
    17.                         chunkTexture.SetPixels(i * TileSizePixel, j * TileSizePixel, TileSizePixel, TileSizePixel, grassTexture.GetPixels());
    18.                         break;
    19.  
    20.                     case TileType.MUD:
    21.                         chunkTexture.SetPixels(i * TileSizePixel, j * TileSizePixel, TileSizePixel, TileSizePixel, mudTexture.GetPixels());
    22.                         break;
    23.                 }
    24.             }
    25.         }
    26.         chunkTexture.Apply();
    27.  
    28. /* ... */
    Here is the settings of my png files (tiles) :
    upload_2020-4-8_15-28-45.png

    Is anybody have an idea of what I'm mlaking wrong ?
    Thanks in advance,
    rOd.
     
  2. Wolfos

    Wolfos

    Joined:
    Mar 17, 2011
    Posts:
    934
  3. er0d

    er0d

    Joined:
    Nov 8, 2017
    Posts:
    20
    Hello Wolfos, thank you for your answer.

    It's already turned off for each image.

    It's what I first wanted to do, but I never managed to generate the tilemap using an algorithm. All the examples and tutorials I found was about to draw manually the tilemap.
    Also, I'd like to generate huge maps, so I wonder about performances.
     
  4. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    656
    Code (CSharp):
    1. Texture2D chunkTexture = new Texture2D(ChunkSidePixelSize, ChunkSidePixelSize);
    2. chunkTexture .wrapMode = TextureWrapMode.Clamp;
    3.  
     
    Jamolbek1 likes this.
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    Summarizing what people above have written:

    - set image to clamp, not repeat
    - disable mipmaps
    - turn OFF compression (this will make colors not be what you think they are)
     
    Jamolbek1 likes this.
  6. GYoung3

    GYoung3

    Joined:
    Oct 8, 2019
    Posts:
    3
    I have this exact same issue. Making a tile map with chunks and this issue is happening to me as well in 2020.3.33f. The debugger prints the correct pixel color, but the pixel color being rendered is wrong and its driving me crazy. I know this is an old post, but I'd love to hear if you solved this. I don't know the etiquette for necroing, but I'm a bit desperate haha
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    ... by default only to one decimal place.... so red == 0.1f looks the same as red == 0.11f and those two reds will not be equivalent.

    Another approach not mentioned above is to quantize the colors before comparing them, or provide your own CompareColor() method that will return true as long as colors are "close enough" in r, g, and b channels.
     
  8. GYoung3

    GYoung3

    Joined:
    Oct 8, 2019
    Posts:
    3
    Thanks for the reply. I’ve been looking at this for a while so when I used the debugger I was using examples like black vs white. Moreover the pixels I’m copying from a sprite and if I put the sprite in the scene, the sprite and the image look different on the edges (the pixel on each edge of the 64x64 tile) Furthermore if I set just the first two rows of pixels to be white and the rest black, the top row will also have a whitish outline. I can’t make sense of it - the documentation and code seem very straightforward. It’s almost as if the tile is starting to repeat itself at the edge if that make sense. I tried the other solutions in this thread to no avail.

    I will post the code tomorrow as well as some images of the renders. Thanks again for the quick response - I would be happy if you checked back tomorrow :)
     
  9. GYoung3

    GYoung3

    Joined:
    Oct 8, 2019
    Posts:
    3
    Hello again,

    My code for generating my tile map is a little messy and needlessly complicated for this issue, because I can recreate the problem with much simpler code. Below I have a tile being drawn by assigning each pixel a color in a color array and then using set pixels to apply it to the texture. The result should be two white rows and two white columns for the first two rows or columns, but what I am getting is something messier than that as you can see in the images attached.

    The Tile 1x is what the tile looks like without zoom - just showing the visible effect it has.
    The Tile 5x gives a better illustration of what's happening.
    The Tile Markup shows the Tile 5x with letters. Letter A is pointing to the grayish pixels in the first column - which my guess is blending the color from the right edge and left edge. Letter B is pointing to another set of gray, but darker gray pixels, almost as its interpolating the pixel values between row/column 2 and row column 3. And C shows the similar effect as A, however the bark is now becoming white. The corner is even more white, not sure why.

    I have been working with unity as a hobbyist for about 6/7 months. But I really like to understand the innerworkings of why certain mechanisms act the way they do. So if anyone could shed some light on why this happening, that'd be great. Thanks!!

    Code (CSharp):
    1. public class DrawTile : MonoBehaviour
    2. {
    3.     private int pixelsPerTileSide = 64;
    4.     private Color[] newTexturePixelArray;
    5.  
    6.     SpriteRenderer spriteRenderer;
    7.     Texture2D newTexture2D;
    8.     void Start()
    9.     {
    10.         spriteRenderer = GetComponent<SpriteRenderer>();
    11.  
    12.         CreatePixelArray();
    13.         ApplyArrayToTexture();
    14.     }
    15.     private void CreatePixelArray()
    16.     {
    17.         newTexturePixelArray = new Color[pixelsPerTileSide * pixelsPerTileSide];
    18.  
    19.         int i = 0;
    20.         for (int pY = 0; pY < pixelsPerTileSide; pY++)
    21.         {
    22.             for (int pX = 0; pX < pixelsPerTileSide; pX++)
    23.             {
    24.                 if (pY < 2 || pX < 2)
    25.                 {
    26.                     newTexturePixelArray[i] = Color.white;
    27.                 }
    28.                 else
    29.                 {
    30.                     newTexturePixelArray[i] = Color.black;
    31.                 }
    32.                 i++;
    33.             }
    34.         }
    35.     }
    36.     private void ApplyArrayToTexture()
    37.     {
    38.         newTexture2D = new Texture2D(pixelsPerTileSide, pixelsPerTileSide);
    39.         newTexture2D.SetPixels(newTexturePixelArray);
    40.         newTexture2D.Apply();
    41.         Sprite worldSprite = Sprite.Create(newTexture2D, new Rect(0, 0, pixelsPerTileSide, pixelsPerTileSide), Vector2.zero);
    42.         spriteRenderer.sprite = worldSprite;
    43.     }
    44. }
    EDIT: This is solved by setting the texture's filter mode to FilterMode.Point
     

    Attached Files:

    Last edited: May 10, 2022