簡體   English   中英

SDL + SDL_ttf:透明混合文本?

[英]SDL + SDL_ttf: Transparent blended text?

我想在具有給定alpha通道的SDL_Surface上渲染消除鋸齒的字符串。

我發現有可能呈現:

  • 帶有字符串渲染方法的Blended變體的消除鋸齒的字符串(即: TTR_RenderText_Blended )。 但后來我無法透明化。
  • 使用Shaded方法的消除鋸齒的字符串。 但后來有一個堅實的背景。 背景和繪制的字符串可以變得透明,但實時背景仍然存在。 傳遞它透明的背景顏色也是不可能的。
  • 一個非抗鋸齒的字符串,我可以使用Solid變體使其透明。 但它沒有消除鋸齒。

謝謝

我知道我在這一點上有點晚了:/

根據SDL_SetAlpha上的SDL文檔:

請注意,不能組合每像素和每表面alpha; 如果可用,則始終使用每像素alpha。

所以常規的SDL_BlitSurface / SDL_SetAlpha在這里不起作用。 但這是可以完成的:

僅使用SDL的示例

我能想到α混合TTF_RenderText_Blended輸出的唯一方法是使用OpenGL,或者調整曲面中每個像素的alpha值。

通過調整每像素alpha值

您可以通過將每像素alpha值從[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_SurfaceTTF_RenderText_Blended轉換為GL紋理,您可以使用:

glColor4f( 1.0, 1.0, 1.0, Alpha );

在紋理四邊形上渲染之前。

但不要忘記先啟用alpha混合!

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

你所要做的就是調用SDL_SetAlphaSDL_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 );

使用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

為什么不使用位圖字體? 您可以使用Alpha通道構建png圖像。 我認為SDL_ttf適用於同一系統,它在內部使用位圖字體構建圖像。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM