Ver Mensaje Individual
  #9  
Antiguo 13-04-2018
Avatar de piXelicidio
piXelicidio piXelicidio is offline
Miembro
 
Registrado: nov 2008
Posts: 21
Reputación: 0
piXelicidio Va por buen camino
DrawText en SDL2

Ahora necesito texto para la applicación de las hormigas, tanto para debug como para la GUI.
SDL2 es muy bonito hasta que te dás cuenta que no puedes dibujar texto...
Bueno si puedes, pero usando SDL2_ttf.dll... ah, pero es muy lento, solo hace el render de la TrueType en memoria de sistema, que hay que convertir a textura... y uff...

Entonces lo más eficiente sería BMFont, seguro alguien tendrá algo hecho por ahí, mil veces,... pero tengo ganas de hacerlo yo y no quiero cargar un bitmap pre-generado, quiero generarlo en tiempo de ejecución y divertirme implementando el DrawTextXY...

Entonces ya esta hecho y funciona! :



El fondo de la imagen son 3500 veces impreso mi nombre con transparencia, alcanzando más de 60fPS.
Con el método basico de hacer el render del texto a una SDL_Surface, luego convertir a SDL_Texture, mandar la textura para la pantalla, y librerar esas memorias, el Frame Rate bajaba a 20 por segundo con solo 100 veces imprimir dos palabras...

Este es el código para generar la textura:

Código:
function Tsdl.createBitmapFont(ttf_FileName: string;
  fontSize: integer): TBitmapFont;
var
  w  :integer;
  charWidth :array[0..255] of integer;
  i,j: Integer;
  c:byte;
  surf :PSDL_Surface;
  surfChar :PSDL_Surface;
  color :TSDL_Color;
  destRect :TSDL_Rect;
  sdlFont :PTTF_Font;
begin
  Result.maxW := 0;
  sdlFont := TTF_OpenFont(StrToSdl( ttf_FileName ), fontSize );
  if sdlFont = nil then
  begin
    errorMsg('Can''t open font '+ttf_FileName + ' ' + string( TTF_GetError ) );
    exit;
  end;
  Result.srcFont := sdlFont;
  for c := 0 to 255 do
  begin
    //storing char widths and finding the max width
    TTF_SizeText(sdlFont, strToSDL(string(char(c))), @w, nil);
    if w > Result.maxW then Result.maxW := w;
    charWidth[c] := w;
  end;
  Result.maxH := TTF_FontHeight(sdlFont);
  Result.texW := Result.maxW * 16;
  Result.texH := Result.maxH * 16;
  //creating the surface to draw the char matrix of 16 x 16
  surf := SDL_CreateRGBSurfaceWithFormat(0, Result.texW, Result.texH, 32, SDL_PIXELFORMAT_RGBA8888);
  SDL_FillRect(surf, nil, $0 );
  c:= 0;
  color.r := 255;
  color.g := 255;
  color.b := 255;
  color.a := 0;
  for j := 0 to 15 do
    for i := 0 to 15 do
      begin
        if c > 0 then
        begin
          //Rendering a single character to a temporary Surface
          surfChar := TTF_RenderText_Blended(sdlFont, strToSDL(string(char(c))), color );
          destRect := sdl.Rect(i*Result.maxW, j*Result.maxH, charWidth[c], Result.maxH);
          Result.asciiSprites[c] := destRect;
          //bliting the character to our big surface matrix
          SDL_BlitSurface(surfChar, nil, surf,  @destRect  );
          SDL_FreeSurface(surfChar);
        end;
        inc(c);
      end;
  //to fix the problem with alpha premultiplied od TTF_RenderText_Blended
  //we get the image as a grayscale mask and convert the intensity to alpha channel
  sdl.ConvertGrayscaleToAlpha( surf );
  //convert to texture;
  Result.srcTex := SDL_CreateTextureFromSurface(sdl.rend, surf);
  SDL_FreeSurface(surf);
end;
Y este es el codigo de imprimir un texto en pantalla:
Código:
function Tsdl.drawText(s: string; x, y: integer; color: cardinal;  alpha: byte): TSDL_Rect;
var
  i :integer;
  b :byte;
  srcRect :PSDL_Rect;
  dstRect :TSDL_Rect;
  sc : PSDL_Color;
begin
  sc := @color;
  SDL_SetTextureColorMod(fFont.srcTex, sc.r, sc.g, sc.b);
  SDL_SetTextureAlphaMod(fFont.srcTex, alpha);
  dstRect := sdl.Rect(x,y, fFont.maxW, fFont.maxH);
  for i:=1 to length(s) do
  begin
    b := ord( s[i] );
    srcRect := @fFont.asciiSprites[b];
    dstRect.w := srcRect.w;
    dstRect.h := srcRect.h;
    SDL_RenderCopy(fRend, fFont.srcTex, srcRect, @dstRect);
    dstRect.x := dstRect.x + dstRect.w;
  end;
  result.x := x;
  result.y := y;
  result.h := fFont.maxH;
  result.w := dstRect.x - x;
end;
Seguro todo mi código explota si se intenta meter a la fuerza Unicode ... ni quiero saber, por ahora mi implementación e intención es solo ASCII latino.
Responder Con Cita