Mercurial > sdl-ios-xcode
view 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 source
<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 >