OpenGL and SDL
Hi, I'm new to SDL and wonder if anyone has some links to some good tutorials on using OpenGL with SDL (setting up a fullscreen OpenGL surface, loading a texture to ABRG or whatever that format it is that NVidia and ATI cards use natively. Can't remember off hand. That sort of thing). I've got a project all setup, the only problem is getting SDL and OpenGL to work together nicely =).
Also, I'd like to load a height map from a PNG, but I have no idea how I'd get the raw pixel data (assuming 8 or 16-bit greyscale) in a nice, useable format (like an array, or pointer). If anyone has any thoughts on this, I'd really appreciate it. Oh, it should be noted I'm also planning on using 32-bit PNGs for textures as well. Thanks!
Also, I'd like to load a height map from a PNG, but I have no idea how I'd get the raw pixel data (assuming 8 or 16-bit greyscale) in a nice, useable format (like an array, or pointer). If anyone has any thoughts on this, I'd really appreciate it. Oh, it should be noted I'm also planning on using 32-bit PNGs for textures as well. Thanks!
Oh, also, would Allegro be a possible alternative? From what I've heard, its input and sound APIs are a good deal more robust and useable than SDLs, but I am unsure if it supports the use of an OpenGL 'surface' or whatever its called under Allegro.
Hey, Dave, I'm trying to work with openGL and SDL also. I did find some tutorials at http://www.gametutorials.com . But I'm trying to do 2D games, and I don't know if I should use textures or just glDrawPixels.
Textures will almost always be faster than glDrawPixels, and they're faster.
I don't know much about SDL, but I think you'll have to create a surface with a good pixel format (eg 32-bit RGBA direct, rowbytes = 4 * width), load your image into another surface (eg with SDL_image), blit to the good surface, and then texture from that.
I don't know much about SDL, but I think you'll have to create a surface with a good pixel format (eg 32-bit RGBA direct, rowbytes = 4 * width), load your image into another surface (eg with SDL_image), blit to the good surface, and then texture from that.
KidTsunami, I'd suggest using textured quads. That way you'll be able to use the z buffer for layers, and rotate/scale all your sprites. And it will be faster than GLDrawpixels I think.
When you say Z Buffer, you mean how far they are from the screen right? Can I do this with an ortho projection?
Absolutely! It works great for assinging sprites a layer. With orthoprojection, the z-buffer won't change a thing except which sprites will be drawn over other sprites. You could have a base layer where z = 0, and then a layer above that (z = 1) etc.
If you have some sort of sprite class or struct, its usually easiest to do something like this:
[SOURCECODE]gltranslatef(sprite.x, sprite.y, sprite.layer);[/SOURCECODE]
Works like a charm. Assuming you don't already know, the way I usually draw sprites is like this(a function DrawSprite of a sprite class):
[SOURCECODE]
glPushMatrix(); //Save matrix
glTranslatef(x, y, layer); //Position Sprite
glRotate(rotation, 0, 0, 1); //Rotate Sprite
glBindTexture(GL_TEXTURE_2D, imageref); //Bind a preloaded texture to quad
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0);
glVertex2f(width/2, height/2);
glTexCoord2f(1.0, 0.0);
glVertex2f(-1*(width/2), height/2);
glTexCoord2f(1.0, 1.0);
glVertex2f(-1*(width/2), -1*(height/2));
glTexCoord2f(0.0, 1.0);
glVertex2f(width/2, -1*(height/2));
glEnd();
glPopMatrix(); //Restore Matrix
[/SOURCECODE]
If you have some sort of sprite class or struct, its usually easiest to do something like this:
[SOURCECODE]gltranslatef(sprite.x, sprite.y, sprite.layer);[/SOURCECODE]
Works like a charm. Assuming you don't already know, the way I usually draw sprites is like this(a function DrawSprite of a sprite class):
[SOURCECODE]
glPushMatrix(); //Save matrix
glTranslatef(x, y, layer); //Position Sprite
glRotate(rotation, 0, 0, 1); //Rotate Sprite
glBindTexture(GL_TEXTURE_2D, imageref); //Bind a preloaded texture to quad
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0);
glVertex2f(width/2, height/2);
glTexCoord2f(1.0, 0.0);
glVertex2f(-1*(width/2), height/2);
glTexCoord2f(1.0, 1.0);
glVertex2f(-1*(width/2), -1*(height/2));
glTexCoord2f(0.0, 1.0);
glVertex2f(width/2, -1*(height/2));
glEnd();
glPopMatrix(); //Restore Matrix
[/SOURCECODE]
Check out the http://nehe.gamedev.net site.
You want to look at the tutorials, and make sure you download the linux/SDL versions.
You should be able to glean a ton of information from those tuts.
Also, check out my response to KidTsunami's similar post here
About Allegro. It's JUST being ported to MacOS X and is close to release judging from posts on this forum. Unfortunately, OpenGL support is an entire other project and will be a bit further off.
If you want to make progress NOW, use SDL and OpenGL and keep an eye on Allegro's site.
Aaron
You want to look at the tutorials, and make sure you download the linux/SDL versions.
You should be able to glean a ton of information from those tuts.
Also, check out my response to KidTsunami's similar post here
About Allegro. It's JUST being ported to MacOS X and is close to release judging from posts on this forum. Unfortunately, OpenGL support is an entire other project and will be a bit further off.
If you want to make progress NOW, use SDL and OpenGL and keep an eye on Allegro's site.
Aaron
"Pay no attention to that man behind the curtain." - Wizard of Oz
Hey, thanks. I didn't even realize there was anything using SDL on NeHe.
If anyone has some code on opening the PNG format and converting it to a usuable format (much like targa loading code, put in a PNG, spit out height, width, and the data in an array or whatever). Featurewise, targa has what I need (alpha channels) but they're just so big. Hopefully I can switch over to PNG at a later date. Thanks again,
Dave
If anyone has some code on opening the PNG format and converting it to a usuable format (much like targa loading code, put in a PNG, spit out height, width, and the data in an array or whatever). Featurewise, targa has what I need (alpha channels) but they're just so big. Hopefully I can switch over to PNG at a later date. Thanks again,
Dave
I guess using libPNG is the way to go, but I haven't tried. (It's the official library for PNG files and is cross-platform)
Unfortunately, it requires zlib, and just thinking about including all these libraries gives me a headache.
Let me know if you have success with it, because I'll eventually want to try it myself.
Unfortunately, it requires zlib, and just thinking about including all these libraries gives me a headache.

