How to render fonts and text with SDL2 efficiently?

前端 未结 2 866
旧巷少年郎
旧巷少年郎 2020-12-14 02:13

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

相关标签:
2条回答
  • 2020-12-14 02:29

    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

    0 讨论(0)
  • 2020-12-14 02:35

    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

    0 讨论(0)
提交回复
热议问题