Search code examples
c++openglglfwglm-mathglad

How come no cube is drawn on my screen with this code in a GLFW window?


I have a bunch of code (copied from various tutorials) that is supposed to draw a random color-changing cube that the camera shifts around every second or so (with a variable, not using timers yet). It worked in the past before I moved my code into distinctive classes and shoved it all into my main function, but now I can't see anything on the main window other than a blank background. I cannot pinpoint any particular issue here as I am getting no errors or exceptions, and my own personally defined code checks out; when I debugged, every variable had a value I expected, and the shaders I used (in string form) worked in the past before I re-organized my code. I can print out the vertices of the cube in the same scope as the glDrawArrays() function as well, and they have the correct values too. Basically, I have no idea what's wrong with my code that is causing nothing to be drawn.

My best guess is that I called - or forgot to call - some opengl function improperly with the wrong data in one of the three methods of my Model class. In my program, I create a Model object (after glfw and glad are initialized, which then calls the Model constructor), update it every once and a while (time doesn't matter) through the update() function, then draw it to my screen every time my main loop is run through the draw() function.

Possible locations of code faults:

    Model::Model(std::vector<GLfloat> vertexBufferData, std::vector<GLfloat> colorBufferData) {

        mVertexBufferData = vertexBufferData;
        mColorBufferData = colorBufferData;

        // Generate 1 buffer, put the resulting identifier in vertexbuffer
        glGenBuffers(1, &VBO);
        // The following commands will talk about our 'vertexbuffer' buffer
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        // Give our vertices to OpenGL.
        glBufferData(GL_ARRAY_BUFFER, sizeof(mVertexBufferData), &mVertexBufferData.front(), GL_STATIC_DRAW);

        glGenBuffers(1, &CBO);
        glBindBuffer(GL_ARRAY_BUFFER, CBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(mColorBufferData), &mColorBufferData.front(), GL_STATIC_DRAW);

        // Create and compile our GLSL program from the shaders
        programID = loadShaders(zachos::DATA_DEF);
        glUseProgram(programID);
    }

    void Model::update() {
        for (int v = 0; v < 12 * 3; v++) {
            mColorBufferData[3 * v + 0] = (float)std::rand() / RAND_MAX;
            mColorBufferData[3 * v + 1] = (float)std::rand() / RAND_MAX;
            mColorBufferData[3 * v + 2] = (float)std::rand() / RAND_MAX;
        }
        glBufferData(GL_ARRAY_BUFFER, sizeof(mColorBufferData), &mColorBufferData.front(), GL_STATIC_DRAW);
    }

    void Model::draw() {

        // Setup some 3D stuff
        glm::mat4 mvp = Mainframe::projection * Mainframe::view * model;

        GLuint MatrixID = glGetUniformLocation(programID, "MVP");
        glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glVertexAttribPointer(
            0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            0,                  // stride
            (void*)0            // array buffer offset
        );
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, CBO);
        glVertexAttribPointer(
            1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
            3,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            0,                                // stride
            (void*)0                          // array buffer offset
        );

        // Draw the array
        glDrawArrays(GL_TRIANGLES, 0, mVertexBufferData.size() / 3);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
    };

My question is simple, how come my program won't draw a cube on my screen? Is the issue within these three functions or elsewhere? I can provide more general information about the drawing process if needed, though I believe the code I provided is enough, since I literally just call model.draw().


Solution

  • sizeof(std::vector) will usually just be 24bytes (since the struct contains 3 pointers typically). So basically both of your buffers have 6 floats loaded in them, which is not enough verts for a single triangle, lets alone a cube!

    You should instead be calling size() on the vector when loading the data into the vertex buffers.

    glBufferData(GL_ARRAY_BUFFER,
       mVertexBufferData.size() * sizeof(float), ///< this!
       mVertexBufferData.data(), ///< prefer calling data() here!
       GL_STATIC_DRAW);