SDL + SDL_ttf: прозрачный смешанный текст? - PullRequest
6 голосов
/ 12 июля 2010

Я хочу отобразить сглаженную строку на SDL_Surface с заданным альфа-каналом.

Я понял, что можно сделать:

  • сглаженная строка с вариантом Blended метода рендеринга строки (например: TTR_RenderText_Blended). Но тогда я не могу сделать это прозрачным.
  • Сглаженная строка с методом Shaded. Но тогда есть солидный фон. Фон и нарисованная строка могут быть прозрачными, но тогда сплошной фон все еще остается. Передача прозрачного фона также невозможна.
  • не сглаженная строка, которую я могу сделать прозрачной, как хочу с вариантом Solid. Но это не сглаживание.

Спасибо

Ответы [ 4 ]

11 голосов
/ 08 октября 2012

Я знаю, что немного опоздала: /

Согласно документации SDL на SDL_SetAlpha:

Обратите внимание, что для каждого пикселя и для каждой поверхности альфане может быть объединено;альфа на пиксель всегда используется, если доступно.

Так что обычная SDL_BlitSurface / SDL_SetAlpha здесь не будет работать.Но это можно сделать:

Example using only SDL

Единственный способ, которым я могу думать о альфа-смешивании TTF_RenderText_Blended, - использовать OpenGL или настроить альфа-значения каждого пикселя вповерхность.

Регулируя альфа-значения на пиксель

Вы можете сделать это, масштабируя альфа-значения на пиксель от [0, 255] до нового диапазона [0, alpha]:

// Changes a surface's alpha value, by altering per-pixel alpha if necessary.
void SetSurfaceAlpha (SDL_Surface *surface, Uint8 alpha)
{
    SDL_PixelFormat* fmt = surface->format;

    // If surface has no alpha channel, just set the surface alpha.
    if( fmt->Amask == 0 ) {
        SDL_SetAlpha( surface, SDL_SRCALPHA, alpha );
    }
    // Else change the alpha of each pixel.
    else {
        unsigned bpp = fmt->BytesPerPixel;
        // Scaling factor to clamp alpha to [0, alpha].
        float scale = alpha / 255.0f;

        SDL_LockSurface(surface);

        for (int y = 0; y < surface->h; ++y) 
        for (int x = 0; x < surface->w; ++x) {
            // Get a pointer to the current pixel.
            Uint32* pixel_ptr = (Uint32 *)( 
                    (Uint8 *)surface->pixels
                    + y * surface->pitch
                    + x * bpp
                    );

            // Get the old pixel components.
            Uint8 r, g, b, a;
            SDL_GetRGBA( *pixel_ptr, fmt, &r, &g, &b, &a );

            // Set the pixel with the new alpha.
            *pixel_ptr = SDL_MapRGBA( fmt, r, g, b, scale * a );
        }   

        SDL_UnlockSurface(surface);
    }       
}           

Я знаю, это выглядит страшно, но довольно просто.Ключевая строка здесь:

*pixel_ptr = SDL_MapRGBA( fmt, r, g, b, scale * a );

Вы можете использовать это так:

text_surface = TTF_RenderText_Blended( font, "Hello World!", color );
SetSurfaceAlpha( text_surface, 128 );

С OpenGL

При использовании OpenGL все намного проще.Предполагая, что вы преобразуете SDL_Surface из TTF_RenderText_Blended в текстуру GL, вы можете просто использовать:

glColor4f( 1.0, 1.0, 1.0, Alpha );

перед рендерингом на текстурированном квадре.

Но не забудьтечтобы сначала включить альфа-смешение!

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1 голос
/ 11 марта 2018

Способ сделать это с TTF - использовать SDL_SetTextureAlphaMod() Примерно так:

SDL_Surface *surface;
SDL_Texture *texture;
SDL_Color color = {255, 255, 255, 128}
surface = TTF_RenderText_Blended_Wrapped(myFont, "HI!", color, 100);
// myFont and the _renderer is pre-defined somewhere in the game
texture = SDL_CreateTextureFromSurface(_renderer, surface);
SDL_SetTextureAlphaMod(texture, color.a);
SDL_RenderCopy(_renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);

/*...*/

SDL_RenderPresent(_renderer);

https://wiki.libsdl.org/SDL_SetTextureAlphaMod

1 голос
/ 27 декабря 2012

Все, что вам нужно сделать, это вызвать SDL_SetAlpha на вашем SDL_Surface после , создавая спрайт, на котором отображается текст, , но перед вызовом SDL_DisplayFormatAlpha на этом спрайте .

// Make the sprite with the text on it
SDL_Surface *swSprite = TTF_RenderText_Solid( font, text, textColor ) ;

// CALL SET ALPHA NOW
SDL_SetAlpha( swSprite, SDL_SRCALPHA, 128 ) ; // 50% opacity

// OK, NOW you can convert it to display format.  I'm presuming
// you called `SDL_SetVideoMode` with the `SDL_HWSURFACE` flag set previously
SDL_Surface* hwSprite = SDL_DisplayFormatAlpha( swSprite ) ;

// If you invert the above 2 steps, it won't work.

// We don't need the software sprite anymore
SDL_FreeSurface( swSprite ) ;

// Now draw the hwSprite as normal
SDL_BlitSurface( hwSprite, NULL, screen, &spriteLocation );
0 голосов
/ 19 июля 2010

Почему бы не использовать растровые шрифты?Вы можете создать изображение PNG с альфа-каналом.Я думаю, что SDL_ttf работает с той же системой, он создает образ, внутри которого используются растровые шрифты.

...