0

I'm trying to render text using SDL_ttf and openGL.

I open the font and render the text to an SDL_Surface and then attached that surface to a texture and bind it for openGL to render it.

I have googled this issue a bunch and not getting many hits which would lead me to believe I'm understand something.

The only two functions that matter since I've pretty much made a temp variable to trouble shoot this issue. They are:

SDL_Surface* CFont::BlendedUTF8Surface() {
    SDL_Surface* Surf_Text;
    SDL_Color Blah;
    Blah.r = 0;
    Blah.b = 255;
    Blah.g = 0;
    if(!(Surf_Text = TTF_RenderUTF8_Blended(pFont,TxtMsg,Blah))) {
        char str[256];
        sprintf_s(str, "? %s \n", TTF_GetError());
        OutputDebugString(str);
    }
    return Surf_Text;

}

This uses SDL_ttf to render the text to the Surf_Text surface. You can see I've maxed the blue channel. I'll talk about this in a minute. Here is the rendering

void CLabel::OnRender(int xOff,int yOff) {

    if(Visible) {
        glColor4f(1.0,1.0,1.0,1.0);
        Font.Color(FontColors.r, FontColors.g, FontColors.b); //useless I overwrote the variable with Blah to test this
        SDL_Surface* Surf_Text; 
        Surf_Text = Font.BlendedUTF8Surface();
        Text_Font.OnLoad(Surf_Text);
        Text_Font.RenderQuad(_X+xOff,_Y+yOff);
        SDL_FreeSurface(Surf_Text);
        glColor4f(0.0,0.0,0.0,1.0);
    }
}

Alright, so far from what I can tell, the problem is probably coming from the current color state and the texture environment mode.

When I render the text in this fashion, the text will change colors but it's like the R and B channels have swtiched. If I make red 255, the text is blue and if I make blue 255, the text is red. Green stays green (RGB vs BGR ?).

