Page 1 of 2 12 LastLast
Results 1 to 10 of 20

Thread: 2D rendering in OpenGL

  1. #1

    2D rendering in OpenGL

    As requested, This is just a simple demonstration on how to perform 2D rendering in OpenGL, (directed at those using (JEDI-)SDL and would like to use HW accel OpenGL for rendering). The code is not that different from standard OGL 3D commands, so it'll help if you understand the basics of OGL. (To cut the length of this demo down, I won't go through setting up the screen, loading textures, etc, etc)

    First of all is setting up OGL to behave like 2D, this is done by disabling Depth Test, and switching the PROJECTION mode to ORTHO view (2D view). To simplify things and keep the code clean, it's a good idea to put the code in a couple of functions.

    Code:
    procedure Start2D;
    var W, H:Single;
        ViewPort : TViewPortArray;
    begin
       glGetIntegerv(GL_VIEWPORT, @ViewPort[0]);
       W  := ViewPort[2];
       H := ViewPort[3];
    
       glDisable(GL_DEPTH_TEST);             //turn off z buffer
       glMatrixMode(GL_PROJECTION);          //set projection matrix
       glPushMatrix;                         //push it
       glLoadIdentity();                     //reset
       glOrtho(0, W, H, 0, 0, 100);          //ortho view
       glMatrixMode(GL_MODELVIEW);           //return to modelview
       glLoadIdentity();                     //reset
    end;
    
    procedure End2D;
    begin
      glEnable(GL_DEPTH_TEST);                //turn on z buffer
      glMatrixMode(GL_PROJECTION);            //set projection matrix
      glPopMatrix;                            //restore projection
      glMatrixMode(GL_MODELVIEW);             //set modelview matrix
      glLoadIdentity();                       //reset
    end;
    To breake things down:

    We need the width and height of the screen in order to set our whole screen to 2D. So without hard coding it in, we can use a simple OpenGL call like: glGetIntegerv(GL_VIEWPORT, @ViewPort[0]), and you will get an array with lots of data, [2] and [3] contain the data what we want.

    glDisable(GL_DEPTH_TEST) disables the Z buffer, telling OGL not to sort polygons, ie, last drawn polys are drawn on top of everything else.

    glMatrixMode(GL_PROJECTION) just sets the mode to Projection (I won't go into this here ).

    glOrtho(0, W, H, 0, 0, 100) is the core of the function, setting the Projection mode to 2D.

    And glMatrixMode(GL_MODELVIEW) just sets the Mode back to ModelView, so we can actually render things.

    (The other reason we use the two functions is in situations where you might want to switch back to 3D, in order to do some cool 3D effects, etc)


    Ok, now time for some extreme basic rendering code. If you have used OGL for 3D before, you'll understand the code pretty well, if not, it's pretty easy to understand. As with all 3D libraries, rendering is done using textured 3D triangles (or quads), This is no different when rendering 2D in OGL.


    Code:
    uses gl, glu, sdl;
    
    repeat
    
      glEnable(GL_TEXTURE_2D);                 //Enable Texturing
      glBindTexture(GL_TEXTURE_2D, MyTexture); //Bind Texture  
    
      glColor3f(1,1,1);                        //Make sure color is white (Normal)
    
      Start2D;                                 //Switch to 2D mode
        glPushMatrix;                          //Save Current Matrix  
    
          //Draw a Quad
          glBegin(GL_QUADS);
            glTexCoord2f(0, 0);   //Top-Left
            glVertex2f(0,0);
    
            glTexCoord2f(100, 0); //Top-Right
            glVertex2f(100, 0);
    
            glTexCoord2f(1, 1);   //Bottom-Right
            glVertex2f(100, 100);
    
            glTexCoord2f(0, 1);   //Bottom-Left
            glVertex2f(100,100);
          glEnd; 
        glPopMatrix;                           //Reload Old Matrix
      End2D; 			
    
      SDL_GL_SwapBuffers;
    until gmQuit;
    Edited by savage to make unit names lower case for cross compilation smoothness

    And to run through it; You'll need GL.pas, and GLU.pas for OGL stuff, SDL.pas for well, SDL.

    First 3 lines are just standard OpenGL texture binding, and resetting color to white.

    Next we call our 2D function to disable 3D.

    glBegin(GL_QUADS) just tells OpenGL we wanna draw using 4 point triangles.

    glTexCoord2f(0, 0) and glVertex2f(0,0) are used to set texture co-ords and plot Vertex's, just like in 3D. The main difference is we don't define a Z axis, and now that we are in 2D mode, X,Y now relate to Screen pixel co-ordinates (starting at Top-Left : 0,0) instead of 3D co-ordinates at 0,0,0.

    I use SDL_GL_SwapBuffers to update the screen as it can handle double buffering.

    Ok, I guess that's the basics, I could post some working source if it'll help.

  2. #2

    2D rendering in OpenGL

    I think that glTexCoord2f(0.0,0.0) refers to bottom left corner not the top left.

    glBegin(GL_QUADS) just tells OpenGL we wanna draw using 4 point triangles.
    I am sure you meant polygons .

    One more thing. If you don't plan on using 3D, I think it is easier to setup 2D view only once. Here is an example.

    [pascal]
    //w,h - screen width and height
    procedure Init2D(w,h : integer);
    begin
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION):
    glLoadIdentity;
    glOrtho(0,w,h,0,0,100); //or gluOrtho2D(0,w,h,0)
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity;
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    end;

    [/pascal]

    Just my two cents .

  3. #3

    2D rendering in OpenGL

    This is yet another adaption of the famous code from gamedev.net that i use, but with one difference, that coordinates will match windows, making (0,0) top-left edge of the window, and (W, H) will be bottom right edge.

    edit: also, my function does not turn off depth test, but relies on you doing it yourself.


    Code:
    // Dwarf with Axe - GAMEDEV forums: 18 July 2002 6:12:57 PM
    //
    // There have been thousands of posts along the lines of
    // "How do I do 2d in OpenGL" to "Duuuhde, I wunt too maek
    // a two dee gaem in ohpun jee el; how do eye set uhp two dee???!?"
    //
    // I have developed a simple, nice, pretty way for all of you to have your 2D fun.
    
    procedure GlEnable2D;
    var
      vport: array[0..3] of integer;
    begin
      glGetIntegerv(GL_VIEWPORT, @vPort);
    
      glMatrixMode(GL_PROJECTION);
      glPushMatrix;
      glLoadIdentity;
      glOrtho(0, vPort[2], 0, -vPort[3], -1, 1);
    
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix;
      glLoadIdentity;
    
      // flip Y axis
      glTranslatef(0, -vPort[3], 0);
    end;
    
    procedure GlDisable2D;
    begin
      glMatrixMode(GL_PROJECTION);
      glPopMatrix;
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix;
    end;
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  4. #4

    2D rendering in OpenGL

    Thanks a lot for sharing!
    Now all I need to do is find some free time to play with it

    What about scrolling, can I render with a starting pixel of (-10, -50)?
    [size=9px]BEGIN GEEK CODE BLOCK
    <br />d s-- : a24 GB GCS GTW GE C++ P L+ W++ N+ K- w++++ M- PS+ PE+ Y- t+ 5+++ X+ R*
    <br />tv b+ DI++ D+ e++ h+ G-
    <br />END GEEK CODE BLOCK[/size]
    <br />Create your own GeekCode block at: <a href="">...</a>

  5. #5

    2D rendering in OpenGL

    Sure. That'd go something like this:

    Code:
      glTranslatef&#40;x, y, -0.1&#41;;
    
      glBegin&#40;GL_QUADS&#41;;
          glTexCoord2f&#40;0, 0&#41;; glVertex2f&#40;0, 0&#41;;
          glTexCoord2f&#40;0, 1&#41;; glVertex2f&#40;0, FHeight&#41;;
          glTexCoord2f&#40;1, 1&#41;; glVertex2f&#40;FWidth, FHeight&#41;;
          glTexCoord2f&#40;1, 0&#41;; glVertex2f&#40;FWidth, 0&#41;;
      glEnd;
    where x and y can have any value you'd like.

  6. #6

    2D rendering in OpenGL

    Just remember that if you call glTranslatef(x,y,0) all other OpenGL operations will be relative to the (x,y). An example
    [pascal]
    glTranslatef(10,20,0);
    glBegin(GL_QUADS);
    ...
    glEnd;

    glTranslatef(20,-10,0);
    glBegin(GL_QUADS);
    ...
    glEnd;
    [/pascal]
    The second call to glTranslatef will move your position to (30,10) not (20,-10) since it is relative to first call. (Its like Delphi TCanvas methods MoveTo and LineTo). To translate to proper position wrap code with
    glPushMatrix and glPopMatrix calls i. e.

    [pascal]
    glPushMatrix;
    glTranslatef(10,20,0);
    glBegin(GL_QUADS);
    ...
    glEnd;
    glPopMatrix;

    glPushMatrix;
    glTranslatef(20,-10,0);
    glBegin(GL_QUADS);
    ...
    glEnd;
    glPopMatrix;
    [/pascal]
    glPushMatrix saves current transformation matrix on a stack and glPopMatrix restores it. Those two are very usefull functions.
    Take a look at KAZ Start2D and End2D procedures. He uses glPushMatrix and glPopMatrix to save old projection matrix, turns on 2D and finally restores old projection.

    Same applies to glRotatef and glScalef if you want to rotate and scale sprites.

  7. #7

    2D rendering in OpenGL

    OpenGL is great for 2D. You automatically have zoom and rotation without needing to creating a whole new set of graphics. And transparency is extremely simple to do. Personally, the only reason I use SDL is for the window management.
    [size=10px]&quot;In science one tries to tell people, in such a way as to be understood by everyone, something that no one ever knew before. But in poetry, it&#39;s the exact opposite.&quot; -- Paul Dirac[/size]

  8. #8

    2D rendering in OpenGL

    Quote Originally Posted by cragwolf
    Personally, the only reason I use SDL is for the window management.
    I personally think that SDL is great for window management and also input management. The new classes in v1.0 make it even easier to use both.
    Just depends if you want an extra layer for that sort of stuff though. I'll be porting the Grid Crazy and Aliens demos to the new classes, so that others can see how easy it is to use them. I originally created them for the SoAoS project.
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  9. #9

    2D rendering in OpenGL

    Thanx for the extra info and fixes guys

    What about scrolling, can I render with a starting pixel of (-10, -50)?
    Yep that's perfectly ok in OpenGL.

    I personally think that SDL is great for window management and also input management. The new classes in v1.0 make it even easier to use both.
    Yep, I use SDL for just about everything in my projects, window management, file loading, input, etc, But I just like to do my own OpenGL for rendering .

  10. #10

    2D rendering in OpenGL

    Quote Originally Posted by grudzio
    glBegin(GL_QUADS) just tells OpenGL we wanna draw using 4 point triangles.
    I am sure you meant polygons .
    Yeah Polygons, I just like to steal the term 4 point triangles from my 3D modeling background (Before the days of quads)

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •