Mixing textures using shader

Hi! I’m trying to mix 3 textures in shader: _MainTex, _MaskTex(RenderTexture) and _BrushTex.

When _BrushTex has opacity on the edges everything is fine:
5584669--576877--Screen Shot 2020-03-13 at 11.56.55.png

But when _BrushTex has hard edges it looks not as I expected:
5584669--576886--Screen Shot 2020-03-13 at 11.59.07.png

All textures has WrapMode.Clamp, so I don’t know where is the problem. I need to mix textures correctly, without stretching edges by X and Y axis. Can anyone help me?

Shader

Shader "MyShader/Paint with Preview" {
    Properties {
        _MainTex ("Main", 2D) = "white" {}
        _MaskTex ("Mask", 2D) = "black" {}
        _BrushTex ("Brush", 2D) = "black" {}
        _BrushOffset ("Brush offset", Vector) = (0, 0, 0, 0)
        _Color ("Main Color", Color) = (1, 1, 1, 1)
    }
  
    SubShader
    {
        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }
        Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {  
            Blend SrcAlpha OneMinusSrcAlpha
            SetTexture [_MainTex]
            {
                combine texture
            }    
        }
        Pass
        {
            Blend One OneMinusSrcAlpha
            SetTexture [_MaskTex]
            {
                combine texture * previous
            }
        }
        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #include "UnityCG.cginc"
            sampler2D _BrushTex;
            float4 _BrushOffset;
            float4 _Color;
    
            float4 frag (v2f_img i) : SV_Target
            {
                float4 result = tex2D(_BrushTex, float2(i.uv.x / _BrushOffset.z - _BrushOffset.x + 0.5f, i.uv.y / _BrushOffset.w - _BrushOffset.y + 0.5f)) * _Color;
                return result;
            }
            ENDCG
        }
    }
}

_BrushOffset code

_BrushOffset - Vector4 for _MainTex / _BrushTex sizes ratio, and paint position:

var brushRatio = new Vector2(MainTextureWidth / (float)BrushTextureWidth, MainTextureHeight / (float)BrushTextureHeight);
var brushOffset = new Vector4(paintPositionUV.x / SourceTextureWidth * brushRatio.x,paintPositionUV.y / SourceTextureHeight * brushRatio.y, 1f / brushRatio.x, 1f / brushRatio.y);

Hi @kmedved ,

Could you clarify your question a bit more? When you say “…trying to mix 3 textures…”, you mean that you are actually trying to combine two textures, using a mask texture to determine the texture blending amount? It looks a bit like that in your images but I’d suggest you use more clear examples if it’s something you try to figure out etc.

If you have texture wrap mode set to clamp, it will not repeat after the borders of the texture. You need to use repeat or other repeating modes (like mirror) to get rid of those extrusion lines on the texture borders. Then the texture will tile beyond the borders.

If I understand correctly your images, your first one of course looks correct because you fade the texture away before the border area is seen?

Anyway I’m not exactly sure what’s the problem.

Hi! Thanks for your reply! Sorry for misleading. I mixing two textures and sampling part of it in fragment shader. Sampled texture render into RenderTexture and then using it as a Brush. So when brush had non-alpha borders, it caused that problem as I said above.

Fixed it by adding zero-alpha padding in fragment shader:

if (i.uv.x <= _BrushTex_TexelSize.x || i.uv.x >= 1.0f - _BrushTex_TexelSize.x ||
    i.uv.y <= _BrushTex_TexelSize.y || i.uv.y >= 1.0f - _BrushTex_TexelSize.x)
{
    color.a = 0;
}