Hello forums,
i need some help understanding the “VAO Pipeline”. i have had it working many times, but often times i change something, opengl would not render my models anymore. in the end it was often a simple issue like the order in which i call glBindBuffer and glEnableVertexAttribArray. now that my engine grows larger, i am getting these problems repeatedly. so here is the code i am having issues with:
//...COMPILE SHADER PROGRAMS AND USE THEM
//THIS IS A FUNCTION WHICH IS SUPPOSED TO DRAW A WIREFRAME PLANE
//IT IS CALLED EVERY FRAME
void Graphic::renderGrid()
{
static GLuint gridvID = 0;
static GLuint gridiID = 0;
static bool loaded = false;
//SOME HARDCODED VARIABLES
int scale = 10;
unsigned int vertexNum = scale * scale;
unsigned int indexNum = scale * scale * 6;
static unsigned int indexArray[600];
static Vertex vertexArray[100];
//ONLY LOAD THE GRID ONCE, USING A "LOADED" BOOLEAN
if (!loaded) {
glCreateBuffers(1, &gridvID);
glCreateBuffers(1, &gridiID);
//FILL VERTEX ARRAY WITH THIS ALGORITHM
for (int vert = 0; vert < vertexNum; vert++) {
static int itx = 0;
static int itz = 0;
vertexArray[vert].position.x = -1.0f*(scale / 2 - itx);
vertexArray[vert].position.y = 0.0f;
vertexArray[vert].position.z = -1.0f*(scale / 2 - itz);
vertexArray[vert].color.r = 1.0f;
vertexArray[vert].color.g = 1.0f;
vertexArray[vert].color.b = 1.0f;
vertexArray[vert].color.a = 1.0f;
if (itx == scale) {
itx = 0;
itz++;
}
else {
itx++;
}
}
//FILL INDEX ARRAY WITH THIS ALGORITHM
int runner = 0;
for (unsigned int row = 0; row < scale; row++) {
for (unsigned int col = 0; col < scale; col++) {
indexArray[runner++] = scale *row + col;
indexArray[runner++] = scale *row + col + scale;
indexArray[runner++] = scale *row + col + scale + 1;
indexArray[runner++] = scale *row + col;
indexArray[runner++] = scale *row + col + scale + 1;
indexArray[runner++] = scale *row + col + 1;
}
}
//UPLOAD VERTEX AND INDEX DATA
//RIGHT ORDER?
glBindBuffer(GL_ARRAY_BUFFER, gridvID);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*vertexNum, vertexArray, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridiID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*indexNum, indexArray, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
loaded = true;
}
//USER CONTROLS THIS BOOLEAN TO SHOW OR HIDE THE GRID
if (showGrid) {
//I WOULD LIKE THIS TO WORK WITHOUT ANY MATRICES, BECAUSE THE GRID SHOULD BE STATIC(OR CHANGE WITH THE PLAYER POSITION)
glm::mat4 translate = glm::translate(Camera::camMatrix(), glm::vec3(0.0f, 0.0f, 0.0f));
//IS THERE ANY WAY TO MAKE GLM::ROTATE WORK WITH A 0 VECTOR? WHENEVER I HAD A ROTATION VECTOR OF 0,0,0 THE MESH DISAPPEARED (BUT THATS A DIFFERENT PROBLEM)
glm::mat4 rotate = glm::rotate(translate, 0.0f, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 gridMatrix = glm::scale(rotate, glm::vec3(1.0f, 1.0f, 1.0f));
glBindBuffer(GL_ARRAY_BUFFER, gridvID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridiID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
ShaderProgram shader;
//UPDATE THE SHADER UNIFORMS EVERY FRAME (IS THERE A MORE EFICIENT WAY?)
if (ShaderProgram::find("ColorShader", shader)) {
shader.addUniform("transformationMatrix", gridMatrix);
shader.addUniform("timeMS", Time::programMS);
}
else {
printf("ColorShader shader not found.
");
}
//I HAD THIS CALL WORKING BEFORE WITHOUT GIVING THE LAST PARAMETER, I JUST BOUND THE INDEX ARRAY ID
glDrawElements(GL_LINES, indexNum, GL_UNSIGNED_INT, indexArray);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
This is basically how i do all my rendering in my engine, but the world models are created in a seperate class from my Graphic class and are being passed as a Model object with pointers to the heap allocated dynamic arrays. It worked before, but appearently i changed something and now it doesnt work any more. Could anybody point me the bug or give me some advice on how to do this in a better way?
Thanks
EDIT:
when i use glDrawArrays it works fine, so it seems to be something with the indexing. Also one thing i noticed is that it once worked when i bound the index array buffer ID (gridiID) as a GL_ARRAY_BUFFER instead of a GL_ELEMENT_ARRAY_BUFFER, what suprised me.