SDL_Surface to OpenGL Texture Corruption

Nibbie
Posts: 3
Joined: 2007.06
Post: #1
Recently I made a function that loaded a bitmap, and converted it to a texture in OpenGL, where everything that was "magic pink" (255, 0, 255) was transparent. From there, I wanted to use this to make a simple monospace font function.

For some reason, I have used the same/similar code yet I get different results when I use arrays. I am not sure if this is due to SDL or OpenGL. I have been getting help from Joseph Duchesne, and we can't seem to figure it out. So he told me this was the place to go. Wow

This is the struct for the monospace font:
Code:
struct MonoFont
{
    int glyph_width;
    int glyph_height;
    int glyph_tex_width;
    int glyph_tex_height;
    GLuint glyphs[128];
};

This function loads the bitmap (used this code for the bmp loader function..works fine on that. The only real difference is that this function uses arrays)
Code:
MonoFont LoadBmpFont(char *filename)
{
    MonoFont Temp;
    
    SDL_Surface *FullFont;
    FullFont = SDL_LoadBMP(filename);

    Temp.glyph_width = FullFont->w / 16;
    Temp.glyph_height = FullFont->h / 6;
    Temp.glyph_tex_width = NextPowerOfTwo(Temp.glyph_width);
    Temp.glyph_tex_height = NextPowerOfTwo(Temp.glyph_height);

    SDL_Surface *GlyphSurfaces[128];

    #if SDL_BYTEORDER == SDL_LIL_ENDIAN
        for(int i=0; i<128; i++)
        {
            GlyphSurfaces[i] = SDL_CreateRGBSurface(SDL_SWSURFACE, Temp.glyph_tex_width,
                Temp.glyph_tex_height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
        }
    #else
        for(int i=0; i<128; i++)
        {
            GlyphSurfaces[i] = SDL_CreateRGBSurface(SDL_SWSURFACE, Temp.glyph_tex_width,
                Temp.glyph_tex_height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
        }
    #endif

    Uint32 ColorKey;
    
    for(int i=0; i<128; i++)
    {
        ColorKey = SDL_MapRGBA(GlyphSurfaces[i]->format, 255, 0, 255, 0);
        SDL_FillRect(GlyphSurfaces[i], 0, ColorKey);
    }

    ColorKey = SDL_MapRGBA(FullFont->format, 255, 0, 255, 0);
    SDL_SetColorKey(FullFont, SDL_SRCCOLORKEY, ColorKey);

    SDL_Rect source;
    source.x = 0;
    source.y = 0;
    source.w = Temp.glyph_width;
    source.h = Temp.glyph_height;

    SDL_Rect dest;
    dest.x = 0;
    dest.y = 0;
    dest.w = Temp.glyph_width;
    dest.h = Temp.glyph_height;

    for(int i=32; i<128; i++)
    {
        SDL_BlitSurface(FullFont, &source, GlyphSurfaces[i], &dest);
    
        source.x += 8;
        if(source.x == 128)
        {
            source.x = 0;
            source.y += 12;
        }
    }

    for(int i=32; i<128; i++)
    {
        glGenTextures(1, &Temp.glyphs[i]);
        glBindTexture(GL_TEXTURE_2D, Temp.glyphs[i]);

        // Todo: Figure out what parameters I need here:
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        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, Temp.glyph_tex_width, Temp.glyph_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, GlyphSurfaces[i]->pixels);
    }

        // Test output of one glyph..is this the problem? -Nope.
    SDL_SaveBMP(GlyphSurfaces[82], "char.bmp");
    return Temp;
}

Finally, I output the text with this function:
Code:
void DrawText(MonoFont font, int x, int y, char *text, ...)
{
    char FullText[1024];
    va_list ParseVars;
    va_start(ParseVars, text);
    vsprintf(FullText, text, ParseVars);
    va_end(ParseVars);

    int ascii;
    int glyph_x = x;

    for(int i=0; i<(int)strlen(text); i++)
    {
        ascii = (int)FullText[i];

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, font.glyphs[ascii]);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0, 0.0);        glVertex2i(glyph_x, y);
            glTexCoord2f(1.0, 0.0);        glVertex2i(glyph_x + font.glyph_tex_width, y);
            glTexCoord2f(1.0, 1.0);        glVertex2i(glyph_x + font.glyph_tex_width, y+font.glyph_tex_height);
            glTexCoord2f(0.0, 0.0);        glVertex2i(glyph_x, y+font.glyph_tex_height);
        glEnd();
        glDisable(GL_TEXTURE_2D);

        glyph_x += font.glyph_width;
    }
}

An interesting thing I found is that the corruption looks different on different machines..so I am not too sure what the problem could be. Any ideas? I'd really appreciate it!

p.s: Here is what the corruption looks like, (on my machine). As you can sorta tell it is supposed to read "Hello World!".
[Image: blahaj9.png]

