MonoGame icon indicating copy to clipboard operation
MonoGame copied to clipboard

Incorrect BlendState.NonPremultiplied alpha behavior?

Open juanjp600 opened this issue 5 years ago • 4 comments
trafficstars

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:

image

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:

image

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

juanjp600 avatar Jan 07 '20 17:01 juanjp600

God bless you for this issue, I literally had this problem just now and you already provided a workaround blendstate for me to use

DaedalusGame avatar Jan 07 '20 18:01 DaedalusGame

+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 avatar Dec 06 '21 08:12 JDoucette

@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.

ThomasFOG avatar Dec 07 '21 12:12 ThomasFOG

@mrhelmut -

  1. 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.
  2. 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.

JDoucette avatar Jan 16 '22 23:01 JDoucette

thank you so much for this! But why does it only occur with RenderTargets, if BlendState.NonPremultiplied is flawed?

zissakos avatar Mar 05 '23 01:03 zissakos