TTF_RenderUTF8_Blended 渲染彩色文本

Posted

技术标签:

【中文标题】TTF_RenderUTF8_Blended 渲染彩色文本【英文标题】:TTF_RenderUTF8_Blended Rendering Colored Text 【发布时间】:2013-06-24 00:01:42 【问题描述】:

我正在尝试使用 SDL_ttf 和 openGL 呈现文本。

我打开字体并将文本渲染到 SDL_Surface,然后将该表面附加到纹理并将其绑定以供 openGL 渲染。

我已经用谷歌搜索了很多这个问题,但没有得到多少点击,这会让我相信我理解了一些东西。

唯一重要的两个函数,因为我几乎制作了一个临时变量来解决这个问题。它们是:

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;


这使用 SDL_ttf 将文本渲染到 Surf_Text 表面。你可以看到我已经最大化了蓝色通道。我一会儿再谈这个。这是效果图

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);
    

好吧,据我所知,问题可能来自当前的颜色状态和纹理环境模式。

当我以这种方式渲染文本时,文本会改变颜色,但就像 R 和 B 通道已经切换一样。如果我制作红色 255,则文本为蓝色,如果我制作蓝色 255,则文本为红色。绿色保持绿色(RGB vs BGR?)。

如果我删除了渲染函数中的glColor4f 调用,则文本根本拒绝渲染彩色。总是黑色(我习惯性地将颜色设置回(0,0,0),每次我渲染一些东西,所以可能因为模式是调制(R = 0 * Texture(Font)R等)所以它会是黑色的。有道理.

如果我将 Texture 环境设置为 DECAL,则文本呈现黑色,文本后面的框呈现我试图呈现文本的颜色。

我想我只是不知道执行此操作的正确方法。有人对 SDL_ttf 和 openGL 纹理环境有任何经验,可以提供一些想法吗?

编辑:

我已经对函数进行了一些重写并测试了表面,并最终弄清楚了一些事情。如果我使用 GL_DECAL 文本呈现正确的颜色,并且像素值在表面上的任何地方都为 0 我尝试渲染的不是红色(渲染值为 255,这很奇怪,因为红色是它应该的第一个通道至少我期望的是 255^3(或以十六进制 FF0000 表示)。使用 DECAL,alpha 空间(文本周围的空白区域,像素值为 0)显示当前 glColor() 调用的颜色。如果我使用混合,则 alpha 区域会消失,但我的文本也会呈现为混合(当然),因此它与底层背景纹理混合。

我想更合适的问题是如何只混合空白而不是文本?我的猜测是我可以调用一个新的 glBlendFunc();但我已经测试过参数,我就像树林里的孩子。不知道如何获得想要的结果。

解决方案尚未完全验证,但表面的格式确实是 BGRA,但我无法实现此更正。我将尝试为此创建一个颜色交换功能。

此修复无效。我没有设置 BGR,而是创建了一个新的 RGB 表面:

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);

在那之后我尝试交换Surface->format->BmaskSurface->format->Rmask 但那也没有效果。

【问题讨论】:

【参考方案1】:

为了处理 BGRRGB 更改,您可以尝试使用此代码从 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;

【讨论】:

我试试看。我的纹理渲染功能(减去检查掩码)的唯一区别是我在我的 min 和 mag 过滤器中使用 GL_LINEAR。我明白你的意思,这是一个更好的计划,我原来只是切换 r 和 b 值。让我烦恼的是,我正在遵循 SDL_ttf 文档,使用 SDL_Color 类型并设置 .r 值。此颜色类型是字体到表面渲染功能的参数。无论我认为是 RGB 还是 BGR,表面都没有理由返回错误的蒙版。 事实上,我不是 TTF 大师,但我知道我可以信任 SDL_Surface 的每一位国王(来自 JPG、BMP、PNG、TTF)这个功能,我不知道有什么可以你的代码有问题... 我的 openGL 版本不支持 GL_BGR 和 GL_BGRA 因为我在使用 openGL 1.1 (dsource.org/forums/…) BGRA 格式。哇。谢谢! 好吧,我试着让 format = 0xE080;和0xE081;因为我猜这些是 BGR 和 BGRA 的 GLenum 值。有趣的是,字体现在只是呈现一个实心框。打算试着弄清楚现在发生了什么。 当我让它正常工作时我会的;)哈哈哈你现在得到积极的评价。大声笑

以上是关于TTF_RenderUTF8_Blended 渲染彩色文本的主要内容,如果未能解决你的问题,请参考以下文章

untiy 3d ShaderLab_第8章_3_ 单光贴图和Forward 渲染路径

_3_ 单光贴图和Forward 渲染路径

格网降水产品

带有模板缓冲区 FBO 的延迟渲染器

音视频学习--H264解析渲染

Django项目配置多个数据库