Example 2-8. SDL and OpenGL
/ s" g ?0 }. ?0 g, o& S$ d
' [7 E1 Q) t4 W% n9 y8 _/ R. a0 O
/*
4 H& g' H E3 A& \
* SDL OpenGL Tutorial.
/ P+ S# O9 P6 g
* (c) Michael Vance, 2000
( `2 f$ J' A! ^; J& l5 g
*
briareos@lokigames.com
& W4 C3 F* V; i6 q! | *
, H1 `0 X' }9 A
* Distributed under terms of the LGPL.
$ l7 Q: v0 m* S/ L */
. n+ ?$ \$ v- L4 R9 L
& v9 `6 C# w4 {' y; H
#include <SDL/SDL.h>
7 L! ]% _% Y7 }#include <GL/gl.h>
& r, R7 \8 k' W u; N#include <GL/glu.h>
1 c$ v( T) O n0 Y( }9 s3 C+ }
$ F b) w" n$ t- @) V+ I
#include <stdio.h>
7 o, h6 ^! b5 i; u$ ^1 Y#include <stdlib.h>
' p2 \3 k- U! h1 s3 E* u8 \& n
- V b: m2 h/ f, u% u
static GLboolean should_rotate = GL_TRUE;
: `+ ?* ]0 {3 y/ n' I' y6 f6 ~# m, k' V1 R* z
static void quit_tutorial( int code )
* D: |) E" D- k4 Y2 Z{
! @7 S& I7 H7 U! A
/*
9 v8 T" Z, e' ^" Z* T: y * Quit SDL so we can release the fullscreen
5 n, r0 R* e+ z) p: c+ C * mode and restore the previous video settings,
0 X$ F& v7 H% ?$ @( E" i" M * etc.
; ^4 @5 v6 K8 c! E9 {+ E
*/
/ I9 K( y# C( A' B SDL_Quit( );
, b$ X$ k# f" d, G) d! ~+ y$ h+ d0 N& z' a* |. g) d; n
/* Exit program. */
+ l7 M' H3 a. y+ x$ u' ]1 e exit( code );
& ]! k3 O3 \! b# ^! h1 U* b}
8 C& I# X' q( _0 J: l
t% \) m$ \6 |" U9 p( ?static void handle_key_down( SDL_keysym* keysym )
6 ?9 @+ J* ~1 L; P' R
{
7 x) n9 S# ~" w* q; j+ R0 W
$ h. c5 H7 X9 \# F# a8 Q8 D- Z /*
: x3 b0 N* ]- }& c * We're only interested if 'Esc' has
/ g3 A+ y, O! x' G6 g$ _+ i$ t8 [4 B
* been presssed.
; J- l. v( n9 j$ s1 _
*
. N8 G: t! t( Z. D7 g; b7 f * EXERCISE:
Q: {9 B+ d& t6 I" P5 b$ L * Handle the arrow keys and have that change the
; l8 X# d4 b+ n' [; R8 _8 P' Q
* viewing position/angle.
! q! ~0 [& W! ^$ t: w, C y4 V
*/
. G: @6 C& K6 S6 @
switch( keysym->sym ) {
8 d2 J, s+ _! w" t3 T( M
case SDLK_ESCAPE:
* j% P9 b) ?; e6 ~$ b% v: \8 A0 a
quit_tutorial( 0 );
2 I) M4 b' \9 p: X7 b, b' M+ ^ break;
" h$ q, E) u D5 O
case SDLK_SPACE:
( w$ r; L8 H& y2 n% l3 n1 l9 p7 D should_rotate = !should_rotate;
]" f1 p' c& H8 o1 P. u0 Z8 a break;
" T6 H+ K5 [! T, B4 O
default:
% N8 h6 z" Q5 ]9 b% j: D% O/ d break;
# u5 M1 M& f9 k- [; M [# A4 T& k2 H9 V
}
8 s) G' R6 c5 c" `2 x
7 i5 [7 Q- Y" ]1 Y. ?. K% I z; n) a}
# p) r: F5 D' A& T/ C2 l# a
: b6 ~7 g% P( }2 X$ n
static void process_events( void )
9 B% C, U8 b" }) X, u1 e{
$ `1 E3 o# I4 O- q4 Q /* Our SDL event placeholder. */
8 J! \3 l* R+ D# h SDL_Event event;
0 f1 k: {8 K) H2 W! d
5 c0 g q/ }; ~; M Z2 b3 v /* Grab all the events off the queue. */
0 w& {& I0 Q* P6 ?
while( SDL_PollEvent( &event ) ) {
: u; Q4 ^0 R4 g* v
- ^- Z) C3 h. z& l. }: t5 T switch( event.type ) {
9 Z# ^* Q7 |5 P) B z3 G1 | case SDL_KEYDOWN:
2 v: w4 a B7 s; r5 p x+ ^ /* Handle key presses. */
$ W1 M. c1 O; C
handle_key_down( &event.key.keysym );
9 q; S6 C; N7 W) L% S s* C' m9 n: X- N4 X break;
' w* Q" w1 e* f, ^
case SDL_QUIT:
/ ^+ W# `) t/ D v- V# z9 W3 [
/* Handle quit requests (like Ctrl-c). */
& ^+ _7 @+ A, L/ Y quit_tutorial( 0 );
) ? n c; N$ ?9 v0 z
break;
# ^; w4 ?3 _# \6 L$ j7 W3 A
}
$ {7 P8 i" K! @6 {9 C# e8 y, D
! ^6 Y" |! r+ L# R5 G0 L8 e }
# u4 I& w4 R5 z& c6 ^9 g' s4 p# A0 j: x- M; {" m! V
}
3 Y' _& N' v# q# z3 g1 f, j1 B6 L
0 t1 I5 o; {1 a
static void draw_screen( void )
5 {( ^+ i" z0 @7 O
{
* M& x1 O) U) I2 R& }% x) E
/* Our angle of rotation. */
3 U* h+ b9 ] N' `; L& D2 x% J9 @
static float angle = 0.0f;
. ?# v; i$ [) I, l
5 ~- `4 E" t7 K* k+ p /*
" t. h0 J9 ^" b" Q- A' P0 |! U
* EXERCISE:
$ G; `* e8 x4 X. i6 l1 y1 w1 ?9 B * Replace this awful mess with vertex
# Z8 t: `2 B3 g. V, b * arrays and a call to glDrawElements.
$ ^! B/ v/ J6 a1 @3 d3 w *
( Z* o E! t* M% ^; b9 N' d4 Y
* EXERCISE:
6 F8 Q3 T& W! Q+ b * After completing the above, change
* q ]( _/ ?# I* w7 t
* it to use compiled vertex arrays.
5 t9 ~6 r2 x" q5 o/ {: n$ h *
* j3 w- U# W' C u& x# t, `- o * EXERCISE:
; d' Q# m: s3 X4 Z: @+ [- N
* Verify my windings are correct here ;).
$ M" }! G1 ^! u9 {+ o) B */
- k$ k2 W' Z3 n5 l0 ]5 v8 j( @
static GLfloat v0[] = { -1.0f, -1.0f, 1.0f };
" x) t8 m; a! c- ^ Z y
static GLfloat v1[] = { 1.0f, -1.0f, 1.0f };
& M% V5 H: w5 Z* Q k8 V
static GLfloat v2[] = { 1.0f, 1.0f, 1.0f };
0 Y- j0 c2 j- g3 r! }+ A D* w* ]; j
static GLfloat v3[] = { -1.0f, 1.0f, 1.0f };
, u+ K/ I, V" ?( W+ n static GLfloat v4[] = { -1.0f, -1.0f, -1.0f };
& H$ ~7 P& t9 j( N static GLfloat v5[] = { 1.0f, -1.0f, -1.0f };
; n; v/ o6 U7 [# K9 F# Q
static GLfloat v6[] = { 1.0f, 1.0f, -1.0f };
" N. l3 u* E3 i" ^ static GLfloat v7[] = { -1.0f, 1.0f, -1.0f };
1 \" w4 R& h ^3 |7 n static GLubyte red[] = { 255, 0, 0, 255 };
7 \7 d; v1 X: S# r$ p static GLubyte green[] = { 0, 255, 0, 255 };
y n0 O3 {8 u, S
static GLubyte blue[] = { 0, 0, 255, 255 };
$ m6 c/ c) T1 h( X$ T. z9 _ P
static GLubyte white[] = { 255, 255, 255, 255 };
! r; V$ ~7 ?7 ~0 T! g4 i3 G: X static GLubyte yellow[] = { 0, 255, 255, 255 };
! f @, G8 l7 a8 H, I* Q static GLubyte black[] = { 0, 0, 0, 255 };
; `, B; k; q5 [3 M h/ N. ]6 k static GLubyte orange[] = { 255, 255, 0, 255 };
- V( N" ^: \# W2 I6 U5 L static GLubyte purple[] = { 255, 0, 255, 0 };
6 |# \, u3 t/ S1 p0 s) h1 Y
, N. H; ~3 {9 N, R& t3 ? /* Clear the color and depth buffers. */
6 N/ U n0 w3 t) R% v/ ?: }- d0 _
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
7 C# M+ ]1 [& }" n3 I, H7 n! {) n
4 s0 S: u# O$ s$ K
/* We don't want to modify the projection matrix. */
6 U: z% D: v- H9 W: m
glMatrixMode( GL_MODELVIEW );
* u/ W. X* f) }+ j glLoadIdentity( );
" G* t% C. n/ v" a' C
+ _* w' @' s/ T8 ^9 o; n
/* Move down the z-axis. */
1 T/ H5 N6 P: \- z, j glTranslatef( 0.0, 0.0, -5.0 );
( f5 L7 L* K" h+ m
, p+ l) D1 G& g% C* b) | /* Rotate. */
" E0 _$ j; j7 c# a( H glRotatef( angle, 0.0, 1.0, 0.0 );
( `; Q" C" t: ^6 _3 r0 F/ H5 }5 F; S: ^' H! Y
if( should_rotate ) {
' N/ R, \ v, R" s" }( `! l$ v
& U7 ^1 R. |( U% X4 g* T
if( ++angle > 360.0f ) {
# s1 z: z9 A) ~9 | angle = 0.0f;
( I F9 u# L4 x( y( T }
) J2 p; \! A) P' H8 ^* N% k# Q! M: U2 ?# D0 z, V$ k
}
) Q8 Q" t) S4 D9 N/ m: B; Y5 Q
- ~/ I7 b6 p: h- }& @ W /* Send our triangle data to the pipeline. */
/ k6 |4 Q4 h J) k
glBegin( GL_TRIANGLES );
5 } r$ ]% f9 P1 |
. l, U: D% d' d4 K. K2 K# g5 K4 P H6 s glColor4ubv( red );
9 l# U, D- E' ~: z
glVertex3fv( v0 );
2 i) L0 ^5 z9 \6 g/ i
glColor4ubv( green );
0 x. j( T7 `3 C/ r# S$ x
glVertex3fv( v1 );
N" P: @0 ~1 z7 m0 e
glColor4ubv( blue );
* w8 M. G; N3 \/ w' ?/ @5 D0 b2 S glVertex3fv( v2 );
- F. N1 r6 n+ G5 t p& W
; z. X/ e: x q) P% E, Y glColor4ubv( red );
2 o* d4 l, E3 t7 t6 H" y {
glVertex3fv( v0 );
- _; k5 a+ z, P( E; e
glColor4ubv( blue );
. H9 W+ I& s6 m( R- `, M
glVertex3fv( v2 );
. j1 R2 D7 H6 E/ J) U/ f glColor4ubv( white );
: ]; v1 g! I3 q2 K2 D7 s0 {% o( g glVertex3fv( v3 );
6 k' Q) G/ D3 w* |
, u# [" R8 D2 t. y* J glColor4ubv( green );
# c& z: a' X. u$ z2 o, N
glVertex3fv( v1 );
# s. }( b/ }1 C3 L. `) V9 H5 c glColor4ubv( black );
8 t: r- S" O% f( H- H! e glVertex3fv( v5 );
7 S' Z/ a/ ~" @
glColor4ubv( orange );
2 N$ J- k3 y9 l1 C }% l6 g
glVertex3fv( v6 );
+ C% y4 H, E3 }2 V- N0 ]
0 a5 w7 l: @4 i+ g6 ?
glColor4ubv( green );
, }8 j3 d/ R7 h8 ^+ o$ H glVertex3fv( v1 );
3 u* b1 g' o0 q) |9 V$ i& q& j. _
glColor4ubv( orange );
5 A6 }; [: q% v3 J
glVertex3fv( v6 );
. N- B* N$ Q; x glColor4ubv( blue );
( N* M9 g) B0 x: K glVertex3fv( v2 );
* a; T# w8 O* | s, d
" G7 ~1 \# q; n- N. w3 y. ~9 K' @
glColor4ubv( black );
# T# I0 V& H1 {! K, d& b1 S glVertex3fv( v5 );
) K, H5 g7 T1 L0 q glColor4ubv( yellow );
$ O m9 m. y& T* c' p2 ~, ]
glVertex3fv( v4 );
' j/ |: B |$ N+ Z8 E. ~/ I7 c
glColor4ubv( purple );
8 O$ v3 H4 G/ B+ V' [7 \ glVertex3fv( v7 );
7 a5 m( I0 O7 E# M$ v- @4 s
( B9 R5 Q* f7 t+ A4 N: _" @ glColor4ubv( black );
4 B# O2 Y, {) \+ m/ Q8 C8 q: k" D glVertex3fv( v5 );
$ h# ?" L& `- g) Z! n glColor4ubv( purple );
4 A7 I# k% p. k% [3 h2 `
glVertex3fv( v7 );
+ |1 w8 a+ e! G, Y" ?9 o% @
glColor4ubv( orange );
( B' k3 H+ ^* j/ I glVertex3fv( v6 );
4 g) h( I7 U/ v
# a1 {* {. g" U U& J) d5 s/ h0 i glColor4ubv( yellow );
4 w( _3 V8 q$ _2 H6 |! S6 @ glVertex3fv( v4 );
' i; m) Y! V* z4 x
glColor4ubv( red );
, s- e* @0 _; m/ C9 j
glVertex3fv( v0 );
* w2 V% F6 F3 s
glColor4ubv( white );
0 t1 l$ s6 u3 X; x% h glVertex3fv( v3 );
6 u5 U3 A P# m) l$ l8 z$ g0 L, i: |2 r* s5 h
glColor4ubv( yellow );
/ C; E9 Z3 p( ?! B U. A$ s: [ glVertex3fv( v4 );
- _ ^ ^5 v& R glColor4ubv( white );
8 x8 o3 @0 @& w
glVertex3fv( v3 );
- b' L* v; e2 M* q" X* O: z" x glColor4ubv( purple );
1 U% F- ?- _) j# k% e, k
glVertex3fv( v7 );
Y' r) w- J) K# C: G( [
& f' a4 s3 s% \1 |/ z7 p. K- u glColor4ubv( white );
% l( [) G2 H4 g+ U ]5 ]1 s
glVertex3fv( v3 );
- d* L" a# a" P% d# [9 N glColor4ubv( blue );
7 r& z7 T" V) D+ _/ M5 o/ h
glVertex3fv( v2 );
( V( k) q( @( T
glColor4ubv( orange );
$ U+ y$ P; k3 B* S/ d, l5 A2 T glVertex3fv( v6 );
; g v- U" {5 C* H) o0 p. j& v, z& w0 u5 f0 k' j0 o8 ^! X4 q1 C
glColor4ubv( white );
' T0 {. ?- i; V* Z- Z$ q
glVertex3fv( v3 );
" ^/ j" Y/ @ t: p
glColor4ubv( orange );
1 o3 \0 F4 i& ]2 }9 S* d% \5 p
glVertex3fv( v6 );
% j2 v7 f8 s* ^# ?& w
glColor4ubv( purple );
" A6 W( k4 O8 o& `
glVertex3fv( v7 );
% \6 W" d9 d8 h0 ?* S5 q
Q! r9 t- N* J& {# f
glColor4ubv( green );
2 W$ ~4 E- l) X6 _* b glVertex3fv( v1 );
' x% [8 w( c1 G glColor4ubv( red );
8 Q4 H% S: d+ K2 ^% Y* K$ ~ q: }
glVertex3fv( v0 );
( P& G6 A; ?4 z2 k/ V S5 Y( @ glColor4ubv( yellow );
7 K& a8 p; s6 g1 T
glVertex3fv( v4 );
5 ?1 @( @* b' s9 z/ K- p$ }, l7 I
$ I$ y) E4 l. g8 P X glColor4ubv( green );
7 ^0 F. l2 p' E" x glVertex3fv( v1 );
9 d% k! h( \5 h8 D: k: E+ s0 `
glColor4ubv( yellow );
( o% y2 @5 P: k/ ]/ p( X3 R glVertex3fv( v4 );
( m( q0 u7 |; w$ b$ G glColor4ubv( black );
% Q3 z: A8 ]9 }. S) w/ }3 \ glVertex3fv( v5 );
% [) D$ K! L0 r' J0 D! a. R; _ N" j1 ^' ?
glEnd( );
2 U6 P4 B' H* K( Q! N; k8 ]7 x2 H: Z
/*
1 ~9 o# S5 U+ `! m+ _9 D
* EXERCISE:
- G$ p, Q' n; z8 h' k4 r# V
* Draw text telling the user that 'Spc'
8 R, W6 b8 O. l* p f2 J e
* pauses the rotation and 'Esc' quits.
& r6 c0 I+ ?1 Q8 Y' n
* Do it using vetors and textured quads.
! S9 }7 Q- e4 T: B
*/
: u1 O" c1 O S+ j! @8 R3 b/ f) s+ O( t7 K- K- k, k9 s
/*
/ c% }2 a+ M# j& m1 A' _0 c! k
* Swap the buffers. This this tells the driver to
, T E3 v7 C( \8 \
* render the next frame from the contents of the
3 ]3 }$ W& s* I. h6 Z; m% {3 y * back-buffer, and to set all rendering operations
* p8 b( \; i& S * to occur on what was the front-buffer.
& C5 z% d- K. X( h( b$ K *
, e$ M1 T, `; k$ D* g9 p * Double buffering prevents nasty visual tearing
9 W1 j ], h8 v1 }; i2 {, q- y * from the application drawing on areas of the
" ?, j1 p" O2 F; a& c * screen that are being updated at the same time.
0 j4 \5 P2 ~+ {7 d */
5 M4 |, F3 Q" H7 c5 x. @4 v, c# [
SDL_GL_SwapBuffers( );
3 ?; [6 L1 Y- W+ E/ m* v}
9 w! V H+ W1 A% y( f1 [. O
# T& Y% [, S& J& b! `# J5 ~static void setup_opengl( int width, int height )
0 t" c9 h0 X6 ?7 G{
" l0 l: ^# g% _. q. F( Z! H% F
float ratio = (float) width / (float) height;
# g8 }, V+ o5 N5 a, G
5 B; t* v. L4 e4 f9 t$ S /* Our shading model--Gouraud (smooth). */
% n0 |* |3 N1 b$ s* M3 n' ]2 Z+ h
glShadeModel( GL_SMOOTH );
0 w; I- M: v" q7 h, R
+ b# C- b- y2 x- R, @7 W" ?7 H /* Culling. */
3 k, w. _: K4 D7 V+ M D glCullFace( GL_BACK );
) @" L. g {9 [) k
glFrontFace( GL_CCW );
7 G$ X2 ^: g/ o glEnable( GL_CULL_FACE );
" F" i2 {' S+ W
C! L" j9 F/ n' S6 s& q. T
/* Set the clear color. */
! v5 F( m/ ]: `0 n1 w' k2 a glClearColor( 0, 0, 0, 0 );
" C m7 ]* m k& l8 T
1 G" r, d" e0 Y8 W7 @9 H; O
/* Setup our viewport. */
) l) R7 W* x8 g6 @, B5 M' w glViewport( 0, 0, width, height );
% B% E. S s: F* o; L; j9 r; b0 V
0 `4 Z6 n& j0 q. y+ F* f
/*
' {2 K3 s$ M: n/ Z
* Change to the projection matrix and set
# n. c6 r n+ U8 {. G' I) W * our viewing volume.
1 a Y$ j+ X- r# @* Q: j+ F. P */
8 {) {4 J# V8 s( ^ glMatrixMode( GL_PROJECTION );
! a4 Y. a6 U' a8 W6 N% G
glLoadIdentity( );
+ r7 d" [0 L4 {& H% l1 N' P O2 v" K /*
4 i% S3 {# J0 z( J1 W2 e" Y
* EXERCISE:
# _% k4 A A. g7 c3 v/ C4 W5 ] * Replace this with a call to glFrustum.
% |& V, O5 C w6 k+ b ] */
# U' z, W' f. E! V9 W gluPerspective( 60.0, ratio, 1.0, 1024.0 );
8 N4 _: z2 S/ f7 v/ R' o% {% a& N
}
& v) j- H% i/ m7 O" U8 f. A- t
int main( int argc, char* argv[] )
- h0 f" N c& e# o4 U
{
' C8 }# s0 b- S$ R. t+ E /* Information about the current video settings. */
& M# [ V) t9 m const SDL_VideoInfo* info = NULL;
+ U4 q: \! r. M- Y
/* Dimensions of our window. */
7 B& Q. \6 f% z- p# y8 ]% ?; `
int width = 0;
5 E# M3 \2 |! F6 J' r$ O
int height = 0;
6 w5 D0 D" s- @ /* Color depth in bits of our window. */
1 h! M% v# Z M. o int bpp = 0;
4 a% j3 x. G: p/ V. B1 Z
/* Flags we will pass into SDL_SetVideoMode. */
$ I9 A: D/ y6 O: m
int flags = 0;
, v1 D) W3 ], _# s$ ?
n! y" ?$ T! l/ O3 _6 Z9 O) E
/* First, initialize SDL's video subsystem. */
8 w6 m9 C6 L* h; I+ }/ O if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
2 l- m1 S8 f* p) s; b
/* Failed, exit. */
% n& Q2 O/ K" d3 D( w" r fprintf( stderr, "Video initialization failed: %s\n",
/ C6 c Y6 e* m" q
SDL_GetError( ) );
% p9 X3 O* \2 H# k quit_tutorial( 1 );
0 c( `) I& o1 H2 F% G6 w }
% }- v$ H1 j2 @5 w# [: R$ Q9 e( d( S9 J" r. Y& i; {
/* Let's get some video information. */
1 `4 V! j1 c4 \; `1 J& w
info = SDL_GetVideoInfo( );
$ r; i0 h+ o& E4 V! M! x+ _/ s# M7 d) B+ t
if( !info ) {
2 a" p+ Z H, } /* This should probably never happen. */
6 U# Z" E l5 Y L fprintf( stderr, "Video query failed: %s\n",
) u/ v6 D2 ?" ^3 U9 x* e SDL_GetError( ) );
6 z' R" p1 m5 `* V quit_tutorial( 1 );
9 I/ m- Q+ N! [( h- {- O3 D3 \
}
: O9 \1 F' c* ~2 G4 ~, D$ |- H% g+ ?/ R
/*
) j# K: b0 R- B! g) f8 X
* Set our width/height to 640/480 (you would
8 z; `! G4 B: |" a# {; n2 {; l
* of course let the user decide this in a normal
& V7 z2 w# t# E- `$ F7 _+ U% K) I
* app). We get the bpp we will request from
- W" f M7 l/ I * the display. On X11, VidMode can't change
0 N0 {# c9 y) D+ F! |6 B
* resolution, so this is probably being overly
& d: _7 x8 j8 a* z; ~
* safe. Under Win32, ChangeDisplaySettings
+ J" O$ U7 @- ?3 r& a, u; d+ Q' @$ c9 J * can change the bpp.
- h1 D7 P9 r$ B
*/
5 E8 ]: E9 w7 f, u) U4 ?
width = 640;
6 S- L; G1 N" ~) |- @0 d. L) ^ height = 480;
4 p1 N6 n$ j7 M bpp = info->vfmt->BitsPerPixel;
+ G* l3 B( U6 |: a
% `) w) r5 V- E7 l /*
/ ~/ b9 O) D4 J+ K# A I * Now, we want to setup our requested
# p/ J+ o& i0 l * window attributes for our OpenGL window.
# G Q9 D4 I7 a/ @" s1 O* }
* We want *at least* 5 bits of red, green
" X+ `: Z! M2 |+ L8 d) Z2 j
* and blue. We also want at least a 16-bit
$ r' J+ E0 Z: n) {4 U, F
* depth buffer.
, Y/ ]" l: c8 j6 a, `' z *
$ g/ [; z3 f( F1 U4 H2 O
* The last thing we do is request a double
5 c# `# M0 S3 p: s! g$ G; A * buffered window. '1' turns on double
3 o8 R' L% ^0 T: j/ e
* buffering, '0' turns it off.
& o! f4 t& q, I6 ]! P
*
7 y$ a3 J. y) j5 D- I8 j * Note that we do not use SDL_DOUBLEBUF in
$ p0 }) F4 S8 `
* the flags to SDL_SetVideoMode. That does
/ x* v7 a" K9 V" v2 x6 M- E * not affect the GL attribute state, only
6 v" y; V/ v% H2 C/ g
* the standard 2D blitting setup.
4 o' }1 X. q ?$ |0 }! I
*/
N2 V# u- x8 J1 D" S
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
: F- l9 |( z' ^% g
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
4 R9 i7 E% e; v2 m SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
5 |' r. W+ N- t6 [6 X SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
" u- f, P# U4 W" H9 y8 D, n A
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
& L9 j& H: e+ Z- Z$ n+ c$ q9 J) u8 ~# j& C4 \4 i! y9 J) S
/*
; S+ @+ l6 e1 F- ~
* We want to request that SDL provide us
/ ~, r7 o; Q3 X* z
* with an OpenGL window, in a fullscreen
+ o( T4 m5 r: f) J$ O * video mode.
! Q5 t# Z3 _. \7 {, Y *
; n$ }/ n. n# T( d! b# [/ ?
* EXERCISE:
* w* p# A% j2 U- f4 p * Make starting windowed an option, and
, y/ K( u& z6 U9 x" k; n * handle the resize events properly with
6 _( R$ j2 d; @$ z3 I( Q
* glViewport.
0 R" n$ N/ Z! D* a */
0 ]9 M+ w0 P# o$ u7 Z
flags = SDL_OPENGL | SDL_FULLSCREEN;
+ i! C }- h( y" f, ?8 E' |3 f9 R! P4 ~6 {0 y
/*
' n+ k& h% V5 j9 H) O6 J7 _: C8 e) g" }
* Set the video mode
, M8 t4 C5 Y5 C( D */
9 g# x+ a- O* W
if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
# B* D" Y: [, [ /*
7 O" P+ a) j0 C" ? * This could happen for a variety of reasons,
6 X! H1 N5 G6 P * including DISPLAY not being set, the specified
/ {. {; V& V) c$ t8 Z5 x * resolution not being available, etc.
( z- w& I3 H8 g, F9 t% p+ W
*/
: {" ]/ X* m8 b3 o: \. T( ^5 G
fprintf( stderr, "Video mode set failed: %s\n",
0 E7 ? m @( l7 K% K
SDL_GetError( ) );
$ r* s, T Z1 K% s, O quit_tutorial( 1 );
1 z$ D7 v2 w6 L) i7 n6 C
}
) c( q/ F8 n; M/ Z! G& D8 U6 `) u P$ k6 L3 N0 ^0 l" V
/*
8 |, }5 L- M( `3 z6 x. D0 f; K) l" e' R * At this point, we should have a properly setup
6 X2 ^# V/ }( h& _4 ]. f
* double-buffered window for use with OpenGL.
4 {7 T9 Q. T8 i) ^. O0 h
*/
9 r! J5 X# c$ n6 w% g+ h
setup_opengl( width, height );
( H. t3 o X- \' V: c
, L) ?1 e, m( O/ Z: ]
/*
g6 K$ H5 k; A5 |$ B! ?* t; }- w
* Now we want to begin our normal app process--
9 @+ S: s, v6 |& v' W5 |/ b * an event loop with a lot of redrawing.
; l) r2 }5 `& E5 F- i3 c2 O
*/
! _! B& W+ M3 m3 l9 c
while( 1 ) {
+ H# }) Y- n) t( R; s0 d
/* Process incoming events. */
' C; \' a% }* `$ f7 a: { process_events( );
0 N) m5 k9 u. c5 b+ k /* Draw the screen. */
8 f, ]) n9 W2 p* R draw_screen( );
/ J* h9 A. W: [
}
* J4 u2 c: U6 o1 B+ n( O& w- v6 {: ~" z8 a7 z4 M
/*
% Q. @+ m. w+ y6 ^
* EXERCISE:
8 [4 |- e% o, s * Record timings using SDL_GetTicks() and
# p" C, h+ e" q& r * and print out frames per second at program
6 \" \8 x9 \( q2 \. p+ U9 B: ~ * end.
+ _; O9 A6 f7 B7 T- K
*/
& b- @) X* M y+ C5 K
+ r/ e& J! q3 {0 l! Q
/* Never reached. */
) }6 J( v) t( d; P$ P7 B return 0;
0 g8 T5 L6 ?3 o" V7 A}
3 ?1 P+ W2 |0 o6 i# D
J+ L2 l6 q$ w+ n/ m2 l#gcc program.c -L/usr/X11R6/lib -lSDL -lGL -lGLU -o program