denormal
denormal

Reputation: 93

Why are the front faces culled rendering a cube with OpenGL?

I'm writing a OpenGL 3.3 program which displays some primitives. The lighting is simple, just diffuse and ambient.

enter image description here

Cube vertex shader.

#version 440 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 a_normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 normal;
out vec3 fragpos;

void main(void)
{
    fragpos = vec3(model * vec4(position, 1.0));
    
    gl_Position = projection * view * vec4(fragpos, 1.0);
    normal = a_normal;
}

Cube fragment shader.

#version 440 core

out vec4 frag_color;

in vec3 normal;
in vec3 fragpos; 

uniform vec4 color;

struct light_source
{
    vec3 position;
    vec3 color;
    bool enable;
};

uniform light_source light0;

vec3 calc_diffuse_light(vec3 light_position, vec3 light_color)
{
    // ambient
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * light_color;
    
    // diffuse 
    vec3 norm = normalize(normal);
    vec3 light_dir = normalize(light_position - fragpos);
    float diff = max(dot(norm, light_dir), 0.0);
    vec3 diffuse = diff * light_color;
            
    return (ambient + diffuse) * color.xyz;
}

void main(void)
{
    vec3 result = vec3(0.0);
    if (light0.enable)
        result += calc_diffuse_light(light0.position, light0.color);
    
    frag_color = vec4(result, 1.0);
}

Cube setup.

#include "gl_cube_model.h"
#include "gl_lights.h"


