2015-03-15 27 views
13

Bir oyundaki metni göstermek için SDL_ttf kullanma hakkında bu yazıyı here gördünüz. Ancak, bu yaklaşım SDL_CreateTextureFromSurface() öğesini ve her bir karede SDL_FreeSurface() ve SDL_DestroyTexture() işlevini çağırmayı gerektirir.SDL2 ile yazı tipi ve metin nasıl verimli bir şekilde oluşturulur?

dokular oluşturmak (ve muhtemelen sonradan GPU'ya bunları göndermek zorunda) significally benim performansını etkileyebilir her çerçeve şey var mı?

sadece benim bütün render karakter seti ile bir doku oluşturmak için SDL_ttf kullanmak ve sonra karakteri ile, kendim oradan karakterini blit akıllıca olurdu?

Edit: Yalnızca ABD-İngilizce (temel ASCII) biçiminde basit monospace yazı tiplerini oluşturmayı düşünüyorum.

+3

belki, ama modern bir yazı ile "metin çizim" yazı 1984 We nasıl çalıştığını (yani "yan yana koyarak sonra harfleri alma ve" gibi bir şey olduğunu unutmayın o zamandan beri oldukça fazla taşındı). Modern yazı tipleri, harfleri bir araya getiriyor, aralarındaki boşlukları düzeltiyor, gerektiğinde ince değiştirmeler gerçekleştiriyor, seçilen noktaya göre düzgün olmayan ana hatları ve yazı tipini temelde bitmap gibi işleyerek kaybedebileceğiniz diğer birçok şeyi. –

+1

Kabul edildi, ancak bu tartışma uğruna, kendimizi sadece basit tek-yazı fontları ve ASCII karakterleriyle sınırlandırdığımızı varsayalım. Tüm bu doku oluşturma ve silme işleminin CPU/GPU kullanımı – introiboad

+0

fuar noktası (gönderiye eklenmeye değer) açısından gerektireceği hakkında kaba bir fikir edinmeye çalışıyorum. –

cevap

14

Evet, dokuları her çerçevede oluşturmak performansı etkileyebilir. Ayrıca, TrueLype yazı tiplerini SDL_Surfaces'e (SDL_ttf yapar) rasterleştirerek her çerçeve performansı etkileyebilir.

Ben SDL_FontCache tavsiye (tam açıklama: Ben yazar değilim).
https://github.com/grimfang4/SDL_FontCache

+0

Yani, birisi bunu zaten düşündü ve hatta uyguladı. Bağlantı için çok teşekkürler, çok güzel bir projeye benziyor! – introiboad

+1

Rica ederim. Bu kod C++ NFont projesinde yıllarca sürüyordu, ancak daha yakın bir zamanda yeniden kullanım için (ve C desteği) kendi kütüphanesine çıkardım. –

+0

Teşekkürler! Oyunumda kullanacağım gibi görünüyor. – Tedi

3

OpenGL metin yöntemleri

Sen OpenGL kullanarak etkili bir uygulama bulmak için daha olasıdır: bunu tüm kendiniz yapmak zorunda kalmamak Bu dokular sonuçlanan gliflere SDL_ttf kullanır ve önbelleğe daha yaygın SDL daha kullanıldığından, bkz: Şu How to draw text using only OpenGL methods?

, ben freetype-gl için gitmek istiyorum: https://github.com/rougier/freetype-gl doku atlas https://en.wikipedia.org/wiki/Texture_atlas destekler kutudan dışarı.

SDL iyi OpenGL destekler ve zaten, programınızda SDL dokular kullanılarak örneğin eğer sen bile, tek bir program hem GL ve SDL dokuları kullanabilirsiniz:

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

Derleme ve çalıştırın:

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

Ubuntu 17.10 test edilmiştir. memba

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