For my game I have written a shader that allows my texture to tile nicely over multiple objects. I do that by choosing the uv not based on the relative position of the vertex, but on the absolute world position. The custom shader is as follows. Basically it just tiles the texture in a grid of 1x1 world units.
Shader "MyGame/Tile"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
float3 worldPos;
};
void surf (Input IN, inout SurfaceOutput o)
{
//adjust UV for tiling
float2 cell = floor(IN.worldPos.xz);
float2 offset = IN.worldPos.xz - cell;
float2 uv = offset;
float4 mainTex = tex2D(_MainTex, uv);
o.Albedo = mainTex.rgb;
}
ENDCG
}
FallBack "Diffuse"
}
I have done this approach in Cg and in HLSL shaders on XNA before and it always worked like a charm. With the Unity shader, however, I get a very visible seam on the edges of the texture. I tried a Unity surface shader as well as a vertex/fragment shader, both with the same results.
The texture itself looks as follows. In my game it is actually a .tga, not a .png, but that doesn't cause the problem. The problem occurs on all texture filter settings and on repeat or clamp mode equally.
Now I've seen someone have a similar problem here: Seams between planes when lightmapping. There was, however, no definitive answer on how to solve such a problem. Also, my problem doesn't relate to a lightmap or lighting at all. In the fragment shader I tested, there was no lighting enabled and the issue was still present.
The same question was also posted on the Unity answers site, but I received no answers and not a lot of views, so I am trying it here as well: Visible seams on borders when tiling texture
This describes the reason for your problem: http://hacksoflife.blogspot.com/2011/01/derivatives-i-discontinuities-and.html
This is a great visual example, like yours: http://aras-p.info/blog/2010/01/07/screenspace-vs-mip-mapping/
Unless you're going to disable mipmaps, I don't think this is solvable with Unity, because as far as I know, it won't let you use functions that let you specify what mip level to use in the fragment shader (at least on OS X / OpenGL ES; this might not be a problem if you're only targeting Windows).
That said, I have no idea why you're doing the fragment-level uv calculations that you are; just passing data from the vertex shader works just fine, with a tileable texture:
struct v2f {
float4 position_clip : SV_POSITION;
float2 position_world_xz : TEXCOORD;
};
#pragma vertex vert
v2f vert(float4 vertex : POSITION) {
v2f o;
o.position_clip = mul(UNITY_MATRIX_MVP, vertex);
o.position_world_xz = mul(_Object2World, vertex).xz;
return o;
}
#pragma fragment frag
uniform sampler2D _MainTex;
fixed4 frag(v2f i) : COLOR {
return tex2D(_MainTex, i.position_world_xz);
}