• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<HTML
2><HEAD
3><TITLE
4>Using OpenGL With SDL</TITLE
5><META
6NAME="GENERATOR"
7CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
8"><LINK
9REL="HOME"
10TITLE="SDL Library Documentation"
11HREF="index.html"><LINK
12REL="UP"
13TITLE="Graphics and Video"
14HREF="guidevideo.html"><LINK
15REL="PREVIOUS"
16TITLE="Graphics and Video"
17HREF="guidevideo.html"><LINK
18REL="NEXT"
19TITLE="Input handling"
20HREF="guideinput.html"></HEAD
21><BODY
22CLASS="SECT1"
23BGCOLOR="#FFF8DC"
24TEXT="#000000"
25LINK="#0000ee"
26VLINK="#551a8b"
27ALINK="#ff0000"
28><DIV
29CLASS="NAVHEADER"
30><TABLE
31SUMMARY="Header navigation table"
32WIDTH="100%"
33BORDER="0"
34CELLPADDING="0"
35CELLSPACING="0"
36><TR
37><TH
38COLSPAN="3"
39ALIGN="center"
40>SDL Library Documentation</TH
41></TR
42><TR
43><TD
44WIDTH="10%"
45ALIGN="left"
46VALIGN="bottom"
47><A
48HREF="guidevideo.html"
49ACCESSKEY="P"
50>Prev</A
51></TD
52><TD
53WIDTH="80%"
54ALIGN="center"
55VALIGN="bottom"
56>Chapter 2. Graphics and Video</TD
57><TD
58WIDTH="10%"
59ALIGN="right"
60VALIGN="bottom"
61><A
62HREF="guideinput.html"
63ACCESSKEY="N"
64>Next</A
65></TD
66></TR
67></TABLE
68><HR
69ALIGN="LEFT"
70WIDTH="100%"></DIV
71><DIV
72CLASS="SECT1"
73><H1
74CLASS="SECT1"
75><A
76NAME="GUIDEVIDEOOPENGL"
77></A
78>Using OpenGL With SDL</H1
79><P
80>SDL has the ability to create and use OpenGL contexts on several platforms(Linux/X11, Win32, BeOS, MacOS Classic/Toolbox, Mac OS X, FreeBSD/X11 and Solaris/X11). This allows you to use SDL's audio, event handling, threads and times in your OpenGL applications (a function often performed by GLUT).</P
81><DIV
82CLASS="SECT2"
83><H2
84CLASS="SECT2"
85><A
86NAME="AEN103"
87></A
88>Initialisation</H2
89><P
90>Initialising SDL to use OpenGL is not very different to initialising SDL normally. There are three differences; you must pass <TT
91CLASS="LITERAL"
92>SDL_OPENGL</TT
93> to <A
94HREF="sdlsetvideomode.html"
95><TT
96CLASS="FUNCTION"
97>SDL_SetVideoMode</TT
98></A
99>, you must specify several GL attributes (depth buffer size, framebuffer sizes) using <A
100HREF="sdlglsetattribute.html"
101><TT
102CLASS="FUNCTION"
103>SDL_GL_SetAttribute</TT
104></A
105> and finally, if you wish to use double buffering you must specify it as a GL attribute, <SPAN
106CLASS="emphasis"
107><I
108CLASS="EMPHASIS"
109>not</I
110></SPAN
111> by passing the <TT
112CLASS="LITERAL"
113>SDL_DOUBLEBUF</TT
114> flag to <TT
115CLASS="FUNCTION"
116>SDL_SetVideoMode</TT
117>.</P
118><DIV
119CLASS="EXAMPLE"
120><A
121NAME="AEN114"
122></A
123><P
124><B
125>Example 2-7. Initializing SDL with OpenGL</B
126></P
127><PRE
128CLASS="PROGRAMLISTING"
129>    /* Information about the current video settings. */
130    const SDL_VideoInfo* info = NULL;
131    /* Dimensions of our window. */
132    int width = 0;
133    int height = 0;
134    /* Color depth in bits of our window. */
135    int bpp = 0;
136    /* Flags we will pass into SDL_SetVideoMode. */
137    int flags = 0;
138
139    /* First, initialize SDL's video subsystem. */
140    if( SDL_Init( SDL_INIT_VIDEO ) &#60; 0 ) {
141        /* Failed, exit. */
142        fprintf( stderr, "Video initialization failed: %s\n",
143             SDL_GetError( ) );
144        quit_tutorial( 1 );
145    }
146
147    /* Let's get some video information. */
148    info = SDL_GetVideoInfo( );
149
150    if( !info ) {
151        /* This should probably never happen. */
152        fprintf( stderr, "Video query failed: %s\n",
153             SDL_GetError( ) );
154        quit_tutorial( 1 );
155    }
156
157    /*
158     * Set our width/height to 640/480 (you would
159     * of course let the user decide this in a normal
160     * app). We get the bpp we will request from
161     * the display. On X11, VidMode can't change
162     * resolution, so this is probably being overly
163     * safe. Under Win32, ChangeDisplaySettings
164     * can change the bpp.
165     */
166    width = 640;
167    height = 480;
168    bpp = info-&#62;vfmt-&#62;BitsPerPixel;
169
170    /*
171     * Now, we want to setup our requested
172     * window attributes for our OpenGL window.
173     * We want *at least* 5 bits of red, green
174     * and blue. We also want at least a 16-bit
175     * depth buffer.
176     *
177     * The last thing we do is request a double
178     * buffered window. '1' turns on double
179     * buffering, '0' turns it off.
180     *
181     * Note that we do not use SDL_DOUBLEBUF in
182     * the flags to SDL_SetVideoMode. That does
183     * not affect the GL attribute state, only
184     * the standard 2D blitting setup.
185     */
186    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
187    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
188    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
189    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
190    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
191
192    /*
193     * We want to request that SDL provide us
194     * with an OpenGL window, in a fullscreen
195     * video mode.
196     *
197     * EXERCISE:
198     * Make starting windowed an option, and
199     * handle the resize events properly with
200     * glViewport.
201     */
202    flags = SDL_OPENGL | SDL_FULLSCREEN;
203
204    /*
205     * Set the video mode
206     */
207    if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
208        /*
209         * This could happen for a variety of reasons,
210         * including DISPLAY not being set, the specified
211         * resolution not being available, etc.
212         */
213        fprintf( stderr, "Video mode set failed: %s\n",
214             SDL_GetError( ) );
215        quit_tutorial( 1 );
216    }</PRE
217></DIV
218></DIV
219><DIV
220CLASS="SECT2"
221><H2
222CLASS="SECT2"
223><A
224NAME="AEN117"
225></A
226>Drawing</H2
227><P
228>Apart from initialisation, using OpenGL within SDL is the same as using OpenGL
229with any other API, e.g. GLUT. You still use all the same function calls and
230data types. However if you are using a double-buffered display, then you must
231use
232<A
233HREF="sdlglswapbuffers.html"
234><TT
235CLASS="FUNCTION"
236>SDL_GL_SwapBuffers()</TT
237></A
238>
239to swap the buffers and update the display. To request double-buffering
240with OpenGL, use
241<A
242HREF="sdlglsetattribute.html"
243><TT
244CLASS="FUNCTION"
245>SDL_GL_SetAttribute</TT
246></A
247>
248with <TT
249CLASS="LITERAL"
250>SDL_GL_DOUBLEBUFFER</TT
251>, and use
252<A
253HREF="sdlglgetattribute.html"
254><TT
255CLASS="FUNCTION"
256>SDL_GL_GetAttribute</TT
257></A
258>
259to see if you actually got it.</P
260><P
261>A full example code listing is now presented below.</P
262><DIV
263CLASS="EXAMPLE"
264><A
265NAME="AEN128"
266></A
267><P
268><B
269>Example 2-8. SDL and OpenGL</B
270></P
271><PRE
272CLASS="PROGRAMLISTING"
273>/*
274 * SDL OpenGL Tutorial.
275 * (c) Michael Vance, 2000
276 * briareos@lokigames.com
277 *
278 * Distributed under terms of the LGPL.
279 */
280
281#include &#60;SDL/SDL.h&#62;
282#include &#60;GL/gl.h&#62;
283#include &#60;GL/glu.h&#62;
284
285#include &#60;stdio.h&#62;
286#include &#60;stdlib.h&#62;
287
288static GLboolean should_rotate = GL_TRUE;
289
290static void quit_tutorial( int code )
291{
292    /*
293     * Quit SDL so we can release the fullscreen
294     * mode and restore the previous video settings,
295     * etc.
296     */
297    SDL_Quit( );
298
299    /* Exit program. */
300    exit( code );
301}
302
303static void handle_key_down( SDL_keysym* keysym )
304{
305
306    /*
307     * We're only interested if 'Esc' has
308     * been presssed.
309     *
310     * EXERCISE:
311     * Handle the arrow keys and have that change the
312     * viewing position/angle.
313     */
314    switch( keysym-&#62;sym ) {
315    case SDLK_ESCAPE:
316        quit_tutorial( 0 );
317        break;
318    case SDLK_SPACE:
319        should_rotate = !should_rotate;
320        break;
321    default:
322        break;
323    }
324
325}
326
327static void process_events( void )
328{
329    /* Our SDL event placeholder. */
330    SDL_Event event;
331
332    /* Grab all the events off the queue. */
333    while( SDL_PollEvent( &#38;event ) ) {
334
335        switch( event.type ) {
336        case SDL_KEYDOWN:
337            /* Handle key presses. */
338            handle_key_down( &#38;event.key.keysym );
339            break;
340        case SDL_QUIT:
341            /* Handle quit requests (like Ctrl-c). */
342            quit_tutorial( 0 );
343            break;
344        }
345
346    }
347
348}
349
350static void draw_screen( void )
351{
352    /* Our angle of rotation. */
353    static float angle = 0.0f;
354
355    /*
356     * EXERCISE:
357     * Replace this awful mess with vertex
358     * arrays and a call to glDrawElements.
359     *
360     * EXERCISE:
361     * After completing the above, change
362     * it to use compiled vertex arrays.
363     *
364     * EXERCISE:
365     * Verify my windings are correct here ;).
366     */
367    static GLfloat v0[] = { -1.0f, -1.0f,  1.0f };
368    static GLfloat v1[] = {  1.0f, -1.0f,  1.0f };
369    static GLfloat v2[] = {  1.0f,  1.0f,  1.0f };
370    static GLfloat v3[] = { -1.0f,  1.0f,  1.0f };
371    static GLfloat v4[] = { -1.0f, -1.0f, -1.0f };
372    static GLfloat v5[] = {  1.0f, -1.0f, -1.0f };
373    static GLfloat v6[] = {  1.0f,  1.0f, -1.0f };
374    static GLfloat v7[] = { -1.0f,  1.0f, -1.0f };
375    static GLubyte red[]    = { 255,   0,   0, 255 };
376    static GLubyte green[]  = {   0, 255,   0, 255 };
377    static GLubyte blue[]   = {   0,   0, 255, 255 };
378    static GLubyte white[]  = { 255, 255, 255, 255 };
379    static GLubyte yellow[] = {   0, 255, 255, 255 };
380    static GLubyte black[]  = {   0,   0,   0, 255 };
381    static GLubyte orange[] = { 255, 255,   0, 255 };
382    static GLubyte purple[] = { 255,   0, 255,   0 };
383
384    /* Clear the color and depth buffers. */
385    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
386
387    /* We don't want to modify the projection matrix. */
388    glMatrixMode( GL_MODELVIEW );
389    glLoadIdentity( );
390
391    /* Move down the z-axis. */
392    glTranslatef( 0.0, 0.0, -5.0 );
393
394    /* Rotate. */
395    glRotatef( angle, 0.0, 1.0, 0.0 );
396
397    if( should_rotate ) {
398
399        if( ++angle &#62; 360.0f ) {
400            angle = 0.0f;
401        }
402
403    }
404
405    /* Send our triangle data to the pipeline. */
406    glBegin( GL_TRIANGLES );
407
408    glColor4ubv( red );
409    glVertex3fv( v0 );
410    glColor4ubv( green );
411    glVertex3fv( v1 );
412    glColor4ubv( blue );
413    glVertex3fv( v2 );
414
415    glColor4ubv( red );
416    glVertex3fv( v0 );
417    glColor4ubv( blue );
418    glVertex3fv( v2 );
419    glColor4ubv( white );
420    glVertex3fv( v3 );
421
422    glColor4ubv( green );
423    glVertex3fv( v1 );
424    glColor4ubv( black );
425    glVertex3fv( v5 );
426    glColor4ubv( orange );
427    glVertex3fv( v6 );
428
429    glColor4ubv( green );
430    glVertex3fv( v1 );
431    glColor4ubv( orange );
432    glVertex3fv( v6 );
433    glColor4ubv( blue );
434    glVertex3fv( v2 );
435
436    glColor4ubv( black );
437    glVertex3fv( v5 );
438    glColor4ubv( yellow );
439    glVertex3fv( v4 );
440    glColor4ubv( purple );
441    glVertex3fv( v7 );
442
443    glColor4ubv( black );
444    glVertex3fv( v5 );
445    glColor4ubv( purple );
446    glVertex3fv( v7 );
447    glColor4ubv( orange );
448    glVertex3fv( v6 );
449
450    glColor4ubv( yellow );
451    glVertex3fv( v4 );
452    glColor4ubv( red );
453    glVertex3fv( v0 );
454    glColor4ubv( white );
455    glVertex3fv( v3 );
456
457    glColor4ubv( yellow );
458    glVertex3fv( v4 );
459    glColor4ubv( white );
460    glVertex3fv( v3 );
461    glColor4ubv( purple );
462    glVertex3fv( v7 );
463
464    glColor4ubv( white );
465    glVertex3fv( v3 );
466    glColor4ubv( blue );
467    glVertex3fv( v2 );
468    glColor4ubv( orange );
469    glVertex3fv( v6 );
470
471    glColor4ubv( white );
472    glVertex3fv( v3 );
473    glColor4ubv( orange );
474    glVertex3fv( v6 );
475    glColor4ubv( purple );
476    glVertex3fv( v7 );
477
478    glColor4ubv( green );
479    glVertex3fv( v1 );
480    glColor4ubv( red );
481    glVertex3fv( v0 );
482    glColor4ubv( yellow );
483    glVertex3fv( v4 );
484
485    glColor4ubv( green );
486    glVertex3fv( v1 );
487    glColor4ubv( yellow );
488    glVertex3fv( v4 );
489    glColor4ubv( black );
490    glVertex3fv( v5 );
491
492    glEnd( );
493
494    /*
495     * EXERCISE:
496     * Draw text telling the user that 'Spc'
497     * pauses the rotation and 'Esc' quits.
498     * Do it using vetors and textured quads.
499     */
500
501    /*
502     * Swap the buffers. This this tells the driver to
503     * render the next frame from the contents of the
504     * back-buffer, and to set all rendering operations
505     * to occur on what was the front-buffer.
506     *
507     * Double buffering prevents nasty visual tearing
508     * from the application drawing on areas of the
509     * screen that are being updated at the same time.
510     */
511    SDL_GL_SwapBuffers( );
512}
513
514static void setup_opengl( int width, int height )
515{
516    float ratio = (float) width / (float) height;
517
518    /* Our shading model--Gouraud (smooth). */
519    glShadeModel( GL_SMOOTH );
520
521    /* Culling. */
522    glCullFace( GL_BACK );
523    glFrontFace( GL_CCW );
524    glEnable( GL_CULL_FACE );
525
526    /* Set the clear color. */
527    glClearColor( 0, 0, 0, 0 );
528
529    /* Setup our viewport. */
530    glViewport( 0, 0, width, height );
531
532    /*
533     * Change to the projection matrix and set
534     * our viewing volume.
535     */
536    glMatrixMode( GL_PROJECTION );
537    glLoadIdentity( );
538    /*
539     * EXERCISE:
540     * Replace this with a call to glFrustum.
541     */
542    gluPerspective( 60.0, ratio, 1.0, 1024.0 );
543}
544
545int main( int argc, char* argv[] )
546{
547    /* Information about the current video settings. */
548    const SDL_VideoInfo* info = NULL;
549    /* Dimensions of our window. */
550    int width = 0;
551    int height = 0;
552    /* Color depth in bits of our window. */
553    int bpp = 0;
554    /* Flags we will pass into SDL_SetVideoMode. */
555    int flags = 0;
556
557    /* First, initialize SDL's video subsystem. */
558    if( SDL_Init( SDL_INIT_VIDEO ) &#60; 0 ) {
559        /* Failed, exit. */
560        fprintf( stderr, "Video initialization failed: %s\n",
561             SDL_GetError( ) );
562        quit_tutorial( 1 );
563    }
564
565    /* Let's get some video information. */
566    info = SDL_GetVideoInfo( );
567
568    if( !info ) {
569        /* This should probably never happen. */
570        fprintf( stderr, "Video query failed: %s\n",
571             SDL_GetError( ) );
572        quit_tutorial( 1 );
573    }
574
575    /*
576     * Set our width/height to 640/480 (you would
577     * of course let the user decide this in a normal
578     * app). We get the bpp we will request from
579     * the display. On X11, VidMode can't change
580     * resolution, so this is probably being overly
581     * safe. Under Win32, ChangeDisplaySettings
582     * can change the bpp.
583     */
584    width = 640;
585    height = 480;
586    bpp = info-&#62;vfmt-&#62;BitsPerPixel;
587
588    /*
589     * Now, we want to setup our requested
590     * window attributes for our OpenGL window.
591     * We want *at least* 5 bits of red, green
592     * and blue. We also want at least a 16-bit
593     * depth buffer.
594     *
595     * The last thing we do is request a double
596     * buffered window. '1' turns on double
597     * buffering, '0' turns it off.
598     *
599     * Note that we do not use SDL_DOUBLEBUF in
600     * the flags to SDL_SetVideoMode. That does
601     * not affect the GL attribute state, only
602     * the standard 2D blitting setup.
603     */
604    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
605    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
606    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
607    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
608    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
609
610    /*
611     * We want to request that SDL provide us
612     * with an OpenGL window, in a fullscreen
613     * video mode.
614     *
615     * EXERCISE:
616     * Make starting windowed an option, and
617     * handle the resize events properly with
618     * glViewport.
619     */
620    flags = SDL_OPENGL | SDL_FULLSCREEN;
621
622    /*
623     * Set the video mode
624     */
625    if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
626        /*
627         * This could happen for a variety of reasons,
628         * including DISPLAY not being set, the specified
629         * resolution not being available, etc.
630         */
631        fprintf( stderr, "Video mode set failed: %s\n",
632             SDL_GetError( ) );
633        quit_tutorial( 1 );
634    }
635
636    /*
637     * At this point, we should have a properly setup
638     * double-buffered window for use with OpenGL.
639     */
640    setup_opengl( width, height );
641
642    /*
643     * Now we want to begin our normal app process--
644     * an event loop with a lot of redrawing.
645     */
646    while( 1 ) {
647        /* Process incoming events. */
648        process_events( );
649        /* Draw the screen. */
650        draw_screen( );
651    }
652
653    /*
654     * EXERCISE:
655     * Record timings using SDL_GetTicks() and
656     * and print out frames per second at program
657     * end.
658     */
659
660    /* Never reached. */
661    return 0;
662}</PRE
663></DIV
664></DIV
665></DIV
666><DIV
667CLASS="NAVFOOTER"
668><HR
669ALIGN="LEFT"
670WIDTH="100%"><TABLE
671SUMMARY="Footer navigation table"
672WIDTH="100%"
673BORDER="0"
674CELLPADDING="0"
675CELLSPACING="0"
676><TR
677><TD
678WIDTH="33%"
679ALIGN="left"
680VALIGN="top"
681><A
682HREF="guidevideo.html"
683ACCESSKEY="P"
684>Prev</A
685></TD
686><TD
687WIDTH="34%"
688ALIGN="center"
689VALIGN="top"
690><A
691HREF="index.html"
692ACCESSKEY="H"
693>Home</A
694></TD
695><TD
696WIDTH="33%"
697ALIGN="right"
698VALIGN="top"
699><A
700HREF="guideinput.html"
701ACCESSKEY="N"
702>Next</A
703></TD
704></TR
705><TR
706><TD
707WIDTH="33%"
708ALIGN="left"
709VALIGN="top"
710>Graphics and Video</TD
711><TD
712WIDTH="34%"
713ALIGN="center"
714VALIGN="top"
715><A
716HREF="guidevideo.html"
717ACCESSKEY="U"
718>Up</A
719></TD
720><TD
721WIDTH="33%"
722ALIGN="right"
723VALIGN="top"
724>Input handling</TD
725></TR
726></TABLE
727></DIV
728></BODY
729></HTML
730>