C++ 使用FreeType和SDL2渲染文本会生成白色正方形而不是字符

C++ 使用FreeType和SDL2渲染文本会生成白色正方形而不是字符,c++,sdl,freetype,C++,Sdl,Freetype,我正在尝试使用SDL2和FreeType创建一个基本项目来渲染文本,但它所渲染的只是白色方块,而不是每个字符。我正在使用SDL\u CreateRGBSurfaceFrom()渲染每个glygh并将像素数据转换为SDL\u曲面。我试着弄乱rgb组件的位掩码、像素的深度,甚至是曲面的混合模式,但到目前为止,所有这些都不起作用 下面是相关的代码位。字体在文件的前面正确加载,加载后我正在设置字体的大小。是什么导致字符显示为空白方块 #include <sdl.h> #include <

我正在尝试使用SDL2和FreeType创建一个基本项目来渲染文本,但它所渲染的只是白色方块,而不是每个字符。我正在使用
SDL\u CreateRGBSurfaceFrom()
渲染每个glygh并将像素数据转换为
SDL\u曲面。我试着弄乱rgb组件的位掩码、像素的深度,甚至是曲面的混合模式,但到目前为止,所有这些都不起作用

下面是相关的代码位。字体在文件的前面正确加载,加载后我正在设置字体的大小。是什么导致字符显示为空白方块

#include <sdl.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_BITMAP_H
#include FT_OUTLINE_H

#include <iostream>

/// Forward declaration
void Init();
void DeInit();
void Input();
void Update();
void Draw();

/// Memory
SDL_Window* window;
SDL_Surface* target;
FT_Library ftLib;
FT_Bitmap ftTarget;
FT_Face ftFace;

bool running = true;
int x = 0;
int y = 32;

/// Functions
void DrawBitmap(FT_Bitmap bm, int x, int y);

int main(int argc, char* argv[]) {
    Init();
    while (running) {
        Input();
        Update();
        Draw();
    }
    DeInit();

    return 0;
}

void Init() {
    // Init
    SDL_Init(SDL_INIT_EVERYTHING);
    window = SDL_CreateWindow("FreeType Test", 1920/2-600/2, 1080/2-400/2, 600, 400, 0);
    FT_Init_FreeType(&ftLib);
    FT_New_Face(ftLib, "C:\\Windows\\Fonts\\Arial.ttf", 0, &ftFace);
    FT_Set_Char_Size(ftFace, 12 << 6, 12 << 6, 72, 72);

    // Setup
    target = SDL_GetWindowSurface(window);
}

void DeInit() {
    // DeInit
    FT_Done_Face(ftFace);
    FT_Done_FreeType(ftLib);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

void Input() {
    SDL_Event e;
    while (SDL_PollEvent(&e)) {
        switch (e.type) {
        case SDL_QUIT:
            running = false;
            break;
        }
    }
}

void Update() {
    // nothing for now
}

void Draw() {
    SDL_FillRect(target, nullptr, SDL_MapRGBA(target->format, 128, 128, 0, 255));

    // Draw text
    constexpr char text[] = "This is cool B)";
    for (int n = 0; n < sizeof(text); n++)
    {
        FT_Load_Char(ftFace, text[n], FT_LOAD_RENDER);

        DrawBitmap(ftFace->glyph->bitmap, x + ftFace->glyph->bitmap_left, y - ftFace->glyph->bitmap_top);

        x += ftFace->glyph->advance.x >> 6;
        y += ftFace->glyph->advance.y >> 6;
    }

    x = 0;
    y = 32;

    SDL_UpdateWindowSurface(window);
    SDL_Delay(10);
}

void DrawBitmap(FT_Bitmap bm, int x, int y) {
    SDL_Surface* glyph = SDL_CreateRGBSurfaceFrom(bm.buffer, bm.width, bm.rows, 8, bm.pitch, 0, 0, 0, 0xFF);
    SDL_SetSurfaceBlendMode(glyph, SDL_BlendMode::SDL_BLENDMODE_NONE);
    SDL_Rect dest = { x, y, 0, 0 };
    SDL_BlitSurface(glyph, nullptr, target, &dest);
    SDL_FreeSurface(glyph);
}
#包括
#包括
#包括FT_FREETYPE_H
#包括FT_位图_H
#包括FT_大纲
#包括
///远期申报
void Init();
无效脱硝();
无效输入();
无效更新();
无效抽取();
///记忆
SDL_窗口*窗口;
SDL_表面*目标;
自由贸易联盟图书馆自由贸易图书馆;
FT_位图ftTarget;
面部表情;
bool running=true;
int x=0;
int y=32;
///功能
void DrawBitmap(FT_位图bm,int x,int y);
int main(int argc,char*argv[]){
Init();
(跑步时){
输入();
更新();
Draw();
}
脱硝();
返回0;
}
void Init(){
//初始化
SDL_Init(SDL_Init_EVERYTHING);
window=SDL_CreateWindow(“自由式测试”,1920/2-600/21080/2-400/2600400,0);
FT_Init_FreeType(&ftLib);
新字体(ftLib,“C:\\Windows\\font\\Arial.ttf”,0,&ftFace);
设置字符大小(ftFace,12字形->位图,x+ftFace->字形->左侧位图,y-ftFace->字形->顶部位图);
x+=ftFace->glyph->advance.x>>6;
y+=ftFace->glyph->advance.y>>6;
}
x=0;
y=32;
SDL_更新内表面(窗口);
SDL_延迟(10);
}
无效绘制位图(FT_位图bm、int x、int y){
SDL_Surface*glyph=SDL_CreateRGBSurfaceFrom(bm.buffer、bm.width、bm.rows、8、bm.pitch、0、0、0xFF);
SDL_设置曲面BlendMode(图示符,SDL_BlendMode::SDL_BlendMode_NONE);
SDL_Rect dest={x,y,0,0};
SDL_BlitSurface(字形、空PTR、目标和目标);
SDL_自由曲面(字形);
}
您可以设置调色板:

