K4Z
19-10-2006, 02:58 PM
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.
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 :P).
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.
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.
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.
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 :P).
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.
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.