UV mask of a mesh with smaller UV coordinates - New to shaders

I’m very very very new to shaders, so it may be extremely trivial but I’m kind of struggling a bit to wrap my head around this shader matter.

I have generated a mesh composed of squares, each square has it’s relative UV coords, and I want to mask the entire mesh with another texture, but I don’t know how to precisely scale/offset my mask texture to encapsulate every square.

Here’s the situation and what I want to achieve with images, because I really do not know any better way to explain myself:

This is my shader:

Shader "Custom/Surface Mask" {
    Properties{
        _MaskText("Texture", 2D) = "white" {}
        [NoScaleOffset] _MainText("Texture", 2D) = "white" {}
        [NoScaleOffset] _SecText("CoverA", 2D) = "white" {}
    }

    SubShader {
        pass {
            CGPROGRAM

            #pragma vertex MyVertexProgram
            #pragma fragment MyFragmentProgram

            #include "UnityCG.cginc"

            sampler2D _MaskText, _MainText, _SecText;
            float4 _MaskText_ST, _MainText_ST, _SecText_ST;


            struct VertexData {
                float4 position : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct Interpolators {
                float4 localPosition : SV_POSITION;
                float2 uv : TEXCOORD0;
                float2 uvMask : TEXTCORD1;
            };


            Interpolators MyVertexProgram(VertexData v) {
                Interpolators i;
                i.localPosition = UnityObjectToClipPos(v.position);
                i.uv = TRANSFORM_TEX(v.uv, _MaskText);
                i.uvMask = v.uv;

                return i;
            }
            float4 MyFragmentProgram(Interpolators i) : SV_TARGET{
                float4 mask = tex2D(_MaskText, i.uvMask);
                float4 color = tex2D(_MainText, i.uv) * mask.r +
                    tex2D(_SecText, i.uv) * (1 - mask.r);
                return color;
            }

            ENDCG
        }
    }
}

This is the current material: 7232596--870487--material.PNG
Names are a bit confusing… CoverA and Texture have to be tiled to the squares, the mask will basically be used to create patches of grass.

Hope I explained myself well, and I hope you can help! Thanks anyway for reading.

Some other additional and potentially pointless informations:
Additional info The squares making the terrain are generated via script, in the editor not during runtime. I thought of making a big UV when generating the terrain, by picking the most extreme verts as the coordinates for the UV, and then tile the main and secondary texture accordingly, but there has to be a way to do it in the shader, also that is not desirable since I wanted the mask to not repeat itself nor stretch if I then want to change the shape of the terrain, say by adding more squares: It has to adapt to different meshes in short, obviously each mesh will then have it’s own mask.


It all depends on your mesh. When you set the meshes uv’s, you have two options. Either you use one coordinate channel and use integer multiplies for each square. If the texture is set to repeat, the tiling will be the same as before.
For the big texture, you then just scale down the uv. In your case you multiply u in the shader with 1.0/6.0 and v with 1.0 / 4.0. This allowes you, to use one coordinate set for both textures.

To anyone who might stumble upon this:
The solution was exactly what I was already talking about and is also mentioned by the user above. After I generated the squares, which are generated individually, and combined together into the whole terrain mesh, I just had to figure out the overall size of the terrain generated, map the mesh vertices to the UV coordinates, then tile the material accordingly.
Here’s the piece of code that does that, I didn’t had to change much in the shader, just add two floats and use those for the tiling:

Vector2 min = new Vector2(int.MaxValue, int.MaxValue),
        max = new Vector2(int.MinValue, int.MinValue);
foreach (Tile t in tiles){
// Get the lowest and highest tile position in the tilemap
        GetMinMax(t, ref min, ref max);
}
     
// Calculate genereated terrain area
tilemapX = max.x - min.x + 1;
tilemapY = max.y - min.y + 1;

// Get full mesh and create new uv array
Mesh m = meshFilter.sharedMesh;
Vector2[] uvs = new Vector2[m.vertexCount];
for (int i = 0; i < m.vertexCount; i++)
{
    // Pick vertex and offset relative to tilemap position and tile size
    Vector3 v = m.vertices[i] - new Vector3(min.x  - tileSize / 2, min.y - tileSize / 2);
     // Map vertex to uv coord
     uvs[i] = new Vector2(1 / tilemapX * v.x, 1 / tilemapY * v.y);
}
m.uv = uvs;

 // Set scale to material for texture tiling
Material mat = meshRenderer.sharedMaterial;
mat.SetFloat(Shader.PropertyToID("_ScaleX"), (float)x);
mat.SetFloat(Shader.PropertyToID("_ScaleY"), (float)y);

As a side note;The way I’m currently generating the squares one by one and then combine them together into a single mesh isn’t very efficient, vertices end up overlapping and could cause performance issues at large scale, I should generate the entire terrain mesh altogether, that would’ve probably forced me immediately into this solution.