取消绑定顶点数组时,未在OpenGL中绘制形状

时间:2015-07-14 07:08:00

标签: c++ opengl

我正在学习OpenGL,并设置了一个Mesh类来渲染我的形状。绘图只能在没有

的情况下工作
glBindVertexArray(0);
最后,所以我猜我弄乱了一些东西,但我无法弄清楚。

以下是代码: main.cpp

#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <iostream>
#include "mesh.h"

#define WIDTH 1280
#define HEIGHT 720

// Vertex shader
    const char* vs = "\n\
    #version 330                \n\
    layout (location = 0) in vec2 position; \n\
    layout (location = 1) in vec3 color;    \n\
    out vec3 Color;             \n\
                        \n\
    void main() {               \n\
        Color = color;          \n\
        gl_Position = vec4(position, 0.0, 1.0); \n\
    }                   \n\
                        \n\
    ";
// Fragment shader
    const char* fs = "\n\
    #version 330                \n\
    in vec3 Color;              \n\
    out vec4 fragColor;             \n\
                        \n\
    void main() {               \n\
    fragColor = vec4(Color, 1.0);       \n\
    }                   \n\
    ";

bool checkShader(GLuint shader) {
    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

    if (status != GL_TRUE) {
        char buffer[512];
        glGetShaderInfoLog(shader, 512, NULL, buffer);
        std::cout << "Error compiling shader:" << buffer << std::endl;
        return false;
    }
    return true;
}

bool compileShaders() {
    // compile the vertex shader
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vs, NULL);
    glCompileShader(vertexShader);

    if (!checkShader(vertexShader))
        return false;

    // compile the fragment shader
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fs, NULL);
    glCompileShader(fragmentShader);

    if (!checkShader(fragmentShader))
        return false;

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);

    glBindFragDataLocation(shaderProgram, 0, "outColor");

    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    return true;
}

int main() {
    bool success = true;
    bool running = true;

    SDL_Window* window;
    SDL_GLContext context;

    // Initialize SDL/Glew

    if (SDL_Init(SDL_INIT_VIDEO) <  0) {
        std::cerr << "Video initialization failed:" << SDL_GetError() << std::endl;
        success = false;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    window = SDL_CreateWindow("Game Title", SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN |
        SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
    context = SDL_GL_CreateContext(window);

    glewExperimental = GL_TRUE; 
    if (glewInit() != GLEW_OK) {
        std::cerr << "Problem initializing GLEW." << std::endl;
        success = false;
    }

    SDL_Event e;

    // Mesh setup
    float vertices[] = { 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
                 0.5f,-0.5f, 0.0f, 1.0f, 0.0f,
                -0.5f,-0.5f, 0.0f, 0.0f, 1.0f };

    float vertices2[] = { -1.0f,-1.0f, 1.0f, 0.0f, 0.0f,
                  -1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
                  -0.0f, 0.0f, 0.0f, 0.0f, 1.0f };

    GLuint elements[] = { 0, 1, 2 };

    Mesh triangle(vertices, elements, sizeof(vertices), sizeof(elements));
    Mesh triangle2(vertices2, elements, sizeof(vertices2), sizeof(elements));

    if (!compileShaders())
        success = false;

    if (!success) {
        std::cerr << "A problem ocurred during initialization, will exit." << std::endl;
        exit(1);
    }

    while (running) {
        while (SDL_PollEvent(&e)) {
            if (e.type ==  SDL_QUIT)
                running = false;
            if (e.type == SDL_KEYDOWN)
                if (e.key.keysym.sym == SDLK_ESCAPE)
                    running = false;
        }

        glClearColor(0.0f, 1.0f, 0.5f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        triangle.draw();
        triangle2.draw();

        SDL_GL_SwapWindow(window);
        SDL_Delay(1);
    }

    SDL_GL_DeleteContext(context);
    SDL_Quit();
    return 0;
}

mesh.h

#ifndef MESH_H
#define MESH_H
#include <GL/glew.h>

class Mesh {
private:
    GLuint IBO;
    GLuint VBO;
    GLuint VAO;
    float* vertices;
    GLuint* indices;

    int sizeVertices;
    int sizeIndices;
public:
    Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices);
    void draw();
};

#endif //MESH_H

mesh.cpp

#include "mesh.h"

#define POSITION 0
#define COLOR 1

Mesh::Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices) {
    this->vertices = vertices;
    this->indices = indices;
    this->sizeVertices = sizeVertices;
    this->sizeIndices = sizeIndices;

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &IBO);
}

void Mesh::draw() {
    glEnableVertexAttribArray(POSITION);
    glVertexAttribPointer(POSITION, 2, GL_FLOAT, GL_FALSE,5*sizeof(float), 0);

    glEnableVertexAttribArray(COLOR);
    glVertexAttribPointer(COLOR, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(2*sizeof(float)));

    glBindVertexArray(VAO);

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

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, indices, GL_STATIC_DRAW);

    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);

    //glBindVertexArray(0); If I uncomment this, the mesh is not displayed
}

1 个答案:

答案 0 :(得分:1)

glVertexAttribPointer 指针的调用是指在调用时绑定的VAO和VBO。在您的代码中,您在VAO和VBO绑定之前调用 glVertexAttribPointer 。因此围绕这些调用的第一次迭代将失败。在没有解除VAO / VBO的下一次迭代的情况下,VAO / VBO状态将发生(通过环境)或多或少的权利;实际上你已经在两个三角形实例之间交换了VAO / VBO。

更新 - 修正代码

Mesh::Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices) {
    this->vertices = vertices;
    this->indices = indices;
    this->sizeVertices = sizeVertices;
    this->sizeIndices = sizeIndices;

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &IBO);

    /* VAOs contain ARRAY_BUFFERS */
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeVertices, vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(POSITION);
    glVertexAttribPointer(POSITION, 2, GL_FLOAT, GL_FALSE,5*sizeof(float), 0);

    glEnableVertexAttribArray(COLOR);
    glVertexAttribPointer(COLOR, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(2*sizeof(float)));

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

    /* ELEMENT_ARRAY_BUFFERS are not contained in VAOs */
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, indices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void Mesh::draw() {
    /* VAOs keep the glVertexAttribPointer bindings,
     * so it's sufficient to just bind the VAO;
     * no need for binding the VBOs (as long as you don't
       want to change the pointers). */
    glBindVertexArray(VAO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);

    /* Need to bind the ELEMENT_ARRAY_BUFFER though */

    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}