Mercurial > sdl-ios-xcode
diff docs/html/guidevideo.html @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | 55f1f1b3e27d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/html/guidevideo.html Thu Apr 26 16:45:43 2001 +0000 @@ -0,0 +1,705 @@ +<HTML +><HEAD +><TITLE +>Graphics and Video</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.61 +"><LINK +REL="HOME" +TITLE="SDL Library Documentation" +HREF="index.html"><LINK +REL="UP" +TITLE="SDL Guide" +HREF="guide.html"><LINK +REL="PREVIOUS" +TITLE="Initializing SDL" +HREF="guidebasicsinit.html"><LINK +REL="NEXT" +TITLE="Input handling" +HREF="guideinput.html"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFF8DC" +TEXT="#000000" +LINK="#0000ee" +VLINK="#551a8b" +ALINK="#ff0000" +><DIV +CLASS="NAVHEADER" +><TABLE +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>SDL Library Documentation</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="guidebasicsinit.html" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="guideinput.html" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="GUIDEVIDEO" +>Chapter 2. Graphics and Video</A +></H1 +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="GUIDEVIDEOOPENGL" +>Using OpenGL With SDL</A +></H1 +><P +>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 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN65" +>Initialisation</A +></H2 +><P +>Initialising SDL to use OpenGL is not very different to initialising SDL normally. There are three differences; you must pass <TT +CLASS="LITERAL" +>SDL_OPENGL</TT +> to <A +HREF="sdlsetvideomode.html" +><TT +CLASS="FUNCTION" +>SDL_SetVideoMode</TT +></A +>, you must specify several GL attributes (depth buffer size, framebuffer sizes) using <A +HREF="sdlglsetattribute.html" +><TT +CLASS="FUNCTION" +>SDL_GL_SetAttribute</TT +></A +> and finally, if you wish to use double buffering you must specify it as a GL attribute, <I +CLASS="EMPHASIS" +>not</I +> by passing the <TT +CLASS="LITERAL" +>SDL_DOUBLEBUF</TT +> flag to <TT +CLASS="FUNCTION" +>SDL_SetVideoMode</TT +>. +<PRE +CLASS="PROGRAMLISTING" +> /* Information about the current video settings. */ + const SDL_VideoInfo* info = NULL; + /* Dimensions of our window. */ + int width = 0; + int height = 0; + /* Color depth in bits of our window. */ + int bpp = 0; + /* Flags we will pass into SDL_SetVideoMode. */ + int flags = 0; + + /* First, initialize SDL's video subsystem. */ + if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { + /* Failed, exit. */ + fprintf( stderr, "Video initialization failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* Let's get some video information. */ + info = SDL_GetVideoInfo( ); + + if( !info ) { + /* This should probably never happen. */ + fprintf( stderr, "Video query failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* + * Set our width/height to 640/480 (you would + * of course let the user decide this in a normal + * app). We get the bpp we will request from + * the display. On X11, VidMode can't change + * resolution, so this is probably being overly + * safe. Under Win32, ChangeDisplaySettings + * can change the bpp. + */ + width = 640; + height = 480; + bpp = info->vfmt->BitsPerPixel; + + /* + * Now, we want to setup our requested + * window attributes for our OpenGL window. + * We want *at least* 5 bits of red, green + * and blue. We also want at least a 16-bit + * depth buffer. + * + * The last thing we do is request a double + * buffered window. '1' turns on double + * buffering, '0' turns it off. + * + * Note that we do not use SDL_DOUBLEBUF in + * the flags to SDL_SetVideoMode. That does + * not affect the GL attribute state, only + * the standard 2D blitting setup. + */ + SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + + /* + * We want to request that SDL provide us + * with an OpenGL window, in a fullscreen + * video mode. + * + * EXERCISE: + * Make starting windowed an option, and + * handle the resize events properly with + * glViewport. + */ + flags = SDL_OPENGL | SDL_FULLSCREEN; + + /* + * Set the video mode + */ + if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { + /* + * This could happen for a variety of reasons, + * including DISPLAY not being set, the specified + * resolution not being available, etc. + */ + fprintf( stderr, "Video mode set failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + }</PRE +></P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN77" +>Drawing</A +></H2 +><P +>Apart from initialisation, using OpenGL within SDL is the same as using. However if you have request a double buffered display (using <A +HREF="sdlglsetattribute.html" +><TT +CLASS="FUNCTION" +>SDL_GL_SetAttribute</TT +></A +>) and one (which can be checked by using <A +HREF="sdlglgetattribute.html" +><TT +CLASS="FUNCTION" +>SDL_GL_GetAttribute</TT +></A +>), then you must use <A +HREF="sdlglswapbuffers.html" +><TT +CLASS="FUNCTION" +>SDL_GL_SwapBuffers()</TT +></A +> to swap the buffers and update the display.</P +><P +>A full example code listing is now presented below.</P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN87" +></A +><P +><B +>Example 2-1. gl.c - SDL OpenGL Example</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* + * SDL OpenGL Tutorial. + * (c) Michael Vance, 2000 + * briareos@lokigames.com + * + * Distributed under terms of the LGPL. + */ + +#include <SDL/SDL.h> +#include <GL/gl.h> +#include <GL/glu.h> + +#include <stdio.h> +#include <stdlib.h> + +static GLboolean should_rotate = GL_TRUE; + +static void quit_tutorial( int code ) +{ + /* + * Quit SDL so we can release the fullscreen + * mode and restore the previous video settings, + * etc. + */ + SDL_Quit( ); + + /* Exit program. */ + exit( code ); +} + +static void handle_key_down( SDL_keysym* keysym ) +{ + + /* + * We're only interested if 'Esc' has + * been presssed. + * + * EXERCISE: + * Handle the arrow keys and have that change the + * viewing position/angle. + */ + switch( keysym->sym ) { + case SDLK_ESCAPE: + quit_tutorial( 0 ); + break; + case SDLK_SPACE: + should_rotate = !should_rotate; + break; + default: + break; + } + +} + +static void process_events( void ) +{ + /* Our SDL event placeholder. */ + SDL_Event event; + + /* Grab all the events off the queue. */ + while( SDL_PollEvent( &event ) ) { + + switch( event.type ) { + case SDL_KEYDOWN: + /* Handle key presses. */ + handle_key_down( &event.key.keysym ); + break; + case SDL_QUIT: + /* Handle quit requests (like Ctrl-c). */ + quit_tutorial( 0 ); + break; + } + + } + +} + +static void draw_screen( void ) +{ + /* Our angle of rotation. */ + static float angle = 0.0f; + + /* + * EXERCISE: + * Replace this awful mess with vertex + * arrays and a call to glDrawElements. + * + * EXERCISE: + * After completing the above, change + * it to use compiled vertex arrays. + * + * EXERCISE: + * Verify my windings are correct here ;). + */ + static GLfloat v0[] = { -1.0f, -1.0f, 1.0f }; + static GLfloat v1[] = { 1.0f, -1.0f, 1.0f }; + static GLfloat v2[] = { 1.0f, 1.0f, 1.0f }; + static GLfloat v3[] = { -1.0f, 1.0f, 1.0f }; + static GLfloat v4[] = { -1.0f, -1.0f, -1.0f }; + static GLfloat v5[] = { 1.0f, -1.0f, -1.0f }; + static GLfloat v6[] = { 1.0f, 1.0f, -1.0f }; + static GLfloat v7[] = { -1.0f, 1.0f, -1.0f }; + static GLubyte red[] = { 255, 0, 0, 255 }; + static GLubyte green[] = { 0, 255, 0, 255 }; + static GLubyte blue[] = { 0, 0, 255, 255 }; + static GLubyte white[] = { 255, 255, 255, 255 }; + static GLubyte yellow[] = { 0, 255, 255, 255 }; + static GLubyte black[] = { 0, 0, 0, 255 }; + static GLubyte orange[] = { 255, 255, 0, 255 }; + static GLubyte purple[] = { 255, 0, 255, 0 }; + + /* Clear the color and depth buffers. */ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + /* We don't want to modify the projection matrix. */ + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity( ); + + /* Move down the z-axis. */ + glTranslatef( 0.0, 0.0, -5.0 ); + + /* Rotate. */ + glRotatef( angle, 0.0, 1.0, 0.0 ); + + if( should_rotate ) { + + if( ++angle > 360.0f ) { + angle = 0.0f; + } + + } + + /* Send our triangle data to the pipeline. */ + glBegin( GL_TRIANGLES ); + + glColor4ubv( red ); + glVertex3fv( v0 ); + glColor4ubv( green ); + glVertex3fv( v1 ); + glColor4ubv( blue ); + glVertex3fv( v2 ); + + glColor4ubv( red ); + glVertex3fv( v0 ); + glColor4ubv( blue ); + glVertex3fv( v2 ); + glColor4ubv( white ); + glVertex3fv( v3 ); + + glColor4ubv( green ); + glVertex3fv( v1 ); + glColor4ubv( black ); + glVertex3fv( v5 ); + glColor4ubv( orange ); + glVertex3fv( v6 ); + + glColor4ubv( green ); + glVertex3fv( v1 ); + glColor4ubv( orange ); + glVertex3fv( v6 ); + glColor4ubv( blue ); + glVertex3fv( v2 ); + + glColor4ubv( black ); + glVertex3fv( v5 ); + glColor4ubv( yellow ); + glVertex3fv( v4 ); + glColor4ubv( purple ); + glVertex3fv( v7 ); + + glColor4ubv( black ); + glVertex3fv( v5 ); + glColor4ubv( purple ); + glVertex3fv( v7 ); + glColor4ubv( orange ); + glVertex3fv( v6 ); + + glColor4ubv( yellow ); + glVertex3fv( v4 ); + glColor4ubv( red ); + glVertex3fv( v0 ); + glColor4ubv( white ); + glVertex3fv( v3 ); + + glColor4ubv( yellow ); + glVertex3fv( v4 ); + glColor4ubv( white ); + glVertex3fv( v3 ); + glColor4ubv( purple ); + glVertex3fv( v7 ); + + glColor4ubv( white ); + glVertex3fv( v3 ); + glColor4ubv( blue ); + glVertex3fv( v2 ); + glColor4ubv( orange ); + glVertex3fv( v6 ); + + glColor4ubv( white ); + glVertex3fv( v3 ); + glColor4ubv( orange ); + glVertex3fv( v6 ); + glColor4ubv( purple ); + glVertex3fv( v7 ); + + glColor4ubv( green ); + glVertex3fv( v1 ); + glColor4ubv( red ); + glVertex3fv( v0 ); + glColor4ubv( yellow ); + glVertex3fv( v4 ); + + glColor4ubv( green ); + glVertex3fv( v1 ); + glColor4ubv( yellow ); + glVertex3fv( v4 ); + glColor4ubv( black ); + glVertex3fv( v5 ); + + glEnd( ); + + /* + * EXERCISE: + * Draw text telling the user that 'Spc' + * pauses the rotation and 'Esc' quits. + * Do it using vetors and textured quads. + */ + + /* + * Swap the buffers. This this tells the driver to + * render the next frame from the contents of the + * back-buffer, and to set all rendering operations + * to occur on what was the front-buffer. + * + * Double buffering prevents nasty visual tearing + * from the application drawing on areas of the + * screen that are being updated at the same time. + */ + SDL_GL_SwapBuffers( ); +} + +static void setup_opengl( int width, int height ) +{ + float ratio = (float) width / (float) height; + + /* Our shading model--Gouraud (smooth). */ + glShadeModel( GL_SMOOTH ); + + /* Culling. */ + glCullFace( GL_BACK ); + glFrontFace( GL_CCW ); + glEnable( GL_CULL_FACE ); + + /* Set the clear color. */ + glClearColor( 0, 0, 0, 0 ); + + /* Setup our viewport. */ + glViewport( 0, 0, width, height ); + + /* + * Change to the projection matrix and set + * our viewing volume. + */ + glMatrixMode( GL_PROJECTION ); + glLoadIdentity( ); + /* + * EXERCISE: + * Replace this with a call to glFrustum. + */ + gluPerspective( 60.0, ratio, 1.0, 1024.0 ); +} + +int main( int argc, char* argv[] ) +{ + /* Information about the current video settings. */ + const SDL_VideoInfo* info = NULL; + /* Dimensions of our window. */ + int width = 0; + int height = 0; + /* Color depth in bits of our window. */ + int bpp = 0; + /* Flags we will pass into SDL_SetVideoMode. */ + int flags = 0; + + /* First, initialize SDL's video subsystem. */ + if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { + /* Failed, exit. */ + fprintf( stderr, "Video initialization failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* Let's get some video information. */ + info = SDL_GetVideoInfo( ); + + if( !info ) { + /* This should probably never happen. */ + fprintf( stderr, "Video query failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* + * Set our width/height to 640/480 (you would + * of course let the user decide this in a normal + * app). We get the bpp we will request from + * the display. On X11, VidMode can't change + * resolution, so this is probably being overly + * safe. Under Win32, ChangeDisplaySettings + * can change the bpp. + */ + width = 640; + height = 480; + bpp = info->vfmt->BitsPerPixel; + + /* + * Now, we want to setup our requested + * window attributes for our OpenGL window. + * We want *at least* 5 bits of red, green + * and blue. We also want at least a 16-bit + * depth buffer. + * + * The last thing we do is request a double + * buffered window. '1' turns on double + * buffering, '0' turns it off. + * + * Note that we do not use SDL_DOUBLEBUF in + * the flags to SDL_SetVideoMode. That does + * not affect the GL attribute state, only + * the standard 2D blitting setup. + */ + SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + + /* + * We want to request that SDL provide us + * with an OpenGL window, in a fullscreen + * video mode. + * + * EXERCISE: + * Make starting windowed an option, and + * handle the resize events properly with + * glViewport. + */ + flags = SDL_OPENGL | SDL_FULLSCREEN; + + /* + * Set the video mode + */ + if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { + /* + * This could happen for a variety of reasons, + * including DISPLAY not being set, the specified + * resolution not being available, etc. + */ + fprintf( stderr, "Video mode set failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* + * At this point, we should have a properly setup + * double-buffered window for use with OpenGL. + */ + setup_opengl( width, height ); + + /* + * Now we want to begin our normal app process-- + * an event loop with a lot of redrawing. + */ + while( 1 ) { + /* Process incoming events. */ + process_events( ); + /* Draw the screen. */ + draw_screen( ); + } + + /* + * EXERCISE: + * Record timings using SDL_GetTicks() and + * and print out frames per second at program + * end. + */ + + /* Never reached. */ + return 0; +}</PRE +></DIV +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="guidebasicsinit.html" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="index.html" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="guideinput.html" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Initializing SDL</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="guide.html" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Input handling</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file