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

Texture2DArray create mip maps results in textures fading to black

Discussion in 'General Graphics' started by JPMcWhiskers, Aug 31, 2016.

  1. JPMcWhiskers

    JPMcWhiskers

    Joined:
    Sep 22, 2014
    Posts:
    14
    Hey, I have an issue with my new Texture2DArrays. When I get them to generate MipMaps, any distance away from the camera causes the object texture to be rendered completely black.

    Code (CSharp):
    1.  
    2.  
    3. Texture2DArray UnitTextures = new Texture2DArray(32, 32, 1, TextureFormat.DXT1, true);
    4.         Graphics.CopyTexture(Texture1, 0, 0, UnitTextures, 0, 0);
    5.  
    6.  
    (It's the parameter that is true at the end of the new Texture2DArray declaration.)

    My textureArray itself is tiling properly, and when I set the MipMap value to False, the textures don't fade to black.


    OhWhy.png
    Should I not be auto-generating mipmaps then? How does one create mipmaps for Texture2DArrays?
     
  2. JPMcWhiskers

    JPMcWhiskers

    Joined:
    Sep 22, 2014
    Posts:
    14
    Sorry, I solved the issue:

    I had to first change all of my textures from compressed to TrueColor.
    Then I had to change the texture format in the Texture2DArray.
    Then I had to Apply the UnitTextures(recalc mipmaps)

    Now everything works great.
    Code (CSharp):
    1. UnitTextures = new Texture2DArray(32, 32, 19, TextureFormat.RGB24, true);
    2.         Graphics.CopyTexture(Texture1, 0, 0, UnitTextures, 0, 0);
    3.         UnitTextures.Apply(true);
    4.  
     
    DevDunk likes this.
  3. mrmcduck

    mrmcduck

    Joined:
    Nov 26, 2015
    Posts:
    26
    In 2019.3 still an issue, managed to fix it differently since disabling compression is a huge performance loss:
    Use TextureArray constructor which allows to set the amount of mipmaps, and use on less then it would automatically and then copy the mimaps manually with CopyTexture (use the variant where you can set srcMip and dstMip) and skip the last.

    I know that I'm necroing the thread, but kinda sad to see that it's not fixed after 4 years. Correct me if it's not a bug, but I doubt it - I used a render debugger, and the last mipmap is just black within the textureArray, while it exists in the source texture. Also the issue is build only, not appearing in the editor.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    Not a bug. The GPU won't create mip maps for compressed texture formats.*

    The solution is to copy the mip maps from the original Texture2D to the Texture2DArray too.
    Code (csharp):
    1. void CopyTextureToTextureArray(Texture2D texture, Texture2DArray textureArray, int index)
    2. {
    3.     for (int mip=0: mip < texture.mipmapCount; mip++)
    4.         Graphics.CopyTexture(texture, 0, mip, textureArray, index, mip);
    5. }
    You may want to add in some code to make sure both textures have the same mipmapCount, format, and resolution.

    * Supposedly some drivers can do this, especially for OpenGL, but it's not something Unity supports.
     
    adamgolden likes this.
  5. mrmcduck

    mrmcduck

    Joined:
    Nov 26, 2015
    Posts:
    26
    But it copied 9 from 10 mips? It's only the last (1x1mip) that is black. The source you posted is exactly what I've been using. Only thing helped was to reduce the amount of mips by 1 and just ignore the 1x1 mip, so that 2x2 is the smallest.
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    Well, I hope it wasn't exactly the code I posted, because that has at least one bad typo. The
    :
    after the
    int mip=0
    should be a
    ;
    .

    Either way, that's an odd issue that shouldn't he happening. As long as both textures are being generated with the same number of mip levels, it shouldn't a problem. It's possible the texture you're importing only has 9 mips? It's also plausible the mipmapCount doesn't mean exactly what I think it does and it should be
    mip <= texture.mipmapCount
    .
     
  7. mrmcduck

    mrmcduck

    Joined:
    Nov 26, 2015
    Posts:
    26
    I just wanted to state that I've already been copying the mips manually the way you suggested to do before you posted it :)

    In the Editor's Inspector it shows 11 textures, the normal one and mip 1 - 10. In the constructor of the texture array I used 10 as mipCount which seems to be somewhat misleading, because the parameter needs to include the non-mip-texture as well. Then I copy 10 mip levels:

    Code (CSharp):
    1. for (int i = 0; i < 10; i++)
    2.        Graphics.CopyTexture(tbt.texture_abledo, 0, i, txArray_albedo, arrayIdx, i);
    And if you use 11 als param for the array and then copy it 11 times, the last mip (1x1) is black (in build). What makes me think that it may be a bug is, that it works fine in the editor. Textures are 1024x1024, so mips should be 512,256,128,64,32,16,8,4,2,1 which would be 11 different sizes in total.