Re: screen 全体にgraphFilter ( No.1 ) |
- 名前:B.E 日時:2019/11/08 23:03
自分の環境でも試しましたが、GraphFilter()関数はDX_SCREEN_BACKにはフィルター処理はできないみたいですね。
戻り値も-1なんでエラーになってます…。
リファレンスマニュアルに
『LoadGraph、MakeScreen等で作成したグラフィックハンドルGrHandle に対して、〜』
としか書いてないのでそういう仕様なのではないでしょうか?
そもそもDX_SCREEN_BACKがグラフィックハンドルなのか謎です…。
描画先には指定できますがDrawGraph()とかでグラフィックハンドルとして使える訳じゃないですし…。
ちなみに書かれてるコードの『//描画処理』の位置がそこだと、フィルター処理が有効だとしても色は変わらないと思います。
GraphFilter()は今現在の画像にフィルターをかけるので、フィルター処理する前に描画しないといけません。
(コピペミスかもしれませんが一応…。どちらにしろDX_SCREEN_BACKにはフィルター処理されないようなので今回の原因とは関係ないですが…。)
とりあえずDX_SCREEN_BACKにフィルター処理できないならMakeScreen()を使うしかないと思います。
やり方としては、MakeScreen();でフィルターをかける用のスクリーンを作成しておいて、
描画ループの中で、最初にSetDrawScreen()でフィルター用スクリーンを描画先にして、必要な物を描画し
次にGraphFilter()でフィルターをかけ、最後にSetDrawScreen(DX_SCREEN_BACK)で描画対象を裏画面に戻し、
DrawGraph()等でフィルタ処理をかけたスクリーンをコピーすればできます。
まあ上の説明見読めば分かると思いますが、一応コードにするとこんな感じです。
(ちゃんと動作するか確認するために書いちゃったんで、せっかくなんで載せておきます。面倒なんで各種エラー処理は省略してます)
SetGraphMode(640, 480, 32); //画面サイズ指定
DxLib_Init(); //DxLib初期化
int FilterScreenH = MakeScreen(640, 480, FALSE); //画面サイズと同じサイズでフィルター処理用のスクリーンを作成
//この辺りで描画に使う画像等読み込み
char key[256];
int cb = 0, cr = 0;
while (ProcessMessage() == 0) {
GetHitKeyStateAll(key); //キーボードのすべてのキーの押下状態を取得
if (key[KEY_INPUT_W] && cb < 255) { cb++; }
if (key[KEY_INPUT_S] && cb > -255) { cb--; }
if (key[KEY_INPUT_D] && cr < 255) { cr++; }
if (key[KEY_INPUT_A] && cr > -255) { cr--; }
SetDrawScreen(FilterScreenH); //フィルター処理用のスクリーンを描画先にする
ClearDrawScreen(); //フィルター処理用のスクリーンをクリア
//ここに描画処理を書く(描画処理はフィルター処理の前に!!)
GraphFilter(FilterScreenH, DX_GRAPH_FILTER_MONO, cb, cr);//フィルター処理用のスクリーンにフィルター処理
SetDrawScreen(DX_SCREEN_BACK); //裏画面を描画先にする
ClearDrawScreen(); //裏画面をクリア(全画面コピーしてるので省略も可)
DrawGraph(0, 0, FilterScreenH, FALSE); //フィルター処理されたスクリーンを裏画面にコピー
ScreenFlip(); //裏画面を表に反映
}
※screenSizeの宣言が元のコードになかったので分かりやすいように640, 480にしました。
コピペして使うならscreenSize.first, screenSize.secondに直してください。
あとScreenFlip()とかも自分が書きやすい位置にしちゃってます。すいません。
他のやり方として、SetDrawScreen()を何度も呼ぶのが嫌ならGetDrawScreenGraph()で描画中の裏画面ををフィルター処理用のスクリーンに転送し、
フィルター処理かけて、DrawGraph()で裏画面にコピーで戻すとかもできますが、多分転送するより描画先切り替えたほうが早いと思います。
(内部処理がどうなっているか分からないので、正直ちょっと自信ないです…。転送処理が超高速で描画先切り替えが遅いと逆になるかも…。)
一応これで全画面フィルター処理はできると思います。
ただ、もしDX_SCREEN_BACKにフィルター処理ができないのが仕様ではなく、
管理人様が意図していないバグなら、直接フィルター処理できるように修正してもらえるかもしれません…。
|
Re: screen 全体にgraphFilter ( No.2 ) |
- 名前:管理人 日時:2019/11/09 05:19
すみません、DX_SCREEN_BACK はグラフィックハンドルではないので GraphFilter で
フィルター処理を行うことはできません、B.Eさんがご紹介されている MakeScreen で
作成できる「SetDrawScreen の引数として渡せる( 描画対象にできる )グラフィックハンドル」
を使用する方法をお試しください m(_ _)m
> B.Eさん
ご質問へのご対応ありがとうございます m(_ _)m
> 多分転送するより描画先切り替えたほうが早いと思います。
はい、仰られる通り GetDrawScreenGraph で描画結果を取得してフィルターを掛けるより
SetDrawScreen を使用して描画先を切り替えた方が高速です
( 尚、最も高速なのは MakeScreen で2つグラフィックハンドルを作成して、
GraphFilterBlt を使用してフィルターを掛けた結果は別のハンドルに出力する方法です
( GraphFilter では、内部で仮の出力先に一旦出力した後、引数で渡された
グラフィックハンドルに転送するという処理を行っているので… ) )
|
Re: screen 全体にgraphFilter ( No.3 ) |
- 名前:B.E 日時:2019/11/09 16:56
> 管理人様
> ご質問へのご対応ありがとうございます m(_ _)m
いえいえ、こちらこそ管理人様の掲示板でのいつもの迅速な対応助かっております。 m(_ _)m
> ( 尚、最も高速なのは MakeScreen で2つグラフィックハンドルを作成して、
> GraphFilterBlt を使用してフィルターを掛けた結果は別のハンドルに出力する方法です
> ( GraphFilter では、内部で仮の出力先に一旦出力した後、引数で渡された
> グラフィックハンドルに転送するという処理を行っているので… ) )
なるほど、GraphFilter()は加工済の画像データだけほしいときに、元の画像データを処分する処理を、
仮の出力先を使用して元の場所に転送という内部処理でしてくれてるって感じなんですね…。
一回だけ呼ぶ場合だとGraphFilter()のほうが便利ですが、毎フレーム呼ぶような一瞬でも早く処理したいって場合は、
2つグラフィックハンドル用意してGraphFilterBlt()のほうが、仮の出力先確保や元の場所に転送などの内部処理が減る分有利なんですね。
よく分かりました、ありがとうございます。
> にゃーさん さん
という訳でフィルター処理前とフィルター処理後の2つグラフィックハンドル使用するように修正してみました。
こちらの方が前のものより高速です、よろしければ参考にどうぞ。(各種エラー処理は省略してます)
SetGraphMode(640, 480, 32); //画面サイズ指定
DxLib_Init(); //DxLib初期化
int FilterScreenH = MakeScreen(640, 480, FALSE); //画面サイズと同じサイズでフィルター処理前用のスクリーンを作成
int FilterDesScrH = MakeScreen(640, 480, FALSE); //画面サイズと同じサイズでフィルター処理後用のスクリーンを作成
//この辺りで描画に使う画像等読み込み
char key[256];
int cb = 0, cr = 0;
while (ProcessMessage() == 0) {
GetHitKeyStateAll(key); //キーボードのすべてのキーの押下状態を取得
if (key[KEY_INPUT_W] && cb < 255) { cb++; }
if (key[KEY_INPUT_S] && cb > -255) { cb--; }
if (key[KEY_INPUT_D] && cr < 255) { cr++; }
if (key[KEY_INPUT_A] && cr > -255) { cr--; }
SetDrawScreen(FilterScreenH); //フィルター処理前用のスクリーンを描画先にする
ClearDrawScreen(); //フィルター処理前用のスクリーンをクリア
//ここに描画処理を書く
GraphFilterBlt(FilterScreenH, FilterDesScrH, DX_GRAPH_FILTER_MONO, cb, cr);//処理前用のスクリーンにフィルター処理して処理後用スクリーンへ
SetDrawScreen(DX_SCREEN_BACK); //裏画面を描画先にする
DrawGraph(0, 0, FilterDesScrH, FALSE); //フィルター処理後用スクリーンを裏画面にコピー
ScreenFlip(); //裏画面を表に反映
}
|
Re: screen 全体にgraphFilter ( No.4 ) |
- 名前:にゃーさん 日時:2019/11/11 23:56
大変遅くなりましたが、無事自分のやりたいことができました。
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && GetHitKeyStateAll(key) == 0) {
の部分は必ずこうしないといけない という気持ちでしたが
理由をわかっていれば バラしても使えるんですね。。。(バラしてみて初めてなんとなくわかった気がします、、、)
あと「
GraphFilterBlt(FilterScreenH, FilterDesScrH, DX_GRAPH_FILTER_MONO, cb, cr);
SetDrawScreen(DX_SCREEN_BACK);
DrawGraph(0, 0, FilterDesScrH, FALSE);
」の部分も予想外でした。。。
> B.Eさん、管理人様
ご教授ありがとうございました。
ここから頑張って応用させてみようと思います。
あらためて、ありがとうございました。
|
|