If I remove the glColor4f call in the rendering function, the text refused to render colored at all. Always black (I habitually set the color back to (0,0,0) everytime I render someething, so possible since the mode is modulate (R = 0 * Texture (Font) R, etc) so it will be black. Makes sense.

If I set the Texture environment to DECAL then the text renders black and a box behind the text renders the color I am trying to render the text.

I think I just don't know the correct way to do this. Anyone have any experience with SDL_ttf and openGL texture environments that could give some ideas?

Edit:

I've done some rewriting of the functions and testing the surface and have finally figured out a few things. If I use GL_DECAL the text renders the correct color and the pixel values value is 0 everywhere on the surface where it's not the red color I tried rendering (which renders with a value of 255, which is strange since red is the first channel it should have been 255^3 (or in terms of hex FF0000) at least I would expect). With DECAL, the alpha space (the white space around the text that has 0 for a pixel value) shows up the color of the current glColor() call. If I use Blended, the alpha zone disappears but my text renders as blended as well (of course) so it blends with the underlying background texture.

I guess the more appropriate question is how to I blend only the white space and not the text? My guess is that I could call a new glBlendFunc(); but I have tested parameters and I'm like a child in the woods. No clue how to get the desired result.

Solution isn't completely verified, but the format of the surface is indeed BGRA but I cannot implement this correction. I'm going to attempt to create a color swap function for this I guess.

This fix did not work. Instead of setting BGR, I thought just create a new RGB surface:

if (Surface->format->Rmask == 0x00ff0000) {
                Surface = SDL_CreateRGBSurfaceFrom(Surface->pixels, Surface->w, Surface->h, 32, Surface->pitch, Surface->format->Rmask, Surface->format->Gmask, Surface->format->Bmask, Surface->format->Amask);
}

After that failed to work I tried swapping Surface->format->Bmask and Surface->format->Rmask but that had no effect either.

Chemistpp
  • 2,006
  • 2
  • 28
  • 48

1 Answers1

1

In order to handle BGR and RGB changes you can try this code to create a texture from a SDL_Surface

int createTextureFromSurface(SDL_Surface *surface)
{
    int texture;
    // get the number of channels in the SDL surface
    GLint  nbOfColors = surface->format->BytesPerPixel;
    GLenum textureFormat = 0;

    switch (nbOfColors) {
    case 1:
        textureFormat = GL_ALPHA;
        break;
    case 3:     // no alpha channel
        if (surface->format->Rmask == 0x000000ff)
            textureFormat = GL_RGB;
        else
            textureFormat = GL_BGR;
        break;
    case 4:     // contains an alpha channel
        if (surface->format->Rmask == 0x000000ff)
            textureFormat = GL_RGBA;
        else
            textureFormat = GL_BGRA;
        break;
    default:
        qDebug() << "Warning: the image is not truecolor...";
        break;
    }

    glEnable( GL_TEXTURE_2D );
    // Have OpenGL generate a texture object handle for us
    glGenTextures( 1, &texture );

    // Bind the texture object
    glBindTexture( GL_TEXTURE_2D, texture );


    // Edit the texture object's image data using the information SDL_Surface gives us
    glTexImage2D( GL_TEXTURE_2D, 0, nbOfColors, surface->w, surface->h, 0,
                  textureFormat, GL_UNSIGNED_BYTE, surface->pixels );

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    return texture;
}
Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
  • I'll give it a try. The only differences in my texture rendering function (minus checking the mask) is I use GL_LINEAR in my min and mag filters. I see your point, and that is a better plan that my original of just switching the r and b values. What bugs me is that I am following the SDL_ttf documentation, using the SDL_Color type and setting the .r value. This color type is a parameter for the font to surface render function. There is no reason the surface should come back with the wrong mask no matter if it's RGB or BGR I would assume. – Chemistpp Jun 24 '13 at 17:39
  • 1
    In fact, I'm not a TTF master but I know I can trust this function with every king of `SDL_Surface` (from JPG, BMP, PNG, TTF) and I have no clue what could be wrong with your code... – Thomas Ayoub Jun 25 '13 at 06:36
  • my version of openGL isn't supporting GL_BGR and GL_BGRA beacuse I'm on windows using openGL 1.1 (http://www.dsource.org/forums/viewtopic.php?p=7236&sid=89ca5c76c03cc6bfa55725b9dca2d72f) However, I put an exit in the BGR formats and sure enough- the Font is in BGRA format. Wow. Thanks! – Chemistpp Jun 25 '13 at 13:47
  • Well, I tried making format = 0xE080; and 0xE081; as I guess those are the GLenum values for BGR and BGRA. Intrestingly, the font just renders a solid box now. Going to try and figure out what's going on with that now. – Chemistpp Jun 25 '13 at 14:49
  • I will when I get it to work right ;) Hahaha You get positive comment for now. lol – Chemistpp Jun 25 '13 at 14:52
  • Well, with your solution, the font isn't rendering at all. I think it has to do with the fact that even though I'm passing in the BGR and BGRA enums, the font isn't rendering at all. My guess is that since I am using windows, it's not that the enums aren't there, they probably can't even be implemented. I'll upvote your answer ;) – Chemistpp Jun 25 '13 at 14:57
  • I hope you'll find you way. But why using an old version of `OpenGL`? – Thomas Ayoub Jun 25 '13 at 15:12
  • Maybe I'm a dumbass? I have no idea what I'm doing. I don't think I am. Windows Software Development Kit (SDK) for Windows 7 and .NET Framework 4. That is the version of SDK I downloaded. I just saw that post saying us windows nooblets can't use GL_BGR and GL_BGRA. Interestingly: http://lists.libsdl.org/pipermail/sdl-libsdl.org/2000-October/012410.html I am not the only one that has seen this. But there isn't many hits, and that was posted back in 2000. I'll see about updating my openGL and maybe that will fix it? I tried a fix that failed to work: I'll post above – Chemistpp Jun 25 '13 at 15:25
  • Then I think the current version is 4.3 and your talking about 1.1... But I don't call you dumbass ;) – Thomas Ayoub Jun 25 '13 at 15:28
  • Is there a way to check exactly my version? I don't know if I've had 4.3, but I remember now that I installed Microsoft SDK about a year ago so I just re-downloaded it in case there was any update. Well, still the enums GL_BGR and GL_BGRA are coming up as undefined. All attempts to invert red and blue using the surface has failed so I just invert the r and b values in my function and set the SDL_Color .r value to my blue and vice-verse. I might consider the problem is in SDL due to the lack of hits on google concerning this and no one dropped a bomb on this. Thanks for your help VBB. – Chemistpp Jun 25 '13 at 22:01
  • http://ubuntuforums.org/archive/index.php/t-1088836.html http://www.gamedev.net/topic/297183-inversion-of-r-b-pixel-values/ In case anyone comes here, there is more on the subject. With windows, for now, I give up, just inverting r and b in the function when I set the SDL_Color before rendering the font. – Chemistpp Jun 25 '13 at 23:23