Reputation: 1482
So I'm trying to write a simple 3D rendering engine using GLFW and GLEW in C++. However the program crashes on glDrawArrays(GL_TRIANGLES, 0, model.indicesCount);
call. I'm pretty sure I'm doing something wrong but I can't figure out where or what needs to be changed/altered. I'm actually rewriting a perfectly working engine from Java.
My code:
common.h:
#ifndef _COMMON
#define _COMMON
// standard stuff
#include <iostream>
#include <list>
// openGL stuff
#include "GL\glew.h"
#include "GLFW\glfw3.h"
// my stuff
#include "DisplayManager.h"
#include "RawModel.h"
#include "Loader.h"
#include "Renderer.h"
#endif
DisplayManager.h:
#pragma once
#include "common.h"
class DisplayManager{
private:
GLFWwindow* window;
public:
void create(int width = 1280, int height = 720, std::string title = "Untitled"){
if(!glfwInit()){
std::cerr << "GLFW init failed\n";
system("pause");
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
glfwMakeContextCurrent(window);
if(!window){
std::cerr << "Failed to create a window\n";
system("pause");
exit(EXIT_FAILURE);
}
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK){
std::cerr << "GLEW init failed\n";
system("pause");
glfwTerminate();
exit(EXIT_FAILURE);
}
}
void update(){
glfwSwapBuffers(window);
glfwPollEvents();
}
int isCloseRequested(){
return glfwWindowShouldClose(window);
}
void close(){
glfwDestroyWindow(window);
glfwTerminate();
}
};
RawModel.h:
#pragma once
struct RawModel{
public:
GLuint vaoID;
GLuint indicesCount;
RawModel(GLuint vaoID, GLuint indicesCount){
this->vaoID = vaoID;
this->indicesCount = indicesCount;
}
};
Loader.h:
#pragma once
#include "common.h"
#define VERTEX_ATTRIB_INDEX 0
#define VERTEX_SIZE 3
class Loader{
public:
// functions
RawModel loadModel(const GLfloat vertices[], GLuint verticesCount){
GLuint vaoID = createAndBindVao();
storeFloatDataInVAO(VERTEX_ATTRIB_INDEX, vertices, verticesCount, VERTEX_SIZE);
unbindVAO();
return RawModel(vaoID, verticesCount);
}
void cleanUp(){
std::list<GLuint>::iterator vao_it = vaos.begin();
for(; vao_it != vaos.end(); ++vao_it){
const GLuint vao = *vao_it;
glDeleteVertexArrays(1, &vao);
}
std::list<GLuint>::iterator vbo_it = vbos.begin();
for(; vbo_it != vbos.end(); ++vbo_it){
const GLuint vbo = *vbo_it;
glDeleteBuffers(1, &vbo);
}
}
private:
// variables
std::list<GLuint> vaos;
std::list<GLuint> vbos;
// functions
GLuint createAndBindVao(){
GLuint vaoID;
glGenVertexArrays(1, &vaoID);
vaos.push_back(vaoID);
glBindVertexArray(vaoID);
return vaoID;
}
void storeFloatDataInVAO(const GLuint attributeIndex, const GLfloat data[], const GLuint dataLength, const GLuint chunkSize){
GLuint vboID;
glGenBuffers(1, &vboID);
vbos.push_back(vboID);
glBindBuffer(GL_VERTEX_ARRAY, vboID);
glBufferData(GL_VERTEX_ARRAY, sizeof(GLfloat) * dataLength * chunkSize, data, GL_STATIC_DRAW);
glVertexAttribPointer(attributeIndex, chunkSize, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_VERTEX_ARRAY, 0);
}
void unbindVAO(){
glBindVertexArray(0);
}
};
Renderer.h:
#pragma once
#include "common.h"
#define BLACK 0.0f, 0.0f, 0.0f, 1.0f
#define WHITE 1.0f, 1.0f, 1.0f, 1.0f
#define RED 1.0f, 0.0f, 0.0f, 1.0f
#define GREEN 0.0f, 1.0f, 0.0f, 1.0f
#define BLUE 0.0f, 0.0f, 1.0f, 1.0f
#define YELLOW 1.0f, 1.0f, 0.0f, 1.0f
class Renderer{
public:
void prepare(){
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(YELLOW);
};
void render(RawModel model){
glBindVertexArray(model.vaoID);
glEnableVertexAttribArray(VERTEX_ATTRIB_INDEX);
glDrawArrays(GL_TRIANGLES, 0, model.indicesCount);
glDisableVertexAttribArray(VERTEX_ATTRIB_INDEX);
glBindVertexArray(0);
}
};
and the Source.cpp with the main function:
#include "common.h"
static const GLfloat VERTICES[] = {
// X Y Z
-0.5f, 0.5f, 0,
-0.5f, -0.5f, 0,
0.5f, 0.5f, 0
};
int main(){
DisplayManager display;
display.create();
Loader loader;
RawModel model = loader.loadModel(VERTICES, 3);
Renderer renderer;
// main loop
while(!display.isCloseRequested()){
renderer.prepare();
renderer.render(model);
display.update();
}
loader.cleanUp();
display.close();
return EXIT_SUCCESS;
}
If I comment out the glDrawArrays(GL_TRIANGLES, 0, model.indicesCount);
it seams to be working and I get a green window.
Upvotes: 0
Views: 699
Reputation: 45342
The error is here:
glBindBuffer(GL_VERTEX_ARRAY, vboID); glBufferData(GL_VERTEX_ARRAY, sizeof(GLfloat) * dataLength * chunkSize, data, GL_STATIC_DRAW); glVertexAttribPointer(attributeIndex, chunkSize, GL_FLOAT, GL_FALSE, 0, (void*)0); glBindBuffer(GL_VERTEX_ARRAY, 0);
GL_VERTEX_ARRAY
is not a valid buffer target in OpenGL, the correct one is GL_ARRAY_BUFFER
. As a consequence, these commands all should generate a GL error. The attrib pointer function will should generate GL_INVALID_OPERATION
, since no GL_ARRAY_BUFFER
is bound at the time of the call, the others should just generate GL_INVALID_ENUM
. Now you have basically an uninitialized vertex attribute pointer, you later enable that attribute array and try to draw from it, resulting in the crash.
Another thing: I don't see any shaders in your code. Shaders are mandatory in the core profile, which you use. Now glDrawElements()
actually should fail, although some implementors ignore that and use some trivial shaders in that scenario.
Upvotes: 3