Hi there. I am fairly novice with Monogame but have done enough searching on my own without finding answers to warrant making a post here, I think.
I am working on a UI system that creates colored textures from scratch by calling SetData on Texture2D.
I want to be able to make rounded corners dynamically based on a radius value. This is what I have so far (it is incomplete, and only changes the top left corner so far):
public static void ApplyCorners(Texture2D texture, int radius)
{
Vector2 origin = new Vector2(radius, radius);
Color[] data = new Color[radius * radius];
texture.GetData(0, new Rectangle(0, 0, radius, radius), data, 0, radius * radius);
Color[,] rawDataAsGrid = new Color[radius, radius];
for (int row = 0; row < radius; row++)
{
for (int column = 0; column < radius; column++)
{
Vector2 current = new Vector2(row, column);
float distance = Vector2.Distance(current, origin);
float margin = radius - distance;
Color color = data[row * radius + column];
if (margin < 0)
{
if (margin < -1) data[row * radius + column] = Color.Transparent;
else data[row * radius + column] = new Color(color.R, color.G, color.B, (byte)(byte.MaxValue * ((1 + margin) / 5)));
}
else if (margin < 5)
{
data[row * radius + column] = new Color(color.R, color.G, color.B, (byte)(byte.MaxValue * (margin / 5)));
}
}
}
texture.SetData<Color>(0, new Rectangle(0, 0, radius, radius), data, 0, radius * radius);
And that gets me this result:
As you can see my algorithm for rounding the corners is correct but regions where I would expect partial transparency are still fully opaque.
Changing
if (margin < -1) data[row * radius + column] = Color.Transparent;
to
if (margin < -1) data[row * radius + column] = new Color(color.R, color.G, color.B, (byte)(byte.MaxValue * ((1 + margin) / 5)));
gets me this:
Which isn’t rendering any transparency in the corner as I would expect it to.
My spriteBatch code is as follows (these two methods are called in succession):
private void DrawToRenderTarget(SpriteBatch spriteBatch)
{
GraphicsDeviceManager.GraphicsDevice.SetRenderTarget(RenderTarget);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
RenderablesInScope.ForEach((r) => r.Draw(spriteBatch));
spriteBatch.End();
GraphicsDeviceManager.GraphicsDevice.SetRenderTarget(null);
}
private void DrawRenderTarget(SpriteBatch spriteBatch)
{
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
GraphicsDeviceManager.GraphicsDevice.Clear(Color.Red);
spriteBatch.Draw(RenderTarget, ViewPort, Camera.ViewRectangle, Color.White);
spriteBatch.End();
}
and changing BlendState to NonPremultiplied
gives me this result (with the previous change in place):
This leads me to believe that something about the way I am creating my texture (I am not loading it from the contend pipeline but creating it manually) is not pre multiplying alpha and causing the alpha not to work in AlphaBlend mode.
Am I correct? And what can I do to solve this?