Mercurial > sdl-ios-xcode
comparison docs/html/guidevideo.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 | 74212992fb08 |
children | 355632dca928 |
comparison
equal
deleted
inserted
replaced
54:028447a8a758 | 55:55f1f1b3e27d |
---|---|
2 ><HEAD | 2 ><HEAD |
3 ><TITLE | 3 ><TITLE |
4 >Graphics and Video</TITLE | 4 >Graphics and Video</TITLE |
5 ><META | 5 ><META |
6 NAME="GENERATOR" | 6 NAME="GENERATOR" |
7 CONTENT="Modular DocBook HTML Stylesheet Version 1.61 | 7 CONTENT="Modular DocBook HTML Stylesheet Version 1.64 |
8 "><LINK | 8 "><LINK |
9 REL="HOME" | 9 REL="HOME" |
10 TITLE="SDL Library Documentation" | 10 TITLE="SDL Library Documentation" |
11 HREF="index.html"><LINK | 11 HREF="index.html"><LINK |
12 REL="UP" | 12 REL="UP" |
14 HREF="guide.html"><LINK | 14 HREF="guide.html"><LINK |
15 REL="PREVIOUS" | 15 REL="PREVIOUS" |
16 TITLE="Initializing SDL" | 16 TITLE="Initializing SDL" |
17 HREF="guidebasicsinit.html"><LINK | 17 HREF="guidebasicsinit.html"><LINK |
18 REL="NEXT" | 18 REL="NEXT" |
19 TITLE="Input handling" | 19 TITLE="Using OpenGL With SDL" |
20 HREF="guideinput.html"></HEAD | 20 HREF="guidevideoopengl.html"></HEAD |
21 ><BODY | 21 ><BODY |
22 CLASS="CHAPTER" | 22 CLASS="CHAPTER" |
23 BGCOLOR="#FFF8DC" | 23 BGCOLOR="#FFF8DC" |
24 TEXT="#000000" | 24 TEXT="#000000" |
25 LINK="#0000ee" | 25 LINK="#0000ee" |
55 ><TD | 55 ><TD |
56 WIDTH="10%" | 56 WIDTH="10%" |
57 ALIGN="right" | 57 ALIGN="right" |
58 VALIGN="bottom" | 58 VALIGN="bottom" |
59 ><A | 59 ><A |
60 HREF="guideinput.html" | 60 HREF="guidevideoopengl.html" |
61 >Next</A | 61 >Next</A |
62 ></TD | 62 ></TD |
63 ></TR | 63 ></TR |
64 ></TABLE | 64 ></TABLE |
65 ><HR | 65 ><HR |
71 ><A | 71 ><A |
72 NAME="GUIDEVIDEO" | 72 NAME="GUIDEVIDEO" |
73 >Chapter 2. Graphics and Video</A | 73 >Chapter 2. Graphics and Video</A |
74 ></H1 | 74 ></H1 |
75 ><DIV | 75 ><DIV |
76 CLASS="TOC" | |
77 ><DL | |
78 ><DT | |
79 ><B | |
80 >Table of Contents</B | |
81 ></DT | |
82 ><DT | |
83 ><A | |
84 HREF="guidevideo.html#GUIDEVIDEOINTRO" | |
85 >Introduction to SDL Video</A | |
86 ></DT | |
87 ><DT | |
88 ><A | |
89 HREF="guidevideoopengl.html" | |
90 >Using OpenGL With SDL</A | |
91 ></DT | |
92 ></DL | |
93 ></DIV | |
94 ><DIV | |
76 CLASS="SECT1" | 95 CLASS="SECT1" |
77 ><H1 | 96 ><H1 |
78 CLASS="SECT1" | 97 CLASS="SECT1" |
79 ><A | 98 ><A |
80 NAME="GUIDEVIDEOOPENGL" | 99 NAME="GUIDEVIDEOINTRO" |
81 >Using OpenGL With SDL</A | 100 >Introduction to SDL Video</A |
82 ></H1 | 101 ></H1 |
83 ><P | 102 ><P |
84 >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 | 103 >Video is probably the most common thing that SDL is used for, and |
104 so it has the most complete subsystem. Here are a few | |
105 examples to demonstrate the basics.</P | |
85 ><DIV | 106 ><DIV |
86 CLASS="SECT2" | 107 CLASS="SECT2" |
87 ><H2 | 108 ><H2 |
88 CLASS="SECT2" | 109 CLASS="SECT2" |
89 ><A | 110 ><A |
90 NAME="AEN65" | 111 NAME="AEN68" |
91 >Initialisation</A | 112 >Initializing the Video Display</A |
92 ></H2 | 113 ></H2 |
93 ><P | 114 ><P |
94 >Initialising SDL to use OpenGL is not very different to initialising SDL normally. There are three differences; you must pass <TT | 115 >This is what almost all SDL programs have to do in one way or |
95 CLASS="LITERAL" | 116 another.</P |
96 >SDL_OPENGL</TT | 117 ><DIV |
97 > to <A | 118 CLASS="EXAMPLE" |
98 HREF="sdlsetvideomode.html" | 119 ><A |
99 ><TT | 120 NAME="AEN71" |
100 CLASS="FUNCTION" | 121 ></A |
101 >SDL_SetVideoMode</TT | 122 ><P |
102 ></A | 123 ><B |
103 >, you must specify several GL attributes (depth buffer size, framebuffer sizes) using <A | 124 >Example 2-1. Initializing the Video Display</B |
104 HREF="sdlglsetattribute.html" | 125 ></P |
105 ><TT | 126 ><PRE |
106 CLASS="FUNCTION" | 127 CLASS="PROGRAMLISTING" |
107 >SDL_GL_SetAttribute</TT | 128 > SDL_Surface *screen; |
108 ></A | 129 |
109 > and finally, if you wish to use double buffering you must specify it as a GL attribute, <I | 130 /* Initialize the SDL library */ |
110 CLASS="EMPHASIS" | 131 if( SDL_Init(SDL_INIT_VIDEO) < 0 ) { |
111 >not</I | 132 fprintf(stderr, |
112 > by passing the <TT | 133 "Couldn't initialize SDL: %s\n", SDL_GetError()); |
113 CLASS="LITERAL" | 134 exit(1); |
114 >SDL_DOUBLEBUF</TT | 135 } |
115 > flag to <TT | 136 |
116 CLASS="FUNCTION" | 137 /* Clean up on exit */ |
117 >SDL_SetVideoMode</TT | 138 atexit(SDL_Quit); |
118 >. | 139 |
119 <PRE | |
120 CLASS="PROGRAMLISTING" | |
121 > /* Information about the current video settings. */ | |
122 const SDL_VideoInfo* info = NULL; | |
123 /* Dimensions of our window. */ | |
124 int width = 0; | |
125 int height = 0; | |
126 /* Color depth in bits of our window. */ | |
127 int bpp = 0; | |
128 /* Flags we will pass into SDL_SetVideoMode. */ | |
129 int flags = 0; | |
130 | |
131 /* First, initialize SDL's video subsystem. */ | |
132 if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { | |
133 /* Failed, exit. */ | |
134 fprintf( stderr, "Video initialization failed: %s\n", | |
135 SDL_GetError( ) ); | |
136 quit_tutorial( 1 ); | |
137 } | |
138 | |
139 /* Let's get some video information. */ | |
140 info = SDL_GetVideoInfo( ); | |
141 | |
142 if( !info ) { | |
143 /* This should probably never happen. */ | |
144 fprintf( stderr, "Video query failed: %s\n", | |
145 SDL_GetError( ) ); | |
146 quit_tutorial( 1 ); | |
147 } | |
148 | |
149 /* | 140 /* |
150 * Set our width/height to 640/480 (you would | 141 * Initialize the display in a 640x480 8-bit palettized mode, |
151 * of course let the user decide this in a normal | 142 * requesting a software surface |
152 * app). We get the bpp we will request from | |
153 * the display. On X11, VidMode can't change | |
154 * resolution, so this is probably being overly | |
155 * safe. Under Win32, ChangeDisplaySettings | |
156 * can change the bpp. | |
157 */ | 143 */ |
158 width = 640; | 144 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); |
159 height = 480; | 145 if ( screen == NULL ) { |
160 bpp = info->vfmt->BitsPerPixel; | 146 fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n", |
147 SDL_GetError()); | |
148 exit(1); | |
149 }</PRE | |
150 ></DIV | |
151 ></DIV | |
152 ><DIV | |
153 CLASS="SECT2" | |
154 ><H2 | |
155 CLASS="SECT2" | |
156 ><A | |
157 NAME="AEN74" | |
158 >Initializing the Best Video Mode</A | |
159 ></H2 | |
160 ><P | |
161 >If you have a preference for a certain pixel depth but will accept any | |
162 other, use SDL_SetVideoMode with SDL_ANYFORMAT as below. You can also | |
163 use SDL_VideoModeOK() to find the native video mode that is closest to | |
164 the mode you request.</P | |
165 ><DIV | |
166 CLASS="EXAMPLE" | |
167 ><A | |
168 NAME="AEN77" | |
169 ></A | |
170 ><P | |
171 ><B | |
172 >Example 2-2. Initializing the Best Video Mode</B | |
173 ></P | |
174 ><PRE | |
175 CLASS="PROGRAMLISTING" | |
176 > /* Have a preference for 8-bit, but accept any depth */ | |
177 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE|SDL_ANYFORMAT); | |
178 if ( screen == NULL ) { | |
179 fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n", | |
180 SDL_GetError()); | |
181 exit(1); | |
182 } | |
183 printf("Set 640x480 at %d bits-per-pixel mode\n", | |
184 screen->format->BitsPerPixel);</PRE | |
185 ></DIV | |
186 ></DIV | |
187 ><DIV | |
188 CLASS="SECT2" | |
189 ><H2 | |
190 CLASS="SECT2" | |
191 ><A | |
192 NAME="AEN80" | |
193 >Loading and Displaying a BMP File</A | |
194 ></H2 | |
195 ><P | |
196 >The following function loads and displays a BMP file given as | |
197 argument, once SDL is initialised and a video mode has been set.</P | |
198 ><DIV | |
199 CLASS="EXAMPLE" | |
200 ><A | |
201 NAME="AEN83" | |
202 ></A | |
203 ><P | |
204 ><B | |
205 >Example 2-3. Loading and Displaying a BMP File</B | |
206 ></P | |
207 ><PRE | |
208 CLASS="PROGRAMLISTING" | |
209 >void display_bmp(char *file_name) | |
210 { | |
211 SDL_Surface *image; | |
212 | |
213 /* Load the BMP file into a surface */ | |
214 image = SDL_LoadBMP(file_name); | |
215 if (image == NULL) { | |
216 fprintf(stderr, "Couldn't load %s: %s\n", file_name, SDL_GetError()); | |
217 return; | |
218 } | |
161 | 219 |
162 /* | 220 /* |
163 * Now, we want to setup our requested | 221 * Palettized screen modes will have a default palette (a standard |
164 * window attributes for our OpenGL window. | 222 * 8*8*4 colour cube), but if the image is palettized as well we can |
165 * We want *at least* 5 bits of red, green | 223 * use that palette for a nicer colour matching |
166 * and blue. We also want at least a 16-bit | |
167 * depth buffer. | |
168 * | |
169 * The last thing we do is request a double | |
170 * buffered window. '1' turns on double | |
171 * buffering, '0' turns it off. | |
172 * | |
173 * Note that we do not use SDL_DOUBLEBUF in | |
174 * the flags to SDL_SetVideoMode. That does | |
175 * not affect the GL attribute state, only | |
176 * the standard 2D blitting setup. | |
177 */ | 224 */ |
178 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); | 225 if (image->format->palette && screen->format->palette) { |
179 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); | 226 SDL_SetColors(screen, image->format->palette->colors, 0, |
180 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); | 227 image->format->palette->ncolors); |
181 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); | 228 } |
182 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); | 229 |
183 | 230 /* Blit onto the screen surface */ |
184 /* | 231 if(SDL_BlitSurface(image, NULL, screen, NULL) < 0) |
185 * We want to request that SDL provide us | 232 fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); |
186 * with an OpenGL window, in a fullscreen | 233 |
187 * video mode. | 234 SDL_UpdateRect(screen, 0, 0, image->w, image->h); |
188 * | 235 |
189 * EXERCISE: | 236 /* Free the allocated BMP surface */ |
190 * Make starting windowed an option, and | 237 SDL_FreeSurface(image); |
191 * handle the resize events properly with | 238 }</PRE |
192 * glViewport. | 239 ></DIV |
193 */ | |
194 flags = SDL_OPENGL | SDL_FULLSCREEN; | |
195 | |
196 /* | |
197 * Set the video mode | |
198 */ | |
199 if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { | |
200 /* | |
201 * This could happen for a variety of reasons, | |
202 * including DISPLAY not being set, the specified | |
203 * resolution not being available, etc. | |
204 */ | |
205 fprintf( stderr, "Video mode set failed: %s\n", | |
206 SDL_GetError( ) ); | |
207 quit_tutorial( 1 ); | |
208 }</PRE | |
209 ></P | |
210 ></DIV | 240 ></DIV |
211 ><DIV | 241 ><DIV |
212 CLASS="SECT2" | 242 CLASS="SECT2" |
213 ><H2 | 243 ><H2 |
214 CLASS="SECT2" | 244 CLASS="SECT2" |
215 ><A | 245 ><A |
216 NAME="AEN77" | 246 NAME="AEN86" |
217 >Drawing</A | 247 >Drawing Directly to the Display</A |
218 ></H2 | 248 ></H2 |
219 ><P | 249 ><P |
220 >Apart from initialisation, using OpenGL within SDL is the same as using. However if you have request a double buffered display (using <A | 250 >The following two functions can be used to get and set single |
221 HREF="sdlglsetattribute.html" | 251 pixels of a surface. They are carefully written to work with any depth |
222 ><TT | 252 currently supported by SDL. Remember to lock the surface before |
223 CLASS="FUNCTION" | 253 calling them, and to unlock it before calling any other SDL |
224 >SDL_GL_SetAttribute</TT | 254 functions.</P |
225 ></A | 255 ><P |
226 >) and one (which can be checked by using <A | 256 >To convert between pixel values and their red, green, blue |
227 HREF="sdlglgetattribute.html" | 257 components, use SDL_GetRGB() and SDL_MapRGB().</P |
228 ><TT | 258 ><DIV |
229 CLASS="FUNCTION" | 259 CLASS="EXAMPLE" |
230 >SDL_GL_GetAttribute</TT | 260 ><A |
231 ></A | 261 NAME="AEN90" |
232 >), then you must use <A | 262 ></A |
233 HREF="sdlglswapbuffers.html" | 263 ><P |
234 ><TT | 264 ><B |
235 CLASS="FUNCTION" | 265 >Example 2-4. getpixel()</B |
236 >SDL_GL_SwapBuffers()</TT | |
237 ></A | |
238 > to swap the buffers and update the display.</P | |
239 ><P | |
240 >A full example code listing is now presented below.</P | |
241 ><DIV | |
242 CLASS="EXAMPLE" | |
243 ><A | |
244 NAME="AEN87" | |
245 ></A | |
246 ><P | |
247 ><B | |
248 >Example 2-1. gl.c - SDL OpenGL Example</B | |
249 ></P | 266 ></P |
250 ><PRE | 267 ><PRE |
251 CLASS="PROGRAMLISTING" | 268 CLASS="PROGRAMLISTING" |
252 >/* | 269 >/* |
253 * SDL OpenGL Tutorial. | 270 * Return the pixel value at (x, y) |
254 * (c) Michael Vance, 2000 | 271 * NOTE: The surface must be locked before calling this! |
255 * briareos@lokigames.com | |
256 * | |
257 * Distributed under terms of the LGPL. | |
258 */ | 272 */ |
259 | 273 Uint32 getpixel(SDL_Surface *surface, int x, int y) |
260 #include <SDL/SDL.h> | |
261 #include <GL/gl.h> | |
262 #include <GL/glu.h> | |
263 | |
264 #include <stdio.h> | |
265 #include <stdlib.h> | |
266 | |
267 static GLboolean should_rotate = GL_TRUE; | |
268 | |
269 static void quit_tutorial( int code ) | |
270 { | 274 { |
271 /* | 275 int bpp = surface->format->BytesPerPixel; |
272 * Quit SDL so we can release the fullscreen | 276 /* Here p is the address to the pixel we want to retrieve */ |
273 * mode and restore the previous video settings, | 277 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; |
274 * etc. | 278 |
275 */ | 279 switch(bpp) { |
276 SDL_Quit( ); | 280 case 1: |
277 | 281 return *p; |
278 /* Exit program. */ | 282 |
279 exit( code ); | 283 case 2: |
280 } | 284 return *(Uint16 *)p; |
281 | 285 |
282 static void handle_key_down( SDL_keysym* keysym ) | 286 case 3: |
287 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) | |
288 return p[0] << 16 | p[1] << 8 | p[2]; | |
289 else | |
290 return p[0] | p[1] << 8 | p[2] << 16; | |
291 | |
292 case 4: | |
293 return *(Uint32 *)p; | |
294 | |
295 default: | |
296 return 0; /* shouldn't happen, but avoids warnings */ | |
297 } | |
298 }</PRE | |
299 ></DIV | |
300 ><DIV | |
301 CLASS="EXAMPLE" | |
302 ><A | |
303 NAME="AEN93" | |
304 ></A | |
305 ><P | |
306 ><B | |
307 >Example 2-5. putpixel()</B | |
308 ></P | |
309 ><PRE | |
310 CLASS="PROGRAMLISTING" | |
311 >/* | |
312 * Set the pixel at (x, y) to the given value | |
313 * NOTE: The surface must be locked before calling this! | |
314 */ | |
315 void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) | |
283 { | 316 { |
284 | 317 int bpp = surface->format->BytesPerPixel; |
285 /* | 318 /* Here p is the address to the pixel we want to set */ |
286 * We're only interested if 'Esc' has | 319 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; |
287 * been presssed. | 320 |
288 * | 321 switch(bpp) { |
289 * EXERCISE: | 322 case 1: |
290 * Handle the arrow keys and have that change the | 323 *p = pixel; |
291 * viewing position/angle. | |
292 */ | |
293 switch( keysym->sym ) { | |
294 case SDLK_ESCAPE: | |
295 quit_tutorial( 0 ); | |
296 break; | 324 break; |
297 case SDLK_SPACE: | 325 |
298 should_rotate = !should_rotate; | 326 case 2: |
327 *(Uint16 *)p = pixel; | |
299 break; | 328 break; |
300 default: | 329 |
330 case 3: | |
331 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { | |
332 p[0] = (pixel >> 16) & 0xff; | |
333 p[1] = (pixel >> 8) & 0xff; | |
334 p[2] = pixel & 0xff; | |
335 } else { | |
336 p[0] = pixel & 0xff; | |
337 p[1] = (pixel >> 8) & 0xff; | |
338 p[2] = (pixel >> 16) & 0xff; | |
339 } | |
301 break; | 340 break; |
302 } | 341 |
303 | 342 case 4: |
304 } | 343 *(Uint32 *)p = pixel; |
305 | 344 break; |
306 static void process_events( void ) | 345 } |
307 { | 346 }</PRE |
308 /* Our SDL event placeholder. */ | 347 ></DIV |
309 SDL_Event event; | 348 ><P |
310 | 349 >The following code uses the putpixel() function above to set a |
311 /* Grab all the events off the queue. */ | 350 yellow pixel in the middle of the screen.</P |
312 while( SDL_PollEvent( &event ) ) { | 351 ><DIV |
313 | 352 CLASS="EXAMPLE" |
314 switch( event.type ) { | 353 ><A |
315 case SDL_KEYDOWN: | 354 NAME="AEN97" |
316 /* Handle key presses. */ | 355 ></A |
317 handle_key_down( &event.key.keysym ); | 356 ><P |
318 break; | 357 ><B |
319 case SDL_QUIT: | 358 >Example 2-6. Using putpixel()</B |
320 /* Handle quit requests (like Ctrl-c). */ | 359 ></P |
321 quit_tutorial( 0 ); | 360 ><PRE |
322 break; | 361 CLASS="PROGRAMLISTING" |
362 > /* Code to set a yellow pixel at the center of the screen */ | |
363 | |
364 int x, y; | |
365 Uint32 yellow; | |
366 | |
367 /* Map the color yellow to this display (R=0xff, G=0xFF, B=0x00) | |
368 Note: If the display is palettized, you must set the palette first. | |
369 */ | |
370 yellow = SDL_MapRGB(screen->format, 0xff, 0xff, 0x00); | |
371 | |
372 x = screen->w / 2; | |
373 y = screen->h / 2; | |
374 | |
375 /* Lock the screen for direct access to the pixels */ | |
376 if ( SDL_MUSTLOCK(screen) ) { | |
377 if ( SDL_LockSurface(screen) < 0 ) { | |
378 fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); | |
379 return; | |
323 } | 380 } |
324 | 381 } |
325 } | 382 |
326 | 383 putpixel(screen, x, y, yellow); |
327 } | 384 |
328 | 385 if ( SDL_MUSTLOCK(screen) ) { |
329 static void draw_screen( void ) | 386 SDL_UnlockSurface(screen); |
330 { | 387 } |
331 /* Our angle of rotation. */ | 388 /* Update just the part of the display that we've changed */ |
332 static float angle = 0.0f; | 389 SDL_UpdateRect(screen, x, y, 1, 1); |
333 | 390 |
334 /* | 391 return; </PRE |
335 * EXERCISE: | |
336 * Replace this awful mess with vertex | |
337 * arrays and a call to glDrawElements. | |
338 * | |
339 * EXERCISE: | |
340 * After completing the above, change | |
341 * it to use compiled vertex arrays. | |
342 * | |
343 * EXERCISE: | |
344 * Verify my windings are correct here ;). | |
345 */ | |
346 static GLfloat v0[] = { -1.0f, -1.0f, 1.0f }; | |
347 static GLfloat v1[] = { 1.0f, -1.0f, 1.0f }; | |
348 static GLfloat v2[] = { 1.0f, 1.0f, 1.0f }; | |
349 static GLfloat v3[] = { -1.0f, 1.0f, 1.0f }; | |
350 static GLfloat v4[] = { -1.0f, -1.0f, -1.0f }; | |
351 static GLfloat v5[] = { 1.0f, -1.0f, -1.0f }; | |
352 static GLfloat v6[] = { 1.0f, 1.0f, -1.0f }; | |
353 static GLfloat v7[] = { -1.0f, 1.0f, -1.0f }; | |
354 static GLubyte red[] = { 255, 0, 0, 255 }; | |
355 static GLubyte green[] = { 0, 255, 0, 255 }; | |
356 static GLubyte blue[] = { 0, 0, 255, 255 }; | |
357 static GLubyte white[] = { 255, 255, 255, 255 }; | |
358 static GLubyte yellow[] = { 0, 255, 255, 255 }; | |
359 static GLubyte black[] = { 0, 0, 0, 255 }; | |
360 static GLubyte orange[] = { 255, 255, 0, 255 }; | |
361 static GLubyte purple[] = { 255, 0, 255, 0 }; | |
362 | |
363 /* Clear the color and depth buffers. */ | |
364 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); | |
365 | |
366 /* We don't want to modify the projection matrix. */ | |
367 glMatrixMode( GL_MODELVIEW ); | |
368 glLoadIdentity( ); | |
369 | |
370 /* Move down the z-axis. */ | |
371 glTranslatef( 0.0, 0.0, -5.0 ); | |
372 | |
373 /* Rotate. */ | |
374 glRotatef( angle, 0.0, 1.0, 0.0 ); | |
375 | |
376 if( should_rotate ) { | |
377 | |
378 if( ++angle > 360.0f ) { | |
379 angle = 0.0f; | |
380 } | |
381 | |
382 } | |
383 | |
384 /* Send our triangle data to the pipeline. */ | |
385 glBegin( GL_TRIANGLES ); | |
386 | |
387 glColor4ubv( red ); | |
388 glVertex3fv( v0 ); | |
389 glColor4ubv( green ); | |
390 glVertex3fv( v1 ); | |
391 glColor4ubv( blue ); | |
392 glVertex3fv( v2 ); | |
393 | |
394 glColor4ubv( red ); | |
395 glVertex3fv( v0 ); | |
396 glColor4ubv( blue ); | |
397 glVertex3fv( v2 ); | |
398 glColor4ubv( white ); | |
399 glVertex3fv( v3 ); | |
400 | |
401 glColor4ubv( green ); | |
402 glVertex3fv( v1 ); | |
403 glColor4ubv( black ); | |
404 glVertex3fv( v5 ); | |
405 glColor4ubv( orange ); | |
406 glVertex3fv( v6 ); | |
407 | |
408 glColor4ubv( green ); | |
409 glVertex3fv( v1 ); | |
410 glColor4ubv( orange ); | |
411 glVertex3fv( v6 ); | |
412 glColor4ubv( blue ); | |
413 glVertex3fv( v2 ); | |
414 | |
415 glColor4ubv( black ); | |
416 glVertex3fv( v5 ); | |
417 glColor4ubv( yellow ); | |
418 glVertex3fv( v4 ); | |
419 glColor4ubv( purple ); | |
420 glVertex3fv( v7 ); | |
421 | |
422 glColor4ubv( black ); | |
423 glVertex3fv( v5 ); | |
424 glColor4ubv( purple ); | |
425 glVertex3fv( v7 ); | |
426 glColor4ubv( orange ); | |
427 glVertex3fv( v6 ); | |
428 | |
429 glColor4ubv( yellow ); | |
430 glVertex3fv( v4 ); | |
431 glColor4ubv( red ); | |
432 glVertex3fv( v0 ); | |
433 glColor4ubv( white ); | |
434 glVertex3fv( v3 ); | |
435 | |
436 glColor4ubv( yellow ); | |
437 glVertex3fv( v4 ); | |
438 glColor4ubv( white ); | |
439 glVertex3fv( v3 ); | |
440 glColor4ubv( purple ); | |
441 glVertex3fv( v7 ); | |
442 | |
443 glColor4ubv( white ); | |
444 glVertex3fv( v3 ); | |
445 glColor4ubv( blue ); | |
446 glVertex3fv( v2 ); | |
447 glColor4ubv( orange ); | |
448 glVertex3fv( v6 ); | |
449 | |
450 glColor4ubv( white ); | |
451 glVertex3fv( v3 ); | |
452 glColor4ubv( orange ); | |
453 glVertex3fv( v6 ); | |
454 glColor4ubv( purple ); | |
455 glVertex3fv( v7 ); | |
456 | |
457 glColor4ubv( green ); | |
458 glVertex3fv( v1 ); | |
459 glColor4ubv( red ); | |
460 glVertex3fv( v0 ); | |
461 glColor4ubv( yellow ); | |
462 glVertex3fv( v4 ); | |
463 | |
464 glColor4ubv( green ); | |
465 glVertex3fv( v1 ); | |
466 glColor4ubv( yellow ); | |
467 glVertex3fv( v4 ); | |
468 glColor4ubv( black ); | |
469 glVertex3fv( v5 ); | |
470 | |
471 glEnd( ); | |
472 | |
473 /* | |
474 * EXERCISE: | |
475 * Draw text telling the user that 'Spc' | |
476 * pauses the rotation and 'Esc' quits. | |
477 * Do it using vetors and textured quads. | |
478 */ | |
479 | |
480 /* | |
481 * Swap the buffers. This this tells the driver to | |
482 * render the next frame from the contents of the | |
483 * back-buffer, and to set all rendering operations | |
484 * to occur on what was the front-buffer. | |
485 * | |
486 * Double buffering prevents nasty visual tearing | |
487 * from the application drawing on areas of the | |
488 * screen that are being updated at the same time. | |
489 */ | |
490 SDL_GL_SwapBuffers( ); | |
491 } | |
492 | |
493 static void setup_opengl( int width, int height ) | |
494 { | |
495 float ratio = (float) width / (float) height; | |
496 | |
497 /* Our shading model--Gouraud (smooth). */ | |
498 glShadeModel( GL_SMOOTH ); | |
499 | |
500 /* Culling. */ | |
501 glCullFace( GL_BACK ); | |
502 glFrontFace( GL_CCW ); | |
503 glEnable( GL_CULL_FACE ); | |
504 | |
505 /* Set the clear color. */ | |
506 glClearColor( 0, 0, 0, 0 ); | |
507 | |
508 /* Setup our viewport. */ | |
509 glViewport( 0, 0, width, height ); | |
510 | |
511 /* | |
512 * Change to the projection matrix and set | |
513 * our viewing volume. | |
514 */ | |
515 glMatrixMode( GL_PROJECTION ); | |
516 glLoadIdentity( ); | |
517 /* | |
518 * EXERCISE: | |
519 * Replace this with a call to glFrustum. | |
520 */ | |
521 gluPerspective( 60.0, ratio, 1.0, 1024.0 ); | |
522 } | |
523 | |
524 int main( int argc, char* argv[] ) | |
525 { | |
526 /* Information about the current video settings. */ | |
527 const SDL_VideoInfo* info = NULL; | |
528 /* Dimensions of our window. */ | |
529 int width = 0; | |
530 int height = 0; | |
531 /* Color depth in bits of our window. */ | |
532 int bpp = 0; | |
533 /* Flags we will pass into SDL_SetVideoMode. */ | |
534 int flags = 0; | |
535 | |
536 /* First, initialize SDL's video subsystem. */ | |
537 if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { | |
538 /* Failed, exit. */ | |
539 fprintf( stderr, "Video initialization failed: %s\n", | |
540 SDL_GetError( ) ); | |
541 quit_tutorial( 1 ); | |
542 } | |
543 | |
544 /* Let's get some video information. */ | |
545 info = SDL_GetVideoInfo( ); | |
546 | |
547 if( !info ) { | |
548 /* This should probably never happen. */ | |
549 fprintf( stderr, "Video query failed: %s\n", | |
550 SDL_GetError( ) ); | |
551 quit_tutorial( 1 ); | |
552 } | |
553 | |
554 /* | |
555 * Set our width/height to 640/480 (you would | |
556 * of course let the user decide this in a normal | |
557 * app). We get the bpp we will request from | |
558 * the display. On X11, VidMode can't change | |
559 * resolution, so this is probably being overly | |
560 * safe. Under Win32, ChangeDisplaySettings | |
561 * can change the bpp. | |
562 */ | |
563 width = 640; | |
564 height = 480; | |
565 bpp = info->vfmt->BitsPerPixel; | |
566 | |
567 /* | |
568 * Now, we want to setup our requested | |
569 * window attributes for our OpenGL window. | |
570 * We want *at least* 5 bits of red, green | |
571 * and blue. We also want at least a 16-bit | |
572 * depth buffer. | |
573 * | |
574 * The last thing we do is request a double | |
575 * buffered window. '1' turns on double | |
576 * buffering, '0' turns it off. | |
577 * | |
578 * Note that we do not use SDL_DOUBLEBUF in | |
579 * the flags to SDL_SetVideoMode. That does | |
580 * not affect the GL attribute state, only | |
581 * the standard 2D blitting setup. | |
582 */ | |
583 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); | |
584 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); | |
585 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); | |
586 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); | |
587 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); | |
588 | |
589 /* | |
590 * We want to request that SDL provide us | |
591 * with an OpenGL window, in a fullscreen | |
592 * video mode. | |
593 * | |
594 * EXERCISE: | |
595 * Make starting windowed an option, and | |
596 * handle the resize events properly with | |
597 * glViewport. | |
598 */ | |
599 flags = SDL_OPENGL | SDL_FULLSCREEN; | |
600 | |
601 /* | |
602 * Set the video mode | |
603 */ | |
604 if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { | |
605 /* | |
606 * This could happen for a variety of reasons, | |
607 * including DISPLAY not being set, the specified | |
608 * resolution not being available, etc. | |
609 */ | |
610 fprintf( stderr, "Video mode set failed: %s\n", | |
611 SDL_GetError( ) ); | |
612 quit_tutorial( 1 ); | |
613 } | |
614 | |
615 /* | |
616 * At this point, we should have a properly setup | |
617 * double-buffered window for use with OpenGL. | |
618 */ | |
619 setup_opengl( width, height ); | |
620 | |
621 /* | |
622 * Now we want to begin our normal app process-- | |
623 * an event loop with a lot of redrawing. | |
624 */ | |
625 while( 1 ) { | |
626 /* Process incoming events. */ | |
627 process_events( ); | |
628 /* Draw the screen. */ | |
629 draw_screen( ); | |
630 } | |
631 | |
632 /* | |
633 * EXERCISE: | |
634 * Record timings using SDL_GetTicks() and | |
635 * and print out frames per second at program | |
636 * end. | |
637 */ | |
638 | |
639 /* Never reached. */ | |
640 return 0; | |
641 }</PRE | |
642 ></DIV | 392 ></DIV |
643 ></DIV | 393 ></DIV |
644 ></DIV | 394 ></DIV |
645 ></DIV | 395 ></DIV |
646 ><DIV | 396 ><DIV |
672 ><TD | 422 ><TD |
673 WIDTH="33%" | 423 WIDTH="33%" |
674 ALIGN="right" | 424 ALIGN="right" |
675 VALIGN="top" | 425 VALIGN="top" |
676 ><A | 426 ><A |
677 HREF="guideinput.html" | 427 HREF="guidevideoopengl.html" |
678 >Next</A | 428 >Next</A |
679 ></TD | 429 ></TD |
680 ></TR | 430 ></TR |
681 ><TR | 431 ><TR |
682 ><TD | 432 ><TD |
694 ></TD | 444 ></TD |
695 ><TD | 445 ><TD |
696 WIDTH="33%" | 446 WIDTH="33%" |
697 ALIGN="right" | 447 ALIGN="right" |
698 VALIGN="top" | 448 VALIGN="top" |
699 >Input handling</TD | 449 >Using OpenGL With SDL</TD |
700 ></TR | 450 ></TR |
701 ></TABLE | 451 ></TABLE |
702 ></DIV | 452 ></DIV |
703 ></BODY | 453 ></BODY |
704 ></HTML | 454 ></HTML |