Using SDL with OpenGL 2.1
Last Updated 8/6/12
There's a point where SDL's rendering just isn't enough. When you need more power, speed, and flexibility, it's time to move onto OpenGL.While we won't cover how to use OpenGL here (I hear there's a tutorial for that) we will cover how to use SDL to render OpenGL.
SDL and OpenGL 2.1 tutorial with SDL 2 is now available. A SDL and Modern OpenGL tutorial with SDL 2 is also available.
#include "SDL/SDL.h"
#include "SDL/SDL_opengl.h"
First we need to remember to include the SDL OpenGL header so we can use OpenGL's rendering.
bool init()
{
//Initialize SDL
if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
{
return false;
}
//Create Window
if( SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL ) == NULL )
{
return false;
}
//Initialize OpenGL
if( initGL() == false )
{
return false;
}
//Set caption
SDL_WM_SetCaption( "OpenGL Test", NULL );
return true;
}
Here is our init() function.
First we initialize SDL as we always do. Then we create our OpenGL window with an OpenGL context. When we want to use OpenGL we pass the SDL_OPENGL flag to SDL_SetVideoMode() instead of SDL_SWSURFACE. Now the window will use OpenGL's hardware accelerated rendering instead of SDL's software rendering. This also means we can't use SDL rendering calls (like SDL_Flip()) to draw to the screen.
Then we call our initGL() function (which we'll go over in a second) to initialize OpenGL and lastly we set the window caption.
First we initialize SDL as we always do. Then we create our OpenGL window with an OpenGL context. When we want to use OpenGL we pass the SDL_OPENGL flag to SDL_SetVideoMode() instead of SDL_SWSURFACE. Now the window will use OpenGL's hardware accelerated rendering instead of SDL's software rendering. This also means we can't use SDL rendering calls (like SDL_Flip()) to draw to the screen.
Then we call our initGL() function (which we'll go over in a second) to initialize OpenGL and lastly we set the window caption.
bool initGL()
{
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
//Initialize clear color
glClearColor( 0.f, 0.f, 0.f, 1.f );
//Check for error
GLenum error = glGetError();
if( error != GL_NO_ERROR )
{
printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
return false;
}
return true;
}
Here we have some actual OpenGL calls.
We do our post OpenGL window/context creation initialization. All we do here is initialize the OpenGL matrices and initialize the clear color. If there's an error, we report it using gluErrorString().
We do our post OpenGL window/context creation initialization. All we do here is initialize the OpenGL matrices and initialize the clear color. If there's an error, we report it using gluErrorString().
void handleKeys( unsigned char key, int x, int y )
{
//Toggle quad
if( key == 'q' )
{
renderQuad = !renderQuad;
}
}
This handleKeys() function takes in the ASCII value of a key press and the current mouse position (which we're not using here).
All this function does is toggle a bool flag when the q key is pressed.
All this function does is toggle a bool flag when the q key is pressed.
void update()
{
}
void render()
{
//Clear color buffer
glClear( GL_COLOR_BUFFER_BIT );
//Render quad
if( renderQuad == true )
{
glBegin( GL_QUADS );
glVertex2f( -0.5f, -0.5f );
glVertex2f( 0.5f, -0.5f );
glVertex2f( 0.5f, 0.5f );
glVertex2f( -0.5f, 0.5f );
glEnd();
}
//Update screen
SDL_GL_SwapBuffers();
}
Here are the update() and render() functions that represent the update and render portions of the game loop. As you can see, the update() function is just there for the sake of
representing the update portion of the game loop.
Our render function is much more interesting. It clears the color buffer using glClear() then renders a quad to the screen. We can't use SDL_Flip() update the screen, we need to call SDL_GL_SwapBuffers() to update a SDL/OpenGL window.
Our render function is much more interesting. It clears the color buffer using glClear() then renders a quad to the screen. We can't use SDL_Flip() update the screen, we need to call SDL_GL_SwapBuffers() to update a SDL/OpenGL window.
//While there are events to handle
while( SDL_PollEvent( &event ) )
{
if( event.type == SDL_QUIT )
{
quit = true;
}
else if( event.type == SDL_KEYDOWN )
{
//Handle keypress with current mouse position
int x = 0, y = 0;
SDL_GetMouseState( &x, &y );
handleKeys( event.key.keysym.unicode, x, y );
}
}
//Run frame update
update();
//Render frame
render();
//Cap the frame rate
if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
Here's our main loop.
First we handle events and pass in the unicode value to our handleKeys() function. Then we run the update() and render() functions to complete the main loop.
First we handle events and pass in the unicode value to our handleKeys() function. Then we run the update() and render() functions to complete the main loop.
For those of you who have never used OpenGL, a lot of this probably went over your head. For the most part, this tutorial was designed to show people how to use SDL with
OpenGL as opposed to teaching them how to use OpenGL. If you want to learn to use OpenGL check out the OpenGL tutorial set on this site.
The OpenGL tutorial set uses freeGLUT. Not necessarily because it's better (it's not), but because freeGLUT supports context controls in the current stable release. SDL 2.0 will support context control but as of the the last update of this tutorial it's not officially released yet. With this tutorial, you should be able to easily port the freeGLUT based OpenGL applications to SDL.
A word of caution to beginners: there's a reason this tutorial set uses OpenGL. OpenGL is much more powerful, but it's significantly more difficult to use. It takes 8 tutorial to get the same result this tutorial set gets in 1 tutorial. I recommend making games with a simpler APIs like SDL first and then moving on APIs like OpenGL.
If you do think you're ready, click the OpenGL tutorials link and dive in =)
The OpenGL tutorial set uses freeGLUT. Not necessarily because it's better (it's not), but because freeGLUT supports context controls in the current stable release. SDL 2.0 will support context control but as of the the last update of this tutorial it's not officially released yet. With this tutorial, you should be able to easily port the freeGLUT based OpenGL applications to SDL.
A word of caution to beginners: there's a reason this tutorial set uses OpenGL. OpenGL is much more powerful, but it's significantly more difficult to use. It takes 8 tutorial to get the same result this tutorial set gets in 1 tutorial. I recommend making games with a simpler APIs like SDL first and then moving on APIs like OpenGL.
If you do think you're ready, click the OpenGL tutorials link and dive in =)