使用SDL2和OpenGL显示SDL TTF文本

7

我正在尝试使用SDL2 TTF和OpenGL显示文本,但窗口中出现了奇怪的纹理,它具有正确的大小和位置,但您无法看到任何字母。

我尝试使用SDL_CreateRGBSurface()函数来更清晰地恢复像素,但它也没有起作用。我的表面从未为空,并始终通过验证测试。

我在while()循环之前使用get_front()函数,在其内部使用displayMoney()函数,紧接着使用glClear(GL_COLOR_BUFFER_BIT)。

SDL、TTF和OpenGL已经正确初始化并且我已经创建了OpenGL上下文。以下是有问题的代码:

SDL_Surface* get_font()
{
    TTF_Font *font;
    font = TTF_OpenFont("lib/ariali.ttf", 35);
    if (!font) cout << "problem loading font" << endl;
    SDL_Color white = {150,200,200};
    SDL_Color black = {0,100,0};
    SDL_Surface* text = TTF_RenderText_Shaded(font, "MO", white, black);
    if (!text) cout << "text not loaded" << endl;

    return text;
}

void displayMoney(SDL_Surface* surface)
{
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glEnable(GL_TEXTURE_2D);
    GLuint TextureID = 0;
    glGenTextures(1, &TextureID);
    glBindTexture(GL_TEXTURE_2D, TextureID);
        int Mode = GL_RGB;
        if(surface->format->BytesPerPixel == 4) {
            Mode = GL_RGBA;
        }

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, Mode, 128, 64, 0, Mode, GL_UNSIGNED_BYTE, surface->pixels);

        glPushMatrix();
            glTranslated(100,100,0);
            glScalef(100,100,0);
            glBegin(GL_QUADS);
                glTexCoord2f(0, 1); glVertex2f(-0.5f, -0.5f);  
                glTexCoord2f(1, 1); glVertex2f(0.5f, -0.5f); 
                glTexCoord2f(1, 0); glVertex2f(0.5f, 0.5f); 
                glTexCoord2f(0, 0); glVertex2f(-0.5f, 0.5f);  
            glEnd();
        glPopMatrix();
    glBindTexture(GL_TEXTURE_2D, 0); 
}


#include <SDL2/SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#include <GL/gl.h>
#include <GL/glu.h>
#include <stb_image/stb_image.h>
#include <SDL2_ttf/SDL_ttf.h>
#include "init.h"


int main(int argc, char **argv) {

    SDL_Window* window = init();
    if (window == nullptr) {
        cout << "Error window init" << endl;
    }

    if (TTF_Init() < 0) {
        cout << "Error TTF init" << endl;
    }

    SDL_Surface* text = get_font(); 

    while (loop) {

        glClear(GL_COLOR_BUFFER_BIT);

        displayMoney(text);

...

       SDL_GL_SwapWindow(window);

没有任何错误信息。此外,我使用stbi_load函数通过图像测试了我的代码,它完美地工作了。因此,问题似乎出现在SDL部分。

编辑:我最近发现从文本获取的表面具有以下属性:Rmask = Gmask = Bmask = Amask = 0。这显然是个问题,但我不知道该如何解决...


在完成渲染后,您在哪里执行交换链交换?此代码似乎会泄漏生成的纹理。此外,glBegin / glEnd的内容已经过时约8年。 - user7860670
抱歉,我忘了提到我在while循环中使用了SDL_GL_SwapWindow(window)。我不确定您所说的泄漏纹理是什么意思,我是OpenGL的初学者,所以我不知道。我尝试将get_font()代码放在while循环之前,并将displaymoney()代码放在其中。然后在循环后释放表面。结果相同... - Monica
1个回答

3

如SDL_ttf文档所述,位于https://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf.html#SEC42

阴影效果: 使用给定的字体和颜色创建8位调色板表面,并以高质量呈现给定的文本。0像素值为背景,而其他像素从背景颜色中具有不同程度的前景颜色。

因此,您的结果表面的索引采用8位调色板,而不是RGBA(也由缺少表面格式中的颜色掩码所示,正如您已经注意到的)。 RGBA带有alpha通道的表面可以通过例如TTF_RenderText_Blended生成,或者使用不同的纹理格式或执行格式转换。您需要将表面宽度/高度传递给glTexImage2D,而不是128/64常量,因为表面大小可能会变化。

在问题代码中,您还有几个资源泄漏:每次绘制时创建新纹理并永远不删除它(如果文本未更改,则这也是不必要的),并且永远不使用TTF_CloseFont关闭字体。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接