トップページ > 記事閲覧
縮小描画の注意点について
名前:774 日時: 2018/01/02 21:19

あけましておめでとうございます。本年もどうぞよろしくお願いいたします。 下記のように SetWindowSizeChangeEnableFlag 等を使ってバックバッファから表画面に縮小描画 してみたのですが、バックバッファから表画面への転送がバイリニアではなく二アレストになるようです。 ※ バックバッファとウィンドウサイズを両方1920x1080にしてキャプチャした画像を、ツールで1280x720に二アレストで ※ 縮小した画像とほとんど同じになる。 これは仕様でしょうか? それとも、何か足りない命令がありますでしょうか? ChangeWindowMode(TRUE); // ウィンドウモード SetWindowSizeChangeEnableFlag(FALSE, TRUE); // バックバッファから表画面には縮小転送する(=等倍転送しない) SetGraphMode(1920, 1080, 32); // バックバッファは 1920x1080 にする if (DxLib_Init() == -1) {goto EXIT_PROC;} SetWindowSize(1280, 720); // 表示は 1280x720 にする SetDrawMode(DX_DRAWMODE_BILINEAR); // バイリニアを指定 SetDrawScreen(DX_SCREEN_BACK); (Windows 10 Pro x64 / GeForceGTX 1060 / VS2017 / DxLib x64 / DX11)
メンテ

Page: 1 |

Re: 縮小描画の注意点について ( No.1 )
名前:774 日時:2018/01/03 08:43

検索したら ttp://dxlib.o.oo7.jp/cgi/patiobbs/patio.cgi?mode=view&no=3198 等に同じ内容がありましたね。こちらを元に実装してみようと思います。
メンテ
Re: 縮小描画の注意点について ( No.2 )
名前:774 日時:2018/01/03 08:50

私の環境では、デフォルトでは一部のMMDモデルが正常に表示されない(モアレ状になる)ので SetZBufferBitDepth(24) を入れています。 今回検証しているときに気が付きましたが、MakeScreenで作ったオフスクリーンにMMDモデルを描画すると、上記のモアレ状の描画になってしまいます。 オフスクリーンではZバッファ深度指定が有効になっていない(16のまま?)のでしょうか?
メンテ
Re: 縮小描画の注意点について ( No.3 )
名前:管理人 日時:2018/01/03 13:28

はい、MakeScreen で作るオフスクリーンは専用にZバッファが作成されるようになっていて、 そのZバッファのビット深度は SetCreateDrawValidGraphZBufferBitDepth で指定します なので SetCreateDrawValidGraphZBufferBitDepth( 24 ) ; GraphHandle = MakeScreen( 1280, 720, TRUE ) ; のようにしていただければオフスクリーンに描画した際もモアレ状の描画ではなくなります よろしければお試しください m(_ _)m
メンテ
Re: 縮小描画の注意点について ( No.4 )
名前:774 日時:2018/01/03 16:01

ありがとうございます。SetCreateDrawValidGraphZBufferBitDepthにより正常描画を確認しました。 縮小描画の件ですが、 ・バックバッファとオフスクリーンを1920x1080で作成。表示画面は960x540 ・描画はオフスクリーンに対して実施 ・オフスクリーン全体をバックバッファ左上部分にバイリニアで縮小転送 ・ScreenFlipで表示画面部分を等倍転送 という手順でやっています。(概要は下記コードにて) // 初期化など ChangeWindowMode(TRUE); SetWindowMaxSize(1920, 1080); SetWindowMinSize(160, 90); SetWindowSizeChangeEnableFlag(FALSE, FALSE); // 等倍転送 SetGraphMode(1920, 1080, 32); // バックバッファ 1920x1080 SetWindowSize(960, 540); // 実際に表示されるウィンドウのサイズ if (DxLib_Init() == -1) goto EXIT_PROC; g_nGRAPH_OFFSCREEN = MakeScreen(1920, 1080); // オフスクリーン 1920x1080 // ループ(オフスクリーンに描画) SetDrawScreen(g_nGRAPH_OFFSCREEN); SetDrawMode(DX_DRAWMODE_BILINEAR); (各種描画) // 画面へ転送 SetDrawScreen(DX_SCREEN_BACK); // バックバッファ選択 ClearDrawScreen(); SetDrawMode(DX_DRAWMODE_BILINEAR); DrawRectExtendGraph(0, 0, 960, 540, 0, 0, 1920, 1080, g_nGRAPH_OFFSCREEN, FALSE); ScreenFlip(); コード中の960x540を1280x720にしてもOKですが、640x360など「960x540より小さい組み合わせ」だと バイリニアが効いていない状態です。(1280x720は確実に効いている。960x540はたぶん効いている。 640x360、320x180などは効いていない。800台でもおそらく効いていない?) 何か考えられる点がありますでしょうか?
メンテ
Re: 縮小描画の注意点について ( No.5 )
名前:管理人 日時:2018/01/03 19:28

