1

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.

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • 1
    Are you sure that the Text does not simply end up behind_ the 3D objects and is discarded by the depth test? – derhass Dec 30 '19 at 07:23
  • When the matrix is set by `glm::ortho(0.0f,800.0f,0.0f,600.0f)`, then both lines are generate the same result. in both cases `gl_Position.z` is 0.0. That causes that the depth is 0.5. What happens if you manually set `gl_Position.z = -1.0` after the transformation? – Rabbid76 Dec 30 '19 at 09:08
  • The `textShader` shader program has to be installed (`glUseProgram`) before `textShader->setMat4("projection", windowMatrix)` – Rabbid76 Dec 30 '19 at 14:02
  • @Rabbid76 You Genius! You got it! It was case I was updating the uniform before using glUseProgram to install it first. This fixed my issue. I will add the answer to the question below now. Thank you derhass for your suggestion. – Alistair Haslam Dec 30 '19 at 14:06
  • 1
    That answer did work. I was unaware of the tick box. It is ticked now. – Alistair Haslam Feb 05 '20 at 15:25

1 Answers1

1

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));
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174