Search code examples
c++visual-studioopenglglfwglew

My code should render the front of a cube, but instead shows the back. Why?


I'm rendering this cube and it should show the front of the cube but instead it shows the back (green color). How do i solve this? I've been sitting for a couple of hours trying to fix this but nothing helped. I was trying various things like changing the order in which the triangles are rendered and it didn't help either. Thanks for any help. Here's my code.

float vertices[] =
{
    //front
    -0.5f, -0.5f, 0.0f,     1.f, 0.0f, 0.5f,
    0.5f, -0.5f, 0.0f,      1.f, 0.0f, 0.5f,
    0.5f, 0.5f, 0.0f,       1.f, 0.0f, 0.5f,
    -0.5f, 0.5f, 0.0f,      1.f, 0.0f, 0.5f,

    //back
    -0.5f/2, -0.5f/2, -0.5f,        0.0f, 1.f, 0.0f,
    0.5f/2, -0.5f/2, -0.5f,         0.0f, 1.f, 0.0f,
    0.5f/2, 0.5f/2, -0.5f,          0.0f, 1.f, 0.0f,
    -0.5f/2, 0.5f/2, -0.5f,         0.0f, 1.f, 0.0f,
};

unsigned int indices[] =
{
    //front
    0, 2, 3,
    0, 1, 2,
    //back
    4, 6, 7,
    4, 5, 6,
    //top
    3, 6, 2,
    3, 7, 6,
    //bottom
    0, 1, 5,
    0, 5, 4,
    //left
    3, 0, 4,
    3, 4, 7,
    //right
    1, 2, 5,
    2, 6, 5
    
};

int main()
{
    if (!glfwInit())
    {
        std::cout << "ERROR" << std::endl;
        return -1;
    }

    int width = 640;
    int height = 480;

    window = glfwCreateWindow(width, height, "OPENGL", NULL, NULL);

    if (!window)
    {
        std::cout << "ERROR: WINDOW" << std::endl;
    }

    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_VERSION_MINOR, 6);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

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

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);


    std::cout << "OpenGL " << glGetString(GL_VERSION) << std::endl;

    VertexArray va1;

    VertexBuffer vb1(vertices, sizeof(vertices), GL_STATIC_DRAW);
    IndexBuffer ib1(indices, sizeof(indices), GL_STATIC_DRAW);

    va1.linkAttrib(vb1, 0, 3, GL_FLOAT, 6 * sizeof(float), 0);
    va1.linkAttrib(vb1, 1, 3, GL_FLOAT, 6 * sizeof(float), 3 * sizeof(float));

    ShaderSources sources = parseShader("basic.shader");
    unsigned int program = createShaderProgram(sources.vertexSource, sources.fragmentSource);
    glUseProgram(program);

    while (!glfwWindowShouldClose(window))
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(unsigned int), GL_UNSIGNED_INT, nullptr);
        glfwSwapBuffers(window);

        glfwPollEvents();
    }

    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

And here what the cube looks like: enter image description here


Solution

  • You currently are using glEnable(GL_DEPTH_TEST) withglDepthFunc(GL_LESS), which means only fragments having a smaller z (or depth) component are rendered when rendering overlapped triangles. Since your vertex positions are defined with the back-face having a smaller z coordinate than the front-face, all front-face fragments are ignored (since their z coordinate is larger).

    Solutions are:

    • Using glDepthFunc(GL_GREATER) instead of glDepthFunc(GL_LESS) (which may not work in your case, considering your vertices have z <= 0.0 and the depth buffer is cleared to 0.0)
    • Modify your vertex positions to give front-face triangles a smaller z component than back-face triangles.

    I believe that when using matrix transforms, a smaller z component normally indicates the fragment is closer to the camera, which is why glDepthFunc(GL_LESS) is often used.