代码之家  ›  专栏  ›  技术社区  ›  Martijn Courteaux

透明混合文本?

  •  5
  • Martijn Courteaux  · 技术社区  · 16 年前

    SDL_Surface 使用给定的alpha通道。

    我发现有可能呈现:

    • 具有 Blended 字符串呈现方法的变体(即: TTR_RenderText_Blended ). 但我不能让它透明。
    • Shaded
    • 一个非抗锯齿字符串,我可以用 Solid

    谢谢

    4 回复  |  直到 8 年前
        1
  •  -1
  •   ForceMagic chooselife    13 年前

    为什么不使用位图字体?你可以建立一个带有alpha通道的png图像。我认为SDL\uttf与同一个系统工作,它构建一个图像,内部使用位图字体。

        2
  •  12
  •   Daniel Hanrahan    13 年前

    我知道我有点晚了:/

    SDL_SetAlpha :

    注意,每像素和每表面alpha不能组合;如果可用,则始终使用每像素alpha。

    SDL_BlitSurface / 塞塔法 在这里不行。但可以做到:

    Example using only SDL

    我唯一能想到阿尔法混合的方法 TTF_RenderText_Blended

    通过调整每像素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

    SDL_Surface TTF\u RenderText\u混合 对于GL纹理,您只需使用:

    glColor4f( 1.0, 1.0, 1.0, Alpha );
    

    在纹理四边形上渲染之前。

    但别忘了先启用alpha混合!

    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    
        3
  •  1
  •   bobobobo    13 年前

    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 );
    
        4
  •  1
  •   Lord Wolfenstein    8 年前

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