void DrawBitmap(FT_Bitmap bm, int x, int y)
{
    SDL_Surface* glyph = SDL_CreateRGBSurfaceFrom(bm.buffer, bm.width, bm.rows, 8, bm.pitch, 0, 0, 0, 0xFF);

    SDL_Color colors[256];
    for( int i = 0; i < 256; i++)
    {
        colors[i].r = colors[i].g = colors[i].b = i;
    }
    SDL_SetPaletteColors(glyph->format->palette, colors, 0, 256);

    SDL_SetSurfaceBlendMode(glyph, SDL_BlendMode::SDL_BLENDMODE_NONE);
    SDL_Rect dest = { x, y, 0, 0 };
    SDL_BlitSurface(glyph, nullptr, target, &dest);
    SDL_FreeSurface(glyph);
}
void DrawBitmap(FT_位图bm,int x,int y)
{
SDL_Surface*glyph=SDL_CreateRGBSurfaceFrom(bm.buffer、bm.width、bm.rows、8、bm.pitch、0、0、0xFF);
SDL_颜色[256];
对于(int i=0;i<256;i++)
{
颜色[i].r=colors[i].g=colors[i].b=i;
}
SDL_SetPaletteColors(字形->格式->调色板,颜色,0,256);
SDL_设置曲面BlendMode(图示符,SDL_BlendMode::SDL_BlendMode_NONE);
SDL_Rect dest={x,y,0,0};
SDL_BlitSurface(字形、空PTR、目标和目标);
SDL_自由曲面(字形);
}
或者自己进行RGBA转换:

void DrawBitmap(FT_Bitmap bm, int x, int y)
{
    if( bm.width == 0 || bm.rows == 0 )
    {
        return;
    }

    std::vector< unsigned char > rgba( bm.width * bm.rows * 4 );
    for( unsigned int y = 0; y < bm.rows; ++y )
    {
        for( unsigned int x = 0; x < bm.width; ++x )
        {
            unsigned char val = bm.buffer[ ( bm.pitch * y ) + x ];
            size_t base = ( ( bm.width * y ) + x ) * 4;
            rgba[ base + 0 ] = 0xFF;
            rgba[ base + 1 ] = 0xFF;
            rgba[ base + 2 ] = 0xFF;
            rgba[ base + 3 ] = val;
        }
    }

    SDL_Surface* glyph = SDL_CreateRGBSurfaceFrom
        (
        &rgba[0],
        bm.width,
        bm.rows,
        32,
        bm.width*4,
        0x000000ff,
        0x0000ff00,
        0x00ff0000,
        0xff000000
        );

    SDL_SetSurfaceBlendMode(glyph, SDL_BlendMode::SDL_BLENDMODE_BLEND);
    SDL_Rect dest = { x, y, 0, 0 };
    SDL_BlitSurface(glyph, nullptr, target, &dest);
    SDL_FreeSurface(glyph);
}
void DrawBitmap(FT_位图bm,int x,int y)
{
如果(bm.width==0 | | bm.rows==0)
{
返回;
}
std::vectorrgba(bm.width*bm.rows*4);
for(无符号整数y=0;y
a中编辑。我编辑了我的答案以提供这样一个示例。