トップページ > 記事閲覧
ソフトウエアイメージに描画する関数
名前:motoYo 日時: 2020/03/22 14:29

お世話になっております。 現在、自作のゲームを「画像を使わずに」制作しています。 できるだけユーザーが手を加えられないようにしたい、また、画像の色変更等の ある程度の自由度を設けたいと思い、 ソフトウエアイメージを利用して画像を作成し、グラフィックに渡して描画という形をとっています。 数日前、きれいな円の画像を作ろうと思ったのですが、 ソフトウエアイメージに描画する関数には、アンチエイリアスのついた円を描画する関数が 見た限りでは有りませんでした。(通常の円描画は可能でした。) 裏画面に直接描画することもできますが、ゲームのシステム上大量に描画する必要があり、 要求スペックが格段に上がることになってしまいます。 以下の関数を追加していただくことは可能でしょうか? (関数の内容はSoftImageなしの関数と同様です) DrawLineAASoftImage DrawBoxSoftImage DrawBoxAASoftImage DrawCircleAASoftImage DrawOvalSoftImage DrawOvalAASoftImage DrawOval_RectSoftImage DrawTriangleSoftImage DrawTriangleAASoftImage DrawQuadrangleSoftImage DrawQuadrangleAASoftImage DrawRoundRectSoftImage DrawRoundRectAASoftImage よろしくお願いします。
メンテ

Page: 1 |

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

MakeScreen で作成したグラフィックハンドルに対してアルファ値つきの 描画を行う場合は『乗算済みアルファ』というものを使用しないと 『「MakeScreen で作成したグラフィックハンドル」を裏画面に描画した場合』に 正常な透明度で描画されませんので、よろしければこちらの『乗算済みアルファ』に 関する解説をご覧になってください m(_ _)m <乗算済みアルファのすすめ> https://dxlib.xsrv.jp/lecture/PremulAlpha/PremulAlpha.html
メンテ
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; } ※気になった所が有ったので何度か記事修正しました。すいません。
メンテ

Page: 1 |

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

   クッキー保存