Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Depth test problem.

  1. #1
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    4

    Depth test problem.

    Iíve been trying to implement depth testing in my rendering engine, but Iím running into a problem which I canít seem to figure out!

    Iím rendering my entire scene to a FBO texture at a fixed resolution, and this is later scaled to the window framebuffer to achieve quick and easy resolution independence, and I have had this working for quite some time.

    Other than that texture, I have now enabled deth tests and added a renderbuffer to this FBO as such:

    Code :
            glEnable(GL_DEPTH_TEST);
     
            glDepthMask(GL_TRUE);
            glClearDepth(1.f);
     
            glDepthRangef(0.f,
                          1.f);
     
            Ö.
     
            glGenRenderbuffers(1,
                               &g_depth_renderbuffer);
     
            glBindRenderbuffer(GL_RENDERBUFFER,
                               g_depth_renderbuffer);
     
            glRenderbufferStorage(GL_RENDERBUFFER,
                                  GL_DEPTH_COMPONENT,
                                  a_resolution.x,
                                  a_resolution.y);
     
            glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                                      GL_DEPTH_ATTACHMENT,
                                      GL_RENDERBUFFER,
                                      g_depth_renderbuffer);



    Then I have a function to clear all buffers that looks like this:

    Code :
    void
    renderer_clear_all_buffers()
    {
            glBindFramebuffer(GL_FRAMEBUFFER,
                              0);
     
            glClearColor(1.f,
                         0.f,
                         0.f,
                         1.f);
     
            glClear(GL_COLOR_BUFFER_BIT);
     
            glBindFramebuffer(GL_FRAMEBUFFER,
                              g_framebuffer);
     
            glClearColor(0.f,
                         0.f,
                         0.f,
                         1.f);
     
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }

    and then for rendering the scene I do this, in order to avoid having my scene texture that I scale to the screen fail the depth test:

    Code :
    glDepthFunc(GL_LESS);
     
    /*Render scene here*/
     
    glDepthFunc(GL_ALWAYS);
     
    /*Render final framebuffer texture to a quad covering the screen here*/

    Now, with depth testing disabled, if I try to render two object of different sizes at the origin, the one rendered last is always shown above the first one, no matter how I rotate the scene, as expected.
    But with depth testing enabled the opposite happens, and the first object is always rendered completely above the other, no matter how the scene is rotated, even tho the two object now should be rendered over different parts of each other.

    If I change from
    Code :
    glDepthFunc(GL_LESS);
    to
    Code :
    glDepthFunc(GL_LEQUAL);
    , the scene is rendered as if depth testing is disabled again, leading me to believe that all fragments that are not at the far plane get the same value, and after some more digging it would seam that all fragments get the depth value of 0.5.

    I canít spot my error here, so any help to straighten this out would be greatly appreciated!

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,408
    Quote Originally Posted by Dregel View Post
    If I change from
    Code :
    glDepthFunc(GL_LESS);
    to
    Code :
    glDepthFunc(GL_LEQUAL);
    , the scene is rendered as if depth testing is disabled again, leading me to believe that all fragments that are not at the far plane get the same value, and after some more digging it would seam that all fragments get the depth value of 0.5.

    I canít spot my error here, so any help to straighten this out would be greatly appreciated!
    The error would appear to be in the rendering code or the shaders, not the framebuffer setup.

    The fact that glDepthFunc(GL_LESS) results in the first object having precedence indicates that you do have a depth buffer and that depth testing is working correctly.

    How is the Z coordinate generated? Are you using the fixed-function pipeline, or shaders? If it's the fixed-function pipeline, how are you setting the model-view and projection matrices? If you're using shaders, how does the vertex shader set gl_Position?

  3. #3
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    4
    Well yeah, I seem to have functional depth testing in that sense, but It seems as if every single fragment ends up with the same depth value, namely 0.5, and that in turn makes the depth testing not allowing the closest fragment through to the "top", so i guess it could be the rendering or shader code, so here it goes!

    First my vertex shader:
    Code :
    precision highp float;
     
    layout (location = 0) in vec3 pos;
    layout (location = 1) in vec2 uv;
     
    uniform mat4 mvp;
    uniform vec2 uvOffset;
    uniform vec2 uvExtents;
     
    out vec2 TexCoord;
     
    void
    main()
    {
        gl_Position = mvp * vec4(pos, 1.0f);
        TexCoord = (uv * uvExtents) + uvOffset;
        TexCoord.y = 1.0f - TexCoord.y;
    }

    my fragment shader:
    Code :
    precision highp float;
     
    uniform sampler2D spriteTexture;
    uniform vec4 color;
     
    in vec2 TexCoord;
     
    out vec4 FragColor;
     
    void
    main()
    {
        FragColor = texture2D(spriteTexture, TexCoord.xy) * color;
    }

    And here is my rendering code for rendering a simple cube:
    Code :
            scale = mat4_identity();
            scale.m11 = g_job_queue.jobs[i].scale.x;
            scale.m22 = g_job_queue.jobs[i].scale.y;
            scale.m33 = g_job_queue.jobs[i].scale.z;
     
            rotation = quaternion__get_matrix(g_job_queue.jobs[i].rotation);
     
            translation = mat4_identity();
            translation.m41 = g_job_queue.jobs[i].position.x;
            translation.m42 = g_job_queue.jobs[i].position.y;
            translation.m43 = g_job_queue.jobs[i].position.z;
     
            pivot = mat4_identity();
            pivot.m41 = g_job_queue.jobs[i].pivot.x;
            pivot.m42 = g_job_queue.jobs[i].pivot.y;
            pivot.m43 = g_job_queue.jobs[i].pivot.z;
     
            model = mat4_identity();
     
            model = mat4_multiply(model,
                                  scale);
     
            model = mat4_multiply(model,
                                  pivot);
     
            model = mat4_multiply(model,
                                  rotation);
     
            model = mat4_multiply(model,
                                  translation);
     
            mvp = model;
     
            if(g_job_queue.jobs[i].render_in_world == true)
            {
                    mvp = mat4_multiply(mvp,
                                        mat4_invert(g_camera.view));
            }
     
            mvp = mat4_multiply(mvp,
                                g_camera.projection);
     
            glActiveTexture(GL_TEXTURE0);
     
            glBindTexture(GL_TEXTURE_2D,
                          texture_manager_get_texture_gl_name(g_job_queue.jobs[i].texture_id));
     
            glTexParameterf(GL_TEXTURE_2D,
                            GL_TEXTURE_MIN_FILTER,
                            GL_NEAREST);
     
            glTexParameterf(GL_TEXTURE_2D,
                            GL_TEXTURE_MAG_FILTER,
                            GL_NEAREST);
     
            glUniform1i(g_sprite_texture_location,
                        0);
     
            glUniform4f(g_color_location,
                        g_job_queue.jobs[i].color.x,
                        g_job_queue.jobs[i].color.y,
                        g_job_queue.jobs[i].color.z,
                        g_job_queue.jobs[i].color.w);
     
            glUniformMatrix4fv(g_mvp_location,
                               1,
                               GL_FALSE,
                               (GLfloat*)&mvp);
     
            glUniform2f(g_uv_offset_location,
                        g_job_queue.jobs[i].uv_offset.x,
                        g_job_queue.jobs[i].uv_offset.y);
     
            glUniform2f(g_uv_extents_location,
                        g_job_queue.jobs[i].uv_extents.x,
                        g_job_queue.jobs[i].uv_extents.y);
     
            glBindBuffer(GL_ARRAY_BUFFER,
                         g_box_vbo);
     
            glBufferData(GL_ARRAY_BUFFER,
                         sizeof(vertex) * 24,
                         g_box_vertices,
                         GL_STATIC_DRAW);
     
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
                         g_box_ibo);
     
            glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                         sizeof(uint32_t) * 36,
                         g_box_indices,
                         GL_STATIC_DRAW);
     
            glVertexAttribPointer(0,
                                  3,
                                  GL_FLOAT,
                                  GL_FALSE,
                                  sizeof(vertex),
                                  NULL);
     
            glVertexAttribPointer(1,
                                  2,
                                  GL_FLOAT,
                                  GL_FALSE,
                                  sizeof(vertex),
                                  (uint8_t*)NULL + 12);
     
            glDrawElements(GL_TRIANGLES,
                           36,
                           GL_UNSIGNED_INT,
                           0);

    Other than that, the only thing that might be relevant that i can think of is how i create my view and projection matrices, specifically the function i made to create a projection matrix, so here is that cad as well:
    Code :
    mat4
    mat4_perspective(const float a_fov,
                     const float a_aspect,
                     const float a_near,
                     const float a_far)
    {
            mat4    result;
            float   factor;
            int64_t near_factor;
     
            factor = 1.0 / tan_float(a_fov / 2.0);
            near_factor = 1 / (a_near - a_far);
     
            result.m11 = factor / a_aspect;
            result.m12 = 0.0;
            result.m13 = 0.0;
            result.m14 = 0.0;
     
            result.m21 = 0.0;
            result.m22 = factor;
            result.m23 = 0.0;
            result.m24 = 0.0;
     
            result.m31 = 0.0;
            result.m32 = 0.0;
            result.m33 = (a_near + a_far) * near_factor;
            result.m34 = -1.0;
     
            result.m41 = 0.0;
            result.m42 = 0.0;
            result.m43 = (2.0 * a_near * a_far) * near_factor;
            result.m44 = 0.0;
     
            return result;
    }
     
     
    void
    init_opengl()
    {
            g_camera.view = mat4_translate(mat4_identity(),
                                           vec3_new(0.f,
                                                    0.f,
                                                    5.f));
     
            g_camera.projection = mat4_perspective(120.f,
                                                   a_resolution.x / a_resolution.y,
                                                   0.1f,
                                                   100.f);
     
     ...
     
    }

  4. #4
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,687
    When creating your projection matrix what values do you use? This is the kind of undefined behaviour that might happen if you had a near flipping plane of 0.

  5. #5
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    4
    It is included in the last code part of my last post, but here it is again:
    Code :
            view = mat4_translate(mat4_identity(),
                                  vec3_new(0.f,
                                           0.f,
                                           5.f));
     
            projection = mat4_perspective(120.f,
                                          a_resolution.x / a_resolution.y,
                                          0.1f,
                                          100.f);

    But i have also tried with values as high as 90.0 for the near plane with the same results.
    But maybe there is something wrong with my function for generating the projection matrix, because unless i have completely misunderstood the function of the far and near plane, i should not be able to see a cube of size (1.0, 1.0, 1.0) at position (0.0, 0.0, 0.0) with a view from position (0.0, 0.0, 5.0) and with a near plane at 90.0 and far plane at 100.0?

  6. #6
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    4
    And directly after posting my latest post i solved it!
    The problem was in my function for creating projection matrices.

    Code :
    mat4
    mat4_perspective(const float a_fov,
                     const float a_aspect,
                     const float a_near,
                     const float a_far)
    {
            mat4    result;
            float   factor;
            int64_t near_factor;
     
            factor = 1.0 / tan_float(a_fov / 2.0);
            near_factor = 1 / (a_near - a_far);
     
            result.m11 = factor / a_aspect;
            result.m12 = 0.0;
            result.m13 = 0.0;
            result.m14 = 0.0;
     
            result.m21 = 0.0;
            result.m22 = factor;
            result.m23 = 0.0;
            result.m24 = 0.0;
     
            result.m31 = 0.0;
            result.m32 = 0.0;
            result.m33 = (a_near + a_far) * near_factor;
            result.m34 = -1.0;
     
            result.m41 = 0.0;
            result.m42 = 0.0;
            result.m43 = (2.0 * a_near * a_far) * near_factor;
            result.m44 = 0.0;
     
            return result;
    }

    After re-checking the function to make sure that I was not making any mistakes i noticed that the variable near_factor was declared as an int and not a float, effectively truncating values and resulting in weird relations between far and near planes!
    So simply changing the declaration to a float solved the problem!

    A slight oversight that gave me a lot of headache weeks after writing the function! :P

    Thanks for all the help!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •