MonoGame
MonoGame copied to clipboard
Incorrect BlendState.NonPremultiplied alpha behavior?
Recently I've been switching from BlendState.AlphaBlend to BlendState.NonPremultiplied since it simplifies things and improves loading performance by removing the need to premultiply textures loaded through Texture2D.FromStream.
However, there is an issue with the way BlendState.NonPremultiplied behaves. Using the source alpha as AlphaSourceBlend results in more translucency than I would expect, and in fact can reduce the overall opacity of the resulting image when using render targets, as seen here:

The backbuffer is cleared to be magenta, but the background image is fully opaque and thus should hide it completely. The correct result would be as follows:

I've created a sample project demonstrating this: Test.zip
The corrected blendstate is as follows:
var nonPremultiplied = new BlendState
{
ColorSourceBlend = Blend.SourceAlpha,
ColorDestinationBlend = Blend.InverseSourceAlpha,
AlphaSourceBlend = Blend.One,
AlphaDestinationBlend = Blend.InverseSourceAlpha,
};
What version of MonoGame does the bug occur on:
- MonoGame 3.7
What operating system are you using:
- Windows 10 Pro x64
What MonoGame platform are you using:
- WindowsDX
God bless you for this issue, I literally had this problem just now and you already provided a workaround blendstate for me to use
+1. Confirmed failing for me with: MonoGame 3.7, Windows 10, DirectX.
The BlendState provided above corrects the issue.
My situation was using textures loaded with /processorParam:PremultiplyAlpha=True (or simply generated dynamically), for which you pass SpriteBatch.Color()'s color (didn't this used to be called tint?) with an alpha values between 0..255.
@JDoucette would you happen to know if this behavior is the same on XNA or is it really unique to MonoGame? I wouldn't mind a test against 3.8 as well.
Unrelated, but not quite unrelated, if you work from source, FromStream can now load premultiplied assets.
@mrhelmut -
- Unsure if XNA had/has this issue; in my experience I never noticed it. Because this affects alpha blending transparencies, without significant fill with such pixels, it may be hard to catch the error (say, if it's just used for anti-aliased edges). It's possible I've never attempted color transparencies in my games/demos until now.
- I don't have a 3.8 project to test on at the moment; I am running 3.7.1.189, but it shouldn't be hard to test. Draw a few see-through colors over each other, and see if they add or blend together.
thank you so much for this! But why does it only occur with RenderTargets, if BlendState.NonPremultiplied is flawed?