Using SDL_ttf and OpenGL, TTF_RenderUTF8_Blended print Red rectangle

流过昼夜 提交于 2019-12-01 04:42:58

问题


When I render my text using TTF_RenderUTF8_Blended I obtain a solid rectangle on the screen. The color depends on the one I choose, in my case the rectangle is red.

My question

What am I missing? It seems like I'm not getting the proper Alpha values from the surface generated with SDL_DisplayFormatAlpha(TTF_RenderUTF8_Blended( ... )), or am I? Does anyone recognize or know the problem?

Additionnal informations

If I use TTF_RenderUTF8_Solid or TTF_RenderUTF8_Shaded the text is drawn properly, but not blended of course.

I am also drawing other textures on the screen, so I draw the text last to ensure the blending will take into account the current surface.

Edit:SDL_Color g_textColor = {255, 0, 0, 0}; <-- I tried with and without the alpha value, but I get the same result.

I have tried to summarize the code without removing too much details. Variables prefixed with "g_" are global.

Init() function

// This function creates the required texture.
bool Init()
{
    // ...

    g_pFont = TTF_OpenFont("../arial.ttf", 12);
    if(g_pFont == NULL)
        return false;

    // Write text to surface
    g_pText = SDL_DisplayFormatAlpha(TTF_RenderUTF8_Blended(g_pFont, "My first Text!", g_textColor)); //< Doesn't work

    // Note that Solid and Shaded Does work properly if I uncomment them.
    //g_pText = SDL_DisplayFormatAlpha(TTF_RenderUTF8_Solid(g_pFont, "My first Text!", g_textColor));
    //g_pText = SDL_DisplayFormatAlpha(TTF_RenderUTF8_Shaded(g_pFont, "My first Text!", g_textColor, g_bgColor));

    if(g_pText == NULL)
        return false;

    // Prepare the texture for the font
    GLenum textFormat;
    if(g_pText->format->BytesPerPixel == 4)
    {
        // alpha
        if(g_pText->format->Rmask == 0x000000ff)
            textFormat = GL_RGBA;
        else
            textFormat = GL_BGRA_EXT;
    }

    // Create the font's texture
    glGenTextures(1, &g_FontTextureId);
    glBindTexture(GL_TEXTURE_2D, g_FontTextureId);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, g_pText->format->BytesPerPixel, g_pText->w, g_pText->h, 0, textFormat, GL_UNSIGNED_BYTE, g_pText->pixels);

    // ...
}

DrawText() function

// this function is called each frame
void DrawText()
{
    SDL_Rect sourceRect;
    sourceRect.x = 0;
    sourceRect.y = 0;
    sourceRect.h = 10;
    sourceRect.w = 173;

    // DestRect is null so the rect is drawn at 0,0
    SDL_BlitSurface(g_pText, &sourceRect, g_pSurfaceDisplay, NULL);

    glBindTexture(GL_TEXTURE_2D, g_FontTextureId);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBegin( GL_QUADS );

        glTexCoord2f(0.0f, 0.0f);
        glVertex2f(0.0f, 0.0f);

        glTexCoord2f(0.0f, 1.0f);
        glVertex2f(0.0f, 10.0f);

        glTexCoord2f(1.0f, 1.0f);
        glVertex2f(173.0f, 10.0f);

        glTexCoord2f(1.0f, 0.0f);
        glVertex2f(173.0f, 0.0f);

    glEnd();
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}

回答1:


You've made a fairly common mistake. It's on the OpenGL end of things.

When you render the textured quad in DrawText(), you enable OpenGL's blending capability, but you never specify the blending function (i.e. how it should be blended)!

You need this code to enable regular alpha-blending in OpenGL:

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

This info used to be on the OpenGL website, but I can't find it now.

That should stop it from coming out solid red. The reasons the others worked is because they're not alpha-blended, they're actually just red-on-black images with no alpha, so the blending function doesn't matter. But the blended one only contains red color, with an alpha channel to make it less-red.

I notice a few other small problems in your program though.

In the DrawText() function, you are blitting the surface using SDL and rendering with OpenGL. You should not use regular SDL blitting when using OpenGL; it doesn't work. So this line should not be there:

SDL_BlitSurface(g_pText, &sourceRect, g_pSurfaceDisplay, NULL);

Also, this line leaks memory:

g_pText = SDL_DisplayFormatAlpha( TTF_RenderUTF8_Blended(...) );

TTF_RenderUTF8_Blended() returns a pointer to SDL_Surface, which must be freed with SDL_FreeSurface(). Since you're passing it into SDL_DisplayFormatAlpha(), you lose track of it, and it never gets freed (hence the memory leak).

The good news is that you don't need SDL_DisplayFormatAlpha here because TTF_RenderUTF8_Blended returns a 32-bit surface with an alpha-channel anyway! So you can rewrite this line as:

g_pText = TTF_RenderUTF8_Blended(g_pFont, "My first Text!", g_textColor);


来源:https://stackoverflow.com/questions/12700085/using-sdl-ttf-and-opengl-ttf-renderutf8-blended-print-red-rectangle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!