Simple blend script

Having trouble blending 2 textures together.

I following along with Daniel_Brauer and AntonPetrov’s explanations here but I’ve not been able to figure out how to set ShaderLab commands DestBlend and SrcBlend.

It does sorta blend, but some colours aren’t quite right.

Here’s what I’m getting: And here’s what I’m hoping for:

Would someone please tell me where I’m going wrong?

(uv_bottomLayer) + (uv_topLayer) = (fragment)

            fixed4 FragmentFunc(v2f IN) : SV_Target
            {
                fixed4 texture2 = SampleSpriteTexture(IN.uv_topLayer) * IN.color;
                fixed4 texture1 = SampleSpriteTexture(IN.uv_bottomLayer) * IN.color;
            
                if (texture2.a > 0)
                {
                    fixed4 fragment;

                    fragment.rgb = (texture1.rgb * (1 - texture2.a)
                        + texture2.rgb);

                    fragment.a = (1 - (1 - texture1.a) * (1 - texture2.a));

                    return fragment;
                }
                return texture1;
            }

            ENDCG

            Cull Off
            Lighting Off
            ZWrite Off
            BlendOp Add
            Blend One OneMinusSrcAlpha

When you’re blending two textures together within a shader, the DestBlend and SrcBlend aren’t important. That’s just for how the final output color of the shader gets blended with the target. If you want to replicate traditional alpha blending, that’d just be a basic lerp.

return lerp(texture1, texture2, texture2.a);

However the above will cause issues with the alpha. I’d probably do something like this instead:

return float4(lerp(texture1.rgb, texture2.rgb, texture2.a), texture1.a);
or
return float4(lerp(texture1.rgb, texture2.rgb, texture2.a), max(texture1.a, texture2.a));

However, to be honest, I’m not entirely sure what kind of blend you’re looking to do since the png images you posted above don’t have any alpha, and I’m not sure how you produced the “wanted” image. Presumably that was done in photoshop with some specific blend mode? Which one?

as I see, you got what you wanted… you have yellow background and overlay blue over it

blending code

if (texture2.a > 0)
                {
                    fixed4 fragment;
                    fragment.rgb = (texture1.rgb * (1 - texture2.a)
                        + texture2.rgb);
                    fragment.a = (1 - (1 - texture1.a) * (1 - texture2.a));
                    return fragment;
                }

makes alpha cutout (which also can be deleted, blending in “then” already exist), then makes Normal blending
also you use “+ texture2.rgb” which assumes your texture2.rgb is already in premultiplied-alpha mode (otherwise you need to change formula to “+ texture2.rgb * texture2.a”)

citated from https://discussions.unity.com/t/496864

as a common alpha-blending equation with alpha premultiplied in fragment.rgb:
output = background.rgb * (1 - fragment.a) + fragment.rgb;

this another blending is related to destination-final-step to allow chain-blend of (tex3 over (tex2 over tex1)) etc, where your original shader contains only tex1, tex2

BlendOp Add
            Blend One OneMinusSrcAlpha

original case from https://forum.unity.com/threads/wha…-two-transparent-textures-in-a-shader.169313/
was
“I need to blend three transparent textures in one shader to be drawn in one call,”
it is important - by one call… due to this, the solution is in-code-blend formula like
fragment.a = (1 - (1 - texture1.a) * (1 - texture2.a));
or tex3, tex2, tex1 formula from it

if you don’t have case “in one call” (imho you don’t need)
then you can achieve desired effect only by simple blend
delete in-code blending

fragment.rgb = (texture1.rgb * (1 - texture2.a)

etc
and simple blend shader is

Shader "Custom/MyPremultipliedAlpha"
{
    Properties
    {
        _MainTex ("Main Texture", 2D) = "white" {}
    }

    SubShader
    {
        Tags
        {
            "RenderType" = "Transparent"
            "Queue" = "Transparent"
        }
 
        Lighting Off
        ZWrite Off
        Cull Off
 
        Blend One OneMinusSrcAlpha
 
        Pass
        {
            CGPROGRAM

            #pragma vertex ComputeVertex
            #pragma fragment ComputeFragment
   
            sampler2D _MainTex;
   
            struct VertexInput
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
            };

            struct VertexOutput
            {
                float4 vertex : SV_POSITION;
                half2 texcoord : TEXCOORD0;
            };
   
            VertexOutput ComputeVertex (VertexInput vertexInput)
            {
                VertexOutput vertexOutput;
       
                vertexOutput.vertex = UnityObjectToClipPos(vertexInput.vertex);
                vertexOutput.texcoord = vertexInput.texcoord;
                   
                return vertexOutput;
            }
   
            fixed4 ComputeFragment (VertexOutput vertexOutput) : SV_Target
            {
                return tex2D(_MainTex, vertexOutput.texcoord);
            }

            ENDCG
        }
    }
}

(with premult in original texture, which is important to order-independent-blend-to-background, otherwise you should change blend in it to Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha)

which can be chained unlimited-times like

dest = create RT..
Graphics.Blit(tex1, dest, myMat)
Graphics.Blit(tex2, dest, myMat)
Graphics.Blit(tex3, dest, myMat)

it produces formula
(tex3 over (tex2 over tex1))