rfgamaral
rfgamaral

Reputation: 16842

How do I keep an object always in front of everything else in OpenGL?

I have this function which draws a small 3D axis coordinate system on the bottom left corner of the screen but depending on what I have in front of me, it may get clipped.

For instance, I have drawn a plain terrain on the ground, on the XZ plane at Y = 0. The camera is positioned on Y = 1.75 (to simulate an average person's height). If I'm looking up, it works fine, if I'm looking down, it gets clipped by the ground plane.

Looking up: https://i.sstatic.net/Q0i6g.png
Looking down: https://i.sstatic.net/D5LIx.png

The function I call to draw the axis system on the corner is this:

void Axis3D::DrawCameraAxisSystem(float radius, float height, const Vector3D rotation) {
    if(vpHeight == 0) vpHeight = 1;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0, 0, vpWidth, vpHeight);
    gluPerspective(45.0f, 1.0 * vpWidth / vpHeight, 1.0f, 5.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(0.0f, 0.0f, -3.0f);

    glRotatef(-rotation.x, 1.0f, 0.0f, 0.0f);
    glRotatef(-rotation.y, 0.0f, 1.0f, 0.0f);

    DrawAxisSystem(radius, height);
}

An now a couple of main functions I think are relevant to the problem:

glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);

void changeSize(int width, int height) {
    if(height == 0) height = 1;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glViewport(0, 0, width, height);

    gluPerspective(60.0f, 1.0 * width / height, 1.0f, 1000.0f);

    glMatrixMode(GL_MODELVIEW);
}

void renderScene(void) {
    glClearColor(0.7f, 0.7f, 0.7f, 0.0f);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    changeSize(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));

    glLoadIdentity();

    SceneCamera.Move(CameraDirection, elapsedTime);
    SceneCamera.LookAt();

    SceneAxis.DrawCameraAxisSystem(0.03f, 0.8f, SceneCamera.GetRotationAngles());

    glutSwapBuffers();
}

Suggestions?

Upvotes: 11

Views: 16257

Answers (5)

Jesse Stone
Jesse Stone

Reputation: 11

glGetBooleanv(GL_BLEND,     &m_origin_blend);

glGetBooleanv(GL_DEPTH_TEST,&m_origin_depth);

glGetBooleanv(GL_CULL_FACE, &m_origin_cull);
    
setAlphaBlending(true);

setDepthTest(false);

setCullFace(false); //by stone


//your draw() ...


setAlphaBlending(m_origin_blend>0?true:false);

setDepthTest(m_origin_depth>0?true:false);

setCullFace(m_origin_cull>0?true:false);

Upvotes: 0

Milo
Milo

Reputation: 185

You could also reserve a tiny bit of the depth range for your 3D axis. And all the rest for your scene. Like this:

// reserve 1% of the front depth range for the 3D axis
glDepthRange(0, 0.01);

Draw3DAxis();

// reserve 99% of the back depth range for the 3D axis
glDepthRange(0.01, 1.0);

DrawScene();

// restore depth range
glDepthRange(0, 1.0);

Upvotes: 7

peter karasev
peter karasev

Reputation: 2614

You might try enabling blending, then set alpha & color manually in a fragment shader. But that might be overkill ;-)

Upvotes: 0

JCooper
JCooper

Reputation: 6525

Rather than disable depth testing, you can just glClear(GL_DEPTH_BUFFER_BIT); before you render your overlay. Then whatever depth information was there is gone, but the pixels are all still there. However, your overlay will still render appropriately.

Upvotes: 25

ssube
ssube

Reputation: 48327

You want to disable depth testing (so it's not clipped by anything):

glDisable(GL_DEPTH_TEST);

and if you've pre-transformed the points (it doesn't appear you have), set the view and projection matrices to identity.

Edit:

If you need the axis bit to stay tested and in order, then you'll probably want to clear the depth buffer (glClear(GL_DEPTH_BUFFER_BIT)) between rendering it and your main scene. That will reset the depth buffer so that the marker is drawn (and so appears in front), but is still properly culled.

Upvotes: 1

Related Questions