调用glDrawElements时OPENGL_INVALID_OPERATION

时间:2017-05-17 11:59:07

标签: c++ opengl

#include <iostream>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#include <SDL2/SDL.h>

SDL_Window * window = NULL;
SDL_GLContext context = NULL;

const GLfloat vertices[3][4] = {
    0.5f,  0.5f, 0.0f,  // Top Right
    0.5f, -0.5f, 0.0f,  // Bottom Right
    -0.5f, -0.5f, 0.0f,  // Bottom Left
    -0.5f,  0.5f, 0.0f   // Top Left
};

const GLuint indices[3][2]= {  // Note that we start from 0!
    0, 1, 3,   // First Triangle
    1, 2, 3    // Second Triangle
};

const GLchar* vertexShaderSource = {"#version 330 core\n"
"layout (location = 0) in vec3 position;"
"void main(void)\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\n\0"};

//fragment
const GLchar* fragmentShaderSource = {"#version 330 core\n"
"out vec4 color;\n"
"void main(void)\n"
"{\n"
"color = vec4(1.0, 0.5, 0.2, 1.0);\n"
"}\n\0"};

bool init ();

bool init(){
    if (SDL_Init(SDL_INIT_VIDEO)<0){
        std::cout << "Can't make SDL" << std::endl;
    }

    //what version we are using
    SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    //SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

    window = SDL_CreateWindow("Rectangle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 512, 512, SDL_WINDOW_OPENGL);
    if (!window){
        std::cout << "No window created" << std::endl;
        window = NULL;
        return false;
    }

    context = SDL_GL_CreateContext(window);

    //double buffering - 24bit z buffer (might need changing for different systems)
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    //Makes buffer swap sync with VBLANK
    SDL_GL_SetSwapInterval(1);

    glViewport(0, 0, 512, 512);

    return true;
};

int main(int argc, const char * argv[]) {
    if (!init()) std::cout << "Failed to start up!" << std::endl;

    //compiling the shaders
    GLuint shaderProgram, fragmentShader, vertexShader;

    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //error checking
    GLchar info [512];
    GLint success;
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(!success){
        glGetShaderInfoLog(fragmentShader, 512, NULL, info);
        std::cout << "Did not compile fragment shader\n"<< info;
    }

    std::cout<< "vertex shader made" << std::endl;

    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    //error checking
    GLchar infoLog [512];
    GLint success2;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success2);
    if(!success){
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "Did not compile vertex shader\n" << info;
    }

    std::cout << "fragment shader made" << std::endl;

    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    //error checking
    GLchar info3 [512];
    GLint success3;
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success3);
    if(!success){
        glGetProgramInfoLog(shaderProgram, 512, NULL, info3);
        std::cout << "Did not link shaders\n" << info;
    }

    std::cout << "shaders linked" << std::endl;

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    //sets all the VAOs, VBOs, etcs
    GLuint VAO;
    glGenVertexArrays(1, &VAO);

    GLuint VBO;
    glGenBuffers(1, &VBO);

    GLuint EBO;
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);

    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    bool loop = true;

    while (loop) {
        SDL_Event e;
        while(SDL_PollEvent(&e)){
            if (e.type == SDL_QUIT) loop = false;
            if (e.type == SDL_KEYDOWN){
                switch(e.key.keysym.sym){
                    case SDLK_ESCAPE:
                        loop = false;
                        break;
                    case SDLK_q:
                        glUseProgram(shaderProgram);
                        glBindVertexArray(VAO);
                        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
                        glBindVertexArray(0);
                        SDL_GL_SwapWindow(window);
                        break;
                    case SDLK_y:
                        std::cout << glGetString(GL_VERSION) << std::endl;
                }
                std::cout << glGetError() << std::endl;
            }
        }

    }

}

//generates error 1282 for some reason

我使用glGetError查看错误是什么,它返回1282或GL_INVALID_OPERATION。每当我尝试绘制时,都会导致图像出现故障(稍后会上传图片)。

问题绝对不是着色器,因为它们编译得很好。 我想这可能就是我如何设置VBO和VAO:

  //sets all the VAOs, VBOs, etcs
GLuint VAO;
glGenVertexArrays(1, &VAO);

GLuint VBO;
glGenBuffers(1, &VBO);

GLuint EBO;
glGenBuffers(1, &EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);

glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

我直接从本教程https://learnopengl.com/#!Getting-started/Hello-Triangle

复制了所有这些内容

可以在https://learnopengl.com/code_viewer.php?code=getting-started/hellotriangle2

找到本教程的源代码

我将我的代码与教程进行了多次比较,检查我是否拥有所有正确的调用和参数,但我找不到任何错误。我很确定我正确地设置了它。有没有比我更有经验的人看到我做错了什么?

编辑:好的,所以我得到的行就是抛出错误的地方。我不知道我读错了,但我的代码中没有440行。这是第4行,第40个字符吗?在上下文完成后,我还移动了SetSwapInterval()SDL_GL_Doublebuffer个函数。

编辑2 :好的,所以经过一些挖掘后,错误被抛出的线是439,(我有一堆注释掉的东西,这就是为什么这个数字太大了),在glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)之后。投诉是INVALID_OPERATION。它还在第405行说INVALID_VALUE - 我启动程序后glGenBuffers(1, &EBO);之后的行,但没有再说。

编辑3 :经过多次检查后,肯定是glDrawElements()造成这种情况,而不是其他任何内容。

1 个答案:

答案 0 :(得分:0)

您错误地使用该命令来告诉如何在着色器中读取属性。

//WRONG
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);

第五个参数是连续通用顶点属性之间的字节偏移量。您的顶点在缓冲区(VBO)中是连续的,因此不需要步幅:

//RIGHT
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);

glDrawElements在VBO中检测到索引大于1的无效位置:second position (1) + stride (3 floats) = end of buffer并返回&#34;无效操作&#34;

编辑:

着色器中的主要功能:

  

此函数不带参数,不返回值,必须是   声明为void:

使用: void main()代替void main(void)