Re: ソフトウエアイメージに描画する関数 ( No.1 ) |
- 名前:B.E 日時:2020/03/22 17:06
ちょっと気になったんですが、MakeScreen()で作成したグラフィックハンドルに一度描画してソフトウェアイメージにコピーじゃダメなんですかね?
1.MakeRGB8ColorSoftImage()でソフトウェアイメージを作成
2.MakeScreen()でαチャンネル付きの描画用スクリーン作成
3.SetDrawScreen()で描画先に指定
4.SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA,255)で「乗算済みα用のαブレンド」にする
5.既存の描画関数で描画用スクリーンに描画
6.GetDrawScreenSoftImage()でソフトウェアイメージに転送
7.DeleteGraph()で不要になった描画用スクリーンを消去
でアンチエイリアスに対応したソフトウェアイメージの作成は出来ると思いますよ。
そもそもソフトウェアイメージに転送しなくても、MakeScreen()で作成して図形を描画したグラフィックハンドルを、
そのまま描画用素材にすればいいような気がするのですが…、それでは何か不具合があるのでしょうか?
>>裏画面に直接描画することもできますが、ゲームのシステム上大量に描画する必要があり、
>>要求スペックが格段に上がることになってしまいます。
図形描画系はそんなに重い処理では無いと思いますし、ゲーム開始時やシーンの開始時にMakeScreen()で作成したグラフィックハンドルに
一回だけ描画するようにすればいいんじゃないでしょうか?
(ソフトウェアイメージへの描画はもっと重いですし、「画像を使わずに」ということならピクセル単位でアクセスするといった事はしてないでしょうし…)
|
Re: ソフトウエアイメージに描画する関数 ( No.2 ) |
- 名前:motoYo 日時:2020/04/14 12:00
返信が遅くなりました。
MakeScreenの使い方をよくわかっていませんでした。
"アンチエイリアスに対応した円"を描画することは可能でした。
しかしこの場合、アルファ値を持たせて描画をさせたときなどに
SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA,128)等...
SetBackgroundColorで設定できる背景色によって、描画結果が異なってしまいます。
(白背景だと白っぽく、黒背景だと黒っぽくなります。)
(GetDrawScreenGraphで、別のグラフィックハンドルに渡しても変わりませんでした。)
SaveDrawScreen系列でアルファ値を持つ場合も、同様の現象が発生します。
|
Re: ソフトウエアイメージに描画する関数 ( No.3 ) |
- 名前:B.E 日時:2020/04/14 23:48
自分の環境でも確認しました。
確かにアルファチャンネル付きのグラフィックハンドルに半透明描画する時、設定した背景色によって半透明の所の色変わるみたいですね。
いつも背景黒にしてるんで気が付きませんでした。
(DX_BLENDMODE_ALPHAもDX_BLENDMODE_PMA_ALPHAでもどっちも変わるみたいですね…。)
なにか理由はありそうですが、これは管理人様に聞かないとわからないですね。
SaveDrawScreenToPNG()で書き出して、ペイントソフトで色の数値調べて見ましたけど、
透明度が100パーセントの所に描画する時も背景色とブレンドしてるみたいですね…。
これが仕様なのかバグなのかわかりませんが、描画の結果がバラバラになるのは
素材を描画する際の背景色を統一すれば避けれると思うのですがどうですかね?
とりあえず
SetBackgroundColor(128, 128, 128,0);
ClearDrawScreen();
をしてから描画するのが一番無難な感じかと思います。
※色チェックする時勘違いしてたんで、何度か記事を修正しました。すいません。
|
Re: ソフトウエアイメージに描画する関数 ( No.4 ) |
- 名前:管理人 日時:2020/04/15 08:49
|
Re: ソフトウエアイメージに描画する関数 ( No.5 ) |
- 名前:B.E 日時:2020/04/15 10:46
管理人様
すいません、やはり乗算済を使用しても背景色が違うと描画内容が変わるようなのですが…、
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ウインドウモードで起動
ChangeWindowMode(TRUE);
// 画面サイズを400x200にする
SetGraphMode(400, 200, 32);
// DXライブラリの初期化
if (DxLib_Init() < 0) return -1;
// グラフィックハンドルを作成
int BgBlackScreen = MakeScreen(200, 200, TRUE);
// 作成したグラフィックハンドルを描画対象にする
SetDrawScreen(BgBlackScreen);
// 背景色を黒に変更してクリア
SetBackgroundColor(0, 0, 0, 0);
ClearDrawScreen();
// 乗算済みアルファ用のアルファブレンドモードを使って、不透明度50%の赤い円を描画
SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 128);
DrawOvalAA(100, 100, 90, 90, 32, 0xff0000, TRUE);
// グラフィックハンドルを作成
int BgWhiteScreen = MakeScreen(200, 200, TRUE);
// 作成したグラフィックハンドルを描画対象にする
SetDrawScreen(BgWhiteScreen);
// 背景色を白に変更してクリア
SetBackgroundColor(255, 255, 255, 0);
ClearDrawScreen();
// 乗算済みアルファ用のアルファブレンドモードを使って、不透明度50%の赤い円を描画
SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 128);
DrawOvalAA(100, 100, 90, 90, 32, 0xff0000, TRUE);
// 描画先を裏画面に変更
SetDrawScreen(DX_SCREEN_BACK);
// 結果が分かりやすいように画面を黄色にする
SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 255);
DrawBox(0, 0, 400, 200, GetColor(255, 255, 0), TRUE);
// 乗算済みアルファ用のアルファブレンドモードを使ってグラフィックハンドルを描画
SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255);
//黒背景で作成したものを描画
DrawGraph(0, 0, BgBlackScreen, TRUE);
//白背景で作成したものを描画
DrawGraph(200, 0, BgWhiteScreen, TRUE);
// 裏画面の内容を表画面に反映
ScreenFlip();
// キー入力待ち
WaitKey();
// DXライブラリの後始末
DxLib_End();
// ソフトの終了
return 0;
}
背景色が黒の時は正しく描画されているので、
アルファ付きのグラフィックハンドルの背景色は必ず黒にしてDX_BLENDMODE_PMA_ALPHAで描画して、
そのグラフィックハンドルを使ってDX_SCREEN_BACK等に描画する時も、
DX_BLENDMODE_PMA_ALPHAを使用すれば正しい表示になるという認識で大丈夫でしょうか?
(前回、勘違いして乗算済みアルファで描画したグラフィックハンドルをPNGに書き出した物を色チェックしちゃってたみたいで、
SetBackgroundColor(128, 128, 128,0)がいいんじゃないかとか間違った事を書いてしまいました。申し訳ありません。)
|
Re: ソフトウエアイメージに描画する関数 ( No.6 ) |
- 名前:管理人 日時:2020/04/16 10:21
> B.Eさん
> すいません、やはり乗算済を使用しても背景色が違うと描画内容が変わるようなのですが…、
すみません、ご指摘の通り乗算済みアルファを使用する場合は背景色は真っ黒( SetBackgroundColor( 0, 0, 0 ); )
にする必要があります
> 背景色が黒の時は正しく描画されているので、
> アルファ付きのグラフィックハンドルの背景色は必ず黒にしてDX_BLENDMODE_PMA_ALPHAで描画して、
> そのグラフィックハンドルを使ってDX_SCREEN_BACK等に描画する時も、
> DX_BLENDMODE_PMA_ALPHAを使用すれば正しい表示になるという認識で大丈夫でしょうか?
はい、その認識で大丈夫です
|
Re: ソフトウエアイメージに描画する関数 ( No.7 ) |
- 名前:B.E 日時:2020/04/17 20:37
管理人様
>>はい、その認識で大丈夫です
わかりました。ありがとうございます。
motoYoさん
というわけで、素材を描画する時は背景色は黒じゃないとダメみたいです。
前の書き込みで間違った情報書いてしまい、すいません。
お詫びといってはなんですが、以下サンプルです。
(前のやり取りみてれば、やり方はわかると思いますが、一応…)
//MakeScreen()で作ったスクリーンにアンチエイリアス付き画像を大量に描画して、DX_SCREEN_BACKに描画するサンプル
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ウインドウモードで起動
ChangeWindowMode(TRUE);
// 画面サイズを640x480にする
SetGraphMode(640, 480, 32);
// DXライブラリの初期化
if (DxLib_Init() < 0) return -1;
// グラフィックハンドルを作成
int Screen = MakeScreen(640, 480, TRUE);
// 作成したグラフィックハンドルを描画対象にする
SetDrawScreen(Screen);
// 背景色を黒に変更してクリア(デフォルトで黒だしクリアされてるけど一応…)
SetBackgroundColor(0, 0, 0, 0);
ClearDrawScreen();
// 乗算済みアルファで大量にアンチエイリアス付き図形を描画する
float Xpos, Ypos, Size;
int Color;
for (int i = 0; i < 1000; i++) {
SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, (rand() % 192) + 64);//あんまり薄いと見えないので最低でも64で…
Xpos = 0.1f * (rand() % 6200 + 100);
Ypos = 0.1f * (rand() % 4600 + 100);
Size = 0.1f * (rand() % 50 + 50);//あんまり小いさいと見えないので最低でも5ピクセルで…
Color = GetColor(rand() % 256, rand() % 256, rand() % 256);
switch (rand() % 5) {
case 0:// 四角を描く
DrawBoxAA(Xpos - Size, Ypos - Size, Xpos + Size, Ypos + Size, Color, TRUE);
break;
case 1:// 円を描く
DrawCircleAA(Xpos, Ypos, Size, 32,Color, TRUE);
break;
case 2:// 楕円を描く(実はひし形)
DrawOvalAA(Xpos, Ypos, Size, Size * 1.5f, 4, Color, TRUE);
break;
case 3:// 線を引く
DrawLineAA(Xpos - Size, Ypos - Size, Xpos + Size, Ypos + Size, Color, 0.1f * (rand() % 100) + 0.5f);
break;
case 4:// 三角を描く
DrawTriangleAA(Xpos, Ypos - Size, Xpos - Size, Ypos + Size, Xpos + Size, Ypos + Size, Color, TRUE);
break;
}
}
//この辺はグラデーション描画するための準備なんで今回のサンプルとはあんま関係ないです。
//グラデーション描画用ポリゴン構造体配列宣言
VERTEX2D Vert[4] = {
{VGet(0.0f, 0.0f, 0.0f),1.0f,GetColorU8(255, 0, 0, 255),0.0f,0.0f} ,
{VGet(640.0f, 0.0f, 0.0f),1.0f,GetColorU8(0, 255, 0, 255),0.0f,0.0f} ,
{VGet(640.0f, 480.0f, 0.0f),1.0f,GetColorU8(0, 0, 255, 255),0.0f,0.0f} ,
{VGet(0.0f, 480.0f, 0.0f),1.0f,GetColorU8(128, 128, 128, 255),0.0f,0.0f} };
//グラデーション描画用頂点インデックス
unsigned short Indices[6] = { 0,1,2,2,3,0 };
//描画座標用編集初期化
int DrawPosX = 0;
// 描画先を裏画面に変更
SetDrawScreen(DX_SCREEN_BACK);
while (ProcessMessage() == 0) {
// 背景をポリゴンでグラデーション描画
SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 255);
DrawPolygonIndexed2D(Vert, 4, Indices, 2, DX_NONE_GRAPH, FALSE);
// 乗算済みアルファ用のアルファブレンドモードを使ってグラフィックハンドルを描画
SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255);
DrawGraph(DrawPosX, 0, Screen, TRUE);
DrawGraph(DrawPosX - 640, 0, Screen, TRUE);
// 座標移動
DrawPosX += 2;
if (DrawPosX > 640)DrawPosX -= 640;
// 裏画面の内容を表画面に反映
ScreenFlip();
}
// DXライブラリの後始末
DxLib_End();
// ソフトの終了
return 0;
}
※気になった所が有ったので何度か記事修正しました。すいません。
|
|