Possible issue with scaling

Hi there. I’ve been using Monogame for many years now making prototypes and such but I’m now working on a project fulltime and encountered what could possibly be an issue with scaling in Monogame.

First, I’ll post a mockup of what I actually want to render:

However, when I render a hollow rectangle using a single pixel from a texture atlas, it doesn’t scale the pixel properly when the value is large. In the below screenshot, you’ll see that the top and bottom lines of the rectangle, which are supposed to render lines to the width of 367 pixels, it instead renders it with a width of 366 pixels. For smaller values, this doesn’t seem to be a problem. For clarity, the below screenshot is not upscaled and I rendered the hollow rectangle in question as red:
issue_screen0

This may be a problem on my end but I think the maths I’m using to scale and render the pixel is correct. Any help or insight would very much be appreciated. :pray:

Hey @ThePsychefunk, would you be able to share/post your code for rending the hollow rect?

Or create a minimal example using your code and put in a git repo?

Without seeing the code for what you’re doing it’ll be hard to narrow down where the issue is (either your code or MonoGame).

Hey @Aristurtle , alright, here is the code drawing each side of the rectangle:

case Style.HollowRect:
    {
        // problem with monogame with this code
        Vector2 hori = new Vector2(_width / _base.Width, 1f / _base.Height);
        Vector2 vert = new Vector2(1f / _base.Width, (_height - 2f) / _base.Height);

        // Top
        _base.Render(RenderPosition, Origin / hori, Color * BaseOpacity * Opacity, hori, Rotation, Effects);
        // Left
        _base.Render(RenderPosition, Origin / vert - new Vector2(0, 1f / vert.Y), Color * BaseOpacity * Opacity, vert, Rotation, Effects);
        // Right
        _base.Render(RenderPosition, Origin / vert - new Vector2((_width - 1f) / vert.X, 1f / vert.Y), Color * BaseOpacity * Opacity, vert, Rotation, Effects);
        // Bottom
        _base.Render(RenderPosition, Origin / hori - new Vector2(0, _height - 1f), Color * BaseOpacity * Opacity, hori, Rotation, Effects);
    }
    break;

And here are the contents of the Render() function:

public void Render(Vector2 position, Vector2 origin, Color color, Vector2 scale, float rotation, SpriteEffects flip)
{
#if DEBUG
    if (Texture.IsDisposed)
        throw new Exception("Texture2D Is Disposed");
#endif
    Draw.SpriteBatch.Draw(Texture, position, ClipRect, color, rotation, origin - GetDrawOffset(flip), scale, flip, 0);
}

Please provide a stand-alone minimal example with hard coded values.

If the problem persist, then we can investigate further.
Otherwise it’s an issue with the calculations in your engine.

Is it just me or are you beginning rendering offscreen?

Zooming in you can clearly see the issue:

image

image

I think you have an origin offset issue…

origin - GetDrawOffset(flip)

Take a closer at this method and see what it is doing with the origin and offset…

I guess you are flipping the offset and forgetting to negate or add 1

There’s some stuff in there that we don’t get to see values for, but I supsect this is doing stuff similar to how Primitives2D renders lines (an old lib I worked on). If it is the same issue, it’s got to do with how the pixel is rotated. Since it draws at the origin, if rotates 90 degrees it’ll be where you want it to be, but if it rotates 270 degrees it’ll be one pixel to the left.

The easiest thing to try is to swap your y values and draw in the other direction. If you see a change, you know it’s this issue and if you don’t, it’s likely something else.

2 Likes

issue_screen1

@MrValentine , I am not rendering offscreen. In the above screenshot, I moved the rectangles a few pixels to the right and the issue persists.

As for the below code:

origin - GetDrawOffset(flip)

origin and “GetDrawOffset” both return (0, 0). GetDrawOffset is meant for sprites in atlases with trimmed transparency that are flipped.

Another thing I’ve noticed is that if I move the rectangle (the menu has a slide-in animation), the width of the top and bottom lines changes again by one pixel depending on the X position. This is very strange. Also, the larger the Width (effectively the Scale.X value) is, the bigger the gap between the intended width and the width of the rendered line (by just a few pixels).

