25

在这里看到这篇关于使用 SDL_ttf 在游戏中渲染文本的帖子。然而,这种方法需要在每一帧调用 SDL_CreateTextureFromSurface() 以及 SDL_FreeSurface() 和 SDL_DestroyTexture()。

每帧创建纹理(可能随后必须将它们发送到 GPU)是否会对我的性能产生重大影响?

仅使用 SDL_ttf 用我的整个渲染字符集创建纹理然后我自己从那里逐个字符地进行 blit 会更明智吗?

编辑:我希望仅以美国英语(基本 ASCII)呈现简单的等宽字体。

4

2 回答 2

33

是的,每帧创建纹理都会影响性能。此外,每帧将 TrueType 字体光栅化为 SDL_Surfaces(如 SDL_ttf 所做的那样)会影响性能。

我推荐 SDL_FontCache (完全披露:我是作者)。它使用 SDL_ttf 并将生成的字形缓存在纹理中,因此您不必自己完成所有操作:
https ://github.com/grimfang4/SDL_FontCache

于 2015-04-19T04:20:59.903 回答
6

OpenGL 文本方法

您更有可能通过使用 OpenGL 找到有效的实现,因为它比 SDL 使用更广泛,请参阅: 如何仅使用 OpenGL 方法绘制文本?

目前,我会选择freetype-glhttps ://github.com/rougier/freetype-gl,它支持开箱即用的纹理图集https://en.wikipedia.org/wiki/Texture_atlas 。

SDL 很好地支持 OpenGL,如果您已经在程序中使用 SDL 纹理,您甚至可以在单个程序中同时使用 GL 和 SDL 纹理,例如:

#include <SDL2/SDL.h>
#define GLEW_STATIC
#include <GL/glew.h>

int main(void) {
    SDL_GLContext gl_context;
    SDL_Event event;
    SDL_Renderer *renderer = NULL;
    SDL_Texture *texture = NULL;
    SDL_Window *window = NULL;
    Uint8 *base;
    const unsigned int
        WINDOW_WIDTH = 500,
        WINDOW_HEIGHT = WINDOW_WIDTH
    ;
    int pitch;
    unsigned int x, y;
    void *pixels = NULL;

    /* Window setup. */
    SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
    window = SDL_CreateWindow(
        __FILE__, 0, 0,
        WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL
    );
    renderer = SDL_CreateRenderer(window, 0, 0);
    gl_context = SDL_GL_CreateContext(window);

    /* GL drawing. */
    glClearColor(1.0, 0.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    /* Wrapped texture drawing. */
    texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
        SDL_TEXTUREACCESS_STREAMING, WINDOW_WIDTH, WINDOW_HEIGHT);
    SDL_LockTexture(texture, NULL, &pixels, &pitch);
    for (x = 0; x < WINDOW_WIDTH; x++) {
        for (y = 0; y < WINDOW_HEIGHT; y++) {
            base = ((Uint8 *)pixels) + (4 * (x * WINDOW_WIDTH + y));
            base[0] = 0;
            base[1] = 0;
            base[2] = 255;
            base[3] = 255;
        }
    }
    SDL_UnlockTexture(texture);
    SDL_Rect rect;
    rect.x = 0;
    rect.y = 0;
    rect.w = WINDOW_WIDTH / 2;
    rect.h = WINDOW_HEIGHT / 2;
    SDL_RenderCopy(renderer, texture, NULL, &rect);
    SDL_GL_SwapWindow(window);

    /* Main loop. */
    while (1) {
        if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
            break;
    }

    /* Cleanup. */
    SDL_GL_DeleteContext(gl_context);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return EXIT_SUCCESS;
}

编译并运行:

gcc -std=c99 main.c -lSDL2 -lGL
./a.out

在 Ubuntu 17.10 中测试。

GitHub 上游:https ://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/texture_and_opengl.c

于 2016-12-28T12:42:28.023 回答