Bad texture edges

Hi, I’m trying to make a very simple shader. The shader should place one texture on top of another with an offset from the edge.

sampler2D _BackTex;
sampler2D _TopTex;
float     _FrameSize;

float4 frag(v2f IN) : COLOR
{
   //
   float2 frame = float2(_FrameSize, _FrameSize);

   //
   if (IN.texcoord.x >= frame.x &&
       IN.texcoord.x <= (1.0f - frame.x) &&
       IN.texcoord.y >= frame.y &&
       IN.texcoord.y <= (1.0f - frame.y))
   {
      //
      float2 topUV = (IN.texcoord - frame) / (float2(1.0f, 1.0f) - frame * 2.0f);

      //
      return tex2D(_TopTex, topUV);
   }
   else
   {
      //
      return tex2D(_BackTex, IN.texcoord);
   }
}

With some margins, the edges of the internal texture are normal. With other margins, the edges are bad.

It seems to be related to mipmaps. When mipmaps are disabled, there are no distorted edges. But the result is very ugly. Please share your thoughts on solving the problem.

Looks to me like blending across from the opposite side of the texture.

In your image import settings you want to change the wrap settings from “wrap” to “clamp”.

Thanks. I’ve been thinking about it too. But this method does not work at all. The best thing I found is to manually set the MipMaps level. It remains to figure out how to calculate the appropriate level of MipMaps.

// return tex2D(_TopTex, topUV);

return tex2Dlod(_TopTex, float4(topUV, 0, 3));

This is absolutely the problem.

The issue in the screenshot you posted is 100% that problem. If setting the texture to clamp doesn’t fix it, you’re modifying a different texture, or the problem that remained is not the one in that screenshot.

It is possible with the way you have your shader setup that you’re seeing some other kind of problem. Doing texture samples (tex2D()) inside an if statement can be problematic on some GPUs. The shader compiler is likely to “fix” that for you so that the textures aren’t actually sampled inside a branch, but some won’t. I would suggest using something like this:

float2 frame = float2(_FrameSize, _FrameSize);
float2 topUV = (IN.texcoord - frame) / (float2(1.0f, 1.0f) - frame * 2.0f);
float4 top = tex2D(_TopTex, topUV);
float4 back = tex2D(_BackTex, IN.texcoord);

float2 maskUV = abs(topUV-0.5);
float topMask = any(abs(topUV-0.5) > 0.5) ? 0.0 : 1.0;
return topMask ? top : back;

Thank you for this clarification. Your sample code works well.