Konsti Lackner
Konsti Lackner

Reputation: 159

Draw 2D HUD elements over 3D rendered scene

I searched for this and only found a post from 2014 asking about a somewhat similar situation. However, as I couldn't understand what was done there, I'm asking again, specifically for my implementation, hoping this sheds some light on the topic in general as well. I am fairly new to c++ and openGL, so please be so kkind as to excuse stupid mistakes.

I'm trying to implement a simple 2D HUD for my 3D game. Now, my game is fully rendered, due to having a bloom effect in my game, I even rendered my game on a screen quad. What I now want to do ist placing a HUD over this rendered scene, I, however, can't seem to do that.

My screen quad for the game is drawn like so:

unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{
    if (quadVAO == 0)
    {
        float quadVertices[] = {
            // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
            // texCoords
            0.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f,

            0.0f, 1.0f,
            1.0f, 0.0f,
            1.0f, 1.0f
        };
        // setup plane VAO
        glGenVertexArrays(1, &quadVAO);
        glGenBuffers(1, &quadVBO);
        glBindVertexArray(quadVAO);
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    }
    glBindVertexArray(quadVAO);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    glBindVertexArray(0);
}

What I tried to do, ist change my renderQuad method to a renderHUDquad one by basically just changing the dimensions of the quad to make it appear in the bottom left corner of the screen. The code looks as follows:

unsigned int HUDquadVAO = 0;
unsigned int HUDquadVBO;
void renderHUDQuad()
{
    if (HUDquadVAO == 0)
    {
        float HUDquadVertices[] = {
            // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
            // texCoords
            0.0f, 0.02f,
            0.0f, 0.0f,
            0.2f, 0.0f,

            0.0f, 0.02f,
            0.2f, 0.0f,
            0.2f, 0.02f
        };
        // setup plane VAO
        glGenVertexArrays(1, &HUDquadVAO);
        glGenBuffers(1, &HUDquadVBO);
        glBindVertexArray(HUDquadVAO);
        glBindBuffer(GL_ARRAY_BUFFER, HUDquadVBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(HUDquadVertices), &HUDquadVertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    }
    glBindVertexArray(HUDquadVAO);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    glBindVertexArray(0);
}

As this only needs to be a small green quad, i.e. a health bar for the player, I was thinking about just assigning it a green texture or sth.. However, when drawing my two quads like this:

// Third pass = Combined bloom pictures
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            bloomShader->use();
            // Set uniform for multiple layout uniforms
            bloomShader->setUniform("scene", 0);
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, colorAndLightBuffers[0]);
            // Set uniform for multiple layout uniforms
            bloomShader->setUniform("bloomBlur", 1);
            glActiveTexture(GL_TEXTURE1);
            glBindTexture(GL_TEXTURE_2D, pingpongBuffer[horizontal == 0 ? 1 : 0]);
            bloomShader->setUniform("bloom", bloom);
            bloomShader->setUniform("exposure", exposure);
            renderQuad();

            renderHUDQuad();

            // Swap buffers
            glfwSwapBuffers(window);

I only get the HUD element without any of the stuff I drew before as if the rest of the screen was rendered black. I thought I could just add this to the old buffer, as there a way to do this?

Upvotes: 1

Views: 431

Answers (1)

derhass
derhass

Reputation: 45332

You did screw up your GL state very badly:

void renderHUDQuad() {
    if (HUDquadVAO == 0)
    {
        [...]
        glGenVertexArrays(1, &quadVAO);

You actually use quadVAO in the rest of this function, so you overwrite your fullscreen quad by the smaller one, which means the rest of your scene will be scaled down to this quad from the next frame on...

Upvotes: 1

Related Questions