comparison docs/html/guidevideoopengl.html @ 55:55f1f1b3e27d

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