バイリニア補間は『隣接する4つのピクセルの色を補間して描画する』アルゴリズムなので、 1920x1080 の縦横2分の1より小さい解像度になると正常に縮小できなくなります ( 縮小時に考慮しなければならないピクセルが4つ以上になってしまう( 面積が4分の1より小さくなる )ため ) なので、バイリニア補間で縦横2分の1より小さい解像度に縮小する場合は、一度縦横2分の1に縮小してから 更に本来の縮小サイズにする必要があります <初期化時> int g_nGRAPH_OFFSCREEN2 = MakeScreen( 960, 540 ) ; <ループ時> SetDrawScreen(g_nGRAPH_OFFSCREEN2); SetDrawMode(DX_DRAWMODE_BILINEAR); DrawExtendGraph(0, 0, 960, 540, g_nGRAPH_OFFSCREEN, FALSE); SetDrawScreen(DX_SCREEN_BACK); // バックバッファ選択 ClearDrawScreen(); SetDrawMode(DX_DRAWMODE_BILINEAR); DrawExtendGraph(0, 0, 640, 360, g_nGRAPH_OFFSCREEN2, FALSE); ScreenFlip();
メンテ
Re: 縮小描画の注意点について ( No.6 )
名前:774(解決) 日時:2018/01/03 21:49

提供いただいたコードを元にして縮小表示の実装をすることができました。 ありがとうございました。解説文もありがとうございました。
メンテ
Re: 縮小描画の注意点について ( No.7 )
名前:774 日時:2018/02/11 20:16

ちょっと内容は異なりますが、同様(?)のネタなのでここにつなげます。 C#版で、バックバッファ1920x1080、画像サイズ1920x1080、描画は1280x720に縮小、を実施するコードですが、 フォーム無しではバイリニアが効いて縮小描画されるのですすが、 フォームありでは縮小描画はされますがバイリニアが効きません(カクカク)。 同じ処理だと思うのですが、内部処理が異なるのでしょうか? フォームありではDX.SetWindowSizeChangeEnableFlagが効かない?ようなので等倍転送ができず、 FIT転送でなんとかバイリニアが効いた状態で描画したいのですが、うまくいかず悩んでおります。 よろしくお願いいたします。 ■フォーム無し using System; using DxLibDLL; namespace Project1 { static class Program { static void Main() { DX.ChangeWindowMode(DX.TRUE); DX.SetGraphMode(1920, 1080, 32); if (DX.DxLib_Init() < 0) return; DX.SetWindowSize(1280, 720); int GraphHandle = DX.LoadGraph("1920x1080.png"); DX.SetWindowStyleMode(0); DX.SetDrawMode(DX.DX_DRAWMODE_BILINEAR); DX.SetDrawScreen(DX.DX_SCREEN_BACK); while (DX.ProcessMessage() != -1) { DX.DrawGraph(0, 0, GraphHandle, DX.FALSE); DX.ScreenFlip(); } DX.DxLib_End(); } } } ■フォームあり [Program.cs] using System; using System.Windows.Forms; namespace WindowsFormsApp1 { static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); new Form1().Show(); Application.DoEvents(); // 1回呼んでおかないと終了する } } } [Form1.cs] using System; using System.Drawing; using System.Windows.Forms; using DxLibDLL; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Shown(object sender, EventArgs e) { // 【おまじないの2行】 // 1920x1080のディスプレイ環境で実行した場合、例えばDX.ScreenFlip()の前にDX.SaveDrawScreenToBMP()を // 置くと、縦1062px以上を指定するとエラー(-1)になるが、この2行を書くと回避できる。 FormBorderStyle = FormBorderStyle.None; ClientSize = new Size(1920, 1080); DX.ChangeWindowMode(DX.TRUE); DX.SetGraphMode(1920, 1080, 32); DX.SetUserWindow(Handle); if (DX.DxLib_Init() < 0) Close(); ClientSize = new Size(1280, 720); int GraphHandle = DX.LoadGraph("1920x1080.png"); FormBorderStyle = FormBorderStyle.Sizable; DX.SetWindowStyleMode(0); DX.SetDrawMode(DX.DX_DRAWMODE_BILINEAR); DX.SetDrawScreen(DX.DX_SCREEN_BACK); while (DX.ProcessMessage() != -1 && Created) { DX.DrawGraph(0, 0, GraphHandle, DX.FALSE); DX.ScreenFlip(); Application.DoEvents(); } DX.DxLib_End(); Close(); } } }
メンテ
Re: 縮小描画の注意点について ( No.8 )
名前:管理人 日時:2018/02/12 00:13

