Custom BlendState: How do Color- and AlphaBlend mix?

So, I am playing around with Custom BlendStates.

Color Blending makes sense to me, but Alpha Blending confuses me. I don’t understand how Color- and AlphaBlend work together in a custom BlendState.

Imagine the following scenario for example. You have a renderTarget (1,1,1,1) and want to cutout an opaque shape, so the affected area gets transparent. Then draw the renderTarget on top of the world.

It is a specific case but crucial for understanding how that stuff works. So please stick with this example and explain me what is happening. Thank you!

So, I first thought of this custom BlendState:

 BlendState bmSubtract = new BlendState()
    {
    AlphaSourceBlend = Blend.SourceColor,
    AlphaDestinationBlend = Blend.One,
    AlphaBlendFunction = BlendFunction.ReverseSubtract
    };

( destCol x destBlend ) - ( srcCol x srcBlend )

Here already starts the confusion. What is calculated in the AlphaBlendFunction?
Is it the alpha only or also the color. And how is the color of the previous ColorBlendFunction used?
Is srcColor here only a alpha value or (1,1,1,1).

You will get this result if I have not messed up thing:

This is different what I have expected, it is the other way around. Why does it not subtract the white circle from the white destination and creates a circle cutout, so you can see the red game world behind it?

Now, the following BlendState is working the way I want it to. But I don’t understand yet.

BlendState bmSubtract = new BlendState()
        {
            ColorSourceBlend = Blend.One,
            ColorDestinationBlend = Blend.One,
            ColorBlendFunction = BlendFunction.ReverseSubtract,

            AlphaSourceBlend = Blend.SourceColor,
            AlphaDestinationBlend = Blend.One,
            AlphaBlendFunction = BlendFunction.ReverseSubtract
        };

It’s important to realize that the alpha value is not necessarily transparency. It’s simply a 4th channel in your textures that’s used for blending. In the end it’s the resulting color of your texture that’s drawn, alpha only matters when combining your texture with another one. The AlphaBlendFunction only determines how the alpha channel of the resulting texture is computed while the ColorBlendFunction determines how the RGB values are computed. Again, the resulting alpha value only matters when further blending this texture on something else. It’s easier to see this as a simple math problem and work your way back from how you want the blending to behave exactly.

2 Likes

The thing is that the AlphaBlendFunction in some way relies on the ColorBlendFunction. So changing the ColorBlend is affecting the AlphaBlend. It is a mystery to me when or how they are applied and mix with each other. This is the exact point of confusion. I am thankful if you or someone can help me understand.

I still need help!

I have created a better screenshot which should provide you with the necessary information for my issue.
It is super small example.

Additional info: The texture (Blend1) is completely opaque. I tried both premultiplied alpha (yes / no) in the Content Pipeline, but it has no effect which makes sense here.

I expected that (RGB, 1) x (0,0,0,0) - (RGB, 1) x (0,0,0,0) always results in (RGB, 0). Then we would have a complete rectangle cutout. But instead we have the above. And my brain is limited. Please help, why is this happening?

There are two blend operations happening here. The second is when you render the render target to the back buffer. The default blendstate for SpriteBatch is AlphaBlend which assumes the source texture has alpha premultiplied and uses the function Source Color + (Destination Color * (1 - Source Alpha)). Since your source color is white within the circle this just becomes white. To get what you expected use BlendState.NonPremultiplied which does Source Color * Source Alpha + (Destination Color * (1 - Source Alpha)).

1 Like