In any case, I appreciate everyone’s input. I realise that a lot of code isn’t explained and looks suspicious. Later today I will create a new project, do some testing and report back. My apologies for the lack of explanation, this was my first time posting to the Monogame forums. :pray:

2 Likes

There is no right or wrong, there is only exploration.

Reporting back helps others, so, thanks for taking that approach.

1 Like

Alright, so I did a simple test where I added a texture to the content manager. This texture is 1001X1001 in size and there is a single white pixel in the middle of the image at (500, 500). I am using that single pixel to render the line seen in the below screenshot:

It is supposed to be 795 pixels in length but is rendering the line at only 793 pixels. Interestingly, when the aforementioned source texture is 1X1 in size and I use the white pixel contained as the source, the problem goes away and it renders it at the correct scaling of 795 pixels in width. So it seems to me that using a small source area within a larger texture seems to cause problems when scaling.

I started a new project and simply put the following code in Game1.cs:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.IO;

namespace ScaleTest
{
    public class Game1 : Game
    {
        private GraphicsDeviceManager _graphics;
        private SpriteBatch _spriteBatch;
        private Texture2D _pixelTexture;
        private Vector2 _pixelPosition = new Vector2(2, 80);
        private Vector2 _pixelScale = new Vector2(795, 1f);

        public Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        protected override void LoadContent()
        {
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            _pixelTexture = Content.Load<Texture2D>("pixel");
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            // TODO: Add your update logic here
            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                _pixelPosition.X += 1;
            }
            else if (Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                _pixelPosition.X -= 1;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Down))
            {
                _pixelPosition.Y += 1;
            }
            else if (Keyboard.GetState().IsKeyDown(Keys.Up))
            {
                _pixelPosition.Y -= 1;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.S))
            {
                _pixelScale.X += 1;
            }
            else if (Keyboard.GetState().IsKeyDown(Keys.A))
            {
                _pixelScale.X -= 1;
            }

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            // TODO: Add your drawing code here
            _spriteBatch.Begin(SpriteSortMode.Immediate,
                BlendState.AlphaBlend,
                SamplerState.PointClamp,
                DepthStencilState.None,
                RasterizerState.CullNone);

            _spriteBatch.Draw(_pixelTexture, _pixelPosition, new Rectangle(500, 500, 1, 1), Color.White, 0f, Vector2.Zero, _pixelScale, SpriteEffects.None, 0);

            _spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

If there is a setting or something obvious I am missing, please let me know. I am using the WindowsDX version 3.8.1.303 of Monogame. Any help and advice or further inquiries would be very much appreciated. :pray:

*EDIT: Ah I see you’re doing something differently here, using a large texture but taking a portion of that and stretching it out. I’m going to leave this post here for reference but let me play with that also.

This smells funky to me, but your code looks fine. I’m on a different version of MonoGame (3.7.1.189) and ran this test code…

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;

namespace Game1
{
    public class Game1 : Game
    {
        private GraphicsDeviceManager _graphics;
        private SpriteBatch _spriteBatch;

        private Texture2D _pixel;
        private SpriteFont _debugFont;

        public Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            this.IsMouseVisible = true;
        }

        protected override void Initialize()
        {
            _graphics.PreferredBackBufferWidth = 1280;
            _graphics.PreferredBackBufferHeight = 720;
            _graphics.ApplyChanges();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            _pixel = new Texture2D(_graphics.GraphicsDevice, 1, 1);
            _pixel.SetData<Color>(new Color[] { Color.White });

            _debugFont = Content.Load<SpriteFont>("Debug");
        }


        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            LineTestManager manager = new LineTestManager(_spriteBatch, _debugFont, _pixel);
            manager.AddTest(100);
            manager.AddTest(200);
            manager.AddTest(300);
            manager.AddTest(400);
            manager.AddTest(795);

            _spriteBatch.Begin();
            manager.Draw(gameTime);
            manager.StartPosition = new Vector2(100, 400);
            manager.Draw(gameTime);
            _spriteBatch.End();