Thanks for your time!

Edit: Oops, I forgot to mention. I fooled around with outputting some of the SDL_Surfaces to see if that was the problem, but it turns out they all look how they should (when I save them to a bmp during runtime).
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #2
I remember having all sorts of annoying problems getting SDL surfaces to load into OpenGL textures. One possibility is that SDL could be padding the end of each image row. (the 'pitch' field) Don't have the Red Book handy, but there is a function you can call to tell OpenGL about it.

My recommendation though is that loading textures from SDL surfaces just isn't worth the effort. Code for loading PNGs or JPEGs from their respective libraries are not difficult, it just takes a little manual reading. They are also ultimately much faster and more flexible.

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
Nibbie
Posts: 3
Joined: 2007.06
Post: #3
Thanks for the suggestion, Skorche. As for the pitch field, someone on Gamedev.net suggested the same thing. I placed that in the code though, with the same corrupted effect.

I used this:
Code:
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
glPixelStorei(GL_UNPACK_ROW_LENGTH, GlyphSurfaces[i]->pitch / GlyphSurfaces[i]->format->BytesPerPixel);

...

glPopClientAttrib();

As for your other suggestion, I would drop using SDL_Surfaces, if not for the fact if I have it implemented perfectly in another place in my code. I use this code to load a bitmap and make any pixel that is RGB (255, 0, 255) have an alpha value of 0, thus making it transparent.

Code:
Texture LoadBmp(char *filename)
{
    Texture Temp;

    SDL_Surface *bitmap;
    bitmap = SDL_LoadBMP(filename);

    Temp.width = bitmap->w;
    Temp.height = bitmap->h;
    Temp.tex_width = NextPowerOfTwo(bitmap->w);
    Temp.tex_height = NextPowerOfTwo(bitmap->h);

    SDL_Surface *image;
    image = SDL_CreateRGBSurface(SDL_SWSURFACE, Temp.tex_width, Temp.tex_height, 32,
        #if SDL_BYTEORDER == SDL_LIL_ENDIAN
            0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
        #else
            0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
        #endif
        );

    if(image == NULL)
    {
        WriteToLog("Error: Could not create image.");
        return Temp;
    }

    Uint32 ColorKey;
    ColorKey = SDL_MapRGBA(image->format, 255, 0, 255, 0);
    SDL_FillRect(image, 0, ColorKey);

    ColorKey = SDL_MapRGBA(bitmap->format, 255, 0, 255, 0);
    SDL_SetColorKey(bitmap, SDL_SRCCOLORKEY, ColorKey);

    SDL_Rect area;
    area.x = 0;
    area.y = 0;
    area.w = bitmap->w;
    area.h = bitmap->h;

    SDL_BlitSurface(bitmap, &area, image, &area);

    glGenTextures(1, &Temp.id);
    glBindTexture(GL_TEXTURE_2D, Temp.id);

    // Todo: Figure out what parameters I need here:
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    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, Temp.tex_width, Temp.tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);

    SDL_FreeSurface(bitmap);
    SDL_FreeSurface(image);

    return Temp;
}

If you compare the two, you can see how the font code and the bitmap code are pretty much the same thing. I am really happy with the bitmap code, I just am frustrated that I cannot make it work with the font code. I am just hoping there is a stupid mistake that I am not catching. Annoyed
Quote this message in a reply
Nibbie
Posts: 3
Joined: 2007.06
Post: #4
I am a dolt.

Code:
glBegin(GL_QUADS);
            glTexCoord2f(0.0, 0.0);        glVertex2i(glyph_x, y);
            glTexCoord2f(1.0, 0.0);        glVertex2i(glyph_x + font.glyph_tex_width, y);
            glTexCoord2f(1.0, 1.0);        glVertex2i(glyph_x + font.glyph_tex_width, y+font.glyph_tex_height);
            glTexCoord2f(0.0, 0.0);        glVertex2i(glyph_x, y+font.glyph_tex_height);
        glEnd();

The last tex coord is supposed to be: glTexCoord2f(0.0, 1.0); Thanks for all your help...I cannot believe this bug took 5 days to find Rasp. Thanks to Joseph Duchesne!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL ES Texture Masking airfire 6 14,419 Mar 17, 2014 07:07 PM
Last Post: baioses
  OpenGL ES Texture Compression ajrs84 9 3,785 May 7, 2013 03:36 PM
Last Post: ajrs84
  OpenGL ES Texture Masking dalasjoe sin 0 3,786 Apr 13, 2012 12:17 AM
Last Post: dalasjoe sin
  Texture in OpenGL ES 2 looks pixelated vunterslaush 18 22,629 Aug 30, 2011 09:44 PM
Last Post: Frogblast
  Lighting and changing texture colors in OpenGL agreendev 2 7,548 Aug 13, 2010 03:47 PM
Last Post: agreendev