glVertexAttribPointer引发不可能的GL_INVALID_OPERATION错误?

3
我已经缩小了错误范围,发现问题出在这个OpenGL调用中:
glVertexAttribPointer(var.vertex, 4, GL_FLOAT, GL_FALSE, 0, 0);

在此之前没有错误,但在此之后有一个GL_INVALID_OPERATION错误。我的控制台输出如下:

Error in Shader.cpp : bindMesh : 294
        OpenGL Error: Invalid Operation
        (0x502)
        Bound Buffer: 1
        var.vertex = 1

根据此文,唯一可能适用的GL_INVALID_OPERATION条件是绑定缓冲区ID为0。但绑定的缓冲区ID为1。
我使用下面的代码进行错误检查(和打印):
printErrors();
int i = 0;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &i);
printf("\tBound Buffer: %i\n", i);
printf("\tvar.vertex = %i\n", var.vertex);

其中printErrors()的定义如下

void PrintErrors(const char* file, const char* func, int line);
#define printErrors() PrintErrors(__BASE_FILE__,__func__,__LINE__)

void PrintErrors(const char* file, const char* func, int line)
{
    const char* errors[] = {
        "OpenGL Error: Invalid Enumeration\n",
        "OpenGL Error: Invalid Value\n",
        "OpenGL Error: Invalid Operation\n",
        "OpenGL Error: Invalid Frame-Buffer Operation\n",
        "OpenGL Error: Out of Memory\n",
        "OpenGL Error: Stack Underflow\n",
        "OpenGL Error: Stack Overflow\n",
    };

    uint32 i = glGetError();
    while (i != GL_NO_ERROR)
    {
        printf("Error in %s : %s : %i\n\t%s\t(0x%x)\n", file, func, line, errors[i - GL_INVALID_ENUM], i);
        i = glGetError();
    }
}

出了什么问题?

编辑:

var.vertex 的赋值语句如下:

var.vertex = glGetAttribLocation(programID, "Vertex");

这里有一个检查,确保通过 if 语句在绑定的着色器中找到了 var.vertex:

if (var.vertex != INVALID_SHADER_VARIABLE) // INVALID_SHADER_VARIABLE = 0xFFFFFFFF (-1 if it where a signed int)
{
    glBindBuffer(...);
    glBuffferData(...);
    glEnableVertexAttribArray(var.vertex);
    glVertexAttribPointer(var.vertex, 4, GL_FLOAT, GL_FALSE, 0, 0);
}

你可能有一个核心配置上下文,但没有绑定VAO。这是会导致出现此错误的“不可能”条件之一。手册页面在处理诸如GL_INVALID_OPERATIONGL_OUT_OF_MEMORY等错误时远非完整。 - Andon M. Coleman
1
@Wolfgang Skyler:能不能看一下glGetString(GL_VERSION)返回的结果是什么? - Sergey K.
1
OpenGL版本:3.0.10750核心配置向前兼容上下文创建节点 - ATI Radeon HD 4xxx - Wolfgang Skyler
1
@Wolfgang Skyler:那么我的回答就是完全有效的。 - Sergey K.
如果零绑定到GL_ARRAY_BUFFER缓冲对象...,if条件检查为零。绑定的缓冲区是1(如我所述,在提供的代码中进行检查),因此通过条件。 - Wolfgang Skyler
显示剩余2条评论
1个回答

6
在没有扩展 GL_ARB_compatibility 或核心配置文件上下文的 OpenGL 3.1 上下文中,必须绑定一个非零的顶点数组对象。这是会产生 GL_INVALID_OPERATION 的隐藏条件之一,无论何时你尝试做任何与顶点数组相关的事情(例如绘制、设置顶点指针等)。
好消息是,这是一个微不足道的问题,很容易解决。
至少,在初始化程序时,你只需要生成 (glGenVertexArrays (...)) 并绑定 (glBindVertexArray (...)) 一个顶点数组对象即可。

我原以为 glBindBuffer(GL_ARRAY_BUFFER, ...) 就足够了,但看来你还需要一个 VAO。 - Wolfgang Skyler
是的,这在OpenGL 3.1中发生了变化。顶点数组对象实际上存储顶点数组指针,如果您在较新版本的GL中没有一个活动的VAO,则没有地方存储此状态。因此,尝试设置状态是无效的操作。在兼容性配置文件中,这不是问题,顶点数组状态仍然作为正常状态机的一部分存在。 - Andon M. Coleman
哇,我花了2个小时处理同一个不可能的GL_INVALID_OPERATION错误,结果发现只是缺少了VAO。谢谢你,伙计! - fegemo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接