トップページ > 記事閲覧
アルファ値が255より小さい場合、スクリーンを重ねるたびに薄くなる。
名前:佐本 日時: 2024/12/03 14:08

大変使いやすいライブラリ、ありがとうございます。 現在、DxLibを使用して、絵を描くツールを作成しております。 ブラシのテクスチャとなる画像を筆圧に応じて透明度を変えて連続して描画する、という描画ロジックを考えております。 そこで、標題の問題「アルファ値が255より小さい場合、スクリーンを重ねるたびに薄くなる。」で悩んでおります。 アルファ値を有効にしたスクリーンに、アルファ値が255より少ない(たとえば240とか)設定で アルファブレンドモードでDrawGraphしたスクリーンを別のスクリーンに重ねて描画すると スクリーンを重ねるたびに、どんどん薄くなっていきます。 望む結果としては たとえば、アルファ値が240の場合、 スクリーンをいくら重ねても240のアルファ値の画像として描画したいです。 画面に表示するまでにリアルタイムで描画する部分、キャッシュを再描画する部分など 複数のスクリーンを挟むことになります。 どういう描画順序なら望む結果が得られるでしょうか。なにとぞご教示いただければ助かります。 以下、再現のコードを添付いたします。 大変お手数ですが、ご精査のほどよろしくお願いいたします。
メンテ

Page: 1 |

Re: アルファ値が255より小さい場合、スクリーンを重ねるたびに薄くなる。 ( No.1 )
名前:佐本 日時:2024/12/03 14:09

#include "DxLib.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 画面モードを32bitカラーにする SetGraphMode(640, 480, 32); // DXライブラリの初期化 if (DxLib_Init() < 0) return -1; SetBackgroundColor(255, 255, 255); // 背景色の指定 // 画像を読み込む(ただの真っ黒の画像で構いません、16 * 16 pix) int brush = LoadGraph("brush.png"); //重ね用にアルファチャンネル付きの描画可能画像のスクリーンを作成する int screen0 = MakeScreen(640, 480, TRUE); int screen1 = MakeScreen(640, 480, TRUE); int screen2 = MakeScreen(640, 480, TRUE); int screen3 = MakeScreen(640, 480, TRUE); // 描画先を作成したアルファチャンネル付きの描画可能画像にする SetDrawScreen(screen0); ClearDrawScreen(); int opacity = 224; // DrawGraphの際に少しだけ薄くなるように描く SetDrawBlendMode(DX_BLENDMODE_ALPHA, opacity); DrawGraph(0, 0, brush, TRUE); //通常の描画に戻す SetDrawBlendMode(DX_BLENDMODE_NOBLEND, UCHAR_MAX); //スクリーンの重ね書き SetDrawScreen(screen1); ClearDrawScreen(); DrawGraph(0, 0, screen0, TRUE); //スクリーンの重ね書き SetDrawScreen(screen2); ClearDrawScreen(); DrawGraph(0, 0, screen1, TRUE); //スクリーンの重ね書き SetDrawScreen(screen3); ClearDrawScreen(); DrawGraph(0, 0, screen2, TRUE); // 描画先を表画面に戻す SetDrawScreen(DX_SCREEN_FRONT); ClearDrawScreen(); //DX_SCREEN_FRONTに元画像を直接描画(screen0と同条件) SetDrawBlendMode(DX_BLENDMODE_ALPHA, opacity); DrawGraph(0, 100, brush, TRUE); //重ね書きしたスクリーンを重ねた数の順に描画 SetDrawBlendMode(DX_BLENDMODE_NOBLEND, UCHAR_MAX); DrawGraph(32, 100, screen0, TRUE); DrawGraph(64, 100, screen1, TRUE); DrawGraph(96, 100, screen2, TRUE); DrawGraph(128, 100, screen3, TRUE); // キー入力待ち WaitKey(); //リソース開放 DeleteGraph(brush); DeleteGraph(screen0); DeleteGraph(screen1); DeleteGraph(screen2); DeleteGraph(screen3); // DXライブラリの後始末 DxLib_End(); return 0; }
メンテ
Re: アルファ値が255より小さい場合、スクリーンを重ねるたびに薄くなる。 ( No.2 )
名前:管理人 日時:2024/12/04 01:54

アルファブレンドの計算式の原理上、アルファチャンネルを持つスクリーンに対して アルファブレンドの描画を行い、それをアルファチャンネル付き画像として描画した場合 スクリーンを介さずに直接アルファブレンド描画を行った場合とは異なる描画結果となってしまいます こちらの問題を解決する方法として『乗算済みアルファ』という手法があり、それについて 解説しているページがありますので、よろしければご覧ください m(_ _)m <乗算済みアルファのすすめ> https://dxlib.xsrv.jp/lecture/PremulAlpha/PremulAlpha.html
メンテ
Re: アルファ値が255より小さい場合、スクリーンを重ねるたびに薄くなる。 ( No.3 )
名前:佐本 日時:2024/12/04 12:16

