5131
clevermous
1
2
>
3
>
4
>Using OpenGL With SDL
5
>
6
NAME="GENERATOR"
7
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
8
">
9
REL="HOME"
10
TITLE="SDL Library Documentation"
11
HREF="index.html">
12
REL="UP"
13
TITLE="Graphics and Video"
14
HREF="guidevideo.html">
15
REL="PREVIOUS"
16
TITLE="Graphics and Video"
17
HREF="guidevideo.html">
18
REL="NEXT"
19
TITLE="Input handling"
20
HREF="guideinput.html">
21
>
22
CLASS="SECT1"
23
BGCOLOR="#FFF8DC"
24
TEXT="#000000"
25
LINK="#0000ee"
26
VLINK="#551a8b"
27
ALINK="#ff0000"
28
>
29
CLASS="NAVHEADER"
30
>
31
WIDTH="100%"
32
BORDER="0"
33
CELLPADDING="0"
34
CELLSPACING="0"
35
>
36
>
37
COLSPAN="3"
38
ALIGN="center"
39
>SDL Library Documentation
40
>
41
>
42
>
43
WIDTH="10%"
44
ALIGN="left"
45
VALIGN="bottom"
46
>
47
HREF="guidevideo.html"
48
>Prev
49
>
50
>
51
WIDTH="80%"
52
ALIGN="center"
53
VALIGN="bottom"
54
>Chapter 2. Graphics and Video
55
>
56
WIDTH="10%"
57
ALIGN="right"
58
VALIGN="bottom"
59
>
60
HREF="guideinput.html"
61
>Next
62
>
63
>
64
>
65
>
66
ALIGN="LEFT"
67
WIDTH="100%">
68
>
69
CLASS="SECT1"
70
>
71
CLASS="SECT1"
72
>
73
NAME="GUIDEVIDEOOPENGL"
74
>Using OpenGL With SDL
75
>
76
>
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).
78
>
79
CLASS="SECT2"
80
>
81
CLASS="SECT2"
82
>
83
NAME="AEN103"
84
>Initialisation
85
>
86
>
87
>Initialising SDL to use OpenGL is not very different to initialising SDL normally. There are three differences; you must pass
88
CLASS="LITERAL"
89
>SDL_OPENGL
90
> to
91
HREF="sdlsetvideomode.html"
92
>
93
CLASS="FUNCTION"
94
>SDL_SetVideoMode
95
>
96
>, you must specify several GL attributes (depth buffer size, framebuffer sizes) using
97
HREF="sdlglsetattribute.html"
98
>
99
CLASS="FUNCTION"
100
>SDL_GL_SetAttribute
101
>
102
> and finally, if you wish to use double buffering you must specify it as a GL attribute,
103
CLASS="EMPHASIS"
104
>not
105
> by passing the
106
CLASS="LITERAL"
107
>SDL_DOUBLEBUF
108
> flag to
109
CLASS="FUNCTION"
110
>SDL_SetVideoMode
111
>.
112
>
113
CLASS="EXAMPLE"
114
>
115
NAME="AEN114"
116
>
117
>
118
>
119
>Example 2-7. Initializing SDL with OpenGL
120
>
121
>
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 ) < 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->vfmt->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
}
211
>
212
>
213
>
214
CLASS="SECT2"
215
>
216
CLASS="SECT2"
217
>
218
NAME="AEN117"
219
>Drawing
220
>
221
>
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
227
HREF="sdlglswapbuffers.html"
228
>
229
CLASS="FUNCTION"
230
>SDL_GL_SwapBuffers()
231
>
232
>
233
to swap the buffers and update the display. To request double-buffering
234
with OpenGL, use
235
236
HREF="sdlglsetattribute.html"
237
>
238
CLASS="FUNCTION"
239
>SDL_GL_SetAttribute
240
>
241
>
242
with
243
CLASS="LITERAL"
244
>SDL_GL_DOUBLEBUFFER
245
>, and use
246
247
HREF="sdlglgetattribute.html"
248
>
249
CLASS="FUNCTION"
250
>SDL_GL_GetAttribute
251
>
252
>
253
to see if you actually got it.
254
>
255
>A full example code listing is now presented below.
256
>
257
CLASS="EXAMPLE"
258
>
259
NAME="AEN128"
260
>
261
>
262
>
263
>Example 2-8. SDL and OpenGL
264
>
265
>
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 <SDL/SDL.h>
276
#include <GL/gl.h>
277
#include <GL/glu.h>
278
279
#include <stdio.h>
280
#include <stdlib.h>
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->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( &event ) ) {
328
329
switch( event.type ) {
330
case SDL_KEYDOWN:
331
/* Handle key presses. */
332
handle_key_down( &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 > 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 ) < 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->vfmt->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
}
657
>
658
>
659
>
660
>
661
CLASS="NAVFOOTER"
662
>
663
ALIGN="LEFT"
664
WIDTH="100%">
716
>
717
>
718
>
719
>