1

So I have a 3D openGL application and I wanted to display a 2D HUD, I understand the basic concept of how to do this after a lot of googling but nothing I try makes it show up. My current code after going over many other examples is this:

    // HUD ///////////////////////////////////

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, (GLdouble)WIDTH, (GLdouble)HEIGHT, 0, -1, 1);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glColor3f(1, 1, 1);
    glPushMatrix();
    glBegin(GL_QUADS);
    glVertex3f(-5.0f, 5.0f, 0.0f);
    glVertex3f(-5.0f, -5.0f, 0.0f);
    glVertex3f(5.0f, -5.0f, 0.0f);
    glVertex3f(5.0f, 5.0f, 0.0f);
    glEnd();
    glPopMatrix();
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

Right now nothing visually changes, I can get the whole screen to clear to a colour but even then I can't seem to draw a quad on it.

EDIT:

glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClear(GL_DEPTH_BUFFER_BIT);

    glColor3f(1, 1, 1);
    glPushMatrix();
    glBegin(GL_QUADS);
    glVertex3f(-10.0f, 10.0f, 0.0f);
    glVertex3f(-10.0f, -10.0f, 0.0f);
    glVertex3f(10.0f, -10.0f, 0.0f);
    glVertex3f(10.0f, 10.0f, 0.0f);
    glEnd();
    glPopMatrix();

    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

EDIT 2: SKYBOX CODE

