c++openglglm-mathvertex-shaderhud

Switching Ortho to perspective for OpenGL HUD


I'm trying to implement a HUD in OpenGL which will display text in 2D on the front of the viewing window and a 3D perspective view behind (similar to a HUD).

I'm creating my 3D fragments using a projectionView matrix then switch to an ortho matrix to render my quads. I've managed to get this to work without the ortho matrix (see below), but for some reason when using the matrix if I draw 3D objects my 2D text disappears, if rendering the text alone it is present and displays correctly.

Basic rendering loop:

glm::mat4 projection, projectionView, windowMatrix;

projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);
windowMatrix = glm::ortho(0.0f,800.0f,0.0f,600.0f);

while (!glfwWindowShouldClose(window))     //Render loop
{
    glm::mat4 view = camera.GetViewMatrix();
    projectionView = projection * view;
    //Update the Uniform
    threeDShader->setMat4("projection", projectionView);

    //Render() calls glDrawElements()
    threeDObject->Render();

    //Update the Uniform
    textShader->setMat4("projection", windowMatrix);

    //Render params = text, xPos, yPos, scale, color
    //RenderText() calls glDrawArrays()
    textHUD->RenderText("Hello World!", 25.0f, 25.0f, 1.0f, glm::vec3(0.9, 0.2f, 0.8f));
}

The textShader vertex shader is:

#version 420 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
out vec2 TexCoords;

uniform mat4 projection;

void main()
{
    gl_Position = vec4(vertex.xy * vec2(2.0/800,2.0/600) - vec2(1,1), 0.0f, 1.0f);   <----(1)

    //gl_Position = projection * vec4(vertex.xy, 0.0f, 1.0f);   <----(2)
    TexCoords = vertex.zw;
}

The line (1) in the vertex shader code that explicitly states the location on the screen works displaying the text with other 3D objects being in the background. I would prefer to use line (2) which uses the orthographic matrix (which would be neater to change for the resolution), but for some reason works when no other 3D objects are rendered, but disappears when a 3D object is rendered in the scene. They both use separate matricies then draw their vertices/fragments, so in my opinion they should not be interfering with each other.

The fragment shader is the same for each and should not be an issue. I thought it might be something to do with the near clipping plane for the perspective matrix, but with the independent draw calls it shouldn't be an issue.

I've also tried implementing the ortho matrix with a near and far clipping plane similar to the perspective matrix, but to no success.


Solution

  • but for some reason works when no other 3D objects are rendered

    I guess, that threeDObject->Render(); respectively textHUD->RenderText install the shader program by glUseProgram.

    glUniform* changes a uniform variable in the default uniform block of the currently installed program.

    You've install the shader program before you can change the uniform:
    (In the following I suggest, that the sahder program class has a method use(), which installs the program)

    while (!glfwWindowShouldClose(window))     //Render loop
    {
        glm::mat4 view = camera.GetViewMatrix();
        projectionView = projection * view;
    
        // Install 3D shader program and update the Uniform
        threeDShader->use();
        threeDShader->setMat4("projection", projectionView);
    
        //Render() calls glDrawElements()
        threeDObject->Render();
    
        // Install text shader program and update the Uniform
        textShader->use();
        textShader->setMat4("projection", windowMatrix);
    
        //Render params = text, xPos, yPos, scale, color
        //RenderText() calls glDrawArrays()
        textHUD->RenderText("Hello World!", 25.0f, 25.0f, 1.0f, glm::vec3(0.9, 0.2f, 0.8f));
    }