Potential premultiply render issue
andrewandrepowell opened this issue · comments
We spoke about this on discord. You can find the first message where we briefly discussed this here: https://discord.com/channels/586997072373481494/819954682029277185/1262067825783214101
To summarize, I've been running into an issue with Monogame DesktopGL where I've been having issues using a Gum project to implement a dimmer. In the gum project, I have a component with a standard rectangle. I update the rectangle's rendering color from Monogame to implement the dimming effect. What's odd is that I get the intended effect when I run the game on browser with KNI BlazorGL.
After speaking with you, you pointed out the "one must be using premultiplied alpha".
Let me know if you need more information!
https://github.com/andrewandrepowell/GumDimExample
In making that example, I actually figured out a solution to my problem. There might not actually be a real problem with either MonoGame or Gum but instead a failure of understanding on my part. The equivalent line that was causing the problem is the following:
The issue seems to be the dimming causes the CornflowerBlue color to bleed through, and it doesn't quite make sense to me why that happens.
I've looked into this and the issue is that you are using a render target (very important).
Think of it this way - let's say you have the back buffer which has been cleared to blue, and then you draw a fully opaque black rectangle on a render target which will get drawn onto the back buffer. When you do that, the render target gets an alpha of 1 (100%).
But if instead you draw a half-opaque black rectangle on the render target, the render target's alpha gets set to 0.5 (50%). When that gets drawn to the back buffer, then it will only half darken the back buffer, which lets some of the blue through, effectively lightening what you draw.
You need to instead "add" the alpha. You can do this with the NonPremultipliedAddAlpha Gum blend state:
https://docs.flatredball.com/gum/gum-code-reference/graphicaluielement/blendstate
Let me know if this solves it. If so, can you close the issue too?
Hmm. So, what if there's a texture drawn after clearing the back buffer but before drawing the partially transparent black rectangle? Is the alpha of the black rectangle getting multiplied with the alpha of the other textures, but only when targeting the rendered target?
And I'm having issues applying the solution though. From your post, I see the solution should be the following:
// assuming MyColoredRectangle is a valid GraphicalUiElement
MyColoredRectangle.BlendState = Gum.BlendState.NonPremultipliedAddAlpha;
In the GumDimExample, I tried adding the following to the DimmerRuntime:
public override void AfterFullCreation()
{
this.BlendState = Gum.BlendState.NonPremultipliedAddAlpha;
base.AfterFullCreation();
}
Both BlendState and NonPremultipliedAddAlpha cannot be found.
Had all my questions answered