0
$\begingroup$

I'm trying to render a cube and it's wireframe together using OpenGL

The main function is this:

int main(int argc, char** argv)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;



    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(1024, 768, "MyGL", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK) {
        std::cout << "Error!" << std::endl;
    }

    float positions[] = {
                          -0.5f, -0.5f,  0.5f,      //0
                           0.5f, -0.5f,  0.5f,      //1
                           0.5f,  0.5f,  0.5f,      //2
                          -0.5f,  0.5f,  0.5f,      //3
                          -0.5f,  0.5f, -0.5f,      //4
                           0.5f,  0.5f, -0.5f,      //5
                          -0.5f, -0.5f, -0.5f,      //6
                           0.5f, -0.5f, -0.5f       //7
    };

    unsigned int indices[] = {
                              0, 1, 2, 3,
                              4, 5, 6, 7,
                              2, 3, 4, 5,
                              2, 5, 7, 1,
                              1, 0, 6, 7,
                              0, 6, 3, 4
    };

    unsigned int w_indices[] = {
                                0, 1, 1, 2, 2, 3, 3, 0,     // fronte
                                0, 6, 6, 7, 7, 1, 1, 0,     // sotto
                                3, 2, 2, 5, 5, 4, 4, 3,     // sopra
                                4, 5, 5, 7, 7, 6, 6, 4,     // retro
                                2, 5, 5, 7, 7, 1, 1, 2,     // destra
                                3, 4, 4, 6, 6, 0, 0, 3      // sinistra

    };


    unsigned int buffer;
    unsigned int index_buffer[2];

    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(float), positions, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(2, index_buffer);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 24 * sizeof(int), indices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 48 * sizeof(int), w_indices, GL_STATIC_DRAW);

    glm::mat4 proj = glm::ortho(-2.0f, 2.0f, -1.5f, 1.5f, -1.0f, 1.0f);

    glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(-0.4, 0, 0));

    glm::mat4 view2 = glm::rotate(view, 30.0f, glm::vec3(0.0f, -1.0f, 1.0f));

    glm::mat4 mvp = proj * view2;


    ShaderProgramSource source = parseShader("C:\\Users\\Lukkio\\Documents\\Gildo\\res\\shader\\myShader.shader");

    unsigned int shader = createShader(source.vertex_source, source.fragment_source);
    glUseProgram(shader);

    int location = glGetUniformLocation(shader, "u_color");
    int u_mvp = glGetUniformLocation(shader, "u_MVP");



    glUniform4f(location, 0.0, 1.0, 1.0, 1.0);

    glUniformMatrix4fv(u_mvp, 1, GL_FALSE, &mvp[0][0]);

    float r = 0.0f;
    float g = 1.0f;
    float b = 1.0f;

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);


        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


        glUniform4f(location, r, g, b, 0);

        glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, nullptr);

        glUniform4f(location, 1.0, 0.0, 0.0, 0.0);

        glDrawElements(GL_LINES, 48, GL_UNSIGNED_INT, nullptr);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glDeleteProgram(shader);

    glfwTerminate();
    return 0;
}

I'm not an openGL expert, I know bits and pieces but I rarely practice so this is mostly for refreshing.

The way I was trying to achieve this was to create two index buffers, but no matter what I do I can't manage.

I also noticed the 4th argument of glDrawElements but however I cannot manage to find what exactly I would need to pass. Because I'm essentially rendering two different objects I read I might use VAO but regardless of whether or not this is the right approach I'd like to know what is wrong with my approach of two index buffers, and a single vertex buffer.

So here the questions:

  1. Why isn't it working? What am I missing?
  2. For this specific task (object + wireframe) is there maybe a much simpler approach that I'm missing?

Thank you

$\endgroup$
0

1 Answer 1

1
$\begingroup$

I'd like to know what is wrong with my approach of two index buffers, and a single vertex buffer.

There is nothing wrong with that. Reusing resources and avoiding duplicate data is always a good thing.

Why isn't it working? What am I missing?

Basically, you already got the answer: " I read I might use VAO"

In the Vertex Array Object section of this tutorial there is a big red block stating:

Core OpenGL requires that we use a VAO so it knows what to do with our vertex inputs. If we fail to bind a VAO, OpenGL will most likely refuse to draw anything.

Can't tell if there are any other problems with your code, but the missing VAO is probably the main one.

I suggest you read the whole text on the site I linked and follow the instructions to render a single triangle. Afterwards, add some more triangles and try to render them using an index buffer. If you got so far, it should be easy to get your approach working.

For this specific task (object + wireframe) is there maybe a much simpler approach that I'm missing?

I think there are many different ways to do this. One way would be to use a single draw call and check inside the fragment shader if the current pixel is close to one of the sides of the triangle. If this is the case, just overwrite the fragment's colour with your desired wireframe colour. This answer on Stack Overflow shows you how to do that. You just need to modify it a little bit so that "non-wireframe" sections are rendered normally instead of being translucent.

Also, check the other answers in the Stack Overflow link. There a lot of different approaches mentioned.

$\endgroup$
3
  • $\begingroup$ Hi, for sake of this exercise I'd rather not use the shader too much. I read the link you mentioned but I still can't figure why I can sort out my problem with the VAO. Can you maybe give me an insight on why this would work and how would I need to modify my code to achieve the result? $\endgroup$ Sep 28, 2020 at 15:45
  • $\begingroup$ The VAO stores the whole state of the object you want to render. Which Buffers does it use, how is the data in those buffers structured (glVertexAttribPointer), etc. Without the VAO, glDrawElements doesn't know what to render. Maybe I'll find the time on the weekend to give you a minimal working example, but I can't promise that. In the meantime, try to understand from the tutorial how VOAs work. You can't use modern OpenGL without them and as soon as you understood them, you might already know how to solve your problem. $\endgroup$
    – wychmaster
    Sep 29, 2020 at 11:17
  • $\begingroup$ I've asked a related question : computergraphics.stackexchange.com/questions/10332/…. Feel free to jump in. $\endgroup$ Oct 22, 2020 at 16:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.