Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Corrupted Programmatic Texture  (Read 5856 times)

0 Members and 1 Guest are viewing this topic.

Drakmyth

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Corrupted Programmatic Texture
« on: September 16, 2013, 06:42:49 am »
I have been wracking my brain for the past day or so trying to figure this one out, so I thought maybe someone here would be able to see what I'm doing wrong. I'm trying to create a texture that, given a point, will create a circular gradient emanating from that point. I originally had this implemented in a shader, but when I couldn't get it to display properly I re-implemented it in software to make sure I had the logic right. Apparently I don't.

Knowing that Image.SetPixel is a very slow operation, I attempted to create a 2D Color array and pass that in directly instead.

public static class Program
{
    private static readonly Color CornflowerBlue = new Color(100, 149, 237);
    private static readonly Vector2i WindowSize = new Vector2i(1280, 720);

    public static void Main()
    {
        RenderWindow window = new RenderWindow(new VideoMode((uint)WindowSize.X, (uint)WindowSize.Y), "SFML Window");
        window.Closed += (sender, eventArgs) => window.Close();

        Color[,] sourceMap = new Color[WindowSize.X, WindowSize.Y];
        Vector2f startPointInTexels = new Vector2f(0, 0);

        for(int y = 0; y < sourceMap.GetLength(1); y++)
        {
            for (int x = 0; x < sourceMap.GetLength(0); x++)
            {
                Vector2f currentPixelInTexels = new Vector2f(x / (float)WindowSize.X, y / (float)WindowSize.Y);

                float dist = Distance(currentPixelInTexels.X, currentPixelInTexels.Y, startPointInTexels.X, startPointInTexels.Y);
                dist = Math.Min(dist, 1.0f);

                sourceMap[x, y] = new Color((byte)(dist * byte.MaxValue), (byte)(dist * byte.MaxValue), (byte)(dist * byte.MaxValue), 255);
            }
        }
        Sprite sprite = new Sprite(new Texture(new Image(sourceMap)));

        while (window.IsOpen())
        {
            window.DispatchEvents();
            window.Clear(CornflowerBlue);
            window.Draw(sprite);
            window.Display();
        }
    }

    private static float Distance(float x1, float y1, float x2, float y2)
    {
        float x = Math.Abs(x2 - x1);
        float y = Math.Abs(y2 - y1);

        return (float)Math.Sqrt(x * x + y * y);
    }
}
 

But this results in the attached image. From what I can tell, it looks like the underlying OpenGL texture is using an incorrect stride or format, but I couldn't find any way to change these through SFML.NET's API. Does anyone know what I'm missing or doing wrong here?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Corrupted Programmatic Texture
« Reply #1 on: September 16, 2013, 07:46:32 am »
It may be a bug in the Image(Color[][]) constructor. You can check its implementation if you want.
« Last Edit: September 16, 2013, 02:34:27 pm by Laurent »
Laurent Gomila - SFML developer

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Corrupted Programmatic Texture
« Reply #2 on: September 16, 2013, 02:17:19 pm »
There is a bug in the Image(Color[,]) constructor. The problem stems from attempting to pass a 2D array of color structs as a C style pointer array. Looking around I found ways to pass 2D arrays of integers as a C style pointer array (read here). I'm still looking at a way of passing the color struct array, but for now just copy your color array directly into a byte array.

