web-dev-qa-db-fra.com

Comment rendre efficacement les polices et le texte avec SDL2?

Vu cet article ici sur l'utilisation de SDL_ttf pour rendre le texte dans un jeu. Cependant, cette approche nécessite d'appeler SDL_CreateTextureFromSurface (), ainsi que SDL_FreeSurface () et SDL_DestroyTexture () chaque trame unique.

La création de textures (et probablement leur envoi ultérieur au GPU) est-elle quelque chose qui peut avoir un impact significatif sur mes performances?

serait-il plus sage d'utiliser SDL_ttf uniquement pour créer une texture avec l'ensemble de mon jeu de caractères rendu et ensuite de blit à partir de là moi-même, caractère par caractère?

Edit : Je cherche à rendre les polices monospaces simples en anglais américain (ASCII de base) uniquement.

21
introiboad

Oui, la création de textures à chaque image peut affecter les performances. De plus, la pixellisation des polices TrueType en SDL_Surfaces (comme le fait SDL_ttf) chaque trame peut affecter les performances.

Je recommande SDL_FontCache (divulgation complète: je suis l'auteur). Il utilise SDL_ttf et met en cache les glyphes résultants dans les textures afin que vous n'ayez pas à tout faire vous-même:
https://github.com/grimfang4/SDL_FontCache

27
Jonny D

Méthodes de texte OpenGL

Vous êtes plus susceptible de trouver une implémentation efficace en utilisant OpenGL, car il est plus largement utilisé que SDL, voir: Comment dessiner du texte en utilisant uniquement des méthodes OpenGL?

Actuellement, je choisirais freetype-gl : https://github.com/rougier/freetype-gl qui prend en charge l'atlas de texture https://en.wikipedia.org/wiki/Texture_atlas hors de la boîte.

SDL prend bien en charge OpenGL, et vous pouvez même utiliser les deux textures GL et SDL dans un seul programme, si vous utilisez déjà des textures SDL dans votre programme, par exemple:

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

Compiler et exécuter:

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

Testé dans Ubuntu 17.10.

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