Add "scaled" and "pixelperfect" layer sizes.
[sdl_omap.git] / docs / html / guidevideoopengl.html
CommitLineData
e14743d1 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>