OpenGL and SDL

Dave
Unregistered
 
Post: #1
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!
Quote this message in a reply
Dave
Unregistered
 
Post: #2
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.
Quote this message in a reply
KidTsunami
Unregistered
 
Post: #3
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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
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.
Quote this message in a reply
Dave
Unregistered
 
Post: #5
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.
Quote this message in a reply
KidTsunami
Unregistered
 
Post: #6
When you say Z Buffer, you mean how far they are from the screen right? Can I do this with an ortho projection?
Quote this message in a reply
Dave
Unregistered
 
Post: #7
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]
Quote this message in a reply
Member
Posts: 233
Joined: 2003.05
Post: #8
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

"Pay no attention to that man behind the curtain." - Wizard of Oz
Quote this message in a reply
Dave
Unregistered
 
Post: #9
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
Quote this message in a reply
Member
Posts: 233
Joined: 2003.05
Post: #10
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. Wacko

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
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #11
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).
Quote this message in a reply
Dave
Unregistered
 
Post: #12
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 Cool
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #13
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.

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;
}
Quote this message in a reply
Dave
Unregistered
 
Post: #14
Thanks OSC, that's exactly what I needed.
Quote this message in a reply
Post Reply