Невозможно нарисовать несколько объектов, используя VAO и EBO (openGL) - PullRequest
2 голосов
/ 17 февраля 2020

Я экспериментировал с использованием объектов Vertex Array и Element Buffer Objects. Мне удалось нарисовать букву «H» на моем экране, используя одну VAO с привязкой к EBO, поскольку все мои вершины и индексы были в одном массиве. Я хотел разделить каждый прямоугольник на отдельный объект и дать ему другой цвет, но только один из них рисует на экране.

Вот код:

#include <glew.h>
#include <glfw3.h>
#include <iostream>

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

const char* fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "FragColor = vec4(0.2f, 0.6f, 0.7f, 1.0f);\n"
    "}\0";

const char* fragmentShaderSource2 = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "FragColor = vec4(0.7f, 0.4f, 0.3f, 1.0f);\n"
    "}\0";

const char* fragmentShaderSource3 = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "FragColor = vec4(0.1f, 0.2f, 0.6f, 1.0f);\n"
    "}\0";

int main(void)
{
    GLFWwindow* window;

    glewInit();
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK)
        std::cout << "Error!" << std::endl;

    float vertices[] = {
         0.2f, 0.7f, 0.0f,
         0.3f, 0.7f, 0.0f,
         0.3f, 0.2f, 0.0f,
         0.2f, 0.2f, 0.0f
    };

    float vertices2[] = {
         0.6f, 0.7f, 0.0f,
         0.7f, 0.7f, 0.0f,
         0.7f, 0.2f, 0.0f,
         0.6f, 0.2f, 0.0f
    };

    float vertices3[] = {
        0.3f, 0.4f, 0.0f,
        0.3f, 0.5f, 0.0f,
        0.6f, 0.5f, 0.0f,
        0.6f, 0.4f, 0.0f
    };

    unsigned int indices[] = {    
        1, 0, 2,
        2, 3, 0
    };  

    unsigned int indices2[] = {
        5, 4, 6,
        6, 7, 4
    };

    unsigned int indices3[] = {
        8, 9, 11,
        11, 10, 9
    };

    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);

    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    int  success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);

    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);

    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    unsigned int fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader2, 1, &fragmentShaderSource2, NULL);
    glCompileShader(fragmentShader2);

    unsigned int fragmentShader3 = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader3, 1, &fragmentShaderSource3, NULL);
    glCompileShader(fragmentShader3);

    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();

    unsigned int shaderProgram2;
    shaderProgram2 = glCreateProgram();

    unsigned int shaderProgram3;
    shaderProgram3 = glCreateProgram();

    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glAttachShader(shaderProgram2, fragmentShader2);
    glAttachShader(shaderProgram2, vertexShader);
    glLinkProgram(shaderProgram2);
    glAttachShader(shaderProgram3, fragmentShader3);
    glAttachShader(shaderProgram3, vertexShader);
    glLinkProgram(shaderProgram3);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);

    if (!success)
    {
        glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glDeleteShader(fragmentShader2);
    glDeleteShader(fragmentShader3);

    unsigned int VBOs[3], VAOs[3], EBOs[3];

    glGenVertexArrays(3, VAOs);
    glGenBuffers(3, VBOs);
    glGenBuffers(3, EBOs);

    glBindVertexArray(VAOs[0]);
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindVertexArray(VAOs[1]);
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindVertexArray(VAOs[2]);
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[2]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices3), vertices3, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[2]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices3), indices3, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

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

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {

        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAOs[0]);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glUseProgram(shaderProgram2);
        glBindVertexArray(VAOs[1]);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glUseProgram(shaderProgram3);
        glBindVertexArray(VAOs[2]);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }
    glDeleteVertexArrays(3, VAOs);
    glDeleteBuffers(3, VBOs);
    glDeleteBuffers(3, EBOs);

    glfwTerminate();
    return 0;
}

1 Ответ

3 голосов
/ 17 февраля 2020

У вас будет здесь:

float vertices2[] = {
     0.6f, 0.7f, 0.0f,
     0.7f, 0.7f, 0.0f,
     0.7f, 0.2f, 0.0f,
     0.6f, 0.2f, 0.0f
};

вместе с:

unsigned int indices2[] = {
    5, 4, 6,
    6, 7, 4
};

Это не имеет смысла. Вы только копируете 4 вершины в свой VBO[1] и устанавливаете указатель attrib на смещение 0 в этом буфере, поэтому единственными допустимыми индексами являются 0, 1, 2 и 3.

Ваши индексы установлены так, как если бы все ваши вершины были в одном большом массиве, как и раньше, и на самом деле, это была бы гораздо лучшая стратегия: сохранить один большой массив вершин и один массив индексов больших элементов и один VAO, и просто Нарисуйте отдельные части этого массива, изменив аргумент indices в вызове glDrawElements(), например:

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // first 6 indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(6*sizeof(GLuint))); // second 6 indices
// ...

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

...