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
