I'm following a tutorial to set up some VBOs for the modern OpenGL. I managed to get a mesh and shader running (shader set to make each pixel red).
Next tutorial I was to set up the shader to use texture mapping, which seems to load correctly in the debugger, but I'm not so sure since I get an error once I get to glDrawArrays(...);
I think this stuff is kind of hard to get into, so I'm guessing I'm probably doing something horribly wrong somewhere. Sorry in advance for what you might see x)
Error output:
First-chance exception at 0x52E4A415 (nvoglv32.dll) in Modern OpenGL.exe: 0xC0000005: Access violation reading location 0x00000000.
This is my mesh code (or VBO code):
Mesh::Mesh() {
//Generate vertex array
glGenVertexArrays(1, &arrayObject);
for (int i = 0; i < VBO_COUNT; i++) {
//Generate vertex buffer
glGenBuffers(1, &buffers[i]);
}
}
Mesh::Mesh(ObjectData *obj) {
//Initialize first
Mesh::Mesh();
//Set object to parameter
setObject(obj);
}
Mesh::~Mesh() {
for (int i = 0; i < VBO_COUNT; i++) {
//Delete buffer
glDeleteBuffers(1, &buffers[i]);
}
//Delete array
glDeleteVertexArrays(1, &arrayObject);
}
void Mesh::draw() {
//Tell OpenGL which array to use
glBindVertexArray(arrayObject);
glDrawArrays(GL_TRIANGLES, 0, object->vertices.size());
glBindVertexArray(NULL);
}
void Mesh::updateVBO() {
//Tell OpenGL which vertex array to use from now
glBindVertexArray(arrayObject);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
glBufferData(GL_ARRAY_BUFFER, sizeof(object->vertices[0]) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_VERTEX);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
glBufferData(GL_ARRAY_BUFFER, sizeof(object->texCoords[0]) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_TEXCORD);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
//Unbind vertex array
glBindVertexArray(NULL);
}
void Mesh::setObject(ObjectData *obj) {
object = obj;
updateVBO();
}
Here is my shader code:
Shader::Shader(string fileName) {
m_program = glCreateProgram();
m_shaders[SHA_VERTEX] = createShader(loadShader(fileName + ".vs"), GL_VERTEX_SHADER);
m_shaders[SHA_FRAGMENT] = createShader(loadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);
for (int i = 0; i < SHA_COUNT; i++) {
glAttachShader(m_program, m_shaders[i]);
}
glBindAttribLocation(m_program, VBO_VERTEX, "vertices");
glBindAttribLocation(m_program, VBO_TEXCORD, "texCoords");
glLinkProgram(m_program);
checkShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");
glValidateProgram(m_program);
checkShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program");
}
Shader::~Shader() {
for (int i = 0; i < SHA_COUNT; i++) {
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
string Shader::loadShader(string filePath) {
ifstream file;
file.open((filePath).c_str());
string output;
string line;
if(file.is_open()) {
while(file.good()) {
getline(file, line);
output.append(line + "\n");
}
}
else {
printf("Unable to load shader: %s\n", filePath.c_str());
}
return output;
}
void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, string errorMessage) {
GLint success = 0;
GLchar error[1024] = {0};
if (isProgram) {
glGetProgramiv(shader, flag, &success);
}
else {
glGetShaderiv(shader, flag, &success);
}
if (success == GL_FALSE) {
if(isProgram) {
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
}
else {
glGetShaderInfoLog(shader, sizeof(error), NULL, error);
}
printf("%s: '%s'\n", errorMessage.c_str(), error);
}
}
GLuint Shader::createShader(string text, unsigned int type) {
GLuint shader = glCreateShader(type);
if (shader == 0) {
printf("Error compiling shader type %i\n", type);
}
const GLchar *p[1];
p[0] = text.c_str();
GLint lengths[1];
lengths[0] = text.length();
glShaderSource(shader, 1, p, lengths);
glCompileShader(shader);
checkShaderError(shader, GL_COMPILE_STATUS, false, "Error compiling shader!");
return shader;
}
void Shader::bind() {
glUseProgram(m_program);
}
EDIT: Here is my vertices and texCoords:
//Create test objects
ObjectData *obj = new ObjectData();
obj->vertices.push_back(glm::vec3(-1, 0, 0));
obj->vertices.push_back(glm::vec3(0, 0.5, 0));
obj->vertices.push_back(glm::vec3(0, -0.5, 0));
obj->texCoords.push_back(glm::vec2(0.0, 0.5));
obj->texCoords.push_back(glm::vec2(0.5, 0.75));
obj->texCoords.push_back(glm::vec2(0.5, 0.25));
obj->vertices.push_back(glm::vec3(1, 0, 0));
obj->vertices.push_back(glm::vec3(0, 0.5, 0));
obj->vertices.push_back(glm::vec3(0, -0.5, 0));
obj->texCoords.push_back(glm::vec2(1.0, 0.5));
obj->texCoords.push_back(glm::vec2(0.5, 0.75));
obj->texCoords.push_back(glm::vec2(0.5, 0.25));
Here is my object data:
struct ObjectData {
vector <glm::vec3> vertices, normals, colors;
vector <glm::vec2> texCoords;
vector <GLint> indices;
ObjectData();
};