> フォーム無しではバイリニアが効いて縮小描画されるのですすが、 > フォームありでは縮小描画はされますがバイリニアが効きません(カクカク)。 > 同じ処理だと思うのですが、内部処理が異なるのでしょうか? OSの実装がどのようになっているのか私にはわかりませんが、恐らくお察しの通り両者で内部処理が異なるのだと思います > フォームありではDX.SetWindowSizeChangeEnableFlagが効かない?ようなので等倍転送ができず、 > FIT転送でなんとかバイリニアが効いた状態で描画したいのですが、うまくいかず悩んでおります。 No.4 で 774さんがされたような処理( 一度 MakeScreen で作成した画像に描画した後、裏画面に縮小後のサイズにバイリニア補間描画 )を行えば 必ずバイリニアが効いた状態で描画されると思います
メンテ
Re: 縮小描画の注意点について ( No.9 )
名前:774(解決) 日時:2018/02/12 20:36

現状、C# + フォームあり + バックバッファと描画面のサイズが異なる、という場合、MakeScreenで作った オフスクリーンへの描画などではバイリニアは問題なく効いていますし、バックバッファへの描画も問題ありません。 ですが、バックバッファ(DX_SCREEN_BACK)から描画面に転送する際、  ・必ずFIT転送になる(縮小)  ・バイリニアは効かない という問題があります。(Windows 10 x64 Pro, VSC2017, Unicode+64bit DxLib, GeForce GTX 1060) そのため、No.4で書いたようにバックバッファに1280x720縮小で描画しても、描画面への転送ではさらに縮小がかかり、 バイリニアも効きません。なお、フォーム無しでは問題ありません。 上記No.7のコードをさらに検証してみました。 コード中にSetWindowSizeChangeEnableFlag() は入れていません。        フォームなし結果 ----------------------------------------------------------------------------------------------------------------------- DirectX11 バイリニア縮小 追加でSetWindowSizeChangeEnableFlag(TRUE,FALSE)を指定すれば等倍転送になる DirectX9Ex/9/NONE ガクガク縮小 追加でSetWindowSizeChangeEnableFlag(TRUE,FALSE)を指定すれば等倍転送になる        フォームあり結果 ----------------------------------------------------------------------------------------------------------------------- DirectX11 ガクガク縮小 追加でSetWindowSizeChangeEnableFlag()は何を指定しても変化なし ... 常に(TRUE, TRUE)状態 DirectX9Ex/9/NONE 等倍転送 追加でSetWindowSizeChangeEnableFlag()は何を指定しても変化なし ... 常に(TRUE, FALSE)状態 ということで、「C#、フォーム使用、バックバッファ1920x1080、表示1280x720」の状況でNo.4のような等倍転送をするには、 DirectX9Ex/X9にすればよい、という結果になりました。(NONEの描画結果が異なったのが気になります。) とは言え、  @DirectX11に比べてX9Exだと1.5〜2倍くらい遅くなった  ADirectX9ExとX11では文字描画の結果がわずかに異なる(X9の方は若干欠け気味になる。X11の方が好き)  BせっかくX11が動く環境なのでもったいない という理由から、X11をあきらめるわけにはいかないので、バイリニア縮小をあきらめました。
メンテ
Re: 縮小描画の注意点について ( No.10 )
名前:管理人 日時:2018/02/13 00:49

少し力技ですが、MakeScreen で作成するグラフィックハンドルをひとつ増やして、以下のようにすることで 『フォームあり DirectX11』でもバイリニアが適用された表示にできると思います -------- 初期化時 ------------- int Screen1 = MakeScreen( 1920, 1080 ) ; int Screen2 = MakeScreen( 1280, 720 ) ; -------- ループ時 ------------- SetDrawScreen( Screen1 ) ; ClearDrawScreen() ; 〜〜描画処理〜〜 SetDrawScreen( Screen2 ) ; SetDrawMode( DX_DRAWMODE_BILINEAR ) ; DrawExtendGraph( 0, 0, 1280, 720, Screen1, FALSE ) ; SetDrawScreen( DX_SCREEN_BACK ) ; SetDrawMode( DX_DRAWMODE_NEAREST ) ; DrawExtendGraph( 0, 0, 1920, 720, Screen2, FALSE ) ; 一度バイリニアで 1280x720 に縮小した画像を、最近点サンプリングで元の 1920x720 に拡大する、というものです ( その後、OSによって最近点サンプリングで再度 1280x720 に縮小されるので、結果バイリニアの 1280x720 になる、というものです ) よろしければお試しください
メンテ
Re: 縮小描画の注意点について ( No.11 )
名前:774(解決) 日時:2018/02/13 21:10

ご回答ありがとうございます。No.10で提供いただいたコードを元にして、目的を達成できました! 余談ですが、別の方のスレッドを見て SetChangeScreenModeGraphicsSystemResetFlag を使えば バックバッファを1920x1080固定にする必要がない(描画サイズと常に同じにして等倍転送できるので バイリニアがかかる・かからないを気にする必要が無い)と思い試してみました。 上記No.7のコードに SetChangeScreenModeGraphicsSystemResetFlag と ループ内のSetGraphMode変更を 追加したのですが、  フォームなしでは OK  フォームありでは ループ内の SetGraphMode で AccessViolationExceptionが発生 という結果でした。念のため報告いたします。
メンテ

Page: 1 |

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

   クッキー保存