На экране ничего не появляется в OpenGL (GLFW/GLEW)

Недавно я перешел с LWJGL (с которым у меня есть опыт) на OpenGL API С++. Я изучил этот учебник так как я не мог заставить свои классы vbo работать правильно. Код ниже:

#include "GL/glew.h"
#include "GLFW/glfw3.h"

#include <stdlib.h>
#include <stdio.h>

using namespace std;

GLFWwindow* window;

void init()
{

}

static const GLfloat g_vertex_buffer_data[] =
{
    -1.0f, -1.0f, 0.0f,
    1.0f, -1.0f, 0.0f,
    0.0f,  1.0f, 0.0f,
};

void render()
{
    glViewport(0, 0, 640, 480);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDisableVertexAttribArray(0);
    glDeleteBuffers(1, &vertexbuffer);

    glfwSwapBuffers(window);
    glfwPollEvents();
}

static void errorCallback(int error, const char* desc)
{
    fputs(desc, stderr);
}

static void keyCallback(GLFWwindow* window, int key, int scanCode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

void initWindow()
{
    glfwSetErrorCallback(errorCallback);
    if (!glfwInit())
        exit(EXIT_FAILURE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    window = glfwCreateWindow(640, 480, "Hello, world!", NULL, NULL);

    if (!window)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);
    glfwSetKeyCallback(window, keyCallback);

    glewExperimental = true;
    if (glewInit() != GLEW_OK)
        exit(EXIT_FAILURE);
}

void destroyWindow()
{
    glfwDestroyWindow(window);
    glfwTerminate();
    exit(EXIT_SUCCESS);
}

int main(int argCount, char **args)
{
    initWindow();
    init();
    while (!glfwWindowShouldClose(window))
        render();
    destroyWindow();
}

Я перечитывал его снова и снова и просматривал интернет. Однако другие сообщения, которые я читал, являются более явными ошибками. Я, вероятно, делаю здесь действительно очевидную ошибку, и я знаю, насколько неэффективен тот факт, что я создаю буфер для каждого кадра, однако это просто для проверки и посмотреть, смогу ли я заставить его работать. Я был бы признателен, если бы кто-нибудь мог сказать мне, что я делаю неправильно здесь!


person Community    schedule 23.12.2015    source источник


Ответы (1)


Вы используете основной профиль OpenGL 3.3. В таком контексте использование объектов массива вершин (VAO) обязательно. . То же самое относится и к программным объектам. Вы должны указать свои собственные шейдеры и не можете использовать фиксированную конвейерную линию функций. Вызов glLoadIdentity относится к устаревшей функциональности матричного стека, которая также удалена в основных профилях.

Ваш вызов glDrawArrays должен генерировать GL_INVALID_OPERATION, потому что у вас нет объекта программы и нет привязки VAO во время вызова отрисовки. Обычно я рекомендую добавлять проверки ошибок GL хотя бы для отладочных сборок. Если целевая версия GL поддерживает это, я рекомендую вместо этого использовать контекст отладки. Это значительно облегчит обнаружение ошибок во время разработки.

Также обратите внимание, что ни одна из этих проблем не связана с переходом с java с LWJGL на C++. Если вы раньше использовали устаревший контекст/основной профиль с java, вы также можете сделать это на C++ (хотя я настоятельно рекомендую вместо этого изучить современный GL), и вы бы столкнулись с теми же проблемами, если использовали современный контекст основного профиля с LWJGL.

person derhass    schedule 23.12.2015
comment
Просто для уточнения: это рабочий код, и хотя он использует массивы вершин, он все еще является VBO? Ссылка на Pastebin - person ; 24.12.2015
comment
@ZachGoethel: Этот вопрос не имеет смысла. Судя по всему, это не рабочий код, и ответ объясняет, почему. Несмотря на то, что он использует массивы вершин, он все еще является VBO? часть полностью вне меня. VBO являются VBO, потому что они хранят массивы вершин. Не путайте массивы вершин с объектами массивов вершин. Последние хранят только метаинформацию, в то время как VBO хранят фактические массивы вершин. - person derhass; 24.12.2015
comment
Этот код относится к ссылке, которую я дал. И под «Это VBO» я хотел спросить, хранятся ли данные на графическом процессоре или они отправляются каждый кадр. - person ; 24.12.2015
comment
В рамках другого вопроса я переименовал свой класс в MeshRenderer, поскольку его не следует называть VBO. - person ; 24.12.2015
comment
Ссылка, которую вы дали, не содержит кода, связанного с VBO. Он просто демонстрирует создание окна с контекстом GL. Кажется, вы находитесь в стеке в середине следующего урока, в котором прямо указано, что если вам повезет, вы можете увидеть результат (не паникуйте, если вы этого не сделаете). Однако вы пропустили часть VAO в начале этого урока 2, поэтому вы ничего не увидите, даже если добавите шейдеры позже. Мне не очень нравится это руководство, но если вы выполните все шаги до конца второго руководства, оно должно работать. - person derhass; 24.12.2015
comment
Ссылка в моем комментарии. Тот, который говорит «Ссылка на Pastebin» и ведет на pastebin.com/fBw007D0. - person ; 24.12.2015