早速のご返信、ありがとうございます。 乗算済みアルファのページを読み、以下の通り理解しました。 1.乗算したいPNG画像ファイルを読み込むときは、「乗算済みアルファの画像」として読込む。 LoadGraph で読み込み作成するグラフィックハンドルの画像を「乗算済みアルファの画像」にするには LoadGraph で画像ファイルを読み込む前に SetUsePremulAlphaConvertLoad( TRUE ) ; を実行しておきます。 SetUsePremulAlphaConvertLoad(TRUE); graphA = LoadGraph("brush.png"); 2.アルファ付きスクリーンに上記画像を描画(DrawGraph)するときは「乗算済みアルファ用のブレンドモード」を使用する。 そのグラフィックハンドルを使って裏画面に対して DrawGraph などで描画する場合は 「乗算済みアルファ用のブレンドモード」を使用する必要があります。 SetDrawScreen(swcreenA); SetDrawBlendMode( DX_BLENDMODE_PMA_ALPHA, opacity ); DrawGraph(0,0, graphA); 3.上記スクリーンは乗算済みアルファ画像相当になっているので他のスクリーンや背景に描画するときは「乗算済みアルファ用のブレンドモード」を使用する。 SetDrawScreen(swcreenB); SetDrawBlendMode( DX_BLENDMODE_PMA_ALPHA, UCHAR_MAX); DrawGraph(0,0, screenA); 上記の手順さえ守っていれば、スクリーンを何枚重ねても元のアルファ値が維持される。という理解でよろしいでしょうか? この理解のもと元のプログラムを修正してみました。 その結果、薄くなる度合いは改善されましたが、スクリーンを重ねるとやはり少しずつ薄くなるようです。 たびたび、お手数おかけしますが、なにとぞご精査の程、よろしくお願いいたします。 #include "DxLib.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 画面モードを32bitカラーにする SetGraphMode(640, 480, 32); // DXライブラリの初期化 if (DxLib_Init() < 0) return -1; SetBackgroundColor(255, 255, 255); // 背景色の指定 // 画像を読み込む(ただの真っ黒の画像で構いません、16 * 16 pix) // 乗算済みアルファの画像として読込む SetUsePremulAlphaConvertLoad(TRUE); int brush = LoadGraph("brush.png"); //重ね用にアルファチャンネル付きの描画可能画像のスクリーンを作成する int screen0 = MakeScreen(640, 480, TRUE); int screen1 = MakeScreen(640, 480, TRUE); int screen2 = MakeScreen(640, 480, TRUE); int screen3 = MakeScreen(640, 480, TRUE); // 描画先を作成したアルファチャンネル付きの描画可能画像にする SetDrawScreen(screen0); ClearDrawScreen(); int opacity = 224; // DrawGraphの際に少しだけ薄くなるように描く // 乗算済みアルファブレンドモードで描画する SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, opacity); DrawGraph(0, 0, brush, TRUE); //以下、乗算済みアルファブレンド SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, UCHAR_MAX); //スクリーンの重ね書き SetDrawScreen(screen1); ClearDrawScreen(); DrawGraph(0, 0, screen0, TRUE); //スクリーンの重ね書き SetDrawScreen(screen2); ClearDrawScreen(); DrawGraph(0, 0, screen1, TRUE); //スクリーンの重ね書き SetDrawScreen(screen3); ClearDrawScreen(); DrawGraph(0, 0, screen2, TRUE); // 描画先を表画面に戻す SetDrawScreen(DX_SCREEN_FRONT); ClearDrawScreen(); //DX_SCREEN_FRONTに元画像を直接描画(screen0と同条件) SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, opacity); DrawGraph(0, 100, brush, TRUE); //重ね書きしたスクリーンを重ねた数の順に描画 // 乗算済みアルファブレンドモードで描画する SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, UCHAR_MAX); DrawGraph(32, 100, screen0, TRUE); //乗算済みアルファブレンド DrawGraph(64, 100, screen1, TRUE); //乗算済みアルファブレンド DrawGraph(96, 100, screen2, TRUE); //乗算済みアルファブレンド DrawGraph(128, 100, screen3, TRUE); // キー入力待ち WaitKey(); //リソース開放 DeleteGraph(brush); DeleteGraph(screen0); DeleteGraph(screen1); DeleteGraph(screen2); DeleteGraph(screen3); // DXライブラリの後始末 DxLib_End(); return 0; }
メンテ
Re: アルファ値が255より小さい場合、スクリーンを重ねるたびに薄くなる。 ( No.4 )
名前:管理人 日時:2024/12/05 00:01

すみません、乗算済みアルファの制限として『背景色は真っ黒( R=0 G=0 B=0 )にする必要がある』がありまして、 その制限に合わせて一部処理を変更することで正常な結果が得ることが出来ます SetBackgroundColor(255, 255, 255); // 背景色の指定 ↑ 背景色の指定をコメントアウト ↓ // SetBackgroundColor(255, 255, 255); // 背景色の指定 // 描画先を表画面に戻す SetDrawScreen(DX_SCREEN_FRONT); ClearDrawScreen(); ↑ こちらの ClearDrawScreen() の代わりに DrawBox で背景を真っ白に塗りつぶす ↓ // 描画先を表画面に戻す SetDrawScreen(DX_SCREEN_FRONT); SetDrawBlendMode( DX_BLENDMODE_PMA_ALPHA, 255 ); DrawBox( 0, 0, 640, 480, GetColor( 255,255,255 ), TRUE ); よろしければお試しください m(_ _)m
メンテ
Re: アルファ値が255より小さい場合、スクリーンを重ねるたびに薄くなる。 ( No.5 )
名前:佐本 日時:2024/12/05 00:59

ご返信ありがとうございます。 背景色を真っ黒に設定して、 毎回、バックバッファのクリアではなく白(背景にしたい色)で塗りつぶすことで スクリーンを重ねても、同一のアルファ値が保たれることを確認いたしました。 こちらの方法で進めていこうと思います。 迅速なご対応、感謝します。 ありがとうございました。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存