glVertexAttribPointer Повышение GL_INVALID_OPERATION версия 330 - PullRequest
1 голос
/ 20 сентября 2019

Я пытаюсь упростить мой пример, чтобы показать точно ненормальный случай.Я запускаю этот пример на MacOS 10.14.6, собирая компилятор clang LLVM, используя GLFW3.Также я пытаюсь запустить тот же пример на Windows 10/64 с использованием SFML и получил ту же ошибку, поэтому проблема не в среде

OpenGL version 4.1 ATI-2.11.20 
Shading language version 4.10

Точный код, где проблема

glUseProgram(id_shader);
glEnableVertexAttribArray(param_Position);
//HERE IS ERROR "OpenGL ERROR: 0x00000502 GL_INVALID_OPERATION" RAISED
glVertexAttribPointer(param_Position, 3, GL_FLOAT, (GLboolean) false, 0, vertices);

Вот полный исходный код

#include <stdlib.h>
#include <OpenGL/gl3.h>
#include <GLFW/glfw3.h>

#include "engine/Camera.h"

static const char *get_error_string_by_enum(GLenum err)
{
    switch (err) {
        case GL_INVALID_ENUM :
            return "GL_INVALID_ENUM";
        case GL_INVALID_VALUE :
            return "GL_INVALID_VALUE";
        case GL_INVALID_OPERATION :
            return "GL_INVALID_OPERATION";
        case GL_STACK_OVERFLOW :
            return "GL_STACK_OVERFLOW";
        case GL_STACK_UNDERFLOW :
            return "GL_STACK_UNDERFLOW";
        case GL_OUT_OF_MEMORY :
            return "GL_OUT_OF_MEMORY";
#ifdef GL_INVALID_FRAMEBUFFER_OPERATION
        case GL_INVALID_FRAMEBUFFER_OPERATION :
            return "GL_INVALID_FRAMEBUFFER_OPERATION";
#endif
        default: {
            return "UNKNOWN";
        }
    }
}

static void check_gl()
{
    char line[300];
    GLenum err;

    err = glGetError();
    if (err != GL_NO_ERROR) {
        sprintf(line, "OpenGL ERROR: 0x%.8X %s", err, get_error_string_by_enum(err));
        printf("%s\n", line);
        exit(-1);
    }
}

