OpenGL complete example

Apart from initialization, using OpenGL within SDL is the same as using OpenGL with any other API, e.g. GLUT. You still use all the same function calls and data types. However if you are using a double-buffered display, then you must use SDL_GL_SwapBuffers to swap the buffers and update the display. To request double-buffering with OpenGL, use SDL_GL_SetAttribute with SDL_GL_DOUBLEBUFFER, and then use SDL_GL_GetAttribute to see if you actually got it.

A full example code listing is now presented below

   1 #include "SDL.h"
   2 #include "SDL_opengl.h"
   3 
   4 #include <stdio.h>
   5 #include <stdlib.h>
   6 #include <math.h>
   7 
   8 #define WIDTH  640
   9 #define HEIGHT 480
  10 
  11 GLfloat yaw;
  12 GLfloat pitch;
  13 int     level;
  14 
  15 static void subdivide
  16 (
  17     GLfloat point0[3], 
  18     GLfloat point1[3], 
  19     GLfloat point2[3], 
  20     int level
  21 )
  22 {
  23     int coord;
  24     GLfloat midpoint[3][3];
  25     
  26     /* Don't subdivide any further; just draw the triangle */
  27     if (level==0) {
  28         glColor3fv(point0);
  29         glVertex3fv(point0);
  30         glColor3fv(point1);
  31         glVertex3fv(point1);
  32         glColor3fv(point2);
  33         glVertex3fv(point2);
  34         return;
  35     }
  36 
  37     /* Calculate a midpoint on each edge of the triangle */
  38     for(coord = 0; coord<3; coord++) {
  39         midpoint[0][coord] = (point0[coord] + point1[coord])*0.5;
  40         midpoint[1][coord] = (point1[coord] + point2[coord])*0.5;
  41         midpoint[2][coord] = (point2[coord] + point0[coord])*0.5;
  42     }
  43 
  44     /* Subdivide each triangle into three more */    /*     .      */
  45     level--;                                         /*    /X\     */
  46     subdivide(point0,midpoint[0],midpoint[2],level); /*   /xxx\    */
  47     subdivide(point1,midpoint[1],midpoint[0],level); /*  /X\ /X\   */
  48     subdivide(point2,midpoint[2],midpoint[1],level); /* /XXXVXXX\  */
  49 }
  50 
  51 
  52 static void repaint()
  53 {
  54     int i;
  55 
  56     /* Coordinates of the 6 vertices of the octahedron */
  57     static GLfloat point[6][3] = { 
  58         {1.0f,0.0f,0.0f},{-1.0f,0.0f,0.0f},
  59         {0.0f,1.0f,0.0f},{0.0f,-1.0f,0.0f},
  60         {0.0f,0.0f,1.0f},{0.0f,0.0f,-1.0f}
  61     };
  62 
  63     /* indices of the vertices of the triangles which make up each of 
  64      * the 8 faces of the octahedron */
  65     static int triangle[8][3] = { 
  66         {2,4,0},{2,0,5},{2,5,1},{2,1,4},{3,0,4},{3,5,0},{3,1,5},{3,4,1}
  67     };
  68    
  69     /* Clear the color plane and the z-buffer */
  70     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  71 
  72     glLoadIdentity();
  73 
  74     /* Move the object 2 units away from the camera */
  75     glTranslatef(0.0f, 0.0f, -2.0f);
  76 
  77     /* Rotate the object */
  78     glRotatef(pitch, 1.0f, 0.0f, 0.0f);
  79     glRotatef(yaw, 0.0f, 1.0f, 0.0f);
  80 
  81     /* Draw the triangles which make up the object */
  82     glBegin(GL_TRIANGLES);
  83 
  84     for (i=0; i<8; i++) {
  85         subdivide(point[triangle[i][0]],point[triangle[i][1]],point[triangle[i][2]],level);
  86     }
  87     
  88     glEnd();
  89 
  90     /* increment the rotation every frame */
  91     yaw = yaw + 0.05;
  92 
  93     /* finally, swap the back and front buffers */
  94     SDL_GL_SwapBuffers();
  95 }
  96 
  97 
  98 static void setup_sdl() 
  99 {
 100     const SDL_VideoInfo* video;
 101 
 102     if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 103         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
 104         exit(1);
 105     }
 106         
 107     /* Quit SDL properly on exit */
 108     atexit(SDL_Quit);
 109 
 110     /* Get the current video information */
 111     video = SDL_GetVideoInfo( );
 112     if( video == NULL ) {
 113         fprintf(stderr, "Couldn't get video information: %s\n", SDL_GetError());
 114         exit(1);
 115     }
 116 
 117     /* Set the minimum requirements for the OpenGL window */
 118     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
 119     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
 120     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
 121     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
 122     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
 123 
 124     /* Note the SDL_DOUBLEBUF flag is not required to enable double 
 125      * buffering when setting an OpenGL video mode. 
 126      * Double buffering is enabled or disabled using the 
 127      * SDL_GL_DOUBLEBUFFER attribute.
 128      */
 129     if( SDL_SetVideoMode( WIDTH, HEIGHT, video->vfmt->BitsPerPixel, SDL_OPENGL ) == 0 ) {
 130         fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
 131         exit(1);
 132     }
 133 }
 134 
 135 
 136 static void setup_opengl()
 137 {
 138     float aspect = (float)WIDTH / (float)HEIGHT;
 139 
 140     /* Make the viewport cover the whole window */
 141     glViewport(0, 0, WIDTH, HEIGHT);
 142 
 143     /* Set the camera projection matrix:
 144      * field of view: 90 degrees
 145      * near clipping plane at 0.1
 146      * far clipping plane at 100.0
 147      */
 148     glMatrixMode(GL_PROJECTION);
 149     glLoadIdentity();
 150     
 151     gluPerspective(60.0, aspect, 0.1, 100.0);
 152     /* We're done with the camera, now matrix operations 
 153      * will affect the modelview matrix
 154      * */
 155     glMatrixMode(GL_MODELVIEW);
 156 
 157     /* set the clear color to gray */
 158     glClearColor(0.5, 0.5 ,0.5, 0);
 159     
 160     /* We want z-buffer tests enabled*/
 161     glEnable(GL_DEPTH_TEST);
 162 
 163     /* Do draw back-facing polygons*/
 164     glDisable(GL_CULL_FACE);
 165 }
 166 
 167 
 168 static void main_loop() 
 169 {
 170     SDL_Event event;
 171 
 172     while (1) {
 173         /* process pending events */
 174         while( SDL_PollEvent( &event ) ) {
 175             switch( event.type ) {
 176             case SDL_KEYDOWN:
 177                 switch ( event.key.keysym.sym ) {
 178                 case SDLK_ESCAPE:
 179                     exit(0);
 180                                         break;
 181              
 182                 case SDLK_KP_PLUS:
 183                     level++;
 184                     if (level > 5) level=5;
 185                     break;
 186             
 187                 case SDLK_KP_MINUS:
 188                     level--;
 189                     if (level < 0) level=0;
 190                     break;
 191 
 192                 default:
 193                      //no default key processing
 194                      //(stops compiler warnings for unhandled SDL keydefs
 195                      break;
 196                 }
 197             break;
 198 
 199             case SDL_MOUSEMOTION:
 200                 pitch += event.motion.yrel;
 201                 if (pitch < -70) pitch = -70;
 202                 if (pitch > 70) pitch = 70;
 203                 break;
 204 
 205              case SDL_QUIT:
 206                 exit (0);
 207                 break;
 208             }
 209         }
 210 
 211     /* update the screen */    
 212         repaint();
 213 
 214     /* Wait 50ms to avoid using up all the CPU time */
 215         SDL_Delay( 50 );
 216     }
 217 }
 218 
 219 
 220 int main(int argc, char* argv[])
 221 {
 222     setup_sdl();
 223     
 224     setup_opengl();
 225 
 226     yaw   = 45;
 227     pitch = 0;
 228     level = 2;
 229     
 230     main_loop();
 231         
 232     return 0;
 233 }

See also

SDL_Init, SDL_Delay, SDL_GL_SetAttribute, SDL_SetVideoMode


CategoryExamples

OpenGL_Full_Example (last edited 2008-12-11 22:39:08 by KenBull)