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が発生
という結果でした。念のため報告いたします。
|