Copyright Tristan Aubrey-Jones January 2008.
This is an example OpenGL SDL application which creates an animated 3D underwater world (screenshot), with "Thunderbird 4" with headlights moving on a spline path, a randomly generated sand terrain, sunken ship/submarine/treasure chest models, and swaying fish and seaweed. It is designed to demonstrate basic OpenGL features, and the structure is as follows:
#include "textures.h"
// load an SDL surface into an OpenGL texture.
GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord);
// constructor
// opens an image file and stores it in memory
Texture::Texture(const char *file)
{
// load image file
SDL_Surface *surface = IMG_Load(file);
// create opengl texture
GLfloat texcoord[4];
tex = SDL_GL_LoadTexture(surface, texcoord);
minx = texcoord[0];
miny = texcoord[1];
maxx = texcoord[2];
maxy = texcoord[3];
// delete sdl image
SDL_FreeSurface(surface);
}
// destructor
Texture::~Texture()
{
GLuint ts[] = { tex };
glDeleteTextures( 1, &tex );
}
/* Taken from texture.c in example on shaders COMP3004 website
* -------------------------------------------------------------------
* QUOTE STARTS
* ------------------------------------------------------------------/
/*
Return power of 2 greater than input.
*/
static int power_of_two(int input)
{
int value = 1;
while ( value < input ) {
value <<= 1;
}
return value;
}
/*
Load an SDL surface into an OpenGL texture.
*/
GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord)
{
GLuint texture;
int w, h;
SDL_Surface *image;
SDL_Rect area;
Uint32 saved_flags;
Uint8 saved_alpha;
static GLint texture_base = 0;
w = power_of_two(surface->w);/* Use the surface width and height expanded to powers of 2 */
h = power_of_two(surface->h);
texcoord[0] = 0.0f; /* Min X */
texcoord[1] = 0.0f; /* Min Y */
texcoord[2] = (GLfloat)surface->w / w; /* Max X */
texcoord[3] = (GLfloat)surface->h / h; /* Max Y */
image = SDL_CreateRGBSurface(
SDL_SWSURFACE,
w, h,
32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
if ( image == NULL ) {
return 0;
}
/* Save the alpha blending attributes */
saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
saved_alpha = surface->format->alpha;
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
SDL_SetAlpha(surface, 0, 0);
}
/* Copy the surface into the GL texture image */
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);
/* Restore the alpha blending attributes */
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
SDL_SetAlpha(surface, saved_flags, saved_alpha);
}
//SDL_SetColorKey(image, SDL_SRCCOLORKEY, SDL_MapRGB(image->format, 0, 186, 171));
//SDL_SetAlpha(image, SDL_RLEACCEL|SDL_SRCALPHA, 50);
/* Create an OpenGL texture for the image */
// glGenTextures(1, &texture); // generate a texture number
texture = texture_base;
texture_base++;
glBindTexture(GL_TEXTURE_2D, texture); //Map specific texture to the 2D texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
w, h,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image->pixels);
return texture;
}
/*
* ------------------------------------------------------------------
* QUOTE ENDS
* ------------------------------------------------------------------
*/