我正在学习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
}
答案 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);
}