Let me know if you have success with it, because I'll eventually want to try it myself.
"Pay no attention to that man behind the curtain." - Wizard of Oz
zlib is included with Mac OS X, so using libPNG isn't a problem. It's not a very nice API, though. If this is the way you want to go, I can probably dig some code out...
If you don't mind being mac-only, you can use QuickTime to load textures, and if you're using SDL, you can use SDL_image (see the other two recent threads on the subject of texturing from an SDL_Surface).
If you don't mind being mac-only, you can use QuickTime to load textures, and if you're using SDL, you can use SDL_image (see the other two recent threads on the subject of texturing from an SDL_Surface).
I think I'll look into using libPNG. If you're willing to pull out that code you had laying around, that would be great
It's a long time since I touched this, but from memory it loads any PNG image into a 32-bit RGBA texture with mipmaps. It's basically the libPNG sample code in an OpenGL setting...
wrap_s and wrap_t are like GL_CLAMP_TO_EDGE_SGIS or GL_REPEAT or whatever.
wrap_s and wrap_t are like GL_CLAMP_TO_EDGE_SGIS or GL_REPEAT or whatever.
Code:
#include <stdlib.h>
#include <png.h>
static int ST_is_power_of_two(unsigned int number)
{
return (number & (number - 1)) == 0;
}
#define ST_PNG_HEADER_SIZE 8
GLuint ST_load_texture(const char* name, GLenum wrap_s, GLenum wrap_t)
{
FILE *PNG_file = fopen(name, "rb");
if (PNG_file == NULL)
{
return 0;
}
GLubyte PNG_header[ST_PNG_HEADER_SIZE];
fread(PNG_header, 1, ST_PNG_HEADER_SIZE, PNG_file);
if (png_sig_cmp(PNG_header, 0, ST_PNG_HEADER_SIZE) != 0)
{
return 0;
}
png_structp PNG_reader
= png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (PNG_reader == NULL)
{
fclose(PNG_file);
return 0;
}
png_infop PNG_info = png_create_info_struct(PNG_reader);
if (PNG_info == NULL)
{
png_destroy_read_struct(&PNG_reader, NULL, NULL);
fclose(PNG_file);
return 0;
}
png_infop PNG_end_info = png_create_info_struct(PNG_reader);
if (PNG_end_info == NULL)
{
png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
fclose(PNG_file);
return 0;
}
if (setjmp(png_jmpbuf(PNG_reader)))
{
png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
fclose(PNG_file);
return (0);
}
png_init_io(PNG_reader, PNG_file);
png_set_sig_bytes(PNG_reader, ST_PNG_HEADER_SIZE);
png_read_info(PNG_reader, PNG_info);
png_uint_32 width, height;
width = png_get_image_width(PNG_reader, PNG_info);
height = png_get_image_height(PNG_reader, PNG_info);
png_uint_32 bit_depth, color_type;
bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
color_type = png_get_color_type(PNG_reader, PNG_info);
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
png_set_palette_to_rgb(PNG_reader);
}
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
{
png_set_gray_1_2_4_to_8(PNG_reader);
}
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
png_set_gray_to_rgb(PNG_reader);
}
if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
{
png_set_tRNS_to_alpha(PNG_reader);
}
else
{
png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
}
if (bit_depth == 16)
{
png_set_strip_16(PNG_reader);
}
png_read_update_info(PNG_reader, PNG_info);
png_byte* PNG_image_buffer = (png_byte*)malloc(4 * width * height);
png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));
unsigned int row;
for (row = 0; row < height; ++row)
{
PNG_rows[height - 1 - row] = PNG_image_buffer + (row * 4 * width);
}
png_read_image(PNG_reader, PNG_rows);
free(PNG_rows);
png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
fclose(PNG_file);
if (!ST_is_power_of_two(width) || !ST_is_power_of_two(height))
{
free(PNG_image_buffer);
return 0;
}
GLuint texture_ID;
glGenTextures(1, &texture_ID);
glBindTexture(GL_TEXTURE_2D, texture_ID);
gluBuild2DMipmaps(GL_TEXTURE_2D,
GL_RGBA,
width,
height,
GL_RGBA,
GL_UNSIGNED_BYTE,
PNG_image_buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
free(PNG_image_buffer);
return texture_ID;
}
