Hello,
I work on a shader that use 4 textures, provided by a c# so thoses textures might change over time.
I’m getting visible seams between thoses textures.
After a brief search, I found a solution with derivatives, but it’s not fixing the problem, juste enhancing the result a little bit.
Shader "Custom/TileShader"
{
Properties
{
[NoScaleOffset] _TileBottomLeft ("Bottom Left Tile", 2D) = "white" {}
[NoScaleOffset] _TileBottomRight ("Bottom Right Tile", 2D) = "white" {}
[NoScaleOffset] _TileTopLeft ("Top Left Tile", 2D) = "white" {}
[NoScaleOffset] _TileTopRight ("Top Right Tile", 2D) = "white" {}
_GlobalCenterU ("Global U", Range(0.0, 1.0)) = 0.5
_GlobalCenterV ("Global V", Range(0.0, 1.0)) = 0.5
[Toggle] _DebugMode ("Debug Mode", Float) = 0
[Toggle] _SeamsFix ("Seams Fix", Float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _TileBottomLeft;
sampler2D _TileBottomRight;
sampler2D _TileTopLeft;
sampler2D _TileTopRight;
float _GlobalCenterU;
float _GlobalCenterV;
float _DebugMode;
float _SeamsFix;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
float4 frag (v2f i) : SV_Target
{
float2 uv = i.uv;
float2 C = float2(_GlobalCenterU,_GlobalCenterV);
// From local UV to Quad (2x2) UV
float2 UVquad = (C-float2(0.25,0.25)) + uv*0.5; // pour un quad entre 0 et 1
float2 UVquad2 = 2*UVquad;
float2 fuv = frac(UVquad2);
// Sample the correct texture based on the tile
float4 color;
if (UVquad2.x < 1 && UVquad2.y < 1) // Bottom-left tile
{
color = tex2D(_TileBottomLeft, fuv);
}
else if (UVquad2.x >= 1 && UVquad2.y < 1) // Bottom-right tile
{
color = tex2D(_TileBottomRight, fuv);
}
else if (UVquad2.x < 1 && UVquad2.y >= 1) // Top-left tile
{
color = tex2D(_TileTopLeft, fuv);
}
else // Top-right tile
{
color = tex2D(_TileTopRight, fuv);
}
if(UVquad2.x<0 || UVquad2.x>2 ||UVquad2.y<0 || UVquad2.y>2)
{
color = float4(0,0,0,0);
}
if (_SeamsFix > 0.5)
{
float2 ddxUV = ddx(UVquad2);
float2 ddyUV = ddy(UVquad2);
if (UVquad2.x < 1 && UVquad2.y < 1) // Bottom-left tile
{
color = tex2Dgrad(_TileBottomLeft, fuv, ddxUV, ddyUV);
}
else if (UVquad2.x >= 1 && UVquad2.y < 1) // Bottom-right tile
{
color = tex2Dgrad(_TileBottomRight, fuv, ddxUV, ddyUV);
}
else if (UVquad2.x < 1 && UVquad2.y >= 1) // Top-left tile
{
color = tex2Dgrad(_TileTopLeft, fuv, ddxUV, ddyUV);
}
else // Top-right tile
{
color = tex2Dgrad(_TileTopRight, fuv, ddxUV, ddyUV);
}
}
if (_DebugMode>0.5)
{
float2 uv2 = 2.0*uv;
float2 fuv = float2(frac(uv2.x),frac(uv2.y));
if (uv2.x<=1 && uv2.y<=1) color = tex2D(_TileBottomLeft, fuv);
if (uv2.x>1 && uv2.y<=1) color = tex2D(_TileBottomRight, fuv);
if (uv2.x<=1 && uv2.y>1) color = tex2D(_TileTopLeft, fuv);
if (uv2.x>1 && uv2.y>1) color = tex2D(_TileTopRight, fuv);
}
return color;
}
ENDCG
}
}
}
Here is the result without the fix/with the ddx semi fix:
For the texture sampler, I have tried everything. Currently warp mode is clamp, mipmaps are enable.
This seems a basic problem but can’t find any solution.
Thanks !
Ben
PS: I know the shader is not optimised, that was not the point at this time.