Multiple Tiles in 1 Texture

Hi,

I’m trying to reduce drawcalls in my game, a lot of our models use multiple materials with exactly the same tile scale and offsets and shaders, it’s just the texture that changes. This has ended up using a lot of draw calls that I think we could avoid so I’ve written a shader that uses vertex color (applied per face) to offset and repeat UVs within a small part of a larger tile atlas.

e.g. a vertex with RGBA (0.5, 0.5, 0.5, 0.5) would always wrap the UVs into the bottom right quarter of the texture.

The issue I have is 1 pixel lines at the edge of each tile
1381202--70315--$tileLines.png

I’m fairly confident its not a mipmapping issue as when setting the RGBA values I add a 5% border around each tile, also the lines are never more than 1 pixel even when zoomed right in so I think its more likely to be a shader issue.

Here’s my shader

Shader "Custom/VertColorTileSS" {
	Properties {
	_Color ("_Color", Color) = (1, 1, 1, 1)
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Lambert

		sampler2D _MainTex;
		fixed4 _Color;

		struct Input {
			float2 uv_MainTex;
			float4 color : COLOR;
		};

		void surf (Input IN, inout SurfaceOutput o) {
			float2 uv = frac(IN.uv_MainTex) * IN.color.ba + IN.color.rg;
			half4 c = tex2D (_MainTex, uv);
			o.Albedo = c.rgb * _Color.rgb;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

It is most likely a mipmapping issue. Mipmaps are chosen based on the difference in UV coordinates between adjacent pixels. When the difference is large, a smaller mip level is used. It is possible to avoid this by calculating your own derivatives to for use with the texture sampler. I’m not sure if it’s supported on iOS, but I think the simplest approach would be to get the derivative of your continuous UV coordinates with ddx(a) ddy(a) and use those as arguments to tex2D(sampler2D tex , float2 s , float2 dsdx , float2 dsdy).

Cheers that makes a lot of sense, I don’t think I can use ddx ddy because I’m on Android. I compromised and a result (though not exactly what i wanted) by mirror repeating the uvs instead of tiling