Search Unity

Texture2DArray broken?

Discussion in 'Shaders' started by TOES, May 14, 2021.

  1. TOES

    TOES

    Joined:
    Jun 23, 2017
    Posts:
    134
    I need to use a texture array in my GLSL shader, targeting webGL 2. It works perfectly in the editor, but not when running on the web.

    Code (CSharp):
    1. Debug.Log("supports2DArrayTextures: " + SystemInfo.supports2DArrayTextures);
    2.  
    reports true. Texture arrays are supposed to work according to the ES3 specs. Unity docs says:

    Platform Support
    Texture arrays need to be supported by the underlying graphics API and the GPU. They are available on:

    • Direct3D 11/12 (Windows, Xbox One)
    • OpenGL Core (Mac OS X, Linux)
    • Metal (iOS, Mac OS X)
    • OpenGL ES 3.0 (Android, WebGL 2.0)
    • PlayStation 4
    What is happening here, is this a bug in Unity, or am I doing something wrong?

    This is the shader:

    Code (CSharp):
    1. Shader "testshader" {
    2.     Properties{ _MainTex("Base (RGB)", 2D) = "white" {} }
    3.         SubShader{
    4.         Tags { "Queue" = "Geometry" }
    5.         Pass {
    6.         GLSLPROGRAM
    7.         #ifdef VERTEX
    8.  
    9.         varying vec2 TextureCoordinate;
    10.         void main()
    11.         {
    12.             gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    13.             TextureCoordinate = gl_MultiTexCoord0.xy;
    14.         }
    15.         #endif
    16.  
    17. #ifdef FRAGMENT
    18.  
    19. precision mediump sampler2DArray;
    20.  
    21. uniform sampler2D _MainTex;
    22. uniform sampler2DArray textureArray;
    23. varying vec2 TextureCoordinate;
    24.  
    25.  
    26. void main(void)
    27. {
    28.     vec3 uvz = vec3(TextureCoordinate, 0);
    29.     vec4 c = texture(textureArray, uvz);
    30.     gl_FragColor = c;
    31. }
    32.  
    33.  
    34. #endif
    35. ENDGLSL} }}
    36.  
    I always get white from the sampler, no matter what is in the texture arrays. The textures are in the correct format (RGBA32) and size (1024x1024).

    This is the script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Test : MonoBehaviour
    6. {
    7.     public Material testMaterial;
    8.     public Texture2DArray texturesArray;
    9.     public List<Texture2D> textures;
    10.  
    11.     private Texture2DArray createTexture2DArray(List<Texture2D> textures, int size)
    12.     {
    13.         Texture2DArray texture2DArray = new Texture2DArray(size, size, textures.Count, TextureFormat.RGBA32, false);
    14.         texture2DArray.filterMode = FilterMode.Bilinear;
    15.         texture2DArray.wrapMode = TextureWrapMode.Repeat;
    16.  
    17.         for (int i = 0; i < textures.Count; i++)
    18.         {
    19.             //Copy to the array texture
    20.             Graphics.CopyTexture(textures[i], 0, 0, texture2DArray, i, 0);
    21.         }
    22.         return texture2DArray;
    23.     }
    24.  
    25.  
    26.  
    27.     void Start()
    28.     {
    29.         texturesArray = createTexture2DArray(this.textures, 1024);
    30.         testMaterial.SetTexture("textureArray", texturesArray);
    31.         Debug.Log("supports2DArrayTextures: " + SystemInfo.supports2DArrayTextures);
    32.     }
    33.  
    34.     void Update()
    35.     {
    36.  
    37.     }
    38. }
    I have also tested with an HLSL equivalent, using this:

    https://gist.github.com/Spaxe/57de76c993a4dc8bb37275acbe597ef2

    Same story there, works in the editor but not in the browser.

    It looks to me like

    Code (CSharp):
    1. /Graphics.CopyTexture(textures[i], 0, 0, texture2DArray, i, 0);
    Is not working in WebGL, as I get the same result in the editor if I omit this.
     
    Last edited: May 14, 2021
  2. TOES

    TOES

    Joined:
    Jun 23, 2017
    Posts:
    134
    Okay, answering my own question here, as usual...

    I found a workaround:

    Code (CSharp):
    1.  
    2. if (SystemInfo.copyTextureSupport==UnityEngine.Rendering.CopyTextureSupport.None)
    3.    texture2DArray.SetPixelData(t.GetRawTextureData(), 0, i);          
    4. else
    5.    Graphics.CopyTexture(t, 0, 0, texture2DArray, i, 0);
    6. ...
    7. texture2DArray.Apply();
    8.  
    9.  
    The texture formats must match exactly,
     
    quizcanners likes this.