OpenGL: Difference between revisions
Levidsmith (talk | contribs) |
Levidsmith (talk | contribs) No edit summary |
||
Line 158: | Line 158: | ||
glEnable(GL_ALPHA_TEST); | glEnable(GL_ALPHA_TEST); | ||
glAlphaFunc(GL_GREATER, 0.5); | glAlphaFunc(GL_GREATER, 0.5); | ||
SDL_Surface *surface; | SDL_Surface *surface; | ||
SDL_Surface *surface_bkg; | SDL_Surface *surface_bkg; |
Revision as of 05:51, 14 February 2010
I am attempting to integrate OpenGL into the code, so that the game uses hardware graphics acceleration. Hopefully, this will improve some of the framerate issues.
This will also allow me to use Fraps to make videos of the game to post to YouTube.
Below, I have documented the process I went through to enable OpenGL, including all of the issues I came across.
Get code to compile with a single line of OpenGL
I can compile a program using #include "SDL_opengl.h", but I am getting errors about missing functions when an OpenGL method is called.
I installed the OpenGL libraries in cygwin, so I'm not sure if those were necessary:
Installing these files may help
http://www.libsdl.org/extras/win32/cygwin/
Found out that I was using the wrong parameters to compile. I should have been using this:
gcc test.c `sdl-config --libs --cflags` -lglut32 -lglu32 -lopengl32
Display a bitmap to the screen
I got a simple square BMP to display in OpenGL:
Added Tux BMP:
Tux on an image background:
One of the vertices was off, which made the background skewed.
Moving Block
Next Step is to get the player block moving
Pseudo Code:
INTEGER playerX INTEGER playerY INTEGER playerVelocityX INTEGER playerVelocityY Setup_SDL Setup_OpenGL Load_Bitmaps GameLoop { While (User hasn't Quit) { IF (User presses up) THEN playerVelocityY = - PLAYER_SPEED IF (User presses down) THEN playerVelocityY = PLAYER_SPEED IF (User presses left) THEN playerVelocityX = - PLAYER_SPEED IF (User presses right) THEN playerVelocityX = PLAYER_SPEED playerX = playerX + playerVelocityX playerY = playerY + playerVelocityY Render_Screen } }
Change BMP to PNG
Next step is to replace the BMP with a PNG
Some "gotchas"
- Add "IMG_Init(IMG_INIT_PNG);" to the program's startup code
- Replace "SDL_LoadBMP" with "IMG_Load"
- Add -lSDL_image on the compile line (Makefile or go script)
- Add required DLLs to the working directory (libpng12-0.dll, zlib1.dll, SDL_image.dll, etc)
- If the PNG will not display, try passing a BMP to IMG_Load to see if it works
Got SDL and OpenGL to accept the PNG image with transparency, but there are display issues:
PNG with transparency disabled, and background color saved. Basic image is correct, but some discoloration.
Got the non-transparent PNG to display correctly. The problem was with the glTeximage2D line. The "format" parameter was set to "GL_BGR" when it should have been "GL_RBG".
Apparently, changing the format parameter to GL_RBG (from GL_BGR) will make BMPs appear discolored (cyan for yellow).
Another interesting note I found was that all textures MUST be a power of 2 (2, 4, 8, 16, 32, 64, 128, 256, ...) in order to work with OpenGL.
Got the transparent PNG image to display correctly. I changed the "format" parameter in the glTeximage2D (noted above) to "GL_RBGA". However, the transparent pixels show up as white instead of the background color.
The image now displays correctly with transparency! I had to change the "internalformat" parameter for glTeximage2D from "3" to "GL_RBGA".
The methods glEnable(GL_ALPHA_TEST); and glAlphaFun(GL_GREATER, 0.5); must also be called to enable transparency.
Now I just need to write a standard method for generating textures, and I think I will be ready to integrate the code into the main game code.
Below is my test code:
#include "SDL.h" #include "SDL_image.h" #include "SDL_opengl.h" #include <stdio.h> void gameLoop(); void drawScene(); int iPlayerX = 0; int iPlayerY = 0; int iPlayerVelX = 0; int iPlayerVelY = 0; GLuint texture; GLuint texture_bkg; int main(int argc, char *argv[]) { SDL_Surface *screen; if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { printf("Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); screen = SDL_SetVideoMode( 1024, 768, 16, SDL_OPENGL ); IMG_Init(IMG_INIT_JPG|IMG_INIT_PNG); if ( !screen ) { printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } glClearColor( 0, 0, 0, 0 ); glEnable( GL_TEXTURE_2D ); // Need this to display a texture glViewport( 0, 0, 1024, 768 ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( 0, 1024, 768, 0, -1, 1 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5); SDL_Surface *surface; SDL_Surface *surface_bkg; // if ( (surface = SDL_LoadBMP("image.bmp")) ) { // if ( (surface = SDL_LoadBMP("tux.bmp")) ) { // if ( (surface = IMG_Load("tux.png")) ) { // if ( (surface = SDL_LoadBMP("tux1a.bmp")) ) { // if ( (surface = IMG_Load("tux1a.bmp")) ) { if ( (surface = IMG_Load("tux.png")) ) { glGenTextures( 1, &texture ); glBindTexture( GL_TEXTURE_2D, texture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); } else { printf("SDL could not load image: %s\n", SDL_GetError()); SDL_Quit(); return 1; } if ( surface ) { SDL_FreeSurface( surface ); } surface_bkg = SDL_LoadBMP("bkg.bmp"); glGenTextures(1, &texture_bkg); glBindTexture(GL_TEXTURE_2D, texture_bkg); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, 3, surface_bkg->w, surface_bkg->h, 0, GL_BGR, GL_UNSIGNED_BYTE, surface_bkg->pixels ); SDL_FreeSurface(surface_bkg); gameLoop(); glDeleteTextures( 1, &texture ); IMG_Quit(); SDL_Quit(); return 0; } void drawScene() { glClear( GL_COLOR_BUFFER_BIT ); glBindTexture( GL_TEXTURE_2D, texture_bkg ); glBegin( GL_QUADS ); glTexCoord2i( 0, 0 ); glVertex3f( 0, 0, 0 ); glTexCoord2i( 1, 0 ); glVertex3f( 1024, 0, 0 ); glTexCoord2i( 1, 1 ); glVertex3f( 1024, 768, 0 ); glTexCoord2i( 0, 1 ); glVertex3f( 0, 768, 0 ); glEnd(); glBindTexture( GL_TEXTURE_2D, texture ); glBegin( GL_QUADS ); glTexCoord2i( 0, 0 ); glVertex3f( iPlayerX, iPlayerY, 0 ); glTexCoord2i( 1, 0 ); glVertex3f( iPlayerX + 256, iPlayerY, 0 ); glTexCoord2i( 1, 1 ); glVertex3f( iPlayerX + 256, iPlayerY + 256, 0 ); glTexCoord2i( 0, 1 ); glVertex3f( iPlayerX, iPlayerY + 256, 0 ); glEnd(); SDL_GL_SwapBuffers(); } void gameLoop() { int iKeepLooping; SDL_Event event; iKeepLooping = 1; while (iKeepLooping) { while (SDL_PollEvent( &event) ) { switch(event.type) { case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_LEFT) { iPlayerVelX = -2; } if (event.key.keysym.sym == SDLK_RIGHT) { iPlayerVelX = 2; } if (event.key.keysym.sym == SDLK_UP) { iPlayerVelY = -2; } if (event.key.keysym.sym == SDLK_DOWN) { iPlayerVelY = 2; } if (event.key.keysym.sym == SDLK_q) { iKeepLooping = 0; } break; case SDL_KEYUP: iPlayerVelX = 0; iPlayerVelY = 0; break; } } iPlayerX += iPlayerVelX; iPlayerY += iPlayerVelY; drawScene(); } }