How To Use Texture Arrays In Unity

Caleb Faith
3 min readApr 7, 2018

--

“Array textures are an alternative to atlases, as they can store multiple layers of texture data for objects without some of the problems of atlases.” — OpenGL Wiki

NOTE: This tutorial only works with Forward Shading Mode at the moment

A Texture2DArray is a collection of same size images which you can sample with 3 texture coordinates (u, v, w) where w corresponds to the index or layer of the texture array. This eliminates the need to switch textures for different objects thus vastly improving our rendering performance and can also allow combining a mesh with different textures.

I’ve been using it with a Minecraft type terrain that uses different textures for each block type. One of the main benefits is that you can use texture wrapping and mip-mapping. With my game this meant I could easily implement greedy meshing.

Note: You will have to implement adding a third texture coordinate to your meshes.

Creating A Texture2DArray

Sadly Unity does not support creating Texture Arrays in the editor so we have to do it in code. Below is an example using an array of ordinary Texture2D’s to create the Texture2DArray.

NOTE: All textures must have an identical width and height.

public Texture2D[] ordinaryTextures;
public GameObject objectToAddTextureTo;
private void CreateTextureArray()
{
// Create Texture2DArray
Texture2DArray texture2DArray = new
Texture2DArray(ordinaryTextures[0].width,
ordinaryTextures[0].height, ordinaryTextures.Length,
TextureFormat.RGBA32, true, false);
// Apply settings
texture2DArray.filterMode = FilterMode.Bilinear;
texture2DArray.wrapMode = TextureWrapMode.Repeat;
// Loop through ordinary textures and copy pixels to the
// Texture2DArray
for (int i = 0; i < ordinaryTextures.Length; i++)
{
texture2DArray.SetPixels(ordinaryTextures[i].GetPixels(0),
i, 0);
}
// Apply our changes
texture2DArray.Apply();
// Set the texture to a material
objectToAddTextureTo.GetComponent<Renderer>()
.sharedMaterial.SetTexture("_MainTex", texture2DArray);
}

It simply loops through the supplied array of ordinary Texture2D’s and adds their pixel data to the appropriate layer.

Editing The Standard Shader To Use Texture2DArray

This is quite involved but if you follow these steps it will work out! If the line numbers don’t line up let me know and I’ll fix it up.

  1. Head over to the Unity Download Archive and download the ‘built-in shaders’.

2. Rename and copy the following files to your project. I just added ‘Array’ to the end of the names.
e.g. ‘UnityStandardCore.cginc’ to ‘UnityStandardCoreArray.cginc’

  • CGIncludes/UnityStandardCore.cginc
  • CGIncludes/UnityStandardCoreForward.cginc
  • CGIncludes/UnityStadardInput.cginc
  • DefaultResourcesExtra/Standard.shader

3. Open ‘StandardArray.shader’:

Line 3: Shader "StandardArray"Line 8: 8: change the '_MainTex' declaration where it says '2D' to '2DArray'Line 93: #include "UnityStandardCoreForwardArray.cginc"

4. Open ‘UnityStandardCoreForwardArray.cginc’

Line 19 change to: #include “UnityStandardCoreArray.cginc”

5. Open ‘UnityStandardInputArray.cginc’

Line 25: UNITY_DECLARE_TEX2DARRAY(_MainTex);Line 61 (float2 to float3): float3 uv0 : TEXCOORD0;Line 75 (Add lines):texcoord.xy = TRANSFORM_TEX(v.uv0.xy, _MainTex); 
texcoord.z = v.uv0.z;
  • Everywhere it says to sample _MainTex change to ‘UNITY_SAMPLE_TEX2DARRAY(_MainTex, uv)’
  • Every ‘float2 uv’ change to ‘float3 uv’

6. Open ‘UnityStandardCoreArray’

Line 10: #include "UnityStandardInputArray.cginc"Line 251: half alpha = Alpha(i_tex.xyz);

That’s it!

Using The Shader

Now in Unity you should be able to select “StandardArray” as a shader as a part of the material.

Conclusion

As it is dependant on how you use Texture2DArrays you will have to implement changing the Mesh UV’s yourself from Vector2 to Vector3. The ‘z’ component will just correspond to the Texture2DArray layer.

If you need help let me know in the comments and I’ll do my best to help!

--

--