int main()
{
    char line[2000];
    unsigned int windowWidth = 1024;
    unsigned int windowHeight = 1024;

    GLFWwindow* window;

    //SETUP WINDOW AND CONTEXT
    if (!glfwInit()){
        fprintf(stdout, "ERROR on glfwInit");
        return -1;
    }
    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    window = glfwCreateWindow(windowWidth, windowHeight, "OpenGL", NULL, NULL);
    if (!window)
    {
        fprintf(stderr, "Unable to create window.");
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    sprintf(line, "OpenGL version %s\n", (const char *) glGetString(GL_VERSION));
    fprintf(stdout, line);
    sprintf(line, "Shading language version %s\n", (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION));
    fprintf(stdout, line);

    //SETUP OPENGL
    glViewport(0, 0, windowWidth, windowHeight);
    glEnable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glDepthMask(true);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    //SETUP SHADER PROGRAM
    GLint success;
    GLuint id_v = glCreateShader(GL_VERTEX_SHADER);
    GLuint id_f = glCreateShader(GL_FRAGMENT_SHADER);

    const char *vertex_shader_source = "#version 330\n"
                                       "precision mediump float;\n"
                                       "\n"
                                       "in vec4 Position;\n"
                                       "uniform mat4 MVPMatrix;\n"
                                       "\n"
                                       "void main()\n"
                                       "{\n"
                                       "\tgl_Position = MVPMatrix * Position;\n"
                                       "\tgl_PointSize = 10.0;\n"
                                       "}";
    const char *fragment_shader_source = "#version 330\n"
                                         "precision mediump float;\n"
                                         "\n"
                                         "uniform vec4 Color;\n"
                                         "out vec4 FragCoord;\n"
                                         "\n"
                                         "void main()\n"
                                         "{\n"
                                         "  FragCoord = Color;\n"
                                         "}";

    glShaderSource(id_v, 1, &vertex_shader_source, NULL);
    glCompileShader(id_v);
    glGetShaderiv(id_v, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(id_v, 2000, NULL, line);
        fprintf(stderr, line);
        exit(-1);
    }

    glShaderSource(id_f, 1, &fragment_shader_source, NULL);
    glCompileShader(id_f);
    glGetShaderiv(id_f, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(id_f, 2000, NULL, line);
        fprintf(stderr, line);
        exit(-1);
    }

    GLuint id_shader = glCreateProgram();
    glAttachShader(id_shader, id_v);
    glAttachShader(id_shader, id_f);
    glLinkProgram(id_shader);
    glGetProgramiv(id_shader, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(id_shader, 2000, NULL, line);

        fprintf(stderr, "program link error");
        fprintf(stderr, line);
        exit(-1);
    }
    GLuint param_Position = glGetAttribLocation(id_shader, "Position");
    GLuint param_MVPMatrix = glGetUniformLocation(id_shader, "MVPMatrix");
    GLuint param_Color = glGetUniformLocation(id_shader, "Color");
    sprintf(line, "Params: param_Position=%d param_MVPMatrix=%d param_Color=%d\n", param_Position, param_MVPMatrix, param_Color);
    fprintf(stdout, line);

    //SETUP MATRIX
    Camera *c = new Camera();
    c->setCameraType(CameraType::PERSPECTIVE);
    c->setWorldSize(100, 100);
    c->lookFrom(5, 5, 5);
    c->lookAt(0, 0, 0);
    c->setFOV(100);
    c->setUp(0, 0, 1);
    c->calc();
    c->getResultMatrix().dump();

    //SETUP TRIANGLE
    float vertices[] = {
            0, 0, 0,
            1, 0, 0,
            1, 1, 0
    };

    while (!glfwWindowShouldClose(window))
    {
        //CLEAR FRAME
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

        //RENDER TRIANGLE
        glUseProgram(id_shader);
        glUniformMatrix4fv(param_MVPMatrix, 1, (GLboolean) false, c->getResultMatrix().data);
        glUniform4f(param_Color, 1.0f, 0.5f, 0.0f, 1.0f);
        glEnableVertexAttribArray(param_Position);
        check_gl();
        //HERE IS ERROR "OpenGL ERROR: 0x00000502 GL_INVALID_OPERATION" RAISED
        glVertexAttribPointer(param_Position, 3, GL_FLOAT, (GLboolean) false, 0, vertices);
        check_gl();
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glfwSwapBuffers(window);

        glfwPollEvents();
    }

    glfwTerminate();

    return 0;
}

Перед строкой

glVertexAttribPointer(param_Position, 3, GL_FLOAT, (GLboolean) false, 0, vertices);

До и сразу после этой строки ошибок не обнаружено GL_INVALID_OPERATION.

Вывод программы:

Версии среды:

OpenGL version 4.1 ATI-2.11.20
Shading language version 4.10

Имена параметров шейдера:

Params: param_Position=0 param_MVPMatrix=1 param_Color=0

Матрица

-0.593333 -0.342561 -0.577350 -0.577350 
0.593333 -0.342561 -0.577350 -0.577350 
0.000000 0.685122 -0.577350 -0.577350 
0.000000 0.000000 8.640252 8.660253 

Ошибка

OpenGL ERROR: 0x00000502 GL_INVALID_OPERATION

Iуже потратил несколько дней на эту проблему и больше не имею идеи ее ставить.Буду благодарен за любые советы и разъяснения.

PS Вот вывод glfwinfo для моей системы

/glfwinfo -m3 -n2 --profile=compat
GLFW header version: 3.4.0
GLFW library version: 3.4.0
GLFW library version string: "3.4.0 Cocoa NSGL EGL OSMesa"
OpenGL context version string: "4.1 ATI-2.11.20"
OpenGL context version parsed by GLFW: 4.1.0
OpenGL context flags (0x00000001): forward-compatible
OpenGL context flags parsed by GLFW: forward-compatible
OpenGL profile mask (0x00000001): core
OpenGL profile mask parsed by GLFW: core
OpenGL context renderer string: "AMD Radeon R9 M370X OpenGL Engine"
OpenGL context vendor string: "ATI Technologies Inc."
OpenGL context shading language version: "4.10"
OpenGL framebuffer:
 red: 8 green: 8 blue: 8 alpha: 8 depth: 24 stencil: 8
 samples: 0 sample buffers: 0
Vulkan loader: missing

1 Ответ

1 голос
/ 20 сентября 2019

Поскольку вы используете контекст базового профиля (GLFW_OPENGL_CORE_PROFILE), по умолчанию Объект массива вершин 0 недопустим, так как вы должны использовать Объект буфера вершин .

Когда вызывается glVertexAttribPointer, то спецификация массива вершин сохраняется в векторе состояний текущего привязанного объекта массива вершин.Буфер, который в настоящее время связан с целью ARRAY_BUFFER, связан с атрибутом, а имя (значение) объекта сохраняется в векторе состояний VAO.
В профиле совместимости существует объект массива вершин по умолчанию 0, который может быть использован в любое время, но это недопустимо в контексте основного профиля.Кроме того, в профиле совместимости нет необходимости использовать VBO, последний параметр glVertexAttribPointer может быть указателем на данные вершины.

Самое простое решение - перейти на профиль совместимости GLFW_OPENGL_COMPAT_PROFILE:

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);

Если вы не хотите этого делать или ваша система этого не обеспечивает, вам нужно прочитать о Спецификации вершин .Создайте объект буфера вершин объект массива вершин перед циклом программы:

// vertex buffer object
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

// vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo); // this is not necessary, because "vbo" is still bound 
glVertexAttribPointer(param_Position, 3, GL_FLOAT, (GLboolean) false, 0, nullptr);

// the following is not necessary, you can let them bound
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

И используйте его в цикле для рисования сетки:

glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
...