Загруженная текстура с использованием ImageSharp отображает белый цвет (opentk)

После загрузки изображения с помощью ImageSharp, а затем загрузки его в vram, он отображает только белый квад. Я понятия не имею, что я мог сделать неправильно, это первый раз, когда я работаю с opentk кроссплатформенным, не используя abel BitmapData,

Класс текстуры:

public struct Texture2D
{
    public readonly int Handle;
    public readonly int Width;
    public readonly int Height;

    public Texture2D(int[] data, int width, int height)
    {
        Width = width;
        Height = height;

        GL.Enable(EnableCap.Texture2D);
        GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
        Handle = GL.GenTexture();
        GL.BindTexture(TextureTarget.Texture2D, Handle);

        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

        unsafe
        {
            fixed (int* dataptr = data)
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, (IntPtr)dataptr);
            GL.BindTexture(TextureTarget.Texture2D, 0);
        }

        GL.Disable(EnableCap.Texture2D);
    }

    public static implicit operator int(Texture2D texture) => texture.Handle;

    public static Texture2D FromFile(string file) => FromImage(Image.Load(Path.Combine("resources", file)));

    public static Texture2D FromImage(Image<Rgba32> image)
    {
        var xL = image.Width;
        var yL = image.Height;
        var data = new int[image.Width * image.Height];
        for (var x = 0; x < xL; x++)
            for (var y = 0; y < yL; y++)
                data[y * xL + x] = image[x, y].R << 24 | image[x, y].G << 16 | image[x, y].B << 8 | image[x, y].A;
        return new Texture2D(data, image.Width, image.Height);
    }
}

Rendering:

GL.Clear(ClearBufferMask.ColorBufferBit);
GL.PushMatrix();
GL.Begin(PrimitiveType.Quads);
{
    GL.BindTexture(TextureTarget.ProxyTexture2D, loadingTex.Handle);

    var x = app.Width - loadingTex.Width;
    var x2 = app.Width;
    var y = 0;
    var y2 = loadingTex.Height;

    GL.TexCoord2(0, 0);
    GL.Vertex2(x, 0);

    GL.TexCoord2(0, 1);
    GL.Vertex2(x2, 0);

    GL.TexCoord2(1, 1);
    GL.Vertex2(x2, y2);

    GL.TexCoord2(1, 0);
    GL.Vertex2(x, loadingTex.Height);
}
GL.End();
GL.PopMatrix();
GL.Flush();
SwapBuffers();

loadingTex статическая переменная, ссылающаяся на текстуру

1 ответ

Решение

Это только ядро ​​.net, оно работает для.net framework, но есть лучшее решение.

После нескольких исследований я нашел свой ответ.

Краткий ответ: GL.TexImage2D принимает массив всех цветов в вашем изображении.

Длинный ответ:

1. Получение такого массива из изображения.

Ну, на самом деле это довольно просто. Но для этого нужно использовать библиотеку ImageSharp от SixLabors, но если вы найдете библиотеку, то работает аналогичным образом, не стесняйтесь использовать это:)

Первый шаг - загрузить изображение в виде Image<Rgba32>, Затем вам нужно поместить данные изображения в массив 1D (int). Каждый int должен быть структурирован как этот ABGR.

Пример:

var xL = image.Width;
var yL = image.Height;
var data = new int[image.Width * image.Height];
for (var x = 0; x < xL; x++)
    for (var y = 0; y < yL; y++)
    {
        var color = image[x, y];
        data[y * xL + x] = (color.A << 24) | (color.B << 16) | (color.G << 8) | (color.R << 0);
    }

Этот код повторяет каждый пиксель изображения и записывает его в массив int.

2. Загрузка его в память (с использованием небезопасного кода) (это касается только GL.TexImage2D)

Теперь нам нужно получить указатель на этот массив с помощью fixed Постулаты

fixed (int* dataptr = data)

Это утверждение нуждается в теле!

GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr) dataptr);

И этот загружает его в VRam. Давайте пропустим первые 2 аргумента, которые мне не понадобятся, чтобы объяснить их для этой проблемы. Третий аргумент PixelInternalFormat.Rgba говорит графическому процессору, как хранить каждый пиксель в V-Ram. Следующие 2 сообщают графическому процессору размеры изображения. Аргумент 6 пока не важен. Следующий аргумент PixelFormat.Rgba сообщите графическому процессору, в каком формате вы передаете пиксели. Теперь у нас есть PixelType.UnsignedByte что говорит графическому процессору, насколько велика одна часть пикселя (красный, синий, зеленый и альфа - все части пикселя), а не размер самого пикселя. И, наконец, передача данных сама по себе как IntPtr, что по сути является универсальным указателем, который может быть передан в собственную библиотеку.

В заключение: я надеюсь, что ответ не был запутанным, но, надеюсь, вы поняли, как это работает. Это мой первый расширенный ответ, и я не очень опытен в этом. Я надеюсь, что это поможет вам:)

Другие вопросы по тегам