            base.Draw(gameTime);
        }
    }

    public class LineTestManager
    {
        private class LineTest
        {
            public uint Length { get; private set; }
            public Color Colour { get; private set; }

            public LineTest(uint length, Color colour)
            {
                this.Length = length;
                this.Colour = colour;
            }
        }

        private SpriteBatch _spriteBatch;
        private SpriteFont _font;
        private Texture2D _pixel;

        private List<LineTest> _lines = new List<LineTest>();
        private uint _maxLength = 0;

        public Vector2 StartPosition { get; set; } = new Vector2(10, 10);

        public LineTestManager(SpriteBatch spriteBatch, SpriteFont font, Texture2D pixel)
        {
            _spriteBatch = spriteBatch ?? throw new ArgumentNullException();
            _font = font ?? throw new ArgumentNullException();
            _pixel = pixel ?? throw new ArgumentNullException();
        }

        public void AddTest(uint length)
        {
            _lines.Add(new LineTest(length, Color.Red));
            _maxLength = Math.Max(_maxLength, length);
        }

        public void Draw(GameTime gameTime)
        {
            Vector2 padding = new Vector2(_font.MeasureString("".PadLeft(_maxLength.ToString().Length + 2, '0')).X, _font.LineSpacing);

            for (int i = 0; i < _lines.Count; i++)
            {
                LineTest line = _lines[i];
                Vector2 position = this.StartPosition + new Vector2(0, i * padding.Y);

                _spriteBatch.DrawString(_font, line.Length.ToString() + ":", position, line.Colour);

                position.X += padding.X;
                position.Y += _font.LineSpacing / 2f;

                _spriteBatch.Draw(_pixel, new Rectangle((int)position.X, (int)position.Y, (int)line.Length, 1), line.Colour);
            }
        }
    }
}

… and everything is fine on my end. The lines are rendering the appropriate length, as measured by dragging a selection box around it in Paint .Net.

Can you give this code a try? You’ll need to make a new SpriteFont file called Debug.spritefont in your root content folder and add it to your Content project. It probably won’t matter but make sure you update the font to Consolas (<FontName>Consolas</FontName>).

When I create a new project, I’m using MonoGame Windows Project as well, so that might be worth exploring.

Let me know if you see different results here. For reference, here’s a screen cap of what I got.

2 Likes

Hi @Trinith , I appreciate you testing it on your end! I already tested using a single pixel texture of size 1x1 as the source and had 0 issues. It is indeed when using a small portion of a larger texture where problems occur, on my end anyways.

Yea, I caught that after I posted and added an edit above. Sorry about that :slight_smile:

I’m working on another test.

1 Like

Ok, I think I’ve tried to reproduce what you’re doing, except I generated the pixel source texture on the fly instead of having it a content image. You’ll still have to make the debug font (see my other post) but I now have this…

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;

namespace Game1
{
    public class Game1 : Game
    {
        private GraphicsDeviceManager _graphics;
        private SpriteBatch _spriteBatch;

        private Texture2D _pixel;
        private RenderTarget2D _pixelSource;
        private SpriteFont _debugFont;

        private Vector2 _pixelPos = new Vector2(2, 80);

        private LineTestManager _manager;
        private List<ILineTestManagerRenderer> _renderers = new List<ILineTestManagerRenderer>();

        public Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            this.IsMouseVisible = true;
        }

