Meshing OpenGL and SDL

Jones
Unregistered
 
Post: #1
I've decided to try and integrate SDL and OpenGL in all further project of mine, due to the fact that I've heard SDL is far too slow to blit on the PowerPC architecture and non-functioning on the intel one. I'm not gonna continue to use something that is slow, and limited for future projects. This comes as a real kick in the pants as I was just finishing up my (hopefully fancy) collision system for SDL surfaces. Mad

Oh well, I need some resources to start off. I've googled converting SDL surfaces to OpenGL textures (those I never understood Wacko) because I would like to take advantage of the SDL image loading functions, if not the drawing ones. I got this:

http://osdl.sourceforge.net/OSDL/OSDL-0....penGL.html

Which unfortunatly links to some non-existant files. Rather than use a library, I'd like to learn how to swap materials between OpenGL and SDL myself. "Programming Linux Games" tells you how to declare an SDL/OpenGL context, but nothing else.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
getting data from SDL_image to an OpenGL texture is difficult, error-prone, potentially inefficent, and unlikely to be future-proof. I recommend using libjpeg and libpng directly if you want cross-platform code, or following Apple's advice if you want something easy.
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #3
Not sure I agree with all of that, except perhaps the inefficient part.

Using SDL_ConvertSurface() you can convert to any arbitrary pixel format. The only difficulty is creating the format structure, which is somewhat tedious to fill in all the fields for both endians. The downside is that it is slow.

http://www.libsdl.org/cgi/docwiki.cgi/SD...ertSurface

Format for creating to straight RGBA.
Code:
    RGBAFormat.palette = 0; RGBAFormat.colorkey = 0; RGBAFormat.alpha = 0;
    RGBAFormat.BitsPerPixel = 32; RGBAFormat.BytesPerPixel = 4;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    RGBAFormat.Rmask = 0xFF000000; RGBAFormat.Rshift =  0; RGBAFormat.Rloss = 0;
    RGBAFormat.Gmask = 0x00FF0000; RGBAFormat.Gshift =  8; RGBAFormat.Gloss = 0;
    RGBAFormat.Bmask = 0x0000FF00; RGBAFormat.Bshift = 16; RGBAFormat.Bloss = 0;
    RGBAFormat.Amask = 0x000000FF; RGBAFormat.Ashift = 24; RGBAFormat.Aloss = 0;
#else
    RGBAFormat.Rmask = 0x000000FF; RGBAFormat.Rshift = 24; RGBAFormat.Rloss = 0;
    RGBAFormat.Gmask = 0x0000FF00; RGBAFormat.Gshift = 16; RGBAFormat.Gloss = 0;
    RGBAFormat.Bmask = 0x00FF0000; RGBAFormat.Bshift =  8; RGBAFormat.Bloss = 0;
    RGBAFormat.Amask = 0xFF000000; RGBAFormat.Ashift =  0; RGBAFormat.Aloss = 0;
#endif

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Moderator
Posts: 702
Joined: 2002.04
Post: #4
Jones Wrote:I've heard SDL is [...] non-functioning on intel.

As far as I remember, SDL was one of the first libraries to have its name on the whiteboard of Universal Binaries at WWDC...Huh
Here's the announcement of preliminary Universal Binaries of SDL...

Mark Bishop
--
Student and freelance OS X & iOS developer
Quote this message in a reply
Member
Posts: 131
Joined: 2004.10
Post: #5
I don't really agree with OSC. It shouldn't be all that difficult, error prone or future challenged to convert an SDL surface to an OpenGL texture. Depending on how you do it, it may not be that inefficient. It will definitely be one more step though instead of from direct image read to OpenGL it'll be Image read to SDL and then to OpenGL. However if you only do it once at initialization, the hit may be forgivable to, hardly noticeable.

SDL_ConvertSurface may be a way but generally I would just gather the pixel information from the SDL_Surface to populate the OpenGL image.

I've actually written a simple function to convert from SDL image to OpenGL texture/image buffer. It wasn't hard at all. But yeah, it could also be made more efficient as I just kept it simple. I'll have to wait till I get home to post the code but most of it was gathered from discussions on the SDL mailing list or from the Nehe SDL based tutorials. I can't remember.

You could probably do a simple one easily enough. Pick up that 'getpixel' function for the SDL doc and use that to get at the pixel information in the SDL image/surface. Then move that data one pixel at a time to the OpenGL image buffer. I think that's pretty much what I did. Simple and it works and plenty or room for optimization 'if needed'.

But reading in an image directly using libpng or libjpeg and pushing that off to OpenGL isn't all that difficult either. But if you intend to use SDL anyway for the window setup, image handling, event handling etc. then going through the slight pain of writing and debugging your own png or jpg loader may be more annoying than just using the loaders in SDL.
Quote this message in a reply
Member
Posts: 131
Joined: 2004.10
Post: #6
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #7
Zekaric Wrote:Or try this...

http://www.libsdl.org/cgi/docwiki.cgi/Op..._20Example

I would be a bit worried about the "future proof"-ness of that though. While unlikely, it's possible that you could be handed some weird packed format that is 24 or 32 bpp. Also, would that even be endian safe? I'm not sure. It would might probably choke on 8bit PNGs. I don't know how SDL_image handles them.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 131
Joined: 2004.10
Post: #8
Yeah I noticed that as well. SDL doesn't really deal with odd bit packing but endianess 'could 'be an issue. Although OpenGL should handle BGR or RGB (And the A versions as well) so it might not be too bad but I remember some drivers not being too happy with certain color orders. But again, it's not that hard to get to the pixel information of an SDL surface and transfering that to a known OpenGL image format.

