ブレンドモードの設定

2021年9月12日

SDLでブレンドモードを設定するには、「SDL_SetRenderDrawBlendMode関数」または「SDL_SetTextureBlendMode関数」を使用します。

SDL_SetRenderDrawBlendMode関数

図形を描画するときのブレンドモードを設定します。

宣言

int SDL_SetRenderDrawBlendMode( SDL_Renderer* renderer, SDL_BlendMode blendMode );

引数

rendererレンダラのアドレスです。
blendModeブレンドモードの種類です。

戻り値

設定に成功すると「0」を返し、失敗すると「エラーコード( 負の数 )」を返します。

SDL_SetTextureBlendMode関数

テクスチャに対してブレンドモードを設定します。設定したブレンドモードは、テクスチャを描画する際に使用されます。

宣言

int SDL_SetTextureBlendMode( SDL_Texture* texture, SDL_BlendMode blendMode );

引数

textureテクスチャのアドレスです。
blendMode ブレンドモードの種類です。

戻り値

設定に成功すると「0」を返し、失敗すると「エラーコード( 負の数 )」を返します。

サンプルプログラム

#include <SDL_image.h>

struct Color 
{
    Uint8 m_red     = 0;
    Uint8 m_green   = 0;
    Uint8 m_blue    = 0;
    Uint8 m_alpha   = 0;

    Color( Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha ) :

        m_red( red ),
        m_green( green ),
        m_blue( blue ),
        m_alpha( alpha )

    {
    }
};

SDL_Window*     g_window    = nullptr;
SDL_Renderer*   g_renderer  = nullptr;
SDL_Texture*    g_texture   = nullptr;

bool Initialize();
bool Update();
void Draw();
void Finalize();
SDL_Texture* CreateTextureFromFile( const char* file_path );
void DrawFilledRectangle( const SDL_Rect& rectangle, const Color& color, SDL_BlendMode blend_mode );

int main( int argc, char* argv[] )
{
    if ( !Initialize() ) 
    {
        Finalize();
        return -1;
    }

    while ( true )
    {
        if ( !Update() ) break;
        Draw();
    }

    Finalize();

    return 0;
}

bool Initialize() 
{
    if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
    {
        SDL_Log( u8"SDLの初期化処理に失敗しました。エラーメッセージ: %s", SDL_GetError() );
        return false;
    }

    auto format_type_flags                  = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF;
    auto bitmask_of_available_format_type   = IMG_Init( format_type_flags );
    auto is_initialized_sdl_image           = ( bitmask_of_available_format_type & format_type_flags ) == format_type_flags;

    if ( !is_initialized_sdl_image )
    {
        SDL_Log( u8"SDL_imageの初期化処理に失敗しました。エラーメッセージ: %s", IMG_GetError() );
        return false;
    }

    g_window = SDL_CreateWindow(
        u8"サンプル",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        1280,
        720,
        0
    );

    if ( g_window == nullptr )
    {
        SDL_Log( u8"ウィンドウの作成に失敗しました。エラーメッセージ: %s", SDL_GetError() );
        return false;
    }

    g_renderer = SDL_CreateRenderer(
        g_window,
        -1,
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
    );

    if ( g_renderer == nullptr )
    {
        SDL_Log( u8"レンダラの作成に失敗しました。エラーメッセージ: %s", SDL_GetError() );
        return false;
    }

    g_texture = CreateTextureFromFile( u8"image.png" );
    if ( g_texture == nullptr ) return false;

    SDL_SetTextureBlendMode( g_texture, SDL_BLENDMODE_BLEND );

    return true;
}

bool Update() 
{
    auto event_info = SDL_Event();

    while ( SDL_PollEvent( &event_info ) == 1 )
    {
        if ( event_info.type == SDL_QUIT ) return false;
    }

    return true;
}

void Draw() 
{
    auto first_rectangle        = SDL_Rect();
    first_rectangle.w           = 200;
    first_rectangle.h           = 200;
    first_rectangle.x           = 100;
    first_rectangle.y           = 100;

    auto second_rectangle       = first_rectangle;
    second_rectangle.x         += first_rectangle.w / 2;
    second_rectangle.y         += first_rectangle.h / 2;

    auto third_rectangle        = second_rectangle;
    third_rectangle.x          += second_rectangle.w / 2;
    third_rectangle.y          += second_rectangle.h / 2;

    auto render_target_area     = third_rectangle;
    render_target_area.x       += third_rectangle.w / 2;
    render_target_area.y       += third_rectangle.h / 2;

    auto clearing_color         = Color( 128, 128, 128, 255 );
    auto first_rectangle_color  = Color( 255,   0,   0, 255 );
    auto second_rectangle_color = Color(   0, 255,   0, 128 );
    auto third_rectangle_color  = Color(   0,   0, 255, 255 );

    SDL_SetRenderDrawColor( 
        g_renderer, 
        clearing_color.m_red,
        clearing_color.m_green, 
        clearing_color.m_blue, 
        clearing_color.m_alpha
    );
    SDL_RenderClear( g_renderer );

    DrawFilledRectangle( first_rectangle,   first_rectangle_color,  SDL_BLENDMODE_MOD   );
    DrawFilledRectangle( second_rectangle,  second_rectangle_color, SDL_BLENDMODE_BLEND );
    DrawFilledRectangle( third_rectangle,   third_rectangle_color,  SDL_BLENDMODE_ADD   );

    SDL_RenderCopy( g_renderer, g_texture, nullptr, &render_target_area );

    SDL_RenderPresent( g_renderer );
}

void Finalize() 
{
    if ( g_texture  != nullptr )    SDL_DestroyTexture( g_texture );
    if ( g_renderer != nullptr )    SDL_DestroyRenderer( g_renderer );
    if ( g_window   != nullptr )    SDL_DestroyWindow( g_window );
    IMG_Quit();
    SDL_Quit();
}

SDL_Texture* CreateTextureFromFile( const char* file_path )
{
    auto image = IMG_Load( file_path );

    if ( image == nullptr )
    {
        SDL_Log( u8"画像の読み込みに失敗しました。エラーメッセージ: %s", IMG_GetError() );
        return nullptr;
    }

    auto texture = SDL_CreateTextureFromSurface( g_renderer, image );
    SDL_FreeSurface( image );

    if ( texture == nullptr ) SDL_Log( u8"テクスチャの作成に失敗しました。エラーメッセージ: %s", SDL_GetError() );

    return texture;
}

void DrawFilledRectangle( const SDL_Rect& rectangle, const Color& color, SDL_BlendMode blend_mode ) 
{
    SDL_SetRenderDrawBlendMode( g_renderer, blend_mode );
    SDL_SetRenderDrawColor( g_renderer, color.m_red, color.m_green, color.m_blue, color.m_alpha );
    SDL_RenderFillRect( g_renderer, &rectangle );
}

※ このプログラムではSDL_imageを併用しています。

参考ページ