How to render fonts and text with SDL2 efficiently?

本小妞迷上赌 提交于 2019-12-17 22:47:03

问题


Saw this post here about using SDL_ttf to render text in a game. However that approach requires calling SDL_CreateTextureFromSurface(), along with the SDL_FreeSurface() and SDL_DestroyTexture() every single frame.

Is creating textures (and probably subsequently having to send them to the GPU) every frame something that can significally impact my performance?

would it be wiser to use SDL_ttf only to create a texture with my whole rendered charset and then to blit from there myself, character by character?

Edit: I'm looking to render simple monospace fonts in US-English (basic ASCII) only.


回答1:


Yes, creating textures every frame can affect performance. Also, rasterizing TrueType fonts to SDL_Surfaces (as SDL_ttf does) every frame can affect performance.

I recommend SDL_FontCache (full disclosure: I'm the author). It uses SDL_ttf and caches the resulting glyphs in textures so you don't have to do it all yourself:
https://github.com/grimfang4/SDL_FontCache




回答2:


OpenGL text methods

You are more likely to find an efficient implementation by using OpenGL, since it is more widely used than SDL, see: How to draw text using only OpenGL methods?

Currently, I'd go for freetype-gl: https://github.com/rougier/freetype-gl which supports texture atlas https://en.wikipedia.org/wiki/Texture_atlas out of the box.

SDL supports OpenGL well, and you can even use both GL and SDL textures in a single program, if you are already using SDL textures in your program, e.g.:

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

Compile and run:

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

Tested in Ubuntu 17.10.

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



来源:https://stackoverflow.com/questions/29064904/how-to-render-fonts-and-text-with-sdl2-efficiently

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!