使用 SDL2 和 OpenGL 显示带有 SDL TTF 的文本

Mon*_*ica 7 c++ opengl sdl-ttf sdl-2

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

我试过使用 SDL_CreateRGBSurface() 认为它可能是一种更清洁的恢复像素的方法,但它也不起作用。我的表面从不为 NULL,并且总是通过验证测试。

我在 while() 循环之前使用 get_front() 函数,并在使用 glClear(GL_COLOR_BUFFER_BIT) 之后使用其中的 displayMoney() 函数。

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); 
}
Run Code Online (Sandbox Code Playgroud)

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

Run Code Online (Sandbox Code Playgroud)

没有任何错误消息。此外,我没有使用我的表面,而是使用 stbi_load 函数用图像测试了我的代码,它运行得非常好。因此,问题似乎与 SDL 部分有关。

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

kel*_*tar 3

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

着色: 创建 8 位调色板表面,并使用给定的字体和颜色以高质量渲染给定的文本。0像素值是背景,而其他像素具有不同程度的前景色和背景色。

因此,您生成的表面是使用 8 位调色板而不是 RGBA 进行索引的(正如您所指出的,也通过表面格式中缺少颜色遮罩来指示)。带有alpha通道的RGBA表面由例如生成TTF_RenderText_Blended,或使用不同的纹理格式,或进行格式转换。您需要传递表面宽度/高度而glTexImage2D不是 128/64 常数,因为表面尺寸可能会有所不同。

您在问题代码中还存在一些资源泄漏:在每次绘制时创建新纹理并且从不删除它(如果文本没有更改,这也是不必要的),并且从不使用TTF_CloseFont.