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