        protected override void Initialize()
        {
            _graphics.PreferredBackBufferWidth = 1280;
            _graphics.PreferredBackBufferHeight = 720;
            _graphics.ApplyChanges();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            _pixel = new Texture2D(_graphics.GraphicsDevice, 1, 1);
            _pixel.SetData<Color>(new Color[] { Color.White });

            _pixelSource = new RenderTarget2D(_graphics.GraphicsDevice, 1001, 1001);
            this.GraphicsDevice.SetRenderTarget(_pixelSource);
            this.GraphicsDevice.Clear(Color.Transparent);
            _spriteBatch.Begin();
            _spriteBatch.Draw(_pixel, _pixelPos, Color.White);
            _spriteBatch.End();
            this.GraphicsDevice.SetRenderTarget(null);

            _debugFont = Content.Load<SpriteFont>("Debug");

            _manager = new LineTestManager();
            _manager.AddTest(100);
            _manager.AddTest(200);
            _manager.AddTest(300);
            _manager.AddTest(400);
            _manager.AddTest(795);

            _renderers.Add(new LineTestManagerRendererBasic(_spriteBatch, _debugFont, _pixel, _manager));
            _renderers.Add(new LineTestManagerRendererOther(_spriteBatch, _debugFont, _pixelSource, _pixelPos, _manager));
        }


        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
           this.GraphicsDevice.Clear(Color.Black);
            _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp);

            foreach (var renderer in _renderers)
                renderer.Draw(gameTime);

            _spriteBatch.End();

            base.Draw(gameTime);
        }
    }

    public class LineTest
    {
        public uint Length { get; private set; }
        public Color Colour { get; private set; }

        public LineTest(uint length, Color colour)
        {
            this.Length = length;
            this.Colour = colour;
        }
    }

    public class LineTestManager
    {
        private List<LineTest> _lines = new List<LineTest>();

        public IReadOnlyList<LineTest> Lines { get { return _lines; } }
        public uint MaxLength { get; private set; } = 0;

        public void AddTest(uint length)
        {
            _lines.Add(new LineTest(length, Color.Red));
            this.MaxLength = Math.Max(this.MaxLength, length);
        }
    }

    public interface ILineTestManagerRenderer
    {
        Vector2 StartPosition { get; set; }
        void Draw(GameTime gameTime);
    }

    public class LineTestManagerRendererBasic : ILineTestManagerRenderer
    {
        private SpriteBatch _spriteBatch;
        private SpriteFont _font;
        private Texture2D _pixel;

        private LineTestManager _manager;

        public Vector2 StartPosition { get; set; } = new Vector2(10, 10);

        public LineTestManagerRendererBasic(SpriteBatch spriteBatch, SpriteFont spriteFont, Texture2D pixel, LineTestManager manager)
        {
            _spriteBatch = spriteBatch ?? throw new ArgumentNullException();
            _font = spriteFont ?? throw new ArgumentNullException();
            _pixel = pixel ?? throw new ArgumentNullException();
            _manager = manager ?? throw new ArgumentNullException();
        }

        public void Draw(GameTime gameTime)
        {
            Vector2 padding = new Vector2(_font.MeasureString("".PadLeft(_manager.MaxLength.ToString().Length + 2, '0')).X, _font.LineSpacing);

            for (int i = 0; i < _manager.Lines.Count; i++)
            {
                LineTest line = _manager.Lines[i];
                Vector2 position = this.StartPosition + new Vector2(0, i * padding.Y);

                _spriteBatch.DrawString(_font, line.Length.ToString() + ":", position, line.Colour);

                position.X += padding.X;
                position.Y += _font.LineSpacing / 2f;

                _spriteBatch.Draw(_pixel, new Rectangle((int)position.X, (int)position.Y, (int)line.Length, 1), line.Colour);
            }
        }
    }

    public class LineTestManagerRendererOther : ILineTestManagerRenderer
    {
        private SpriteBatch _spriteBatch;
        private SpriteFont _font;
        private Texture2D _pixelSource;
        private Vector2 _pixelPos;

        private LineTestManager _manager;

        public Vector2 StartPosition { get; set; } = new Vector2(10, 150);

        public LineTestManagerRendererOther(SpriteBatch spriteBatch, SpriteFont spriteFont, Texture2D pixelSource, Vector2 pixelPos, LineTestManager manager)
        {
            _spriteBatch = spriteBatch ?? throw new ArgumentNullException();
            _font = spriteFont ?? throw new ArgumentNullException();
            _pixelSource = pixelSource ?? throw new ArgumentNullException();
            _pixelPos = pixelPos;
            _manager = manager ?? throw new ArgumentNullException();
        }

        public void Draw(GameTime gameTime)
        {
            Vector2 padding = new Vector2(_font.MeasureString("".PadLeft(_manager.MaxLength.ToString().Length + 2, '0')).X, _font.LineSpacing);

            for (int i = 0; i < _manager.Lines.Count; i++)
            {
                LineTest line = _manager.Lines[i];
                Vector2 position = this.StartPosition + new Vector2(0, i * padding.Y);

                _spriteBatch.DrawString(_font, line.Length.ToString() + ":", position, line.Colour);

                position.X += padding.X;
                position.Y += _font.LineSpacing / 2f;

                Vector2 pixelScale = new Vector2(line.Length, 1);
                _spriteBatch.Draw(
                    _pixelSource,
                    new Vector2((int)position.X, (int)position.Y),
                    new Rectangle((int)_pixelPos.X, (int)_pixelPos.Y, 1, 1),
                    Color.Red,
                    0f,
                    Vector2.Zero,
                    pixelScale,
                    SpriteEffects.None,
                    0
                );
            }
        }
    }
}

