1
\$\begingroup\$

I have to a little bit of a problem with drawing HUD elements on top of my 3d world using a ortho projection. My 3D world keep getting render but there is nothing showing of my UI.

I wrap the code into a shorter version of my program. But I still have the same problem here.

I think i'm missing something for this to work. First this is a the struct for the game obj

struct GameObject
{

    GLuint Id;
    GLuint Shader;
    GLuint uniformMVP;
    GLuint VBO;
    GLuint VAO;
    GLubyte VertexCpt;
    vec3 WorldPossition;
    float Angle;
    float XScale;
    float YScale;
};



void RenderObject(GameObject *obj, mat4 Projection, mat4 View)
{

    glUseProgram(obj->Shader);

    //Calculate The MVP 
    mat4 Model = glm::translate(glm::mat4(1.f), obj->WorldPossition)*glm::rotate(glm::mat4(1.f), obj->Angle, glm::vec3(0.0f, 0.0f, 1.0f))*glm::scale(glm::mat4(1.f), glm::vec3(obj->XScale, obj->YScale, 1.0f));
    mat4 MVP = Projection * View * Model;

    //Set the MVP into the current shader's MVP varaible
    glUniformMatrix4fv(obj->uniformMVP, 1, GL_FALSE, &MVP[0][0]);


    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, obj->VBO);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    // 2nd attribute buffer : colors
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, obj->VAO);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glDrawArrays(GL_TRIANGLES, 0, obj->VertexCpt);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
}

This is the main loop and the matrices

glm::mat4 ProjectionP = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 projectionO = glm::ortho(0.0f, 1024.f, 0.0f, 768.f, 0.1f, 100.0f);
glm::mat4 View = glm::lookAt(
    glm::vec3(5, 5, 5), // Camera is at (4,3,3), in World Space
    glm::vec3(0, 0, 0), // and looks at the origin
    glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
    );




GameObject obj1 = { 1, SimpleShaderProg, uniformMVP, SquareVBO, orangeVAO, 6, vec3(200, 200, 1), 0.f, 100.f, 200.f };
GameObject obj2 = { 2, SimpleShaderProg, uniformMVP, SquareVBO, orangeVAO, 6, vec3(0, 0, -2), 0.f, 1.f, 1.f };
GameObject obj3 = { 3, SimpleShaderProg, uniformMVP, SquareVBO, orangeVAO, 6, vec3(0, 0, 0), 0.f, 1.f, 1.f };
GameObject obj4 = { 4, SimpleShaderProg, uniformMVP, SquareVBO, orangeVAO, 6, vec3(0, 0, 2), 0.f, 1.f, 1.f };

//Main render loop
double lastTime = glfwGetTime();
while ((glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0))
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glfwPollEvents();


    RenderObject(&obj1, projectionO, mat4(1.f)); //<- This object will be render to the screen
    RenderObject(&obj2, ProjectionP, View);
    RenderObject(&obj3, ProjectionP, View);
    RenderObject(&obj4, ProjectionP, View);

    double currentTime = glfwGetTime();
    if (currentTime - lastTime >= 0.02){

        lastTime += 0.02;
    }
    glfwSwapBuffers(window);
}

This is the current configuration

glViewport(0, 0, windowWidth, windowHeight);
glClearColor(0.2f, 0.4f, 0.1f,1.f);

glEnable(GL_CULL_FACE);                                 //Enable culling
glCullFace(GL_FRONT);                                   //

glEnable(GL_BLEND);                                     //Enable blending for all obj
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glEnable(GL_DEPTH_TEST);                                //Enable depth test for all obj
glDepthFunc(GL_LESS);   

Vertex shader

#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;

uniform mat4 MVP;
out vec3 fragmentColor;

void main(){
    gl_Position =  MVP * vec4(vertexPosition_modelspace,1); 
    fragmentColor = vertexColor;
}

Fragment shader

#version 330 core
in vec3 fragmentColor;
out vec4 color;

void main()
{
    color.rgb =  fragmentColor;
    color.a =  1.f;
}

I hope someone can help me with that , and if you need more information feel free to ask. Thanks. NB: English is not my first language, sry about that.

\$\endgroup\$
1
  • \$\begingroup\$ I didn't realise that there were so many C++ programmers here! \$\endgroup\$
    – Lucien
    Nov 15, 2015 at 19:45

1 Answer 1

4
\$\begingroup\$

One way is to disable GL_DEPTH_TEST for rendering 2D stuff. So draw everything of the 3D world like normal, then disable depth testing and then draw your UI at last. Another approach would make use of the depth test by setting the z-component of the vertices for the 2D stuff to 0 (and the near plane in the prohection matrix to something greater than 0) to always pass the depth test as the topmost object on screen, however you would need to pass another coordinate per vertex or set it as a constant in the shader. Generally i find method 1 easier as you don't need to worry about the third coordinate. And simply "first render 3D, then render 2D" is not that much of a sorting task to do.

\$\endgroup\$
3
  • \$\begingroup\$ It depends on the use case whether it is useful or not. You can render your UI over top by sorting your draw calls, too. \$\endgroup\$
    – cozmic
    Nov 16, 2015 at 10:07
  • \$\begingroup\$ that makes sense, although the answer is a bit unclear. My vote is locked in unless you edit. You should add a little clarification of how your method works into the answer. \$\endgroup\$
    – Lucien
    Nov 16, 2015 at 15:50
  • \$\begingroup\$ I will edit the answer later, dont have time atm \$\endgroup\$
    – cozmic
    Nov 16, 2015 at 16:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .