c# - glBufferData 总是因 GL_INVALID_ENUM 而失败,即使它不应该

标签 c# c++ opengl-es pinvoke

谁能看出这段代码有什么问题吗?

我对 glBufferData 的调用始终失败,错误代码为 GL_INVALID_ENUM。但是,我的值是正确的 - 我什至尝试直接对值进行硬编码(以防万一)。根据docs这应该有效。

编辑

我创建了一个最小的 - 或尽可能最小的 ANGLE + XAML + UWP 可以获得 - sample on GitHub 。所有工作都在 5 个主要文件中进行:

如果您下载并运行代码,它应该在glBufferData on line 61之后抛出异常。

要在基于缓冲区的数组和直接数组之间切换,只需更改行:SimpleRenderer.cs#L31

原版

就我而言,它似乎与 C++ 代码相匹配 - 运行良好。我在 Windows UWP 上使用 ANGLE。 (如果您需要更多上下文,我有完整的代码 here)

GLfloat[] vertexPositions = new[] {
     0.0f,  0.5f, 0.0f,
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f
};

Gles.glGenBuffers(1, out GLuint mVertexPositionBuffer);
Gles.glBindBuffer(0x8892 /*Gles.GL_ARRAY_BUFFER*/, mVertexPositionBuffer);
var gcData = GCHandle.Alloc(vertexPositions, GCHandleType.Pinned);
try {
    var size = vertexPositions.Length * Marshal.SizeOf<GLfloat>();
    var data = gcData.AddrOfPinnedObject();
    Gles.glBufferData(0x8892 /*Gles.GL_ARRAY_BUFFER*/, size, data, 0x88E4 /*Gles.GL_STATIC_DRAW*/);
    // Gles.glGetError() == Gles.GL_INVALID_ENUM
} finally {
    gcData.Free();
}

我的 p/invoke 层 Gles 看起来像这样:

[DllImport(libGLESv2)]
public static extern void glGenBuffers(GLsizei n, out GLuint buffers);
[DllImport(libGLESv2)]
public static extern void glBindBuffer(GLenum target, GLuint buffer);
[DllImport(libGLESv2)]
public static extern void glBufferData(GLenum target, GLsizeiptr size, IntPtr data, GLenum usage);

这就是我的 C++ 代码的样子:

GLfloat vertexPositions[] = { ... };
glGenBuffers(1, &mVertexPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);

我相信我的其余设置/绘图代码是正确的,因为这绘制得很好:

GLfloat[] vertexPositions = new[] {
     0.0f,  0.5f, 0.0f,
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f
};
var gcData = GCHandle.Alloc(vertexPositions, GCHandleType.Pinned);
try {
    Gles.glVertexAttribPointer((GLuint)mPositionAttribLocation, 3, Gles.GL_FLOAT, Gles.GL_FALSE, 0, gcData.AddrOfPinnedObject());
} finally {
    gcData.Free();
}
Gles.glEnableVertexAttribArray((GLuint)mPositionAttribLocation);
Gles.glDrawArrays(Gles.GL_TRIANGLES, 0, 3);

最佳答案

如果您使用 32 位架构,例如x86 ,那么 GLsizeiptr 必须是 32 位数据类型。

要解决此问题,别名 GLsizeiptr 的类型必须为 System.Int32:

using GLsizeiptr = System.Int32;

如果类型为System.Int64,则最后一个参数为

public static extern void glBufferData(
    GLenum target, GLsizeiptr size, IntPtr data, GLenum usage);

会错位。

这会导致 glBufferData 中出现 GL_INVALID_ENUM 错误,因为最后一个参数(usage)的值不是GL_STREAM_DRAWGL_STREAM_READ...。

关于c# - glBufferData 总是因 GL_INVALID_ENUM 而失败,即使它不应该,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51908102/

相关文章:

c# - 正则表达式仅数字和字符

c# - MATLAB/.NET Interop - 不允许在 .NET 对象上设置属性

c++ - 关于使用#define 有条件地排除主函数时的 C++ 预处理器

c++ - 静态断言和 SFINAE

ios 8 opengl es 1.1 停产了吗?

c# - 如何重新排序 DataGridView 中的列?

c# - 如何简化用于设置模拟的 It.IsAny<T>() 参数

c++ - 关于C++类的几个问题

Android OpenGL 应用程序在模拟器中加载后停止工作

android - 游戏开发 : OpenGlContext error issue