It’s now generating a 1001x1001 texture and sticking a pixel in it, then using that full size texture as the source and a sourceRectangle at the location of the pixel to get the pixel. I think I’m scaling in the same way you are and it’s actually seemingly rendering the lines the right size.

Do you maybe wanna give this a try on your end and see if you get a different result?

I’ve gotta step away for a while but I’ll try to remember to check this later.

2 Likes

Hi @Trinith. My apologies for the late response.

I have replicated your test (copy and pasted your code) and I got the below result:

The above 5 lines are correct in size, but with the bottom 5 lines the scaling is less accurate the longer the line becomes:
100: 100 pixels
200: 200 pixels
300: 299 pixels
400: 399 pixels
795: 793 pixels

Indeed, it seems like using a portion of a larger texture and upscaling that causes scaling inaccuracies.

Interesting! So now we have a point where the same code on your machine is producing a different result than on my machine. That’s something! At least you know it’s not a code issue :smiley:

Some things that come to mind…

  1. I mentioned before but I’m on a different (older) version of MonoGame, which is 3.7.1.189. I did some quick digging and it looks like you can find the older version here: MonoGame 3.7.1
    It might be worthwhile downloading that version, or at the very least getting your local project to run those dlls exclusively, to see if the latest version of MonoGame has broken something. Another way to try this is for you to just test with binaries that I built, which include my version of the MG dlls. I’ve temporarily hosted it here.
  2. I want to make sure we’re making the same project. I know that there’s a difference sometimes in DX and OpenGL. I’m making my project using MonoGame Windows Project in the New Project Wizard, which says it’s DirectX. There are a lot of other options, are you using the same one as me?
  3. I notice your windows style is different than mine and that you don’t actually have any borders at all on the left/right. Your canvas size still is 1280x720, which is the size I intend, but it still jumps out at me. Did you do anything specifically to disable some window decorations? Is your desktop scaling set to 100%? Just stuff like that… I think MonoGame is pretty good about it, but I’ve worked in stuff before where that made a difference. Honestly, this last one is grasping at straws.

Anyway, take a look. I thnk especially running my binaries to see if they give the result you have or the result I have is a good test. See what happens and we can go from there!

1 Like

Alright, I downloaded the files you hosted on google drive, ran it (out of curiosity), and the issue was still persisting. I’m not super knowledgeable about this stuff, but it seems like there’s an issue with my machine then? I’m assuming when running your program it’s running version 3.7.1.189 and not the version I’m currently using for any of my projects. Let me know if I’m wrong on this (I’m not a super experienced developer). I’ll post a screenshot of your program below:

Yes, I’m specifically using the “Monogame Windows Project” from the project wizard since I have other issues with the cross platform version that I won’t get into now.

Oh, this is because I cut out the windows border without realising it when I cropped the image. In the above screenshot of your program I simply took the screenshot using the windows snipping tool, so the borders should be included. :+1:

In any case, I’m assuming my machine is the reason this issue is occurring. Here are my specs:
Asus ROG Zephyrus G14
AMD Ryzen 9 4900HS with Radeon Graphics 3.00 GHz
16.0 GB (15.4 GB 使用可能)
64-bit operating system

