使用 ImageSharp 加载的纹理显示白色 (opentk)
Loaded texture using ImageSharp displays white (opentk)
在 ImageSharp 的帮助下加载图像并将其加载到 vram 后,它只呈现一个白色四边形。我基本上不知道我做错了什么,这是第一次使用 opentk crossplatform 而不是 beeing abel 使用 BitmapData
.
纹理class:
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);
}
}
渲染:
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
是引用纹理的静态变量
This is .net core only, it works for .net framework, but there are better solution.
经过大量研究,我找到了答案。
简短回答:GL.TexImage2D
接受图像中所有颜色的数组。
长答案:
- 从图像中获取这样的数组。
嗯,其实这很容易。但这需要您使用 SixLabors 的 ImageSharp 库,但如果您找到一个以类似方式工作的库,请随意使用它。
第一步是将图像加载到Image<Rgba32>
。
然后您需要将图像数据放入一维(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 数组。
- 将其加载到内存中(使用不安全代码)(这仅涵盖
GL.TexImage2D
)
现在我们需要使用 fixed
语句
获取指向该数组的指针
fixed (int* dataptr = data)
This statement needs a body!
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr) dataptr);
并且这个将它加载到 VRAM 中。让我们跳过前 2 个参数,我不需要为这个问题解释它们。第三个参数 PixelInternalFormat.Rgba
告诉 gpu 如何将每个像素存储到 V-Ram 中。接下来的 2 个告诉 gpu 图像的尺寸。论点 6 目前并不重要。下一个参数 PixelFormat.Rgba
告诉 gpu 您传递像素的格式。
现在我们有 PixelType.UnsignedByte
是什么告诉 gpu 像素的一部分有多大(红色、蓝色、绿色和 Alpha 都是像素的一部分),而不是像素本身的大小。最后将数据自身作为 IntPtr 传递,这基本上是一个可以传递给本机库的通用指针。
在 ImageSharp 的帮助下加载图像并将其加载到 vram 后,它只呈现一个白色四边形。我基本上不知道我做错了什么,这是第一次使用 opentk crossplatform 而不是 beeing abel 使用 BitmapData
.
纹理class:
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);
}
}
渲染:
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
是引用纹理的静态变量
This is .net core only, it works for .net framework, but there are better solution.
经过大量研究,我找到了答案。
简短回答:GL.TexImage2D
接受图像中所有颜色的数组。
长答案:
- 从图像中获取这样的数组。
嗯,其实这很容易。但这需要您使用 SixLabors 的 ImageSharp 库,但如果您找到一个以类似方式工作的库,请随意使用它。
第一步是将图像加载到Image<Rgba32>
。
然后您需要将图像数据放入一维(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 数组。
- 将其加载到内存中(使用不安全代码)(这仅涵盖
GL.TexImage2D
)
现在我们需要使用 fixed
语句
fixed (int* dataptr = data)
This statement needs a body!
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr) dataptr);
并且这个将它加载到 VRAM 中。让我们跳过前 2 个参数,我不需要为这个问题解释它们。第三个参数 PixelInternalFormat.Rgba
告诉 gpu 如何将每个像素存储到 V-Ram 中。接下来的 2 个告诉 gpu 图像的尺寸。论点 6 目前并不重要。下一个参数 PixelFormat.Rgba
告诉 gpu 您传递像素的格式。
现在我们有 PixelType.UnsignedByte
是什么告诉 gpu 像素的一部分有多大(红色、蓝色、绿色和 Alpha 都是像素的一部分),而不是像素本身的大小。最后将数据自身作为 IntPtr 传递,这基本上是一个可以传递给本机库的通用指针。