OpenGL
Contingut
Introducció
Necessito OpenGL perquè em decanto per C++ en comptes de JAVA per fer projectes que tinguin un alt contingut visual. En aquest cas, l'origen és desenvolupar l'espectacle 5 maneres de calcular g.
No tinc cap experiència amb OpenGL.
Amb OPenGL sembla que em puc decantar per dues opcions: SDL i GLUT. Jo em decanto per GLUT (al final serà SDL, doncs GLUT està molt limitat en algunes coses, com per exemple escriure text, que a mi m'interessa):
Another option, as opposed to SDL, is GLUT. It's a little more restrictive than SDL, but it's smaller and most people find it easier to use. I believe the packages are "freeglut3" and "freeglut3-dev"
Què són SDL i GLUT? Són toolkits que treballen sobre OpenGL, doncs programar directament sobre OpenGL és difícil i enravassat. Així doncs, han nascut una sèrie d'APIs i toolkits per facilitar la feina als programadors. SDL i GLUT són els més coneguts, però n'hi ha més.
GLUT (pronounced like the glut in gluttony) is the OpenGL Utility Toolkit, a window system independent toolkit for writing OpenGL programs. It implements a simple windowing application programming interface (API) for OpenGL. GLUT makes it considerably easier to learn about and explore OpenGL programming. GLUT provides a portable API so you can write a single OpenGL program that works across all PC and workstation OS platforms.
GLUT is not open source. Mark Kilgard maintains the copyright. There are a number of newer and open source alternatives. Com per exemple freeglut.
Vull compilar un codi que necessita SDL, i no tinc instal.lada la llibreria. (veure més avall...)
gcc main.cpp -o main.o `sdl-config --cflags --libs` -lGL -lGLU
El programa «sdl-config» no está instalado actualmente. Puede instalarlo escribiendo: sudo apt-get install libsdl1.2-dev
Tal vez quiera ejecutar `apt-get -f install' para corregirlo: Los siguientes paquetes tienen dependencias incumplidas:
kmid: Depende: kdebase-runtime (>= 4:4.3.2) pero 4:4.2.2-0ubuntu1 va a ser instalado Depende: kdelibs5 (>= 4:4.3.2) pero 4:4.2.2-0ubuntu5 va a ser instalado Depende: libqt4-svg (>= 4.5.1) pero 4.5.0-0ubuntu4.3 va a ser instalado Depende: libqtcore4 (>= 4.5.1) pero 4.5.0-0ubuntu4.3 va a ser instalado Depende: libqtgui4 (>= 4.5.1) pero 4.5.0-0ubuntu4.3 va a ser instalado
SDL: Simple DirectMedia Layer
The Official Guide to Learning OpenGL, Version 1.1:
GLUT-FREEGLUT
$ gcc bezsurf.c -o bezsurf.o -lglut -lGL -lGLU
No tinc instal.lat glut
sudo apt-get -f install (arregla les dependències) sudo apt-get install freeglut3-dev libglew1.5-dev
NOTA! Estic instal.lant freeglut i no glut. Ja va bé perquè és l'opció open source. Però ara per ara no sé si el codi escrit per a glut o per a freeglut és 100% compatible.
Llegeixo que de fet GLUT ja no es manté, i que formalment ha estat reemplaçat per freeglut (que a més n'ha millorat aspectes i limitacions que tenia GLUT). Per tant, freeglut és l'opció correcta i natural.
començo pels exemples que trobo a
$ gcc -g -o aaindex aaindex.c -lglut -lGL -lGLEW compila bé, però no s'executa (el problema només és d'aquest fitxer, els altres funcionen. Veure més avall) $ ./aaindex
freeglut (./aaindex): ERROR: Internal error <Visual with necessary capabilities not found> in function fgOpenWindow X Error of failed request: BadWindow (invalid Window parameter) Major opcode of failed request: 4 (X_DestroyWindow) Resource id in failed request: 0x0 Serial number of failed request: 29 Current serial number in output stream: 32
Buscant pel Google:
It could be due to your X server not supporting the glX extensions. Do you have the glx module loaded and are you using a display driver (and card) that supports OpenGL?
- http://ubuntuforums.org/archive/index.php/t-333966.html
- http://ubuntuforums.org/archive/index.php/t-379112.html
$ glxgears
funciona. És una aplicació gràfica d'exemple que suposo que demostra que tinc ben configurat tot el tema de OpenGL
$ glxinfo name of display: :0.0 display: :0 screen: 0 direct rendering: Yes server glx vendor string: SGI server glx version string: 1.2 server glx extensions: GLX_ARB_multisample, GLX_EXT_import_context, GLX_EXT_texture_from_pixmap, GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_MESA_copy_sub_buffer, GLX_OML_swap_method, GLX_SGI_make_current_read, GLX_SGI_swap_control, GLX_SGIS_multisample, GLX_SGIX_fbconfig, GLX_SGIX_visual_select_group client glx vendor string: SGI client glx version string: 1.4 client glx extensions: GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_import_context, GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_MESA_allocate_memory, GLX_MESA_copy_sub_buffer, GLX_MESA_swap_control, GLX_MESA_swap_frame_usage, GLX_OML_swap_method, GLX_OML_sync_control, GLX_SGI_make_current_read, GLX_SGI_swap_control, GLX_SGI_video_sync, GLX_SGIS_multisample, GLX_SGIX_fbconfig, GLX_SGIX_pbuffer, GLX_SGIX_visual_select_group, GLX_EXT_texture_from_pixmap ...
nota: direct rendering: Yes significa que estic utilitzant acceleració gràfica. (correcte, estic aprofitant la potència de la targeta gràfica).
$ glxgears -info GL_RENDERER = Mesa DRI R300 20060815 x86/MMX/SSE2 TCL GL_VERSION = 1.3 Mesa 7.4 GL_VENDOR = DRI R300 Project GL_EXTENSIONS = GL_ARB_depth_texture GL_ARB_fragment_program GL_ARB_imaging ...
Les dades de la meva targeta gràfica (portàtil DELL INSPIRON 6000) són:
Handle 0x0A00, DMI type 10, 6 bytes On Board Device Information Type: Video Status: Enabled Description: ATI MOBILITY Radeon X300
Solució (una solució... perquè de moment no sé res de OpenGL): en el fitxer aaindex.c comentar la línia:
glutInitDisplayMode (GLUT_SINGLE | GLUT_INDEX);
que està dins del main:
$ gcc -g -o aaindex aaindex.c -lglut -lGL -lGLEW $ ./aaindex
Al tanto perquè el aargb.c funciona bé, amb la següent línia:
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
Per tant, ficant aquesta línia també funciona aaindex.c. Tots els altres funcionen (quasi tots)
accanti.c: funciona accpersp.c : funciona alpa.c: funciona alpa3D.c: funciona bezcurve.c bezmesh.c bezsurf.c checker.c clip.c colormat.c cube.c dof.c double.c drawf.c feedback.c fog.c fogindex.c -> GLUT_INDEX no funciona hello.c image.c -> Si executo des de la consola (./image), he de comentar els printf per veure bé l'efecte. La solució està en fer doble click sobre el binari, i aleshores no tinc consola i no tinc aquest efecte engorrós. Això també val per molts d'altres exemples. light.c lines.c list.c material.c mipmap.c model.c movelight.c pickdepth.c picksquare.c planet.c polyoff.c polys.c quadric.c robot.c scene.c select.c smooth.c stencil.c stroke.c surface.c teapots.c tess.c -> memory corruption tesswind.c texbind.c texgen.c texsub.c texturesurf.c torus.c trim.c varray.c wrap.c
Fullscreen mode
Vull fer un exemple amb fullscreen, doncs tots els exemples anteriors són amb finestra.
GLUT vs. FreeGLUT As far as I know, nothing much has been done with GLUT per se since about 1999 (anyone else know differently?) But I've been happily using freeGlut for many years now, and I like it. It seems to faithfully implement the GLUT 3.7 features, plus add a few extensions of its own.
Em preocupa el tema de poder fer un exemple amb mode fullscreen. Llegir:
Amb SDL, que sembla ser que és més potent, es pot fer. Però amb GLUT també s'ha de poder fer.
GLUT was originally to get a window open as fast as possible with least amount of code possible (for quick OpenGL programs) and for simple keyboard interface ... SDL on the other hand is designed to be used more extensively
sembla ser que glutGameMode és el mode que es necessita per al fullscreen.
I've also read on the freeglut webpage that glutGameMode works on Linux with it, so I'm about to check it out.
Desembre 2005:
Freeglut's gamemode/fullscreen support is badly broken.
A mí sí que em funciona el fullscreen. Per exemple a image.c he afegit la funció glutFullScreen() després del glutCreateWindow i abans del init():
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); glutFullScreen(); init();
Ara ja entro en mode FullScreenMode, però encara es veu els botons de la finestra, i el menú del Ubuntu. Com arreglar-ho? Doncs una solució que crec que és vàlida és:
Sistema > Preferencias > Combinación de teclas > Gestión de ventanas
i fico Toogle FullScreen Mode (que estava desactivat): ALT+V (o la que jo vulgui)
També hi ha Toogle Maximi
Descoberta!: de fet, en els codis d'exemple anteriors, només cal posar glutFullScreen(); per tenir el fullscreen mode des del principi. Si no ho poso, fent ALT-V (o la combinació de tecles que utilitzo) ja entro en mode fullscreen immediatament. Per tant, per programar puc treballar amb una finestra petita, i quan vulgui veure el resultat final faing ALT-V.
Si m'apareix incones per sota... no passa res. El refresc de les pantalles l'he de programar jo. Aquests exemples que he vist són senzills.
Escriure text
es fa amb glutBitmapString
void glutBitmapCharacter (void *font, int character) int glutBitmapHeight (void *font) int glutBitmapLength (void *font, const unsigned char *string) void glutBitmapString (void *font, const unsigned char *string) int glutBitmapWidth (void *font, int character)
glRasterPos2f(0, 0); -> compte amb aquesta funció (float); també hi ha glRasterPos2i glutBitmapString (GLUT_BITMAP_9_BY_15, (const unsigned char*)"hola joan"); glutBitmapString (GLUT_BITMAP_9_BY_15, "hola joan");
- http://rnasa.tic.udc.es/gc/Tutorial%20OpenGL/index.htm: un exemple senzill amb explicació
- http://linux.die.net/man/3/glrasterpos2i
void glRasterPos2f( GLfloat x, GLfloat y ) Specify the $x$, $y$ for the raster position.
The object coordinates presented by glRasterPos are treated just like those of a glVertex command: They are transformed by the current modelview and projection matrices and passed to the clipping stage. If the vertex is not culled, then it is projected and scaled to window coordinates, which become the new current raster position, and the GL_CURRENT_RASTER_POSITION_VALID flag is set. If the vertex is culled, then the valid bit is cleared and the current raster position and associated color and texture coordinates are undefined.
To set a valid raster position outside the viewport, first set a valid raster position, then call glBitmap with NULL as the bitmap parameter.
glBitmap — draw a bitmap void glBitmap( GLsizei width, -> Specify the pixel width and height of the bitmap image. GLsizei height, GLfloat xorig, -> Specify the location of the origin in the bitmap image. The origin is measured from the lower left corner of the bitmap, with right and up being the positive axes. GLfloat yorig, GLfloat xmove, -> Specify the x and y offsets to be added to the current raster position after the bitmap is drawn. GLfloat ymove, const GLubyte * bitmap -> Specifies the address of the bitmap image );
Per exemple, funciona:
glColor3f(1,1,1); glRasterPos2f(-0.95, 0); //glBitmap (0, 0, 0.0, 0.0, 130.0, 130.0, NULL); glutBitmapString (GLUT_BITMAP_9_BY_15, "hola joan"); glFlush();
Mirar hello3.c
El que em falta ara és fer que les lletres siguin ben grosses. Em falta implementar la tècnica del doble buffering. El que voldria fer és fer que hi hagi un número en que els números ballen, i al cap de 5 segons s'atura...
Nothing is drawn, and the raster position is unaffected when either:
* font is not a valid OpenGLUT bitmap font * string is an empty string or NULL pointer * The current OpenGL raster position is invalid -> que és el que a mi em passava. M'he d'assegurar que la raster position sigui vàlida.
Mirar fontdemo, bitfont i stroke
tutorial de glut:
A glut hi ha dues maneres de rasteritzar les fonts: com a bitmaps, o com a strokes (vectorials) (mirar els dos exemples de stroke.c). En qualsevol cas, és un tema bastant limitat. Una possibilitat és tenir els números i lletres com a bitmaps (.bmp), i quan vull fer la representació d'una cadena com "23423" doncs cridar als bitmaps.
Doble buffering
mirar per exemple /home/joan/opengl/stroke.c ...
SDL (Simple DirectMedia Layer)
Instal.lació de SDL a Ubuntu
$ sudo apt-get install libsdl1.2-dev libsdl1.2debian
Si ho mirem, ara ja tenim la llibreria /usr/include/SDL
A la xarxa hi ha un llibre per descarregar:
que ja he descarregat amb tots els exemples:
- pdf: Fitxer:-ebook-Programacion de videojuegos con SDL.pdf
- codis d'exemple: Fitxer:LibroSDL.zip
- codi depurat i comentat: Fitxer:Programacio videojocs SDL.zip. El codi del llibre està escrit per a VC++. Jo he tret tot el que no cal, he depurat algun error i he comentat com es compila el codi, tot per a Linux/Ubuntu.
altres referències:
Per dibuixar text SDL sembla més funcional:
g_graphics->drawText(FONT_TYPE, "Press 'i' for instructions.", FONT_SIZE, 340,345,255,255,255,0,0,0);
o bé (http://www.gamedev.net/community/forums/topic.asp?topic_id=392881)
int DisplayMsg(std::string Line1, std::string Line2, std::string Line3, std::string Line4) { SDL_Surface *FinalMessage = load_image("GFX\\mbox.bmp"); SDL_Event events; bool MSG = true; RenderTextToSurface(Line1, 5,5, FinalMessage); RenderTextToSurface(Line2, 5,25+3, FinalMessage); RenderTextToSurface(Line3, 5,45+6, FinalMessage); RenderTextToSurface(Line4, 5,65+9, FinalMessage); while (MSG) { SDL_PollEvent(&events); if (events.key.keysym.sym == SDLK_RETURN) // If enter: { MSG = false; } put_surface(0, 380, FinalMessage, screen); if(SDL_Flip(screen) == -1) { SDL_FreeSurface(FinalMessage); return 1; } } SDL_FreeSurface(FinalMessage); return 0; // Normal termination }
It loads a 640x100 bitmap and displays it at the bottom of the screen after blitting text to it.
If you want to put your text onto a target surface and centered, then you could use my RenderTextToSurface function and make the X the screen width / 2.
int RenderTextToSurface(std::string Text, int x, int y, SDL_Surface *Dest) { SDL_Color TXT_Color; TXT_Color.r = 0xFF; TXT_Color.g = 0xFF; TXT_Color.b = 0xFF; SDL_Surface *TTF_Message; TTF_Font *font = TTF_OpenFont("font.ttf", 24); if(!(TTF_Message = TTF_RenderText_Solid(font, Text.c_str(), TXT_Color))) { SDL_FreeSurface(TTF_Message); Log("Error in function 'RenderTextToSurface': TTF_Message could not be blitted: returned 1"); return 1; } put_surface(x, y, TTF_Message, Dest); SDL_FreeSurface(TTF_Message); return 0; }
article: http://linuxdevcenter.com/pub/a/linux/2003/10/23/sdl_anim.html
$ gcc gllines.cpp -o gllines.o `sdl-config --cflags --libs` -lGL -lGLU $ ./gllines.o
i ja funciona
SDL_TTF
En el llibre que m'he descarregat (Fitxer:-ebook-Programacion de videojuegos con SDL.pdf) hi ha tot un apartat de com utilitzar SDL_TTF: podem importar qualsevol font ttf de què disposem (com per exemple les de Windows). A més a més, es pot escollir el tamany, color, efectes (negreta, cursiva), i tres tipus de qualitat. Mirar l'exemple del llibre.
La gràcia de les fonts ttf és que n'hi ha moltes disponibles. Per exemple:
La manera d'instal.lar una font ttf a Ubuntu és ben fàcil:
- http://www.wikihow.com/Install-True-Type-Fonts-on-Ubuntu
- https://lists.ubuntu.com/archives/ubuntu-ca/2009-March/005718.html
Copy the Fonts that you have to /usr/share/fonts. You do that this way: sudo su Password cd /usr/share/fonts/truetype mkdir 500fonts cd /home/user/Desktop/500fonts cp -r *.TTF /usr/share/fonts/truetype/500fonts exit sudo fc-cache -fv (## note the space after the word cache) Password after a few moments exit exit It looks at all the fonts in the Font Cache and re-installs them. So if you have a Windows Font CD of TTF Fonts, you can now use it in LINUX. You can add the ones out of the list to the open office folder, in /usr/share/fonts/truetype/openoffice, and they should appear in openoffice.
Mirar també:
Per exemple, una font xula que puc utilitzar és la 256bytes.zip (apartat Computers). Faig el procés i instal.lo dues fonts: 256bytes.ttf i biodisc.ttf. S'instal.len bé, però la primera no funciona i la segona sí.
Instal.lació de SDL_TTF a Ubuntu:
wget http://www.libsdl.org/projects/SDL_ttf/release/SDL_ttf-2.0.9.tar.gz tar xvzf SDL_ttf-2.0.9.tar.gz cd SDL_ttf-2.0.9 ./configure && make sudo make install
També:
$ sudo apt-get install libsdl-ttf2.0-0 libsdl-ttf2.0-dev
Libraries have been installed in /usr/local/lib
$ ls -la /usr/local/lib ... lrwxrwxrwx 1 root root 23 2010-03-25 00:17 libSDL_ttf-2.0.so.0 -> libSDL_ttf-2.0.so.0.6.3 -rwxr-xr-x 1 root root 66734 2010-03-25 00:17 libSDL_ttf-2.0.so.0.6.3 -rw-r--r-- 1 root root 67380 2010-03-25 00:17 libSDL_ttf.a -rwxr-xr-x 1 root root 883 2010-03-25 00:17 libSDL_ttf.la lrwxrwxrwx 1 root root 23 2010-03-25 00:17 libSDL_ttf.so -> libSDL_ttf-2.0.so.0.6.3 ...
Compilació de l'ejemplo4_1:
$ gcc main.c -o ejemplo4_1 `sdl-config --cflags --libs` -lGL -lGLU -lSDL_ttf o bé $ g++ -O2 -W -Wall -pedantic `sdl-config --cflags` -I//usr/local/include/SDL/ -lSDL -lSDL_ttf -lpthread -L/usr/local/lib main.c -o ejemplo4_1
main.c (ejemplo4_1) compila bé, i també funciona després de dos canvis:
- canviar la línia per fuente = TTF_OpenFont("/usr/share/fonts/truetype/1001freefonts/BIOST.TTF",20);
- en el codi falta la línia SDL_Flip(screen);, que fa que es bolqui el buffer secundari al principal (s'està utilitzant doble buffer). Això va després de SDL_BlitSurface.
main.c (és l'exemple més petit i senzill que he aconseguit, que utilitzi SDL_ttf)
/*************************************************************************** Ejemplo4_1 (C) 2003 by Alberto Garcia Serrano Programación de videojuegos con SDL ***************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <SDL.h> #include "SDL_ttf.h" int main(int argc, char *argv[]) { SDL_Color bgcolor,fgcolor; SDL_Rect rectangulo; SDL_Surface *screen,*ttext; TTF_Font *fuente; const char texto[14]="Hola Mundo..."; char msg[14]; SDL_Event event; int done = 0; // Inicializamos SDL if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("No se pudo iniciar SDL: %s\n",SDL_GetError()); return 1; } // Inicializamos modo de video screen = SDL_SetVideoMode(640,480,24,SDL_HWSURFACE|SDL_DOUBLEBUF); if (screen == NULL) { printf("No se puede inicializar el modo gráfico: \n",SDL_GetError()); return 1; } atexit(SDL_Quit); SDL_WM_SetCaption("Hola Joan!", 0); // Inicializamos SDL_ttf if (TTF_Init() < 0) { printf("No se pudo iniciar SDL_ttf: %s\n",SDL_GetError()); return 1; } atexit(TTF_Quit); // carga la funte de letra //el segon paràmetre és el tamany de la font //fuente = TTF_OpenFont("/usr/share/fonts/truetype/1001freefonts/BIOST.TTF",80); fuente = TTF_OpenFont("/usr/share/fonts/truetype/ttf-japanese-mincho.ttf",20); //fuente = TTF_OpenFont("/usr/share/fonts/truetype/freefont/FreeSans.ttf",20); //fuente = TTF_OpenFont("/usr/share/fonts/truetype/1001freefonts/256BYTES.TTF",80); // inicializa colores para el texto fgcolor.r=200; fgcolor.g=200; fgcolor.b=10; bgcolor.r=255; bgcolor.g=0; bgcolor.b=0; sprintf(msg,"%s",texto); //printf("%s\n",msg); ttext = TTF_RenderText_Shaded(fuente,msg,fgcolor,bgcolor); rectangulo.y=100; rectangulo.x=100; rectangulo.w=ttext->w; rectangulo.h=ttext->h; // Usamos color rojo para la transparencia del fondo //havia fet que el color de fons de ttext sigui el vermell, i ara vull que aquest color sigui transparent. SDL_SetColorKey(ttext,SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB(ttext->format,255,0,0)); // Volcamos la superficie a la pantalla //amb el valor NULL indiquem a SDL que volem copiar tota la superfície del text en la pantalla SDL_BlitSurface(ttext,NULL,screen,&rectangulo); // Mostramos la pantalla //Si estamos usando doble buffer (como es el caso de nuestro ejemplo), esta función intercambia los buffers, es decir, vuelca el contenido del buffer //secundario al principal. Si tiene éxito devuelve 0, si no, devuelve –1. Si no usáramos doble buffer o nuestro //hardware no lo soportara, tendríamos que usar SDL_UpdateRec SDL_Flip(screen); // destruimos la fuente de letra TTF_CloseFont(fuente); // liberar superficie SDL_FreeSurface(ttext); // Esperamos la pulsación de una tecla para salir while(done == 0) { while ( SDL_PollEvent(&event) ) { if ( event.type == SDL_KEYDOWN ) done = 1; } } return 0; }
Nota important!: Vaig perdre bastant temps mirant quines fonts acceptaven accents i caràcters especials. A més, observava aliasing en les lletres. Les dues coses es solucionen utilitzant
ttext = TTF_RenderUTF8_Blended(fuente,msg,fgcolor);
en comptes de
ttext = TTF_RenderText_Shaded(fuente,msg,fgcolor,bgcolor);
També funciona el main2 (i funciona amb la lletra BIOST.TTF que he importat), que he trobat a http://www.gamedev.net/community/forums/topic.asp?topic_id=284259:
main2.c
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <GL/gl.h> #include <GL/glu.h> #include <SDL/SDL.h> #include <SDL/SDL_ttf.h> /* adjust these accordingly */ char fontpath[] = "/usr/share/fonts/truetype/1001freefonts/BIOST.TTF"; int screenwidth = 640; int screenheight = 480; //int round(double x) //{ // return (int)(x + 0.5); //} int nextpoweroftwo(int x) { double logbase2 = log(x) / log(2); //return round(pow(2,ceil(logbase2))); return (int)((pow(2,ceil(logbase2)))+0.5); } char *init_sdl(SDL_Surface** screen) { if(SDL_Init(SDL_INIT_VIDEO)) return SDL_GetError(); atexit(SDL_Quit); *screen = SDL_SetVideoMode(screenwidth, screenheight, 0, SDL_OPENGL); SDL_WM_SetCaption("C-Junkie's SDLGL text example", 0); if(TTF_Init()) return TTF_GetError(); atexit(TTF_Quit); return 0; } void SDL_GL_RenderText(char *text, TTF_Font *font, SDL_Color color, SDL_Rect *location) { SDL_Surface *initial; SDL_Surface *intermediary; SDL_Rect rect; int w,h; int texture; /* Use SDL_TTF to render our text */ initial = TTF_RenderText_Blended(font, text, color); /* Convert the rendered text to a known format */ w = nextpoweroftwo(initial->w); h = nextpoweroftwo(initial->h); intermediary = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); SDL_BlitSurface(initial, 0, intermediary, 0); /* Tell GL about our new texture */ glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, intermediary->pixels ); /* GL_NEAREST looks horrible, if scaled... */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* prepare to render our texture */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture); glColor3f(1.0f, 1.0f, 1.0f); /* Draw a quad at location */ glBegin(GL_QUADS); /* Recall that the origin is in the lower-left corner That is why the TexCoords specify different corners than the Vertex coors seem to. */ glTexCoord2f(0.0f, 1.0f); glVertex2f(location->x , location->y); glTexCoord2f(1.0f, 1.0f); glVertex2f(location->x + w, location->y); glTexCoord2f(1.0f, 0.0f); glVertex2f(location->x + w, location->y + h); glTexCoord2f(0.0f, 0.0f); glVertex2f(location->x , location->y + h); glEnd(); /* Bad things happen if we delete the texture before it finishes */ glFinish(); /* return the deltas in the unused w,h part of the rect */ location->w = initial->w; location->h = initial->h; /* Clean up */ SDL_FreeSurface(initial); SDL_FreeSurface(intermediary); glDeleteTextures(1, &texture); } void glEnable2D() { int vPort[4]; glGetIntegerv(GL_VIEWPORT, vPort); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, vPort[2], 0, vPort[3], -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); } void glDisable2D() { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } void init_gl() { /* Irrelevant stuff for this demo */ glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); /* Required if you want alpha-blended textures (for our fonts) */ glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); /* Required setup stuff */ glViewport(0, 0, 800, 600); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, screenwidth / (float)screenheight, 0.1f, 50.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main() { SDL_Surface *screen; TTF_Font* font; char *err; SDL_Color color; SDL_Rect position; SDL_Event event; int done; /* Do boring initialization */ if((err = init_sdl(&screen))) { printf("Error while initializing: %s", err); return 1; } if(!(font = TTF_OpenFont(fontpath, 40))) { printf("Error loading font: %s", TTF_GetError()); return 1; } init_gl(); done = 0; while(!done) { /* render a fun litte quad */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -5.0f); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); glColor3f(0.5f, 0.0f, 0.0f); glVertex3f(-1.5f, -1.0f, 1.0f); glColor3f(0.0f, 0.5f, 0.0f); glVertex3f( 1.0f, -2.0f, 1.0f); glColor3f(0.0f, 0.0f, 0.5f); glVertex3f( 1.5f, 1.0f, 1.0f); glColor3f(0.5f, 0.0f, 0.0f); glVertex3f(-2.0f, 1.0f, -1.0f); glEnd(); /* Go in HUD-drawing mode */ glEnable2D(); glDisable(GL_DEPTH_TEST); /* Draw some text */ color.r = 255; color.g = 255; color.b = 255; /** A quick note about position. * Enable2D puts the origin in the lower-left corner of the * screen, which is different from the normal coordinate * space of most 2D api's. position, therefore, * gives the X,Y coordinates of the lower-left corner of the * rectangle **/ position.x = screenwidth / 3; position.y = screenheight / 2; SDL_GL_RenderText("Hello, World!", font, color, &position); position.y -= position.h; SDL_GL_RenderText("A line right underneath", font, color, &position); position.y -= position.h; SDL_GL_RenderText("Yay text rendering.", font, color, &position); /* Come out of HUD mode */ glEnable(GL_DEPTH_TEST); glDisable2D(); /* Show the screen */ SDL_GL_SwapBuffers( ); /* Wait until you click the X */ SDL_WaitEvent(&event); switch(event.type) { case SDL_QUIT: done = 1; break; } } /* Clean up (the atexit's take care of the rest) */ TTF_CloseFont(font); return 0; }
Lletra lligada (per la Maria)
La lletra que més s'assembla a la lletra lligada que fan a l'escola
escullo little_days.zip
Fullscreen mode
Molt fàcil: és una de les opcions que puc posar en SDL_SetVideoMode (veure el llibre Programación de Videojuegos...)
*screen = SDL_SetVideoMode(screenwidth, screenheight, 0, SDL_OPENGL|SDL_FULLSCREEN);
SDL_image (carregar un JPG)
Per carregar un JPG i altres formats d'imatges és necessària la llibreria SDL_image:
$ sudo apt-get install libsdl-image1.2-dev $ gcc prova2.c -o prova2 `sdl-config --cflags --libs` -lGL -lGLU -lSDL_ttf -lSDL_image ... SDL_Surface *foto; foto = IMG_Load("/home/joan/arthropoda/fotosarthropoda/originals/12/05/120501_102722.JPG"); ...
SDL_mixer (so, audio)
$ sudo apt-get install libsdl-mixer1.2-dev
Fer zoom d'una imatge, SDL_gfx
Fer zoom d'una imatge, ampliant-la, és a dir, perdent resolució, no és evident. A vegades interessa tenir imatges petites per tal de què sigui fàcil de carregar-les. però s'han de mostrar més grans (apareix el pixelat). Això ho he necessitat a joanillo_arcade_frontend.
Eines per fer el zoom d'una imatge:
$ sudo apt-get install libsdl-gfx1.2-dev
Es compila amb -lSDL_gfx, i s'ha d'incloure "SDL_rotozoom.h"
g++ -o joanillo_arcade_frontend joanillo_arcade_frontend-0.0.8.cpp `sdl-config --cflags --libs` -lSDL_image -lSDL_ttf -lSDL_gfx ... #include "SDL_rotozoom.h" ... void resizeImage( SDL_Surface*& img, const double newwidth, const double newheight ); ... int main () { ... srf_rompng = IMG_Load(("imatge.png").c_str()); resizeImage (srf_rompng, 600, 600); ... } void resizeImage( SDL_Surface*& img, const double newwidth, const double newheight ) { // Zoom function uses doubles for rates of scaling, rather than // exact size values. This is how we get around that: double zoomx = newwidth / (float)img->w; double zoomy = newheight / (float)img->h; // This function assumes no smoothing, so that any colorkeys wont bleed. SDL_Surface* sized = zoomSurface( img, zoomx, zoomy, SMOOTHING_OFF ); // Copy transparency data. //matchColorKeys( img, sized ); // The original picture is no longer needed. SDL_FreeSurface( img ); // Set it instead to the new image. img = sized; }
SDL 2.0 (necessari per compilar l'emulador Gearboy (febrer 2015)
El primer que hem de fer és instal.lar SDL2.0.3:
$ ./configure $ make $ sudo make install $ sdl2-config --version 2.0.3
Hi ha un tutorial per a la programació amb SDL 2.0 que segueix la mateixa pauta que la versió 1.0
Per tal de compilar els exemples a Linux he de fer un parell de canvis:
En el codi font (!):
//#include <SDL.h> #include <SDL2/SDL.h>
I en el Makefile: (!!)
#LINKER_FLAGS specifies the libraries we're linking against #LINKER_FLAGS = -lSDL2 LINKER_FLAGS = -lSDL2 `sdl2-config --libs`
La comanda sdl2-config --libs ens dóna informació de les llibreries necessàries amb les que hem d'enllaçar per a la compilació:
$ sdl2-config --libs -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL2 -lpthread
Amb aquests canvis ja funciona. Ho he provat amb Ubuntu. Ara caldrà comprovar el bon funcionament amb la Raspberry, doncs precisament aques codi m'interessa perquè és similar al que hi ha a Gearboy, que compila bé però les tecles no responen.
El que ha costat més és que funcioni l'exemple en mode fullscreen. Per tal de què funcioni ha sigut important el mode SDL_WINDOW_BORDERLESS, i ara SDL_WINDOW_RESIZABLE ja no cal i SDL_WINDOW_OPENGL tampoc. SDL_WINDOW_INPUT_FOCUS tampoc no cal per tal de què funcioni l'exemple.
gWindow = SDL_CreateWindow( "SDL Tutorial", 0, 0, 640, 480, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_BORDERLESS);
SDL 2.0 (necessari per compilar mupeng4plus a la RPi)
- https://www.raspberrypi.org/forums/viewtopic.php?t=56756&p=430647
- http://www.libsdl.org/download-2.0.php -> és el mateix enllaç que l'apartat anterior
Descarreguem:
- SDL2-2.0.4.tar.gz - GPG signed
$ ./configure $ make $ sudo make install
ho he compilat i instal.lat tant a Ubuntu 16.04 com a la Raspberry Pi 3 amb Raspbian.
Si quan compilo el primer programa de test em dóna l'error:
$ ./SDL_Lesson0 SDL_Init Error: No available video devic This error message occurs when there is no available video driver built into SDL2 for your display system (X11, Mir, Wayland, RPI ...). Have you installed SDL2 package from Ubuntu repository or compiled from source ? When compiled from source, you should check that the supported video drivers are going to be built into the binary at the end of the "configure" step. Otherwise you need to install the required development headers (for X11 and Mir)
Aleshores compilo des del paquet Debian i torno a compilar des de les fonts:
$ sudo apt-get install libsdl2-dev
i torno a compilar des de les fonts com havia fet, i ara ja compila bé.
Programació SDL2. Test
Compilo tres programes petits de test:
test.cpp:
#include <iostream> #include <SDL2/SDL.h> /* * Lesson 0: Test to make sure SDL is setup properly */ int main(int, char**){ if (SDL_Init(SDL_INIT_VIDEO) != 0){ std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl; return 1; } SDL_Quit(); return 0; }
minimal_main.c o minimal_main.cpp:
#include <SDL2/SDL.h> // +--------------------------------------------------+ // | Minimal SDL2 Test Program | // | Creates a graphics window then shuts it down | // | after 10 seconds. | // +--------------------------------------------------+ int main ( int argc, char** argv ) { SDL_Window *window; SDL_Init(SDL_INIT_VIDEO); window = SDL_CreateWindow( "SDL2 TEST PROGRAM", // window title SDL_WINDOWPOS_CENTERED, // the x position of the window SDL_WINDOWPOS_CENTERED, // the y position of the window 400,400, // window width and height SDL_WINDOW_RESIZABLE // create resizeable window ); if(window == NULL) // if no win, show error { printf("Could not create SDL2 test window: %s\n", SDL_GetError()); return 1; } SDL_Delay(10000); // 10sec delay SDL_DestroyWindow(window); // kill window SDL_Quit(); // clean up return 0; // return success }
01_hello_SDL.cpp:
/*This source code copyrighted by Lazy Foo' Productions (2004-2015) and may not be redistributed without written permission.*/ //Using SDL and standard IO //#include <SDL.h> #include <SDL2/SDL.h> #include <stdio.h> //Screen dimension constants const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; int main( int argc, char* args[] ) { //The window we'll be rendering to SDL_Window* window = NULL; //The surface contained by the window SDL_Surface* screenSurface = NULL; //Initialize SDL if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() ); } else { //Create window window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if( window == NULL ) { printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() ); } else { //Get window surface screenSurface = SDL_GetWindowSurface( window ); //Fill the surface white SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) ); //Update the surface SDL_UpdateWindowSurface( window ); //Wait two seconds SDL_Delay( 2000 ); } } //Destroy window SDL_DestroyWindow( window ); //Quit SDL subsystems SDL_Quit(); return 0; }
$ gcc minimal_main.c `sdl2-config --cflags --libs` -o myprog $ g++ minimal_main.cpp `sdl2-config --cflags --libs` -o myprog $ g++ test.cpp `sdl2-config --cflags --libs` -o test
$ sdl2-config --cflags --libs -I/usr/local/include/SDL2 -D_REENTRANT -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL2
$ g++ 01_hello_SDL.cpp -w -lSDL2 -L/usr/local/lib/ -o 01_hello_SDL $ g++ 01_hello_SDL.cpp `sdl2-config --cflags --libs` -o 01_hello_SDL
També podem compilar amb un Makefile senzill:
CXX = g++ # Update these paths to match your installation # You may also need to update the linker option rpath, which sets where to look for # the SDL2 libraries at runtime to match your install SDL_LIB = -L/usr/local/lib -lSDL2 -Wl,-rpath=/usr/local/lib SDL_INCLUDE = -I/usr/local/include # You may need to change -std=c++11 to -std=c++0x if your compiler is a bit older CXXFLAGS = -Wall -c -std=c++11 $(SDL_INCLUDE) LDFLAGS = $(SDL_LIB) EXE = SDL_Lesson0 all: $(EXE) $(EXE): test.o $(CXX) $< $(LDFLAGS) -o $@ main.o: test.cpp $(CXX) $(CXXFLAGS) $< -o $@ clean: rm *.o && rm $(EXE) #g++ -Wall -c -std=c++11 -I/usr/local/include -c -o test.o test.cpp #g++ test.o -L/usr/local/lib -lSDL2 -Wl,-rpath=/usr/local/lib -o SDL_Lesson0
Tutorial LazyFoo
Lesson 02: Getting an Image on the Screen. Now that we can get a window to appear, lets blit an image onto it.
$ g++ 02_getting_an_image_on_the_screen.cpp `sdl2-config --cflags --libs` -o test_02
Lesson 03: Event Driven Programming. Here we'll start handling user input by allow the user to X out the window.
$ g++ 03_event_driven_programming.cpp `sdl2-config --cflags --libs` -o test_03
Lesson 04: Key presses. Here we'll learn to handle keyboard input.
$ g++ 04_key_presses.cpp `sdl2-config --cflags --libs` -o test_04
Lesson 05: Optimized Surface Loading and Soft Stretching. Now that we know how to load and blit surfaces, it's time to make our blits faster. We'll also take a smaller image and stretch it to fit the screen.
$ g++ 05_optimized_surface_loading_and_soft_stretching.cpp `sdl2-config --cflags --libs` -o test_05
Lesson 06: Extension Libraries and Loading Other Image Formats. Here we'll be using the SDL_image extension library to load png images.
$ sudo apt-get install libsdl2-image-dev o bé compilar des de les fonts $ g++ 06_extension_libraries_and_loading_other_image_formats.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_06
Lesson 07: Texture Loading and Rendering. A big new feature in SDL 2.0 is hardware accelerated texture based 2D rendering. Here we'll be loading an image to render it using textures
$ g++ 07_texture_loading_and_rendering.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_07
Lesson 08: Geometry Rendering. Another new feature in SDL 2.0 is hardware accelerated primitive rendering. Here we'll be using it to render some common shapes.
$ g++ 08_geometry_rendering.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_08
Lesson 09: The Viewport. SDL 2.0 also lets you control where you render on the screen you using the viewport. We'll be using the viewport to create subscreens.
$ g++ 09_the_viewport.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_09
Lesson 10: Color Keying. Here we'll use color keying to give texture transparent backgrounds.
g++ 10_color_keying.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_10 g++ 11_clip_rendering_and_sprite_sheets.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_11 g++ 12_color_modulation.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_12 g++ 13_alpha_blending.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_13 g++ 14_animated_sprites_and_vsync.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_14 g++ 15_rotation_and_flipping.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_15 sudo apt-get install libsdl2-ttf-dev g++ 16_true_type_fonts.cpp `sdl2-config --cflags --libs` -lSDL2_image -lSDL2_ttf -o test_16 g++ 17_mouse_events.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_17 g++ 18_key_states.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_18 g++ 19_gamepads_and_joysticks.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_19 g++ 20_force_feedback.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_20 sudo apt-get install libsdl2-mixer-dev g++ 21_sound_effects_and_music.cpp `sdl2-config --cflags --libs` -lSDL2_image -lSDL2_mixer -o test_21 g++ 22_timing.cpp `sdl2-config --cflags --libs` -lSDL2_image -lSDL2_ttf -o test_22 g++ 23_advanced_timers.cpp `sdl2-config --cflags --libs` -lSDL2_image -lSDL2_ttf -o test_23 g++ 24_calculating_frame_rate.cpp `sdl2-config --cflags --libs` -lSDL2_image -lSDL2_ttf -o test_24 g++ 25_capping_frame_rate.cpp `sdl2-config --cflags --libs` -lSDL2_image -lSDL2_ttf -o test_25 g++ 26_motion.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_26 g++ 27_collision_detection.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_27 g++ 28_per-pixel_collision_detection.cpp `sdl2-config --cflags --libs` -lSDL2_image -o test_28
Lesson 11: Clip Rendering and Sprite Sheets. Using clip rendering, you can keep multiple images on one texture and render the part you need. We'll be using this to render individual sprites from a sprite sheet.
Lesson 12: Color Modulation. We'll be altering the color of rendered textures using color modulation.
Lesson 13: Alpha Blending. Here we'll be using SDL 2.0 new hardware accelerated alpha blending.
Lesson 14: Animated Sprites and Vsync. Here we'll be using a sequence of sprites to animate them.
Lesson 15: Rotation and Flipping. Here we'll be using SDL 2.0's new texture rotation and flipping.
Lesson 16: True Type Fonts. Here we'll be rendering text from true type fonts using SDL_ttf.
Lesson 17: Mouse Events. Here we'll learn to read mouse input using mouse events.
Lesson 18: Key States. There's other ways to read the keys besides event polling. Here will get the current states of the keyboard using get states.
Lesson 19: Gamepads and Joysticks. Here we'll learn to read input from a game controller.
Lesson 20: Force Feedback. Another new feature for SDL 2.0 is rumble support using the SDL haptics. We'll make our controller rumble when a button is pressed.
Lesson 21: Sound Effects and Music. Here we'll be using SDL_mixer to add music and sound to our SDL App.
Lesson 22: Timing. Here we'll be using SDL's time capabilites.
Lesson 23: Advanced Timers. Here we'll extend SDL time capabilities to make our own custom timer.
Lesson 24: Calculating Frame Rate. Here we'll use the timers we built to measure frame rate.
Lesson 25: Capping Frame Rate. If you need a constant frame rate when vsync isn't available, frame rate capping can be used as a fall back.
Lesson 26: Motion. Here we'll be taking what we learned about render and handling input to make a dot move around the screen.
Lesson 27: Collision Detection. Here we'll have two objects interact with each other using bounding box collision detection.
Lesson 28: Per-pixel Collision Detection. Here we'll have two object collide using per-pixel collision detection.
Lesson 29: Circular Collision Detection. Here we'll learn to detect collisions with circles and boxes.
Lesson 30: Scrolling. Here we'll be implement a camera to scroll levels larger than the screen.
Lesson 31: Scrolling Backgrounds. Here we'll using a scrolling background to give the illusion of an infinite level.
Lesson 32: Text Input and Clipboard Handling. Here we'll using SDL 2.0's new way of handling text input and its new clip board handling feature.
Lesson 33: File Reading and Writing. Here we'll using SDL's RWOps API to do binary file IO.
Lesson 34: Audio Recording. SDL 2 is planned to have an audio recording feature. As of SDL 2.0.0, it is not yet implemented. This here is just a place holder until it is ready to go. Please do not e-mail me saying this link is broken. You'll just look silly.
Lesson 35: Window Events. Here we'll be handling events from a resizable window.
Lesson 36: Multiple Windows. A new feature in SDL is the ability to support more than one window. Here we'll make an application that has 3 windows.
Lesson 37: Multiple Displays. Another new feature of SDL 2.0 is the ability to handle more than one physical display. Here we'll make our window jump from display to display.
Lesson 38: Particle Engines. Here we'll use a simple particle effect to create a simple trail effect.
Lesson 39: Tiling. Here we'll make a simple level using a tiling engine.
Lesson 40: Texture Manipulation. Here we'll be directly accessing and manipulating a texture's pixels.
Lesson 41: Bitmap Fonts. Here we'll be using a texture as a font using bitmap font techniques.
Lesson 42: Texture Streaming. Here we'll be rendering from a streaming data source using texture streaming.
Lesson 43: Render to Texture. Here we'll be taking a scene and rendering it to a texture.
Lesson 44: Frame Independent Movement. Here we'll be making the dot move independent of the current frame rate.
Lesson 45: Timer Callbacks. SDL has another timing mechanism called timer callbacks. Here we'll be setting a function to be called back after a certain amount of time.
Lesson 46: Multithreading. Multithreading allows your program to do things simultaneously. Here we'll make things print to the console from outside our main thread.
Lesson 47: Semaphores. A major issue in multithreaded applications is that you need to make sure that they don't try to access the same data at the same time. Semaphores are a way to make sure only a certain amount of threads are performing an action at the same time.
Lesson 48: Atomic Operations. Atomic operations are another way to synchronize threads. Here we'll be redoing the previous tutorial with atomic counters.
Lesson 49: Mutexes and Conditions. Mutexes and conditions are yet another way to synchronize threads. Here we'll be using the added benefit that they allow threads to communicate with each other.
Lesson 50: SDL and OpenGL 2. SDL is a powerful tool when combined with OpenGL. If you're just starting out with OpenGL or want to maximize compatibility, you can use SDL with OpenGL 2.1. In this tutorial we will make a minimalist OpenGL 2.1 program.
Lesson 51: SDL and Modern OpenGL. SDL 2.0 now has support for OpenGL 3.0+ with context controls. Here we'll be making a minimalist OpenGL 3+ core program.
Lesson 52: Hello Mobile. Here we'll be loading and displaying an image in our first mobile app!
Lesson 53: Extensions and Changing Orientation. Here we'll be using SDL extension libraries and handling changing orientation.
Lesson 54: Touches. Here we'll be handling single touch input
Lesson 55: Multitouch. Here we'll be handling multitouch events like pinches and rotation.
creat per Joan Quintana Compte, març 2010, setembre 2016