stanoddly / GameKit

Apache License 2.0
1 stars 0 forks source link

Transparent image has artifacts with StbImageSharp #13

Closed stanoddly closed 1 week ago

stanoddly commented 1 week ago

When I tried to introduce textures in #7, I noticed that the implementation by default shows this:

image

However this is the original :exploding_head: image

Likely there is some multisampling with blending happening, even though it's not configured (default values, all is 0) so it should be disabled.

Anyway I should provide some pipeline setup.

stanoddly commented 1 week ago

I'm puzzled. It seems like it's in fact something with the original image and StbImageSharp, so SDL3 setup works as expected. I managed to find it by accident, I did some changes in the image in GIMP, exported to a file and voilà, it worked!

I did check if the image is loaded properly, I checked a single pixel which is shown at (7, 21) as while. I could have miscalculated the position in the byte array.

Anyway I mistakenly thought it has a higher priority, but it doesn't in the end.

stanoddly commented 1 week ago

Got it! The original image has nonempty RGB even if it's fully transparent. And because my code doesn't handle transparency, it showed weird artifacts. StbImageSharp works as expected.

An investigation code snippet:

using System.IO.Abstractions;
using StbImageSharp;

IFileSystem fileSystem = new FileSystem();

ImageResult imageResultBad;
using (Stream fileStream = fileSystem.FileStream.New("Content/Earth_bad.png", FileMode.Open, FileAccess.Read, FileShare.Read))
{
   imageResultBad = ImageResult.FromStream(fileStream, ColorComponents.RedGreenBlueAlpha);
}

ImageResult imageResultGood;
using (Stream fileStream =
       fileSystem.FileStream.New("Content/Earth_good.png", FileMode.Open, FileAccess.Read, FileShare.Read))
{
   imageResultGood = ImageResult.FromStream(fileStream, ColorComponents.RedGreenBlueAlpha);
}

ReadOnlySpan<byte> dataBad = imageResultBad.Data;
ReadOnlySpan<byte> dataGood = imageResultGood.Data;

if (dataBad.Length != dataGood.Length)
{
       throw new Exception("images have different sizes");
}

string[] colorNames = ["red", "green", "blue", "alpha"];
int offset = 0;
Console.WriteLine($"bytes count: {dataBad.Length}");
foreach (string colorName in colorNames)
{
   Console.WriteLine($"name: {colorName}");       
   int mismatchCount = 0;

   for (int i = offset; i < dataBad.Length; i+=4)
   {
       if (dataBad[i] != dataGood[i])
       {
           mismatchCount++;
       }
   }
   Console.WriteLine($"  mismatch %: {(float)mismatchCount / dataBad.Length * 100.0f} %");
   offset++;
}

This is the result:

bytes count: 16384
name: red
  mismatch %: 1.0681152 %
name: green
  mismatch %: 1.0681152 %
name: blue
  mismatch %: 1.0681152 %
name: alpha
  mismatch %: 0 %