OpenGL 3 VAO + Shaders with Indices

I’ve played with OpenGL a fair bit in the past, but never anything using the “newer” VAO/VBO and Shader stuff, so bear with me here…

What I’ve already managed to achieve is being able to render a VAO - consisting of for now a Vertex VBO and a Colour VBO, though hopefully with textures and normals added in later - using a vertex and fragment shader. What I’d like to do is extend it so that I can define each vertex only once and use indices to specify which ones are actually used, when rendering a model that shares vertices…

If I’m understanding things right, I need to be using glDrawElements to draw the indexed version, having set up a VBO bound to the GL_ELEMENT_ARRAY_BUFFER target. I can’t make it work though, and I can’t for the life of me work out why not…

The code that I’ve got so far that works fine looks - roughly - like the following: (I say roughly because it’s actually several different C++ classes spread across a few files, but that’s essentially what the OpenGL specific calls look like)


// Setup

// vertex shader
GLuint mVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(mVertexShader, 1, (const GLchar**)&src, &len);
glCompileShader(mVertexShader);

// fragment shader
GLuint mFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(mFragmentShader, 1, (const GLchar**)&src, &len);
glCompileShader(mFragmentShader);

// program
GLuint mProgram = glCreateProgram();
glAttachShader(mProgram, mVertexShader);
glAttachShader(mProgram, mFragmentShader);
glBindAttribLocation(mProgram, 0, "in_Position");
glBindAttribLocation(mProgram, 1, "in_Colour");
glLinkProgram(mProgram);

// vao
GLuint mVao
glGenVertexArrays(1, &mVao);

// vertex vbo
GLuint mVertexVbo
glGenBuffers(1, &mVertexVbo);
glBindBuffer(GL_ARRAY_BUFFER, mVertexVbo);
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(GLfloat), rawVertexData, GL_STATIC_DRAW);

// colour vbo
GLuint mColourVbo
glGenBuffers(1, &mColourVbo);
glBindBuffer(GL_ARRAY_BUFFER, mColourVbo);
glBufferData(GL_ARRAY_BUFFER, colourCount * sizeof(GLfloat), rawColourData, GL_STATIC_DRAW);

// Render

// program
glUseProgram(mProgram);
glUniformMatrix4fv(glGetUniformLocation(mProgram, "mvpmatrix"),
                       1,
                       GL_FALSE,
                       glm::value_ptr(matrix));

// general setup
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// vao
glBindVertexArray(mVao);

// vertex vbo
glBindBuffer(GL_ARRAY_BUFFER, mVertexVbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

// colour vbo
glBindBuffer(GL_ARRAY_BUFFER, mColourVbo);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);

glDrawArrays(GL_TRIANGLES, 0, rows);

My understanding was that in order to use Indices instead I’d simply replace the last line with


// index vbo
GLuint mIndexVbo
glGenBuffers(1, &mIndexVbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexVbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLubyte), rawIndexData, GL_STATIC_DRAW);

glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_BYTE, 0);

But when I do that I get a black screen instead of my - currently - two triangles being drawn…

What am I doing wrong? :slight_smile:

Ok - I don’t know what the problem was, but I’ve put the exact snippit of code that I had before back into my code and it works perfectly this time… Stoopid computers :slight_smile:

Hi,
Shouldn’t these calls


glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(GLfloat), rawVertexData, GL_STATIC_DRAW);
...
glBufferData(GL_ARRAY_BUFFER, colourCount * sizeof(GLfloat), rawColourData, GL_STATIC_DRAW);

be


glBufferData(GL_ARRAY_BUFFER, vertexCount * 3 * sizeof(GLfloat), rawVertexData, GL_STATIC_DRAW);
...
glBufferData(GL_ARRAY_BUFFER, colourCount * 3 * sizeof(GLfloat), rawColourData, GL_STATIC_DRAW);

since each vertex/color has 3 components?

No, because the way the code was structured the counts were actually the number of gloats in the arrays being given to the VBO, so vertexCount was actually the number of floats in rawVertexData and not the number of vertices in rawVertexData…

As I said, having cleared the code out and re-written it it all works fine now so I suspect I just had something slightly wrong first time that wasn’t jumping out…

I might not know much about OpenGL except for what little I’ve learned recently, but I have been looking into starting with learning the newer VBO code and forget about the old style of glBegin(…); glEnd();

From what I have seen from the tutorials I have on VBOs is that if you pass indices you have to have a IBO set up for that, but still have to have a VBO to house the vertices, normals, and colors. The IBO should only house the indices though.

However, according to what I discovered in a similar thread I posted, your normals had better follow the same index as the vertices, and so should the colors otherwise the code gets a lot more complicated to parse the index on your own and build your model but changing the normals as necessary during the process. Otherwise your faces will always transition smoothly into each other and thus you won’t have any flat faces and only rounded ones.