irishMTS irishMTS - 1 month ago 6
C++ Question

How to properly add OpenGL code into an external function

I am attempting to be able to take some OpenGL code that draws objects from a vertex array and add it to a class file. However, the code only runs currently when I have it in my main.cpp file. I call init() from my main() function, before heading into my draw loop.

init(){
GLuint containerVAO, VBO;
glGenVertexArrays(1, &containerVAO);
glGenBuffers(1, &VBO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindVertexArray(containerVAO);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Normal attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),(GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
}


The relevant code in my draw loop:

glUseProgram(noTextureShaderID);
glBindVertexArray(containerVAO);
///many different uniforms added here
glDrawArrays(GL_TRIANGLES, 0, 36);


This creates a cube no problem.
Now, when I replace the code inside my init() function (which initialises all objects, not just this one, I change it to this:

init(){
square.init(noTextureShaderID, vertices[], NULL, 36);
//Square is a global variable within my main.cpp file
}


And then I use this function:

void Mesh::init(const GLuint& shaderid, GLfloat vertices[], const char* tex_file, int num_vertices)
{
GLuint VBO;
vao = NULL; //This is a variable within the Mesh class
g_point_count = num_vertices;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &VBO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindVertexArray(vao);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Normal attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
}


Then, in my draw function I call this instead:

glUseProgram(noTextureShaderID);
glBindVertexArray(square.vao);
///many different uniforms added here
glDrawArrays(GL_TRIANGLES, 0, g_point_count);


But even though both programs seem to have the same code, only the first version generates a cube. What am I missing in this regard?

Answer

Your code is not identical in both cases, and this has nothing to do with OpenGL:

void Mesh::init(const GLuint& shaderid, GLfloat vertices[], const char* tex_file, int num_vertices)
{
     // ...
     glBufferData(..., sizeof(vertices), ...);
}

vertices is passed by reference here, the inner function will never see the array, and sizeof(vertices) will be identical to sizeof(GLfloat*), which is typically 4 or 8 on todays machines. Hence, your buffer is just containing the first one or two floats.

You either have to explicitely provide the array size as an additional parameter, or you use some (reference to an) higher-level object like std:vector, which completely manages the array internally and allows you to query the size.

Comments