Home Game Development unity – Pass texture array into shader and paint mesh vertices depending on vertexattributes

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

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

[ad_1]

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?

[ad_2]