Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with creating a 2D interface in a 3D openGL world

I am working on a project that requires that I create a 2D interface rendered "on top" or a 3D world. On some other forums, I read that you could use "GluOrtho2D()" for the job, and switch back to GluPerspective() once you were done. The only thing is, my test code I wrote for it only displays the 3D world, not the 2D quad. When I disable the 3D rendering code, however, the quad appears where it was supposed to be. I trimmed down the code to openGL only statements, which I wrote down below. The code is written in Python using the Pyglet library.


The scene initialization code:

glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, float(width)/height, .1, 10000.)
glMatrixMode(GL_MODELVIEW)
glClearDepth(1.0)
glShadeModel(GL_FLAT)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL) 
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

The frame rendering code. The call to builder.buildMap() creates the 3D scene, and the glBegin-glEnd pair draws a 2D quad:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
stage.set3DMode(window.width, window.height)
builder.buildMap()
stage.set2DMode(window.width, window.height)
glBegin (GL_QUADS)
glVertex2i(0, 0)
glVertex2i(0, 200)
glVertex2i(200, 200)
glVertex2i(200, 0) 
glEnd()

the stage.set3DMode function:

glDisable(GL_DEPTH_TEST) 
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0, width, 0, height)
glMatrixMode(GL_MODELVIEW)

and the stage.set3DMode function:

glEnable(GL_DEPTH_TEST) 
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, float(width)/float(height), .1, 10000.)
glMatrixMode(GL_MODELVIEW)

I really hope someone can point out my mistake! And thank you for helping me :)

like image 463
Bartvbl Avatar asked Nov 26 '10 23:11

Bartvbl


3 Answers

It looks like you don't call glLoadIdentity() after switching to GL_MODELVIEW. The simplest way to remember is to call it every time you change the projection matrix, switch to GL_MODELVIEW and call glLoadIdentity() (unless you really want to retain the old one).

like image 171
Yakov Galka Avatar answered Sep 20 '22 21:09

Yakov Galka


I use the following matrices for 2d rendering:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, h, 0, 0, 1);
glViewport(0, 0, w, h);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375f, 0.375f, 0);
like image 36
jonaskje Avatar answered Sep 22 '22 21:09

jonaskje


A lot of people get it wrong how to use glViewport and the like. They always place it in the reshape callback which is simply wrong.

You always to the full setup in your rendering function, just before you need those settings. So your code should be (pesudocode):

render_scene():
    // first clear the whole window
    glViewport(0, 0, window.width, window.height)
    glClearDepth(1.0)
    glClearColor(1., 1., 1., 1.);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)

    glViewport(3Dstuff.x, 3Dstuff.y, 3Dstuff.w, 3Dstuff.h)
    // maybe also set scissor to clip
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(60.0, float(width)/height, .1, 10000.)
    glMatrixMode(GL_MODELVIEW)
    setup3DstuffModelview()
    glDepthFunc(...)
    glEnable(GL_DEPTH_TEST)
    // other state stuff
    render3Dstuff()

    // now the 2D stuff
    glViewport(2Dstuff.x, 2Dstuff.y, 2Dstuff.w, 2Dstuff.h)
    // clear depth and stencil -- if you need parts of the 3D depth / stencil
    // for some algorithm retain it or save and restore by FBO renderbuffers or
    // glReadPixels, glDrawPixels
    glClearDepth(1.0)
    glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(...)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    setup2DstuffModelview()
    glDepthFunc(...)
    glDisable(GL_DEPTH_TEST)
    // other state stuff
    render2Dstuff()

    // repeat for all the layers you need

This is really important: OpenGL is a state machine. Unless you can prove that no undetermined state changes happen you always re-/set all the states you need prior to rendering a certain geometry.

like image 23
datenwolf Avatar answered Sep 21 '22 21:09

datenwolf