如何将像素从简单的字节数组上传到OpenGl纹理?
我使用的是glTexImage2D,我得到的只是一个白色的矩形,而不是像素化的纹理。第9个参数(指向像素数据的32位指针)是这个问题。我尝试了很多参数类型(byte,ref byte,byte[],ref byte[],int & IntPtr + byte[],out byte,out byte[],byte*)。glGetError()总是返回GL_NO_ERROR。一定是我做错了什么,因为它从来都不是一些乱七八糟的像素。它总是白色的。glGenTextures工作正常。与OpenGL中的always一样,第一个id的值为1。我可以毫无问题地画出彩色线条。所以我的纹理有问题。我控制着DllImport。因此,如果需要,我可以更改参数类型。
GL.glBindTexture(GL.GL_TEXTURE_2D, id);
int w = 4;
int h = 4;
byte[] bytes = new byte[w * h * 4];
for (int i = 0; i < bytes.Length; i++)
bytes[i] = (byte)Utils.random(256);
GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, w, h, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, bytes);[DllImport(GL_LIBRARY)] public static extern void glTexImage2D(uint what, int level, int internalFormat, int width, int height, int border, int format,
int type, byte[] bytes);发布于 2012-04-13 08:27:23
一个常见的错误是不更改最小滤镜,因为默认值是mipmapped,这会使纹理不完整。执行以下操作:
GL.glBindTexture(GL_TEXTURE_2D, id);
GL.glTexParameteri(GL_TEXTURE_2D, GL_MIN_FILTER, GL_NEAREST);然后绘制纹理。
发布于 2012-04-13 15:57:26
尽管已上载某些内容,但纹理仍保持白色,这表示未正确上载所有mipmap级别,或过滤器设置未正确设置。
感兴趣的是
glTexParameteri(GL_TEXTURE_..., GL_MIN_FILTER, GL_...);使用GL_NEAREST或GL_LINEAR禁用With映射。默认情况下会启用Mipmapping。
另一个重要的事情是在上传之前设置数据的结构,即调用glTexImage。为此,您可以使用函数glPixelStorei来设置GL_UNPACK_...参数。您需要设置对齐、步幅等设置。我建议您参考文档。
发布于 2012-04-14 04:15:41
您的P/Invoke声明错误。
简短的答案是:
[System.Runtime.InteropServices.DllImport(Library, EntryPoint = "glTexImage2D", ExactSpelling = true)]
internal extern static void glTexImage2D(int target, int level, int internalformat, Int32 width, Int32 height, int border, int format, int type, IntPtr pixels);这个P/Invoke声明是安全的(不直接使用指针,而是IntPtr)。
问题出在.NET内存管理上。内存块并不固定在某个特定的内存地址上:垃圾收集器(GC)可以自由地将内存移动到任何地方(例如,它可以在堆空间中移动已分配内存的堆栈,反之亦然)。
实际上,您需要的是告诉.NET GC内存不能移动。为此,您应该使用固定语句或其他垃圾收集器相关的方法。
例如:
public static void TexImage2D(int target, int level, int internalformat, Int32 width, Int32 height, int border, int format, int type, object pixels) {
GCHandle pp_pixels = GCHandle.Alloc(pixels, GCHandleType.Pinned);
try {
if (Delegates.pglTexImage2D != null)
Delegates.pglTexImage2D(target, level, internalformat, width, height, border, format, type, pp_pixels.AddrOfPinnedObject());
else
throw new InvalidOperationException("binding point TexImage2D cannot be found");
} finally {
pp_pixels.Free();
}
}TexImage2D函数的object参数用于任何数据数组(实现Array类的对象(即byte[]、short[]、int[]等))。
实际上,上面的代码告诉GC:获取像素的地址,直到我在内存句柄上调用Free()时才移动它。
在固定语句中使用是另一种选择,但需要一个不安全的P/Invoke声明,并且在代码中使用它会有点冗长(对于每个调用,您必须定义一个不安全和固定的语句)。
https://stackoverflow.com/questions/10133395
复制相似问题