rename input.c to avoid conflicts, some small refactoring
[sdl_omap.git] / docs / html / guidevideoopengl.html
1 <HTML
2 ><HEAD
3 ><TITLE
4 >Using OpenGL With SDL</TITLE
5 ><META
6 NAME="GENERATOR"
7 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
8 "><LINK
9 REL="HOME"
10 TITLE="SDL Library Documentation"
11 HREF="index.html"><LINK
12 REL="UP"
13 TITLE="Graphics and Video"
14 HREF="guidevideo.html"><LINK
15 REL="PREVIOUS"
16 TITLE="Graphics and Video"
17 HREF="guidevideo.html"><LINK
18 REL="NEXT"
19 TITLE="Input handling"
20 HREF="guideinput.html"></HEAD
21 ><BODY
22 CLASS="SECT1"
23 BGCOLOR="#FFF8DC"
24 TEXT="#000000"
25 LINK="#0000ee"
26 VLINK="#551a8b"
27 ALINK="#ff0000"
28 ><DIV
29 CLASS="NAVHEADER"
30 ><TABLE
31 SUMMARY="Header navigation table"
32 WIDTH="100%"
33 BORDER="0"
34 CELLPADDING="0"
35 CELLSPACING="0"
36 ><TR
37 ><TH
38 COLSPAN="3"
39 ALIGN="center"
40 >SDL Library Documentation</TH
41 ></TR
42 ><TR
43 ><TD
44 WIDTH="10%"
45 ALIGN="left"
46 VALIGN="bottom"
47 ><A
48 HREF="guidevideo.html"
49 ACCESSKEY="P"
50 >Prev</A
51 ></TD
52 ><TD
53 WIDTH="80%"
54 ALIGN="center"
55 VALIGN="bottom"
56 >Chapter 2. Graphics and Video</TD
57 ><TD
58 WIDTH="10%"
59 ALIGN="right"
60 VALIGN="bottom"
61 ><A
62 HREF="guideinput.html"
63 ACCESSKEY="N"
64 >Next</A
65 ></TD
66 ></TR
67 ></TABLE
68 ><HR
69 ALIGN="LEFT"
70 WIDTH="100%"></DIV
71 ><DIV
72 CLASS="SECT1"
73 ><H1
74 CLASS="SECT1"
75 ><A
76 NAME="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
82 CLASS="SECT2"
83 ><H2
84 CLASS="SECT2"
85 ><A
86 NAME="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
91 CLASS="LITERAL"
92 >SDL_OPENGL</TT
93 > to <A
94 HREF="sdlsetvideomode.html"
95 ><TT
96 CLASS="FUNCTION"
97 >SDL_SetVideoMode</TT
98 ></A
99 >, you must specify several GL attributes (depth buffer size, framebuffer sizes) using <A
100 HREF="sdlglsetattribute.html"
101 ><TT
102 CLASS="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
106 CLASS="emphasis"
107 ><I
108 CLASS="EMPHASIS"
109 >not</I
110 ></SPAN
111 > by passing the <TT
112 CLASS="LITERAL"
113 >SDL_DOUBLEBUF</TT
114 > flag to <TT
115 CLASS="FUNCTION"
116 >SDL_SetVideoMode</TT
117 >.</P
118 ><DIV
119 CLASS="EXAMPLE"
120 ><A
121 NAME="AEN114"
122 ></A
123 ><P
124 ><B
125 >Example 2-7. Initializing SDL with OpenGL</B
126 ></P
127 ><PRE
128 CLASS="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
220 CLASS="SECT2"
221 ><H2
222 CLASS="SECT2"
223 ><A
224 NAME="AEN117"
225 ></A
226 >Drawing</H2
227 ><P
228 >Apart from initialisation, using OpenGL within SDL is the same as using OpenGL
229 with any other API, e.g. GLUT. You still use all the same function calls and
230 data types. However if you are using a double-buffered display, then you must
231 use
232 <A
233 HREF="sdlglswapbuffers.html"
234 ><TT
235 CLASS="FUNCTION"
236 >SDL_GL_SwapBuffers()</TT
237 ></A
238 >
239 to swap the buffers and update the display. To request double-buffering
240 with OpenGL, use
241 <A
242 HREF="sdlglsetattribute.html"
243 ><TT
244 CLASS="FUNCTION"
245 >SDL_GL_SetAttribute</TT
246 ></A
247 >
248 with <TT
249 CLASS="LITERAL"
250 >SDL_GL_DOUBLEBUFFER</TT
251 >, and use
252 <A
253 HREF="sdlglgetattribute.html"
254 ><TT
255 CLASS="FUNCTION"
256 >SDL_GL_GetAttribute</TT
257 ></A
258 >
259 to see if you actually got it.</P
260 ><P
261 >A full example code listing is now presented below.</P
262 ><DIV
263 CLASS="EXAMPLE"
264 ><A
265 NAME="AEN128"
266 ></A
267 ><P
268 ><B
269 >Example 2-8. SDL and OpenGL</B
270 ></P
271 ><PRE
272 CLASS="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
288 static GLboolean should_rotate = GL_TRUE;
289
290 static 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
303 static 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
327 static 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
350 static 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
514 static 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
545 int 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
667 CLASS="NAVFOOTER"
668 ><HR
669 ALIGN="LEFT"
670 WIDTH="100%"><TABLE
671 SUMMARY="Footer navigation table"
672 WIDTH="100%"
673 BORDER="0"
674 CELLPADDING="0"
675 CELLSPACING="0"
676 ><TR
677 ><TD
678 WIDTH="33%"
679 ALIGN="left"
680 VALIGN="top"
681 ><A
682 HREF="guidevideo.html"
683 ACCESSKEY="P"
684 >Prev</A
685 ></TD
686 ><TD
687 WIDTH="34%"
688 ALIGN="center"
689 VALIGN="top"
690 ><A
691 HREF="index.html"
692 ACCESSKEY="H"
693 >Home</A
694 ></TD
695 ><TD
696 WIDTH="33%"
697 ALIGN="right"
698 VALIGN="top"
699 ><A
700 HREF="guideinput.html"
701 ACCESSKEY="N"
702 >Next</A
703 ></TD
704 ></TR
705 ><TR
706 ><TD
707 WIDTH="33%"
708 ALIGN="left"
709 VALIGN="top"
710 >Graphics and Video</TD
711 ><TD
712 WIDTH="34%"
713 ALIGN="center"
714 VALIGN="top"
715 ><A
716 HREF="guidevideo.html"
717 ACCESSKEY="U"
718 >Up</A
719 ></TD
720 ><TD
721 WIDTH="33%"
722 ALIGN="right"
723 VALIGN="top"
724 >Input handling</TD
725 ></TR
726 ></TABLE
727 ></DIV
728 ></BODY
729 ></HTML
730 >