ご返答ありがとうございます、理解できました
その上で、すみません、暫くブレンドモード関連に触れていなかったので
失念していたのですが、へけぽんさんがご所望のブレンドモードは
実装できないことがわかりました
DXライブラリのブレンドモードは Direct3D が対応しているブレンド機能を
ほぼそのまま使用しているのですが、Direct3D にも『描画先の色を反転したものと
描画元の色を乗算した上でアルファブレンドの処理も行う』ことができる機能は存在せず、
実現するにはシェーダーなどを使って幾つかの処理に分ける必要がありました
DXライブラリの既存の機能でも『描画対象にできるグラフィックハンドル』と
GraphBlendBlt を使用して実現することができましたので、よろしければ下記の
サンプルプログラムをご覧ください m(_ _;m
#include "DxLib.h"
int TempScreen1 ;
int TempScreen2 ;
// アルファ値の透過処理付きのブレンドモード DX_BLENDMODE_INVDESTCOLOR 描画
int DrawInvDestColorBlendGraph( int x, int y, int GrHandle, int BlendParam )
{
int TempScreenSizeX ;
int TempScreenSizeY ;
int Result ;
int SizeX ;
int SizeY ;
int BackupBlendMode ;
int BackupBlendParam ;
int BackupDrawScreen ;
// 現在のブレンドモードと描画先のグラフィックハンドルを取得
GetDrawBlendMode( &BackupBlendMode, &BackupBlendParam ) ;
BackupDrawScreen = GetDrawScreen() ;
// 描画先が裏画面や表画面の場合はエラー
if( BackupDrawScreen == DX_SCREEN_BACK || BackupDrawScreen == DX_SCREEN_FRONT )
return -1 ;
// 描画する画像のサイズを取得
if( GetGraphSize( GrHandle, &SizeX, &SizeY ) < 0 )
return -1 ;
// 作業用グラフィックハンドルが無効の場合か、作業用グラフィックハンドルの
// サイズが描画する画像のサイズより小さかったら作業用グラフィックハンドルを作成しなおす
Result = GetGraphSize( TempScreen1, &TempScreenSizeX, &TempScreenSizeY ) ;
if( Result < 0 || TempScreenSizeX < SizeX || TempScreenSizeY < SizeY )
{
// 作業用グラフィックハンドルが有効だった場合は削除
if( Result >= 0 )
{
DeleteGraph( TempScreen1 ) ;
DeleteGraph( TempScreen2 ) ;
}
// 新しいサイズで作業用グラフィックハンドルを作成する
TempScreen1 = MakeScreen( SizeX, SizeY, TRUE ) ;
TempScreen2 = MakeScreen( SizeX, SizeY, TRUE ) ;
if( TempScreen1 < 0 || TempScreen2 < 0 )
return -1 ;
}
// 作業用グラフィックハンドルに『GrHandle を描画する範囲』の『描画先の画像』をコピーする
SetDrawScreen( TempScreen1 ) ;
SetDrawBlendMode( DX_BLENDMODE_SRCCOLOR, 255 ) ;
DrawGraph( -x, -y, BackupDrawScreen, TRUE ) ;
// 作業用グラフィックハンドルに GrHandle をブレンドモード DX_BLENDMODE_INVDESTCOLOR で描画する
SetDrawBlendMode( DX_BLENDMODE_INVDESTCOLOR, 255 ) ;
DrawGraph( 0, 0, GrHandle, TRUE ) ;
// 作業用グラフィックハンドルの RGB と、GrHandle の A を合成したものを
// 作業用グラフィックハンドルその2に転送する
GraphBlendBlt( GrHandle, TempScreen1, TempScreen2, 255, DX_GRAPH_BLEND_RGBA_SELECT_MIX,
DX_RGBA_SELECT_BLEND_R, DX_RGBA_SELECT_BLEND_G, DX_RGBA_SELECT_BLEND_B, DX_RGBA_SELECT_SRC_A ) ;
// 描画先を元に戻す
SetDrawScreen( BackupDrawScreen ) ;
// ブレンドモードを DX_BLENDMODE_ALPHA に変更する
SetDrawBlendMode( DX_BLENDMODE_ALPHA, BlendParam ) ;
// 指定の座標に作業用グラフィックハンドルその2を描画する
DrawRectGraph( x, y, 0, 0, SizeX, SizeY, TempScreen2, TRUE, FALSE ) ;
// ブレンドモードを元に戻す
SetDrawBlendMode( BackupBlendMode, BackupBlendParam ) ;
// 正常終了
return 0 ;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int Screen ;
int BackGrHandle ;
int GrHandle ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// 仮の画面を作成
Screen = MakeScreen( 640, 480, FALSE ) ;
// 背景画像を読み込み
BackGrHandle = LoadGraph( "BackImage.bmp" ) ;
// 描画画像を読み込み
GrHandle = LoadGraph( "Test1.bmp" ) ;
// メインループ
while( ProcessMessage() == 0 )
{
// 描画先を仮の画面に変更
SetDrawScreen( Screen ) ;
// 描画先をクリア
ClearDrawScreen() ;
// 背景画像を描画
DrawGraph( 0, 0, BackGrHandle, FALSE ) ;
// アルファ値の透過処理付きのブレンドモード DX_BLENDMODE_INVDESTCOLOR で画像を描画
DrawInvDestColorBlendGraph( 240, 0, GrHandle, 255 ) ;
// 描画先を裏画面に変更
SetDrawScreen( DX_SCREEN_BACK ) ;
// 裏画面に仮の画面を描画
DrawGraph( 0, 0, Screen, FALSE ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
DrawInvDestColorBlendGraph が「DX_BLENDMODE_ALPHA + DX_BLENDMODE_INVDESTCOLOR」を
行っている関数なのですが、仕組みとしては
1.描画先の画像を作業用画像1に転送
2.作業用画像1に引数で渡された画像を DX_BLENDMODE_INVDESTCOLOR で描画
3.RGB を作業用画像1、A を引数で渡された画像にしたものを作業用画像2に転送
4.描画先に作業用画像2を描画
というようなことを行っています
WinMain で裏画面に直接描画せず、わざわざ MakeScreen で作成した『描画対象にできる画像』を
描画先にしているのは、上記の 1 を実行するためです( 裏画面の内容も GetDrawScreenGraph で
取得することができるのですが、『描画対象にできる画像』を DrawGraph で転送するほうが
圧倒的に高速なので )
見ての通り沢山の処理を実行する必要があるので多用すると重いと思いますが、使い所を
考えて1フレームに数回実行するくらいでしたら問題ないと思います