Again, thank you so much for conducting these tests! I think I might just find a way to work around the issue and continue with development as usual.

Ahhh gotcha! Quick tip, if you hold alt and press print-screen, it will capture the entirety of the window that is in focus :slight_smile: Anyway, this isn’t the issue here so I think it’s ok. Did you verfify your desktop scaling is at 100% though?

That’s pretty telling… in that I think we can safely assume that whatever the issue is, it’s on your PC specically and not actually a problem with MonoGame. While maybe not specifically helpful to you, that’s something at least!

I’m reasonably sure that an application will always look in its local folder first for a dll before it expands out to system paths, but I’m not 100% certain. Maybe someone else following this thread could back me up on this? If you wanted to be 100% certain, you could remove your current version of MonoGame from your PC and install 3.7.1.x and check, but that’s up to you.

At this point, I’m actually not sure what to tell you… it could be your graphics card or drivers, it could be OS settings, I have no idea! All we know is that the issue shows up only on your machine. Out of curiosity, do you have another PC that you can test on?

If you intend to release to others, maybe be cautious here. If you can use the approach of using a single 1x1 pixel texture to draw your lines, that would be preferrable since that seems to work for both of us, but if you need to use a larger texture and scale then you could probably fix it by fudging offsets and lengths by some factor. Unfortunately, this will make it not work correctly for others :frowning:

I’m sorry we couldn’t find a way to resolve this for you! If you think of any other tests you want to try and need someone to help out, feel free to @ me. I don’t always check this place regularly but that will send me an email notification I believe.

Good luck!

1 Like
  1. Turn off multisample anti aliasing and try it.
  2. Point on for your sampling. (Can be point clamp wrap or mirror)
1 Like

I came intrigued from another thread and I also tried the provided tester on two laptops. On each of them, the lines seem to be drawn correctly:

Specs

  1. Intel® Celeron® N3050 @ 2.48 GHz with Intel Integrated Graphics
    4 GB RAM
    64 bit OS

  2. AMD Ryzen 7 5800H with Radeon Graphics @ 3.20 GHz
    Nvidia RTX 3060
    64 GB RAM
    64 bit OS

This indeed looks like a problem outside your code, but what I’d suggest is to don’t bother too much with it if you can’t figure it out in a reasonable time. There’s probably a floating point operation failing to provide correct precision somewhere. Maybe others will pinpoint the exact issue which indeed seems a platform one.

For such situations I usually have a class that provides me a color texture that I pick up with another class meant to draw primitives, here, maybe this Texture Color class may be of help since I understand that picking up color pixels from the margin of the texture works fine:

namespace Your_Project_Namespace
{
    /// <summary>
    /// Initializes and allows use of solid colors as Texture2D in order to be drawn arbitrarly.
    /// Every new color used is cached
    /// </summary>
    public static class TextureColors
    {
        private static Dictionary<Color, Texture2D> textureColors = new Dictionary<Color, Texture2D>();

        public static void InitializeTextureColors()
        {
            AddColorTexture(DialogBackground);
        }

        public static Texture2D GetTextureColor(Color color)
        {
            if (!textureColors.ContainsKey(color))
                AddColorTexture(color);

            return textureColors[color];
        }

        private static void AddColorTexture(Color color)
        {
            textureColors.Add(color, GetColorTexture(color));
        }

        private static Texture2D GetColorTexture(Color color)
        {
            Texture2D pixel = new Texture2D(Renderer.GetGraphics().GraphicsDevice, 1, 1);	// Point to your graphics device here
            pixel.SetData(new[] { color });

            return pixel;
        }
    }
}

Hope this helps, cheers!

1 Like

My apologies for the late response. I have been very busy these past few days.

I will eventually conduct tests and see what I can do. If I can’t manage to solve the problem outright, I might just change how I export/create textures for certain UI elements.

Thank you everyone for your helpful responses and words of encouragement! :muscle:
Once things have calmed down, I might report back to this thread for record-keeping purposes (and for those who might be interested).

2 Likes