Thread: OpenGL: Switching between 2D and 3D

  1. #1
    Registered User
    Join Date
    Aug 2001
    Posts
    411

    OpenGL: Switching between 2D and 3D

    Here is where I stand. Im looking to optimize this because I have 2D and 3D elements every frame. I have considered that after the first call to Perspective#D I save the Projection Matrix with glGetMatrix() into a local variable, then just reload it with glLoadMatrix(). Has anyone tried anything like that before? I am concerned that there may be more Matrices other than GL_PROJECTION that I need to save... What about glViewport, do I need to call it if I load the Projection Matrix?

    Code:
    void cRenderEngine::Perspective3D(float p_fov, float p_near, float p_far, float width, float height) {
    	renderMode = RENDER_3D;
    	fov3d = p_fov;
    	near3d = p_near;
    	far3d = p_far;
    	width3d = width;
    	height3d = height;
    	float lw = (float)width, lh = (float)height;
    	if(height == 0) height = 1;
    	glViewport(0,0,width,height);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluPerspective(p_fov,lw/lh,p_near,p_far);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
    }
    void cRenderEngine::Render3D() {
    	if(renderMode==RENDER_3D) return;
    	Perspective3D(fov3d,near3d,far3d,width3d,height3d);
    }
    
    void cRenderEngine::Perspective2D(RECT size) {
    	renderMode = RENDER_2D;
    	per2D = size;
    	glViewport(size.left, size.bottom, size.right, size.top);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D(size.left, size.right, size.bottom, size.top);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
    }
    void cRenderEngine::Render2D() {
    	if(renderMode==RENDER_2D) return;
    	Perspective2D(per2D);
    }

  2. #2
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Your other matrices should be fine. The only thing you are changing is how you project your geometry.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  3. #3
    Registered User
    Join Date
    Aug 2001
    Posts
    411
    Revised code

    Code:
    void cRenderEngine::Perspective3D(float p_fov, float p_near, float p_far, float width, float height) {
    	renderMode = RENDER_3D;
    	float lw = (float)width, lh = (float)height;
    	if(height == 0) height = 1;
    	glViewport(0,0,width,height);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluPerspective(p_fov,lw/lh,p_near,p_far);
    	glGetFloatv(GL_PROJECTION_MATRIX , matrix3D);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
    }
    void cRenderEngine::Render3D() {
    	if(renderMode==RENDER_3D) return;
    	glMatrixMode(GL_PROJECTION);
    	glLoadMatrixf(matrix3D);
    	glMatrixMode(GL_MODELVIEW);
    }
    
    void cRenderEngine::Perspective2D(RECT size) {
    	renderMode = RENDER_2D;
    	glViewport(size.left, size.bottom, size.right, size.top);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D(size.left, size.right, size.bottom, size.top);
    	glGetFloatv(GL_PROJECTION_MATRIX, matrix2D);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
    }
    void cRenderEngine::Render2D() {
    	if(renderMode==RENDER_2D) return;
    	glMatrixMode(GL_PROJECTION);
    	glLoadMatrixf(matrix2D);
    	glMatrixMode(GL_MODELVIEW);
    }
    It dosent work though. Still trying to figure out the problem.

  4. #4
    Registered User
    Join Date
    Aug 2001
    Posts
    411
    Ive tried 50 different things, but this just dosen't work.

    There must be more to the perspective calls (gluPerspective,gluOrtho2D) than just the Projection Matrix.

  5. #5
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Well why don't you tell us what the problem is rather than 'it doesn't work'. Is the 3D rendering or 2D rendering messing up for instance.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  6. #6
    Registered User
    Join Date
    Aug 2001
    Posts
    411
    Its hard to explain, I can see the 3d, but its not quite right... I cant see the 2D at all.

    I tried adding viewport calls before the load matrix calls, and load identites, nothing I did seemed to have an effect.

    It makes sence though, It should work right?

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Hey Eber there might be an internal clip matrix that takes into account the pixel aspect ratios for your screen mode. This would cause the calculations to change a bit. So no you could not simply just use the projection matrix or the inverse of it to get back to 2D.

    I thought there was a glUnproject() or something like that?

  8. #8
    Registered User
    Join Date
    Aug 2001
    Posts
    411
    gluUnProject dosent have anything to do with this i believe. I agree, there must be something other than just the projection matrix that controls rendering.

    gluUnProject
    The gluUnProject function maps window coordinates to object coordinates.

    int gluUnProject(
    GLdouble winx,
    GLdouble winy,
    GLdouble winz,
    const GLdouble modelMatrix[16],
    const GLdouble projMatrix[16],
    const GLint viewport[4],
    GLdouble * objx,
    GLdouble * objy,
    GLdouble * objz
    );

    Parameters
    winx, winy, winz
    The window coordinates to be mapped.
    modelMatrix
    The modelview matrix (as from a glGetDoublev call).
    projMatrix
    The projection matrix (as from a glGetDoublev call).
    viewport
    The viewport (as from a glGetIntegerv call).
    objx, objy, objz
    The computed object coordinates.
    Return Values
    If the function succeeds, the return value is GL_TRUE.

    If the function fails, the return value is GL_FALSE.

    Remarks
    The gluUnProject function maps the specified window coordinates into object coordinates using modelMatrix, projMatrix, and viewport. The result is stored in objx, objy, and objz.

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Ok now that makes sense. That unprojects from camera space to local space. I was under the impression it could unproject from screen space to local space....which was quite suspect given that all of my 3D books say that projection cannot be undone. This is because the z and w are simply thrown out in the end and there is no way to get them back.

    I would say the clip matrix is where you are running into troubles. I have the formulas and matrix for both Direct3D and OpenGL style clip matrices.

    The clip matrix is most certainly internal. I use these to compute the screen coords of my virtual sun in the world. This allows me to create lense flares and also tells me how bright the screen glare quad (a pure white quad overlaid over the entire screen - alpha blended with existing screen image). I don't have time right now to write it here....but after I get back from work I will post it here. This allows you to figure out what the screen coords would be given any 3D object. You probably only need one more inverse transformation and you will have it.

    If you have the Special Effects programming book this is covered in the 2D and 3D lense flare chapters.

  10. #10
    Registered User
    Join Date
    Aug 2001
    Posts
    411
    I wonder if you can put perspective calls inside a display list?

  11. #11
    Registered User
    Join Date
    Aug 2001
    Posts
    411
    OMG, I am missing a stattement the Render#D functions, setting the renderMode variable once the modeis changed, it works perfect. Final code if anyone is intrested.

    Code:
    void cRenderEngine::Perspective3D(float p_fov, float p_near, float p_far, float width, float height) {
    	renderMode = RENDER_3D;
    	float lw = (float)width, lh = (float)height;
    	if(height == 0) height = 1;
    	glViewport(0,0,width,height);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluPerspective(p_fov,lw/lh,p_near,p_far);
    	glMatrixMode(GL_MODELVIEW);
    	glGetDoublev(GL_PROJECTION_MATRIX , matrix3D);
    	glLoadIdentity();
    }
    void cRenderEngine::Render3D() {
    	if(renderMode==RENDER_3D) return;
    	renderMode = RENDER_3D;
    	glMatrixMode(GL_PROJECTION);
    	glLoadMatrixd(matrix3D);
    	glMatrixMode(GL_MODELVIEW);
    }
    void cRenderEngine::Perspective2D(RECT size) {
    	renderMode = RENDER_2D;
    	glViewport(size.left, size.bottom, size.right, size.top);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D(size.left, size.right, size.bottom, size.top);
    	glMatrixMode(GL_MODELVIEW);
    	glGetDoublev(GL_PROJECTION_MATRIX, matrix2D);
    	glLoadIdentity();
    }
    void cRenderEngine::Render2D() {
    	if(renderMode==RENDER_2D) return;
    	renderMode = RENDER_2D;
    	glMatrixMode(GL_PROJECTION);
    	glLoadMatrixd(matrix2D);
    	glMatrixMode(GL_MODELVIEW);
    }

  12. #12
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Glad you got it working Eber. I don't do OpenGL so I really couldn't help with the code portion. I was trying to approach the problem from general 3D principles that apply to all 3D graphics.

    Hope to see the results soon.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Wiki FAQ
    By dwks in forum A Brief History of Cprogramming.com
    Replies: 192
    Last Post: 04-29-2008, 01:17 PM
  2. Replies: 16
    Last Post: 09-22-2006, 03:39 PM
  3. OpenGL - 2d text in 3d game
    By mikeb1986 in forum C++ Programming
    Replies: 1
    Last Post: 03-22-2006, 01:24 PM
  4. 3D to 2D
    By vasanth in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 07-09-2003, 10:29 PM
  5. 2D Programming in OpenGL
    By guyver137 in forum Game Programming
    Replies: 2
    Last Post: 01-18-2003, 03:31 PM