glDisable(GL_CULL_FACE);
    glDepthFunc(GL_LEQUAL);  // Change depth function so depth test passes when values are equal to depth buffer's content
    skyShader.Bind();
    view = glm::mat4(glm::mat3(camera.GetViewProjection()));    // Remove any translation component of the view matrix
    glUniformMatrix4fv(glGetUniformLocation(skyShader.getProg(), "view"), 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(glGetUniformLocation(skyShader.getProg(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
    // SKYBOX CUBE ///////////////////////////////// 
    glBindVertexArray(skyboxVAO);
    glActiveTexture(GL_TEXTURE0);
    glUniform1i(glGetUniformLocation(skyShader.getProg(), "skybox"), 0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);
    glDepthFunc(GL_LESS); // Set depth function back to default
thesyncer
  • 23
  • 5
  • 1
    You are drawing just 5 pixels at the top left corner of your image., the other 3/4 of your quad are outside of the frustum. – derhass Apr 14 '16 at 18:54
  • @derhass Maybe I'm just being stupid but I don't follow, I've changed the vertex values but still don't see anything. – thesyncer Apr 14 '16 at 18:59
  • @derhass I've changed them to only positive values, increased the numbers and also tried 2d vertexes. – thesyncer Apr 14 '16 at 19:02
  • Note that it is totally unclear what state your OpenGL context is in, at the time you call this. There are _tons_ of different states which might lead to the quad not being drawn. – derhass Apr 14 '16 at 19:05
  • @derhass I am pretty sure it's just a state I'm overlooking somewhere, have never done 2D over 3D though so I'm probably missing something glaring. – thesyncer Apr 14 '16 at 19:11
  • Possible duplicate of [Opengl: 2d HUD over 3D](http://stackoverflow.com/questions/5467218/opengl-2d-hud-over-3d) or why is this code not working. – Ciro Santilli OurBigBook.com Apr 14 '16 at 23:02

1 Answers1

3

I'm not sure what HEIGHT and WIDTH are set to so I just used 100 for both. When I ran the code you posted I can see your quad in the top-left corner of the screen.

What I would recommend is to simply your HUD code until you've got a grasp of what is happening.

For example:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glPushMatrix();
glBegin(GL_QUADS);
glVertex3f(-0.5f,  0.5f, 0f);
glVertex3f(-0.5f, -0.5f, 0f);
glVertex3f( 0.5f, -0.5f, 0f);
glVertex3f( 0.5f,  0.5f, 0f);
glEnd();
glPopMatrix();

Given the rest of your GL state is unchanged, that should draw a white quad that fills 50% of the screen, positioned in the center:

default view matrix

This is because the view defaults to a glOrtho call that looks like this:

glOrtho(-1f, 1f, -1f, 1f, -1f, 1f);

Now let's set WIDTH and HEIGHT to 10f. This is what your glOrtho call would be:

glOrtho(0f, 10f, 10f, 0f, -1f, 1f);

This is what gets rendered:

modified view matrix

If your HEIGHT and WIDTH is bigger, say 800x600, that quad would be so small it wouldn't even appear.


EDIT: Using glPushMatrix and glPopMatrix to isolate modifications to the model-view and projection matrices

After reading your edits and comments let me add some sample code that I believe illustrates what you want. It doesn't deal with the depth buffer, which may be what is causing you issues, but I wanted to keep it simple and build on what I had before:

int width = 500;   // window width
int height = 500;  // window height

// define our GL viewport
glViewport(0, 0, width, height);

// setup 3d projection
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glPerspective(60f, width/height, 1f, 50f);

// setup 3d modelview
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

// move the camera to put the tetrahedron behind the UI element
glRotatef(135f, 0f, 0f, 1f);
glTranslatef(0f, 5f, -30f);

// draw 3d object (tetrahedron)
glBegin(GL_TRIANGLES);
// triangle 1
glColor3f(1f, 0f, 0f);          // red
glVertex3f(0f, 10f, 0f);        // a
glColor3f(1f, 1f, 0f);          // yellow
glVertex3f(0f, -10f, -10f);     // b
glColor3f(0f, 1f, 0f);          // green
glVertex3f(-10f, -10f, 10f);    // c
// triangle 2
glColor3f(1f, 0f, 0f);          // red
glVertex3f(0f, 10f, 0f);        // a
glColor3f(1f, 0f, 1f);          // purple
glVertex3f(10f, -10f, 10f);     // d
glColor3f(1f, 1f, 0f);          // yellow
glVertex3f(0f, -10f, -10f);     // b
// triangle 3
glColor3f(1f, 0f, 0f);          // red
glVertex3f(0f, 10f, 0f);        // a
glColor3f(0f, 1f, 0f);          // green
glVertex3f(-10f, -10f, 10f);    // c
glColor3f(1f, 0f, 1f);          // purple
glVertex3f(10f, -10f, 10f);     // d
// triangle 4
glColor3f(1f, 1f, 0f);          // yellow
glVertex3f(0f, -10f, -10f);     // b
glColor3f(1f, 0f, 1f);          // purple
glVertex3f(10f, -10f, 10f);     // d
glColor3f(0f, 1f, 0f);          // green
glVertex3f(-10f, -10f, 10f);    // c
glEnd();

// revert to original modelview matrix
glPopMatrix();
// revert to original projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();

// setup 2d projection
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0f, 1f, 1f, 0f, -1f, 1f);

// setup 2d modelview
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

// draw the 2d interface
glBegin(GL_QUADS);
glColor3f(0.5f, 0.5f, 0.5f);    // grey
glVertex3f(0.05f, 0.05f, 0f);   // top-left
glVertex3f(0.95f, 0.05f, 0f);   // top-right
glVertex3f(0.95f, 0.2f, 0f);    // bottom-right
glVertex3f(0.05f, 0.2f, 0f);    // bottom-left
glEnd();

// revert to original modelview matrix
glPopMatrix();
// revert to original projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();

This renders the following:

interface over tetrahedron

You'll notice when we setup the ModelView matrix for the 2d interface we're using this to define the view frustum:

glOrtho(0f, 1f, 1f, 0f, -1f, 1f);

This defines our view space as top-left being 0,0 and bottom right being 1,1. This allows us to place things on the screen without regard for the viewport size. When we draw our 2d interface we just have to supply values within a 0.0 to 1.0 range and it will fit it to the viewport.

Important: You should always remember that the model-view and projection matrices are stacks. Before you make any modifications to them remember to push a new layer on the stack and then pop it back off when you're done. By doing this you can isolate your changes.

Exide
  • 859
  • 8
  • 24
  • Thanks for the in depth response, you helped me understand some points better. I'm still having issues however, I've changed my code in an edit, I've been able to see there is a quad being drawn if I position it's z position into the scene, it hides my 3D objects but I still can't see the quad it's self. I think my skybox code is perhaps causing depth issues, I've edited it in also. – thesyncer Apr 14 '16 at 20:47
  • Can you post a screenshot of what you're seeing? That might help me understand a bit more. – Exide Apr 14 '16 at 20:51
  • http://i.imgur.com/XaNWM24.jpg with my skybox on. http://i.imgur.com/Xm8WbH5.png rotated perspective with skybox commented out, that's a flat quad through the centre of the scene. – thesyncer Apr 14 '16 at 20:53
  • Let me know if the edits to my answer help. If not, I'll explore how the depth buffer affects things. – Exide Apr 14 '16 at 23:01
  • I figured out that the reason my skybox was causing issues with nothing being drawn was an issue with my shaders. I resolved that now and your sample code was really useful, I'm using it now but the final issue I have is the quad is still being drawn in 3D space, i.e. if I move my camera it is in the 3D scene and stays in space relative to other objects despite the use of glOrtho. In this picture you can see where the quad is, on the red ring http://i.imgur.com/PNeyoi1.jpg – thesyncer Apr 15 '16 at 16:51
  • I suspect either your camera transforms or HUD transforms are not isolated with calls to ```glPushMatrix``` and ```glPopMatrix```. I added a bit to the bottom of my answer with regard to pushing and popping the matrix stacks. – Exide Apr 16 '16 at 22:51