As far as 8 bit PNGs, it will depend on how you load the data and the desired format of the loaded data. libpng can be told to augment the 8 bit to 24 bit so I can only assume that SDL_Image would/could do the same.
Quote this message in a reply
Jones
Unregistered
 
Post: #9
Skorche Wrote:Not sure I agree with all of that, except perhaps the inefficient part.

Using SDL_ConvertSurface() you can convert to any arbitrary pixel format. The only difficulty is creating the format structure, which is somewhat tedious to fill in all the fields for both endians. The downside is that it is slow.

http://www.libsdl.org/cgi/docwiki.cgi/SD...ertSurface

Format for creating to straight RGBA.
Code:
    RGBAFormat.palette = 0; RGBAFormat.colorkey = 0; RGBAFormat.alpha = 0;
    RGBAFormat.BitsPerPixel = 32; RGBAFormat.BytesPerPixel = 4;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    RGBAFormat.Rmask = 0xFF000000; RGBAFormat.Rshift =  0; RGBAFormat.Rloss = 0;
    RGBAFormat.Gmask = 0x00FF0000; RGBAFormat.Gshift =  8; RGBAFormat.Gloss = 0;
    RGBAFormat.Bmask = 0x0000FF00; RGBAFormat.Bshift = 16; RGBAFormat.Bloss = 0;
    RGBAFormat.Amask = 0x000000FF; RGBAFormat.Ashift = 24; RGBAFormat.Aloss = 0;
#else
    RGBAFormat.Rmask = 0x000000FF; RGBAFormat.Rshift = 24; RGBAFormat.Rloss = 0;
    RGBAFormat.Gmask = 0x0000FF00; RGBAFormat.Gshift = 16; RGBAFormat.Gloss = 0;
    RGBAFormat.Bmask = 0x00FF0000; RGBAFormat.Bshift =  8; RGBAFormat.Bloss = 0;
    RGBAFormat.Amask = 0xFF000000; RGBAFormat.Ashift =  0; RGBAFormat.Aloss = 0;
#endif


Thanks for providing that formatting stuff, but I have no idea how to use it. Smile Must it be converted to an array of sorts for use as the *format argument?

I'm also looking into libpng. Which ever makes things faster, I will use.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
Skorche's method is certainly safe and future-proof. It will still be inefficient, though.
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #11
I make no claims that it will be fast, but it hasn't been a problem yet for me.

In response to your question, RGBAFormat is just a variable of type SDL_PixelFormat that you would pass to SDL_ConvertSurface().

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Jones
Unregistered
 
Post: #12
Ok, now I see. It has become clear.

After experimenting with SDL & OpenGL together, I realize that it's much easier/faster to get OpenGL going with GLUT. Could I use GLUT for the window stuff and SDL for sound/networking/input?

Thanks!

Eh: What is "endian"? (Perhaps this is a stupid question).

I went and checked zekaric's method, it appears to support only 24 and 32 bit pictures, which is fine. Nobody wants to look at 16 bit graphics anymore. But what kind of futur-un-proofness would I encounter?
Quote this message in a reply
Jones
Unregistered
 
Post: #13
Ah, I'm guessing from the errors I'm getting, the answer is no. Darn.
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #14
I'm guessing that you will have serious problems using GLUT and SDL. For one, I think you need an SDL window open to get key and mouse events. There really isn't much to make it work, the only difference is that you would pass a couple of parameters about your OpenGL context and add an extra flag when opening the window.

Code:
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
    SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);

    Uint32 videoflags = SDL_OPENGL;
    if(fullscreen) videoflags |= SDL_FULLSCREEN;
    
    if (SDL_SetVideoMode(w, h, 0, videoflags) == NULL) {
        fprintf(stderr, "SDL_error: %s\n", SDL_GetError());
        exit(1);
    }

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #15
Jones Wrote:Eh: What is "endian"? (Perhaps this is a stupid question).
Not at all.

Roughly speaking, endianness is the order in which a CPU interprets bytes and/or bits in primitive data types. The PowerPC architecture is what's known as big-endian, and the Intel architecture is known as little-endian. What this means:

Take an int, 0x12345678, for example. On a big-endian architecture, this number is represented in physical memory as 0x12, 0x34, 0x56, 0x78. On a little-endian architecture, on the other hand, it's represented as 0x78, 0x56, 0x34, 0x12.

When you're writing cross-platform or cross-architecture code, what this means is that you have to take endianness into consideration when manipulating certain data at a byte level. It's usually as easy as doing a conditional byte reordering in any file I/O or networking code. Something like this:
Code:
// swapInt32 reverses the order of bytes in a 32-bit integer
#define swapInt32(int32) ((((int32) << 24) & 0xFF000000) | (((int32) << 8) & 0x00FF0000) | (((int32) >> 8) & 0x0000FF00) | (((int32) >> 24) | 0x000000FF))

#if defined(__BIG_ENDIAN__)

#define swapInt32Big(int32) (int32)
#define swapInt32Little(int32) swapInt32(int32)

#elif defined(__LITTLE_ENDIAN__)

#define swapInt32Big(int32) swapInt32(int32)
#define swapInt32Little(int32) (int32)

#else
#error Unknown endianness
#endif

...

// Reading big-endian value
fread(int32, sizeof(int32), 1, file);
myValue = swapInt32Big(int32);

// Reading little-endian value
fread(int32, sizeof(int32), 1, file);
myValue2 = swapInt32Little(int32);

// Writing values
int32 = swapInt32Big(myValue);
fwrite(int32, sizeof(int32), 1, file);
int32 = swapInt32Little(myValue2);
fwrite(int32, sizeof(int32), 1, file);
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Meshing MDD and Obj OptimisticMonkey 0 3,444 May 3, 2011 06:25 PM
Last Post: OptimisticMonkey