2015-03-15 17 views
13

Dieser Beitrag here sah die Verwendung von SDL_ttf zum Rendern von Text in einem Spiel. Dieser Ansatz erfordert jedoch das Aufrufen von SDL_CreateTextureFromSurface() zusammen mit SDL_FreeSurface() und SDL_DestroyTexture() in jedem einzelnen Frame.Wie man Schriftarten und Text mit SDL2 effizient rendert?

Erzeugt Texturen (und wahrscheinlich müssen sie anschließend an die GPU senden) jeden Frame etwas, das meine Leistung signifikant beeinflussen kann?

Wäre es klüger, SDL_ttf nur zu verwenden, um eine Textur mit meinem gesamten gerenderten Zeichensatz zu erstellen und dann von mir selbst, Charakter für Charakter, zu blitten?

Bearbeiten: Ich bin auf der Suche nach einfachen Monospace-Fonts in US-Englisch (nur ASCII-Basis).

+3

vielleicht, aber denken Sie daran, dass „Zeichnen von Text“ mit einer modernen Schrift ist nichts, wie „die Briefe bekommen und sie dann nebeneinander setzen“ (das, wie Schriftarten in 1984. Wir arbeiteten seitdem viel bewegt). Moderne Schriftarten fügen Buchstaben zusammen, korrigieren den Abstand zwischen ihnen, führen bei Bedarf subtile Ersetzungen durch, glätten Konturen auf der Grundlage der gewählten Punktgröße und viele andere Dinge, die Sie verlieren, indem Sie die Schriftart im Grunde als Bitmap behandeln. –

+1

Einverstanden, aber für diese Diskussion nehmen wir an, wir beschränken uns auf einfache Monospace-Fonts und nur ASCII-Zeichen. Ich versuche, eine grobe Vorstellung davon zu bekommen, was all diese Textur-Erstellung und Löschung in Bezug auf die CPU/GPU-Nutzung – introiboad

+0

Messepunkt (Wert hinzufügen, um den Beitrag hinzuzufügen) –

Antwort

14

Ja, die Erstellung von Texturen für jeden Frame kann die Leistung beeinträchtigen. Das Rastern von TrueType-Schriftarten auf SDL_Surfaces (wie es SDL_ttf vornimmt) kann außerdem Auswirkungen auf die Leistung haben.

Ich empfehle SDL_FontCache (vollständige Offenlegung: Ich bin der Autor). Es verwendet SDL_ttf und speichert die resultierenden Glyphen in Texturen, so dass Sie alles selbst nicht tun müssen:
https://github.com/grimfang4/SDL_FontCache

+0

Also hat jemand schon daran gedacht und es sogar umgesetzt. Vielen Dank für den Link, sieht aus wie ein sehr schönes Projekt! – introiboad

+1

Gern geschehen. Der Code gibt es seit Jahren im C++ NFont-Projekt, aber erst kürzlich habe ich ihn in eine eigene Bibliothek ausgelagert, um ihn besser wiederverwenden zu können (und C-Unterstützung). –

+0

Danke! Scheint so, als würde ich es in meinem Spiel benutzen. – Tedi

3

OpenGL Text Methoden

Sie sind eher eine effiziente Implementierung zu finden, indem mit Hilfe von OpenGL da es weiter verbreitet als SDL verwendet wird, finden sie unter: How to draw text using only OpenGL methods?

Derzeit gehe ich würde für Freetype-gl: https://github.com/rougier/freetype-gl die https://en.wikipedia.org/wiki/Texture_atlas Texturatlas unterstützt aus der Box.

SDL unterstützt OpenGL gut, und Sie können sogar beiden GL und SDL Texturen in einem einzigen Programm verwenden, wenn Sie bereits SDL Texturen in Ihrem Programm, zum Beispiel verwenden:

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

kompilieren und ausführen:

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

Getestet in Ubuntu 17.10.

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