Pass texture array into shader and paint mesh vertices depending on vertexattributes

Well,

I’m a newbie with shaders, I’m just trying to paint a mesh depending on the vertex attribute passed with one or another texture.

The idea is to achieve this, for example:

...

For this, I have been reading some documentation.

So, if I understand fine, I need a vertex subshader with the following structure:

		struct Input
		{
			float2 uv_MainTex;
			float arrayIndex;
		};

Then pass its information from the vert out parameter of type Input, to be used in the surf shader as an Input IN param:

		void vert(inout appdata_full v, out Input o)
		{
			o.uv_MainTex = v.texcoord.xy;
			o.arrayIndex = v.texcoord.z;
		}

		void surf(Input IN, inout SurfaceOutputStandard o)
		{
			fixed4 c = UNITY_SAMPLE_TEX2DARRAY(_Top, float3(IN.uv_MainTex, IN.arrayIndex)) * _Color;
			o.Albedo = c.rgb;

			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
		}

The full code of the shader:

Shader "Custom/z3nth10n/MultiTriplanar"
{
	Properties
	{
		_Top("Top Main Texture", 2DArray) = "" { }
		_Color("Color", Color) = (1,1,1,1)
		_Glossiness("Smoothness", Range(0,1)) = 0.5
		_Metallic("Metallic", Range(0,1)) = 0.0
		_ZOffset("Z Buffer Offset", Float) = 0
	}
	
	SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 200
		Offset[_ZOffset],[_ZOffset]

			CGPROGRAM
		#pragma surface surf Standard fullforwardshadows vertex:vert
		#pragma vertex vert
		#pragma require 2darray

		struct Input
		{
			float2 uv_MainTex;
			float arrayIndex;
		};

		UNITY_DECLARE_TEX2DARRAY(_Top);

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		void vert(inout appdata_full v, out Input o)
		{
			o.uv_MainTex = v.texcoord.xy;
			o.arrayIndex = v.texcoord.z;
		}

		void surf(Input IN, inout SurfaceOutputStandard o)
		{
			fixed4 c = UNITY_SAMPLE_TEX2DARRAY(_Top, float3(IN.uv_MainTex, IN.arrayIndex)) * _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"
}

This is the full project: https://drive.google.com/file/d/1wJ9QyvkSA_rBAXfN1rFowDpWY5EhqEDV/view?usp=sharing

If you open the Custom/z3nth10n/MultiTriplanar shader you will notice that there is more code, I want to achieve tri-planar implementation with NativeArrays and VertexAttributes later, but now I’m focusing on this part.

As you can see the mesh is showing like this:

...

It has no tiling and any information has passed through the VertexAttribute Mesh Data Buffers.

Also, there is my implementation in C# to show you how I pass the vertex data to the mesh buffers:

using System.Linq;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;

public class PlaneVerticesTest : MonoBehaviour
{
    [StructLayout(LayoutKind.Sequential)]
    private struct BiomeVertexLayout
    {
        public Vector3 texcoord;
    }

    public Texture2DArray texArray;

    // Start is called before the first frame update
    private void Start()
    {
        //var texArray = Resources.Load<Texture2DArray>("TextureArrays/Biome1DiffuseTextureArray");
        var textureCount = texArray.depth;

        var mesh = GetComponent<MeshFilter>().mesh;

        Debug.Log(SystemInfo.SupportsVertexAttributeFormat(VertexAttributeFormat.Float32, 4));

        var layout = new[]
        {
            new VertexAttributeDescriptor(VertexAttribute.TexCoord0) //, VertexAttributeFormat.Float32, 4)
        };
        mesh.SetVertexBufferParams(mesh.vertexCount, layout);

        var data = Enumerable.Range(0, mesh.vertexCount).Select(i => new Vector3(mesh.uv[i].x, mesh.uv[i].y, i % textureCount)).ToArray();
        mesh.SetVertexBufferData(data, 0, 0, mesh.vertexCount);
    }

    // Update is called once per frame
    private void Update()
    {
    }
}

As you can see I’m using var data = Enumerable.Range(0, mesh.vertexCount).Select(i => new Vector3(mesh.uv[i].x, mesh.uv[i].y, i % textureCount)).ToArray();

That means that per each vertex index, I’m just passing the same arrayIndex to the shader Input object (treating the textureCount part with a modulus operator).

Can anyone give me some guidance on this?