Texture2D distortion with additive blend

Hello everyone,

This is my first attempt to derive a Texture2D programmatically. The idea is simple, I try to generate by code a texture that should look like this :
image.
I am working on the inside of the texture.

This is what I achieved so far :
image

As you can see, on the “diagonals”, I have distortions. If we look closer :

image

If I run the same code but without a saturation on the alpha channel, I obtained the figure below where we can easily see the artefacts/distortions.
image

To be complete, I have written a small demo with a 1/4th of the square. The code is below.

Do you know what I need to change to ensure I have no distortion ? I am sure it should be somewhere in the shaders and how they are drawn on the screen…

Thank you !

public class App : Game
{
  private SpriteBatch spriteBatch;
  private RenderTarget2D target;
  private readonly GraphicsDeviceManager graphics;

  public App()
  {
      graphics = new GraphicsDeviceManager(this);
  }

 protected override void Initialize()
 {
     base.Initialize();
     graphics.PreferredBackBufferWidth = Constants.WINDOW_WIDTH;
     graphics.PreferredBackBufferHeight = Constants.WINDOW_HEIGHT;
     textureTest = Create(GraphicsDevice, 300, 300);

     spriteBatch = new SpriteBatch(GraphicsDevice);

     target = new RenderTarget2D(
         GraphicsDevice,
         Constants.VIRTUAL_WIDTH,
         Constants.VIRTUAL_HEIGHT,
         false,
         SurfaceFormat.Color,
         DepthFormat.None, GraphicsDevice.PresentationParameters.MultiSampleCount,
         RenderTargetUsage.DiscardContents
     );
 }

  protected override void Draw(GameTime gameTime)
  {
      graphics.GraphicsDevice.SetRenderTarget(target);
      GraphicsDevice.Clear(Color.Black);
      spriteBatch.Begin(blendState: BlendState.Additive);
      spriteBatch.Draw(textureTest, new Vector2(50, 50), Color.Yellow);
      spriteBatch.End();
    
      graphics.GraphicsDevice.SetRenderTarget(null);
      spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive);
      var dst = new Rectangle(0, 0, Window.ClientBounds.Width, Window.ClientBounds.Height);
      spriteBatch.Draw(target, dst, Color.White);
      spriteBatch.End();
  }

  private Texture2D Create(GraphicsDevice device, int width, int height)
  {
      Debug.Assert(width == height);

      // initialize a texture
      Texture2D texture = new Texture2D(device, width, height);

      var data = new float[width * height];
      var granularity = 1f / (float)height;

      for (int i = 0; i < height; i++)
      {
          for (int j = i; j < width; j++)
          {
              data[i * width + j] = 1f - granularity * i;
          }

          for (int k = i; k < height; k++)
          {
              data[k * width + i] = 1f - granularity * i;
          }
      }

      texture.SetData(data.Select(d => new Color(Color.White, d)).ToArray());

      return texture;
  }
}
    public class Constants
    {
        public const int WINDOW_WIDTH = 1024;
        public const int WINDOW_HEIGHT = 768;
        public const int VIRTUAL_WIDTH = 640;
        public const int VIRTUAL_HEIGHT = 480;
    }

hi Renaudyes,

Without thinking too much into the details, since you are using additive blending you are actually writing a diagonal artifact on each corner through the k=i loop, if it is not additive it will not cause this problem but since it is, you need to change that one, you can try to remove that loop and see your output, I think you are writing in those areas many times since i can see full yellow around the borders. Since your loop goes in square pattern it creates the black areas. I think you can avoid writing in the same locations so many times by calculating the color value according to the step or width if you want and make it darker and transparent as you move inwards or outwards, that will make your algorithm faster too instead of so many nested loops

Hello,

Thank your for your answer !
In the function Create where I define my Texture2D (and where the k=i loop you mentioned is), there is nothing related to the additive blending yet.
If my code was wrong I would write the data[i] float which instead of “adding” it.

I ran my code with a 20*20 texture and this is what the data contains :


You can see that the diagonal (yellow) makes sense and the black lines should not appear.

One remark, maybe I was not precise enough but the square you based your assumptions on is not created thanks to the provided code. That’s why you have that border.
The provided code generates a 1/4 of the square without any border such as the picture below where you see the same artifacts.
image

Made some gradient corners in paint just:
Corner

Mirrored and flipped to make a box:
Box

The visual artifacts are still there. An optical illusion maybe instead of a coding issue. Haven’t read it but here’s a Stack Overflow link with a similar issue:

(Live online demo from Stack Overflow link) GLSL Sandbox

Hello,

Thank you. I’ve tried several approaches and it seems you are right !
So it means that to match the first picture of my post I have two options :

  1. Create a texture using Photoshop or something similar,
  2. Using shaders.

I’m wondering what is the most effective (performance wise). I assume the texture is used by a shader under the hood. So it makes no real difference right ?