cube_model::cube_model(float size, const glm::vec3& position, const glm::vec4& color) :
    model_base(position),
    m_color(color)
{
    float halfwidth = size / 2.0f;
    float vertices[] =
    {
        //  Three position components + normals.

        // front face
        -halfwidth, -halfwidth, halfwidth, 0.0f, 0.0f, 1.0f, // front bottom left
        -halfwidth,  halfwidth, halfwidth, 0.0f, 0.0f, 1.0f, // front top left
         halfwidth,  halfwidth, halfwidth, 0.0f, 0.0f, 1.0f, // front top right
         halfwidth, -halfwidth, halfwidth, 0.0f, 0.0f, 1.0f, // front bottom right
        -halfwidth, -halfwidth, halfwidth, 0.0f, 0.0f, 1.0f, // front bottom left
         halfwidth,  halfwidth, halfwidth, 0.0f, 0.0f, 1.0f, // front top right

        // back face
        -halfwidth, -halfwidth, -halfwidth, 0.0f, 0.0f, -1.0f, // back bottom left
        -halfwidth,  halfwidth, -halfwidth, 0.0f, 0.0f, -1.0f, // back top left
         halfwidth,  halfwidth, -halfwidth, 0.0f, 0.0f, -1.0f, // back top right
         halfwidth, -halfwidth, -halfwidth, 0.0f, 0.0f, -1.0f, // back bottom right
        -halfwidth, -halfwidth, -halfwidth, 0.0f, 0.0f, -1.0f, // back bottom left
         halfwidth,  halfwidth, -halfwidth, 0.0f, 0.0f, -1.0f, // back top right

         // left face
         -halfwidth, -halfwidth, -halfwidth, -1.0f, 0.0f, 0.0f, // back bottom left
         -halfwidth,  halfwidth, -halfwidth, -1.0f, 0.0f, 0.0f, // back top left
         -halfwidth,  halfwidth, halfwidth,  -1.0f, 0.0f, 0.0f, // front top left
         -halfwidth, -halfwidth, halfwidth,  -1.0f, 0.0f, 0.0f, // front bottom left
         -halfwidth, -halfwidth, -halfwidth, -1.0f, 0.0f, 0.0f, // back bottom left
         -halfwidth,  halfwidth, halfwidth,  -1.0f, 0.0f, 0.0f, // front top left

         // right face
         halfwidth, -halfwidth, halfwidth,  1.0f, 0.0f, 0.0f, // front bottom right
         halfwidth,  halfwidth, halfwidth,  1.0f, 0.0f, 0.0f, // front top right
         halfwidth,  halfwidth, -halfwidth, 1.0f, 0.0f, 0.0f, // back top right
         halfwidth, -halfwidth, -halfwidth, 1.0f, 0.0f, 0.0f, // back bottom right
         halfwidth, -halfwidth, halfwidth,  1.0f, 0.0f, 0.0f, // front bottom right
         halfwidth,  halfwidth, -halfwidth, 1.0f, 0.0f, 0.0f, // back top right

         // top face
         -halfwidth,  halfwidth, halfwidth,  0.0f, 1.0f, 0.0f, // front top left
         -halfwidth,  halfwidth, -halfwidth, 0.0f, 1.0f, 0.0f, // back top left
          halfwidth,  halfwidth, -halfwidth, 0.0f, 1.0f, 0.0f, // back top right
          halfwidth,  halfwidth, halfwidth,  0.0f, 1.0f, 0.0f, // front top right
         -halfwidth,  halfwidth, halfwidth,  0.0f, 1.0f, 0.0f, // front top left
          halfwidth,  halfwidth, -halfwidth, 0.0f, 1.0f, 0.0f, // back top right

         // bottom face
         -halfwidth, -halfwidth, halfwidth,  0.0f, -1.0f, 0.0f, // front bottom left
         -halfwidth, -halfwidth, -halfwidth, 0.0f, -1.0f, 0.0f, // back bottom left
          halfwidth, -halfwidth, -halfwidth, 0.0f, -1.0f, 0.0f, // back bottom right
          halfwidth, -halfwidth, halfwidth,  0.0f, -1.0f, 0.0f, // front bottom right
         -halfwidth, -halfwidth, halfwidth,  0.0f, -1.0f, 0.0f, // front bottom left
          halfwidth, -halfwidth, -halfwidth, 0.0f, -1.0f, 0.0f, // back bottom right
    };

    glDisable(GL_CULL_FACE);

    // Generate VAO.
    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    // Generate VBO.
    glGenBuffers(1, &m_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Vertex position attribute.
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    // Vertex normal attribute.
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    string vert_source;
    if (!read_file_text(SHADER_DIR + "pos_norm.vert", vert_source))
        throw runtime_error("error loading vert shader");

    string frag_source;
    if (!read_file_text(SHADER_DIR + "flat_shade_light.frag", frag_source))
        throw runtime_error("error loading frag shader");

    m_sha.init_from_str(vert_source, frag_source);
}

cube_model::~cube_model()
{
    glDeleteVertexArrays(1, &m_vao);
    glDeleteBuffers(1, &m_vbo);
}

void cube_model::render(const glm::mat4& projection, const glm::mat4& view, const std::shared_ptr<gl_lights>& lights)
{
    m_sha.use();

    glBindVertexArray(m_vao);
    glUniformMatrix4fv(m_sha.get_uniform("model"), 1, GL_FALSE, glm::value_ptr(m_model));
    glUniformMatrix4fv(m_sha.get_uniform("view"), 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(m_sha.get_uniform("projection"), 1, GL_FALSE, glm::value_ptr(projection));
    glUniform4fv(m_sha.get_uniform("color"), 1, glm::value_ptr(m_color));

    glUniform3fv(m_sha.get_uniform("light0.position"), 1, glm::value_ptr(lights->position(0)));
    glUniform3fv(m_sha.get_uniform("light0.color"), 1, glm::value_ptr(lights->color(0)));
    int enabled = (lights->is_enabled(0) ? 1 : 0);
    glUniform1iv(m_sha.get_uniform("light0.enable"), 1, &enabled);

    glDrawArrays(GL_TRIANGLES, 0, 6 * 6);
    glFinish();
}

Note glDisable(GL_CULL_FACE); in there. It seems like the back and front face culling is not to blame for this, and in the code that calls cube_model::render, the depth buffer is cleared so I can't blame depth buffering either.

Upvotes: 0

Views: 520

Answers (2)

MattK
MattK

Reputation: 26

You need to use Depth Testing. just call glEnable(GL_DEPTH_TEST) before your loop starts.

Then you need to clear the depth buffer every frame otherwise it would be using the same depth buffer every time it renders even if the scene changed. Use this inside the main loop: glClear(GL_DEPTH_BUFFER_BIT);

Upvotes: 0

Rabbid76
Rabbid76

Reputation: 210878

You missed to enable the Depth Test.

glEnable(GL_DEPTH_TEST)

Once the depth test is enabled, you have to clear the depth buffer, too:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Upvotes: 1

Related Questions