Texture2DArray Can not create compressed format. Small Editor Demo

Hi everyone,

I stuck currently to create Texture2Darray with a compresses format.
The reason is

Texture2DArray array = new Texture2DArray(textures[0].width, textures[0].height, textures.Length, textures[0].format, true);

Array. provide only SetPixels and SetPixels32 and these both requires RGB and RGBA format only. But not BC7/DXT5 or the newer compression typ.

Does any know how to build a compressed Texture2DArray and provide some lines of code please?!

Thanks a lot!


With this small example you’re able to select a brunch of textures and save them as Texture2DArray asset to the same directory in Unity. Drag and drop the file was created to the Tex2DArray shader slot myArr.

using UnityEngine;
using UnityEditor;
using System.IO;

public class EditorExportAsset {
    [MenuItem("Assets/Build : Texture2DArray Asset From Selection")]
    static void ExportResource() {

        // Selection is unsorted and does not reflect the sort of the displayed filenames of unity
        Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);

        if (selection.Length > 0) {

            // Redirect to the Path of the first selected object
            string pathfull = new FileInfo(AssetDatabase.GetAssetPath(selection[0])).FullName;
            // FileInfo reversed IBM format back to Unity
            pathfull = pathfull.Replace("\\", "/");

            string name = selection[0].name.ToLower();
            var pathfull_l = pathfull.ToLower();
            pathfull = pathfull.Substring(0, pathfull_l.LastIndexOf("/"+name));

            // Debug.Log(pathfull +  "   " + pathfull_l.LastIndexOf("/" + name)  +  "  " +name) ;

            // Bring up save panel
            pathfull = EditorUtility.SaveFilePanel("Save Resource Texture2DArray", pathfull, "Texture2DArray", "asset");

            // Create relative Path for AssetDatabase.Save
            pathfull_l = pathfull.ToLower();
            pathfull = pathfull.Substring(pathfull_l.IndexOf("/assets/") + 1);
                      
            if (pathfull.Length != 0) {

                // Build the resource file from the active selection.
                Texture2D[] textures = new Texture2D[selection.Length];

                //Debug.Log(textures[0].format);

                for (int i = 0; i < textures.Length; i++) {
                    textures[i] = (Texture2D)selection[i];
                }

                Texture2DArray array = new Texture2DArray(textures[0].width, textures[0].height, textures.Length, textures[0].format, true);

                // Graphics.CopyTexture() ??
                for (int i = 0; i < textures.Length; i++)
                    array.SetPixels32(textures[i].GetPixels32(), i);

                array.Apply();

                AssetDatabase.CreateAsset(array, pathfull);
            }

        } else {
            Debug.LogWarning("# Build Texture2DArray Asset From Selection : No Selection ");
        }
    }
}
Shader "Example/TextureArrayShader" {
    Properties{
        _Color("Color", Color) = (1,1,1,1)
        _MyArr("Tex", 2DArray) = "" {}
        _Index("Texture Index", Int) = 0
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0
    }
        SubShader{
        Tags{ "RenderType" = "Opapue" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows

        // Use shader model 3.5 target, to get
#pragma target 3.5

        UNITY_DECLARE_TEX2DARRAY(_MyArr);

    struct Input {
        float2 uv_MyArr;
    };

    half _Glossiness;
    half _Metallic;
    fixed4 _Color;

    float _Index;

    void surf(Input IN, inout SurfaceOutputStandard o) {
        // Albedo comes from a texture tinted by color
        // 2nd attribute is float3 !!! uvs and index
        fixed4 c = UNITY_SAMPLE_TEX2DARRAY(_MyArr, float3(IN.uv_MyArr, _Index)) * _Color;
        o.Albedo = c.rgb;
        // Metallic and smoothness come from slider variables
        o.Metallic = _Metallic;
        o.Smoothness = _Glossiness;
        o.Alpha = c.a;
    }
    ENDCG
    }
        FallBack "Diffuse"
}
4 Likes

Hello mighty Bgolus, could you please follow up in https://answers.unity.com/questions/1565099/using-graphicscopytexture-with-compressed-dxt-text.html?
Thanks

Not enough information there to give an answer, and I don’t post on Unity Answers. Please make a new thread here.

I am using Graphics.CopyTexture for the copying into Texture2DArray using:

// Create Texture2DArray using one of the textures
Texture2DArray texture2DArray = new Texture2DArray(texture.width, texture.height, length, texture.format, true, false);
texture2DArray.filterMode = texture.filterMode;
texture2DArray.wrapMode = texture.wrapMode;

//Copy to texture2DArray
for(int i = 0; i < texture.mipmapCount; i++) { // Copy all mipmap levels
      Graphics.CopyTexture(texture, 0, i, texture2DArray, indexIntoTexture2DArray, i); texture2DArray
}

With uncompressed textures, everything works fine, but when used with compressed DXT1(BC7) textures, I am getting:

Invalid texture format: 10(25)
UnityEngine.Graphics:CopyTexture(Texture, Int32, Int32, Texture, Int32, Int32)
Image invalid format!
UnityEngine.Graphics:CopyTexture(Texture, Int32, Int32, Texture, Int32, Int32)

I am using Unity 2018.3 with Forward only (prepared for VR). If you will need more info, please dont hesitate.

That’s telling me that you’re trying to copy a DXT1 format texture into a BC7 format texture array. Those are not the same format.

Nope, just saying it’s happening in both compressions.
Imagine having a texture, I will create a texture2Darray able to hold this texture (same dimensions, type, wrap mode, etc.) using the code above and then copy it and all of its mip maps into texture2Darray.

This works for me without errors, in the editor at least.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class TextureArrayTest : MonoBehaviour {
    public Texture2D[] textures;
    public Texture2DArray tempTextureArray;

    public void Go()
    {
        Texture2DArray texture2DArray = new Texture2DArray(textures[0].width, textures[0].height, textures.Length, textures[0].format, true, false);
        for(int i = 0; i < textures.Length; i++)
        {
            for(int m = 0; m < textures[i].mipmapCount; m++)
            {
                Graphics.CopyTexture(textures[i], 0, m, texture2DArray, i, m);
            }
        }
        if (tempTextureArray != null)
            DestroyImmediate(tempTextureArray);
        tempTextureArray = texture2DArray;
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(TextureArrayTest))]
public class TextureArrayTestEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (GUILayout.Button("Make Array"))
            (target as TextureArrayTest).Go();
    }
}
#endif

That leads me to believe you’re getting the error on a platform that doesn’t support CopyTexture?

With compressed textures Im still getting similar error, although the texture2DArray is filled (as in my scrips).

About the platform,
Debug.Log(SystemInfo.copyTextureSupport)
returns
Basic, Copy3D, DifferentTypes, TextureToRT, RTToTexture
And having NVIDIA GTX 1080 Ti so that should not be problem.

Here is the image of texture setting.

3885508--330295--Capture2.JPG

If your using the latest 2018.3 betas, Unity broke CopyTexture with texture arrays.

4 Likes

Lal… confirmed. Tried in 2018.2.8f1 and no problem. In 2018.3.0b7 error occured, but textures are copied in Tex2DArray.

Thanks both of you!