This code works and provides the expected result, but is slower due to the extra copy.

            RenderWindow window = new RenderWindow(new VideoMode((uint)WindowSize.X, (uint)WindowSize.Y), "SFML Window");
            window.Closed += (sender, eventArgs) => window.Close();

            Color[,] sourceMap = new Color[WindowSize.X, WindowSize.Y];
            Vector2f startPointInTexels = new Vector2f(0, 0);

            for (int y = 0; y < sourceMap.GetLength(1); y++)
            {
                for (int x = 0; x < sourceMap.GetLength(0); x++)
                {
                    Vector2f currentPixelInTexels = new Vector2f(x / (float)WindowSize.X, y / (float)WindowSize.Y);

                    float dist = Distance(currentPixelInTexels.X, currentPixelInTexels.Y, startPointInTexels.X, startPointInTexels.Y);
                    dist = Math.Min(dist, 1.0f);

                    sourceMap[x, y] = new Color((byte)(dist * byte.MaxValue), (byte)(dist * byte.MaxValue), (byte)(dist * byte.MaxValue), 255);
                }
            }
            byte[] pixelarray = new byte[WindowSize.X * WindowSize.Y * 4];
            int pos = 0;
            for (int y = 0; y < sourceMap.GetLength(1); y++)
            {
                for (int x = 0; x < sourceMap.GetLength(0); x++)
                {
                    pixelarray[pos] = sourceMap[x, y].R;
                    pixelarray[pos + 1] = sourceMap[x, y].B;
                    pixelarray[pos + 2] = sourceMap[x, y].G;
                    pixelarray[pos + 3] = sourceMap[x, y].A;
                    pos += 4;
                }
            }
            Sprite sprite = new Sprite(new Texture(new Image((uint)WindowSize.X, (uint)WindowSize.Y, pixelarray)));

            while (window.IsOpen())
            {
                window.DispatchEvents();
                window.Clear(CornflowerBlue);
                window.Draw(sprite);
                window.Display();
            }
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Corrupted Programmatic Texture
« Reply #3 on: September 16, 2013, 02:44:26 pm »
Quote
The problem stems from attempting to pass a 2D array of color structs as a C style pointer array
According to the MSDN documentation, using the fixed keyword on a multi-dimensionnal arrays gives a pointer to a one-dimensionnal array (elements are contiguous in memory). So the current implementation should work.
Laurent Gomila - SFML developer

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Corrupted Programmatic Texture
« Reply #4 on: September 16, 2013, 03:26:23 pm »
According to the MSDN documentation, using the fixed keyword on a multi-dimensionnal arrays gives a pointer to a one-dimensionnal array (elements are contiguous in memory). So the current implementation should work.

Hmmm, the current implementation should work. Even in a test I wrote this worked correctly (see below). For now I will keep trying different things.

public static void Main()
        {   //   x,y
            Color[,] colarray = new Color[2, 2];
            colarray[0, 0] = new Color(0, 1, 2, 3);
            colarray[1, 0] = new Color(4, 5, 6, 7);
            colarray[0, 1] = new Color(8, 9, 10, 11);
            colarray[1, 1] = new Color(12, 13, 14, 15);
            byte[] lineararray = new byte[16];
            unsafe
            {
                fixed (Color* colptr = colarray)
                {
                    //Copy our fixed "unmanaged" array to a managed array
                    //result should contain the numbers 0-15
                    System.Runtime.InteropServices.Marshal.Copy(new IntPtr(colptr), lineararray, 0, 16);
                }
            }
            for (int i = 0; i < 16; i++)
            {
                Console.Write(lineararray[i] + " ");
            }
        }
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Corrupted Programmatic Texture
« Reply #5 on: September 16, 2013, 03:53:02 pm »
Ah, I'm glad it works for you, because I'm sure that I had tested this implementation in depth. Whenever some voodoo .Net code is involved, I test the code a lot to make sure that it is working as expected.
Laurent Gomila - SFML developer

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Corrupted Programmatic Texture
« Reply #6 on: September 16, 2013, 03:59:41 pm »
Ah, I'm glad it works for you, because I'm sure that I had tested this implementation in depth. Whenever some voodoo .Net code is involved, I test the code a lot to make sure that it is working as expected.

The test I wrote works (prints the byte values in proper order), but the actual Image(Color[,]) constructor does not work for me  :(
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Corrupted Programmatic Texture
« Reply #7 on: September 16, 2013, 04:44:54 pm »
Ah. It seems like I need to do new tests. Maybe there's an error in CSFML.
Laurent Gomila - SFML developer

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Corrupted Programmatic Texture
« Reply #8 on: September 16, 2013, 05:00:51 pm »
Ah. It seems like I need to do new tests. Maybe there's an error in CSFML.

I sent you a PM regarding this issue (to avoid spamming this thread) explaining what the issue is.

To sum it up, the C# fixed statement orders the single dimension C style array with each column together instead of the RGBA format with each row together.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Corrupted Programmatic Texture
« Reply #9 on: September 16, 2013, 10:12:53 pm »
It's fixed. Thanks for your help :)
Laurent Gomila - SFML developer

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Corrupted Programmatic Texture
« Reply #10 on: September 17, 2013, 12:21:58 am »
It's fixed. Thanks for your help :)

Just tested the changes and it works  :D Thanks for the speedy fix.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Drakmyth

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Corrupted Programmatic Texture
« Reply #11 on: September 17, 2013, 11:39:07 pm »
Well it's good to know that I wasn't missing anything I suppose. Thanks for working out what the problem was and for coming up with a fix so quickly.