トップページ > 記事閲覧
Spine描画時の補間に関して
名前:Ingaan 日時: 2024/09/19 02:46

DxLibを使ってSpineを描画しているのですが、いまいち関連するパラメータが何なのか分かりません。 (1)DrawPolygonIndexed2D()に影響する補間設定 SFMLやDirectX環境下のSDLと比べると画素間の切れ目がはっきり出てしまい、 特にアニメーション時に生じる波打ちが気になってしまいます。 [DxLibによる描画結果。波打ちが生じてしまう。](ttps://ibb.co/0rS2xZm) [SFMLによる描画結果。輪郭は滑らか。](ttps://ibb.co/vXKH9vT) [DxLibによる描画結果。画素の境目が目立つ。](ttps://ibb.co/pQHr06g) [SDLによる描画結果。境目は目立たない。](ttps://ibb.co/4K3DzL2) SFMLではglTexParameteriに対してGL_REPEAT並び、GL_LINEARを指定していて、 これはDirectXではD3D11_TEXTURE_ADDRESS_WRAP並びD3D11_FILTER_MIN_MAG_MIP_LINEARに相当するようなので、 DxLib::SetDrawMode(DX_DRAWMODE_BILINEAR); DxLib::SetTextureAddressMode(DX_TEXADDRESS_WRAP); の指定をしているのですが、指定しない場合と比較して改善が見られませんでした。 またD3D11_SAMPLER_DESCの設定に関してSDLとDxLibのコードを追いましたが、フィルタ周りに特に大きな差異はなさそうでした。 画質を向上させるにはどのような設定をいじればよいのでしょうか? (2)SaveDrawScreenToPNG()実行のための事前準備 上記の話とは直接関係ないのですが、検証用にSaveDrawScreenToPNGを使ってファイル出力しようとしたところ、 画面寸法約1800 × 1000に対して、(0, 0, 128, 128)が限度で、(0, 0, 129, 129)指定でエラーになりました。 直感的には::GetClientRect()の限度まで指定できそうな気がするのですが、何か事前に実行すべき関数があるのでしょうか? 以上、よろしくお願いします。
メンテ

Page: 1 |

Re: Spine描画時の補間に関して ( No.1 )
名前:管理人 日時:2024/09/19 16:51

> DxLib::SetDrawMode(DX_DRAWMODE_BILINEAR); > DxLib::SetTextureAddressMode(DX_TEXADDRESS_WRAP); > の指定をしているのですが、指定しない場合と比較して改善が見られませんでした。 アップしていただいた画像を拝見する限りでは SetDrawMode(DX_DRAWMODE_BILINEAR); の効果が反映されていないようで、 SetDrawMode(DX_DRAWMODE_NEAREST); の描画となってしまっているようです DrawPolygonIndexed2D の実行直前に SetDrawMode(DX_DRAWMODE_BILINEAR); を実行しても同様の描画結果となってしまいますでしょうか? > 上記の話とは直接関係ないのですが、検証用にSaveDrawScreenToPNGを使ってファイル出力しようとしたところ、 > 画面寸法約1800 × 1000に対して、(0, 0, 128, 128)が限度で、(0, 0, 129, 129)指定でエラーになりました。 手元で 1920 × 1080 の範囲の SaveDrawScreenToPNG を実行してみましたが、問題なく pngファイルを保存することができました お使いのDXライブラリのバージョンは幾つでしょうか? もし最新版をお使いではありませんでしたら、最新版を使用することで問題が解決する可能性がありますので、 よろしければこちらの暫定の最新版をお試しください m(_ _)m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 12 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい)
メンテ
Re: Spine描画時の補間に関して ( No.2 )
名前:Ingaan 日時:2024/09/19 22:19

すみません、リファレンスを見直したらSetDrawMode()はDxLib_Init()の呼び出し後に実行していたので、 元々前に呼び出していたのを後にずらしたら線形補間が反映されました。 (GetDrawMode()で確認しましたが、呼び出し前に設定してもInitで最近傍補間に戻されてしまうんですね…) SaveDrawScreenToPNG()の方はライブラリを差し替えましたが、現象は変わらず、128×128がエラーにならない限度でした。 [いくつかの寸法に対するSaveDrawScreenToPNGの戻り値](ttps://ibb.co/rvW7gzt)
メンテ
Re: Spine描画時の補間に関して ( No.3 )
名前:管理人 日時:2024/09/20 02:47

線形補間の問題は解決したようで何よりです > (GetDrawMode()で確認しましたが、呼び出し前に設定してもInitで最近傍補間に戻されてしまうんですね…) はい、殆どの関数は DxLib_Init 実行後にのみ有効となっています > SaveDrawScreenToPNG()の方はライブラリを差し替えましたが、現象は変わらず、128×128がエラーにならない限度でした。 最新のライブラリでも駄目でしたか… うーん…謎です… ↓こちらのような画面中央に描画した四角形をただpngで保存するだけのようなシンプルなプログラムでも  Ingaanさんの環境では SaveDrawScreenToPNG が失敗してしまうのでしょうか? #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; // 画面モードを 1280x720 に設定 SetGraphMode( 1280, 720, 32 ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1 ; // 画面の中央に四角形を描画 DrawBox( 640 - 100, 360 - 100, 640 + 100, 360 + 100, GetColor( 255,255,255 ), TRUE ) ; // 画面全体をPNGで保存 SaveDrawScreenToPNG( 0, 0, 1280, 720, "TestPngSave.png" ) ; // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0; }
メンテ
Re: Spine描画時の補間に関して ( No.4 )
名前:Ingaan 日時:2024/09/20 22:23

SaveDrawScreenToPNGはシンプルなプログラムの場合、正常に出力されました。 Spine描画プログラムではInit呼び出しの前に次の設定をしていることが影響しているのかもしれません。 ==================== #ifdef _WIN32 HWND hWnd = static_cast<HWND>(pWindowHandle); if (hWnd != nullptr) { iRet = DxLib::SetUserWindow(hWnd); if (iRet == -1)return; } iRet = DxLib::SetUserWindowMessageProcessDXLibFlag(hWnd != nullptr ? FALSE : TRUE); if (iRet == -1)return; iRet = DxLib::SetChangeScreenModeGraphicsSystemResetFlag(hWnd != nullptr ? FALSE : TRUE); if (iRet == -1)return; iRet = DxLib::ChangeWindowMode(TRUE); if (iRet == -1)return; #endif ==================== こちらでSaveDrawScreenToPNGのソースコードを追ってみたところ、以下のような動きでした。 1. SaveDrawScreen_WCHAR_T()で指定座標とGSYS.DrawSetting.DrawSizeX, Yを比較 2. DrawSizeX, YはNS_GetGraphSizeで書き込み 3. GetGraphSizeはDX_SCREEN_BACKの場合GSYS.Screen.MainScreenSizeX, Yの値を格納 4. MainScreenSizeX, YはGraphics_Screen_SetMainScreenSizeで変更 5. NS_SetGraphModeでDxLib_InitializeFlag == FALSEならばSetMainScreenSize呼び出し 元々リサイズするたびに::GetClientRect()の値を元にSetGraphModeを呼ぶようにしていましたが、初期化前には呼び出していませんでした。 そこで、DxLib_Init()の呼び出し前に以下のコードを追加したらうまくいきましたが、正しいやり方なのかわかりません。 ==================== #ifdef _WIN32 // 中略 int iDesktopWidth = ::GetSystemMetrics(SM_CXSCREEN); int iDesktopHeight = ::GetSystemMetrics(SM_CYSCREEN); iRet = DxLib::SetGraphMode(iDesktopWidth, iDesktopHeight, 32); #endif ==================== それとライブラリの話というよりデバッグ一般の話になってしまって恐縮なのですが、 例えばVisual Studioの場合、静的ライブラリの内部にステップインするにはどのようにするのでしょうか? 実行時のデータを追ってみようとDxLibMake3_24d.zipに含まれている.slnを元に、ソースコードを最新のものに書き換えて生成した DxLib_d.lib, DxLib_d.pdbを使おうと思ったのですが、設定が悪いのかうまくいきませんでした。
メンテ
Re: Spine描画時の補間に関して ( No.5 )
名前:管理人 日時:2024/09/20 23:34

> SaveDrawScreenToPNGはシンプルなプログラムの場合、正常に出力されました。 お試し頂きありがとうございます > Spine描画プログラムではInit呼び出しの前に次の設定をしていることが影響しているのかもしれません。 SetUserWindow, SetUserWindowMessageProcessDXLibFlag, SetChangeScreenModeGraphicsSystemResetFlag, ChangeWindowMode を使用する以下のようなテストプログラムで試してみましたが、 SaveDrawScreenToPNG は正常に動作しました #include "DxLib.h" // メッセージ処理用関数 LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { return DefWindowProc( hWnd, msg, wParam, lParam ); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow ) { char szClassNme[] = "ウィンドウクラスネーム"; HWND hWnd ; // ウインドウの作成 if( hPreInst == NULL ) { WNDCLASS myProg; myProg.style = CS_HREDRAW | CS_VREDRAW; myProg.lpfnWndProc = WndProc; myProg.cbClsExtra = 0; myProg.cbWndExtra = 0; myProg.hInstance = hInstance; myProg.hIcon = NULL; myProg.hCursor = LoadCursor( NULL, IDC_ARROW ); myProg.hbrBackground = ( HBRUSH )GetStockObject( WHITE_BRUSH ); myProg.lpszMenuName = NULL; myProg.lpszClassName = szClassNme; if( !RegisterClass( &myProg ) ) { return FALSE; } } hWnd = CreateWindow( szClassNme, "テストプログラム", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); SetUserWindow( hWnd ) ; SetUserWindowMessageProcessDXLibFlag( TRUE ) ; SetChangeScreenModeGraphicsSystemResetFlag( FALSE ) ; ChangeWindowMode( TRUE ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1; SetDrawScreen( DX_SCREEN_BACK ) ; // メッセージループ while( ProcessMessage() == 0 ) { // メッセージがあったら処理する MSG msg ; if( PeekMessage( &msg, hWnd, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ) ; DispatchMessage( &msg ) ; } // ウインドウに四角形を描画する ClearDrawScreen() ; // 描画先のサイズを取得 int w, h; GetDrawScreenSize( &w, &h ); // 画面の中心に四角形を描画 DrawBox( 100, 100, w - 100, h - 100, GetColor( 255,255,255 ), TRUE ) ; // 初回のループのみ png を保存 static bool flag = false; if( flag == false ) { flag = true; SaveDrawScreenToPNG( 0, 0, w, h, "TestSavePng.png" ); } ScreenFlip() ; } // DXライブラリの後始末 DxLib_End(); return 0; } > そこで、DxLib_Init()の呼び出し前に以下のコードを追加したらうまくいきましたが、正しいやり方なのかわかりません。 > ==================== > #ifdef _WIN32 > // 中略 >  int iDesktopWidth = ::GetSystemMetrics(SM_CXSCREEN); >  int iDesktopHeight = ::GetSystemMetrics(SM_CYSCREEN); >  >  iRet = DxLib::SetGraphMode(iDesktopWidth, iDesktopHeight, 32); > #endif > ==================== なぜこちらでエラーが発生しなくなったのかは不明ですが、特に変な挙動をしていないのでしたら こちらの対処方で問題ないと思います > それとライブラリの話というよりデバッグ一般の話になってしまって恐縮なのですが、 > 例えばVisual Studioの場合、静的ライブラリの内部にステップインするにはどのようにするのでしょうか? すみません、私も静的ライブラリの内部にステップインすることが可能なのかや、仮に可能だった場合 どのようにすれば良いのかなどは分かりません… なので静的ライブラリの内部でブレークしたい場合などは、静的ライブラリのソースファイルを プロジェクトに入れてしまうという方法でステップインできるようにしています DXライブラリもこちら↓の『DXライブラリのソースファイルを直接コンパイルして使用するプロジェクト』のように プロジェクトにDXライブラリのソースファイルを含めてしまうことでDXライブラリの関数にステップインできるようになります https://dxlib.xsrv.jp/temp/DxLibSourceTest_WithUseCLib.zip
メンテ
Re: Spine描画時の補間に関して ( No.6 )
名前:Ingaan 日時:2024/09/21 02:00

ステップインの方法ご教示ありがとうございます。参考にさせていただきます。 PNGの方はその後色々試した結果、やはり駄目でした。 SFMLの同様の機能のsf::Image::saveToFileは1920×1080(125%)のディスプレイに対して1802×1022のウィンドウを作成、 作成後にウィンドウを2928×1660までリサイズしてもPNGを出力できます。 SDLの同様の機能のIMG_SavePNGも200×200のウィンドウを作成し、その後3190×1809までリサイズしてもPNGを出力できます。 DxLibの場合、200×200でウィンドウを作成し、その後1802×1022にリサイズしてもSetGraphModeを呼ぶことで 描画自体は問題なくできるのですが、SaveDrawScreenToPNGは128×128が限度になります。 仮に先の修正コードを加えても、その後::GetClientRect()で得られる大きさが1942×1102のように ディスプレイの大きさを超えた時点でSaveDrawScreenToPNGはエラー返答になりました。
メンテ
Re: Spine描画時の補間に関して ( No.7 )
名前:管理人 日時:2024/09/21 22:02

> DxLibの場合、200×200でウィンドウを作成し、その後1802×1022にリサイズしてもSetGraphModeを呼ぶことで > 描画自体は問題なくできるのですが、SaveDrawScreenToPNGは128×128が限度になります。 私の環境ではリサイズ後のサイズで SetGraphMode を呼ぶことで SaveDrawScreenToPNG も正常に動作しました 手元で実際に SaveDrawScreenToPNG がエラーになるところを確認できれば原因も直ぐに 特定できると思いますので、もし不都合が無ければ SaveDrawScreenToPNG でエラーが 発生してしまうプロジェクトを zip などで圧縮して頂いて、こちらのメールアドレス BQE00322(あっとまーく)nifty.com ( (あっとまーく) を @ に置き換えてください ) に送っていただけないでしょうか? m(_ _)m
メンテ
Re: Spine描画時の補間に関して ( No.8 )
名前:Ingaan 日時:2024/09/22 02:36

ソースコードの方、指定のメールアドレス先に添付して送信しました。 ご確認よろしくお願いいたします。
メンテ
Re: Spine描画時の補間に関して ( No.9 )
名前:管理人 日時:2024/09/23 01:34

ありがとうございます、頂いたプログラムを手元で実行したところ原因が分かりました 『SetChangeScreenModeGraphicsSystemResetFlag( FALSE ); を実行して SetGraphMode を実行しても グラフィック関連がリセットされない状態で SetGraphMode を実行すると SaveDrawScreenToPNG の 画面サイズが正常かどうかの判定に使用している画面サイズの情報が更新されない』 というバグがありました ( このバグによりウィンドウの初期サイズ以上の大きさの SaveDrawScreenToPNG が失敗する状態でした ) バグを修正したことで Ingaanさんにお送りいただいたプログラムでも問題なく SaveDrawScreenToPNG が動作するようになりましたので、よろしければこちらの 修正版をお使いください m(_ _;m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 12 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい)
メンテ
Re: Spine描画時の補間に関して ( No.10 )
名前:Ingaan 日時:2024/09/24 22:23

対応ありがとうございます。 リサイズへの追従を確認できました。 (SetGraphModeにモニタ解像度より大きい値をエラーになることを失念しており、 SaveDrawScreenToPNG呼び出し前にもSM_CXSCREEN、SM_CYSCREENによる制限を掛けるようにしました。) しかし透過情報にどう対応すればよいのか分かりません。 画面消去色ではない箇所まで透過色として扱われてしまうようで、 画面消去色は透過としつつ、この部分を画面表示通りに保存するにはどのようにすればよいのでしょうか? [SaveDrawScreenToJPEGによる出力結果](ttps://ibb.co/R61sf67) [SaveDrawScreenToPNGによる出力結果](ttps://ibb.co/1TmJdww)
メンテ
Re: Spine描画時の補間に関して ( No.11 )
名前:管理人 日時:2024/09/25 04:53

> 画面消去色ではない箇所まで透過色として扱われてしまうようで、 > 画面消去色は透過としつつ、この部分を画面表示通りに保存するにはどのようにすればよいのでしょうか? すみません、『画面消去色ではない箇所まで透過色として扱われてしまう』というのは 具体的にはどのような状況なのか、もう少し詳しく教えていただけないでしょうか? また、お送りいただいたプログラムの内、DxlibSpineTestC について、Setting を選択して表示される ダイアログがシステムのディスプレイ設定の『テキスト、アプリ、その他の項目のサイズを変更する』で 200% に設定していると正常に表示されず、Binary のチェックを外す事ができませんでした あと、表示倍率を 100% に変更して Binary のチェックを外し手順通りに2つの atlas.txt を 選択したところ Failed to load spine(s) と表示され、ロードが行えませんでした ご確認をお願いします m(_ _)m
メンテ
Re: Spine描画時の補間に関して ( No.12 )
名前:Ingaan 日時:2024/09/25 21:57

状況としましては出力結果として上げた画像のように、画面上には形状が描き出されていて、 SaveDrawScreenToJPEGやBMPで保存した際には画面通りの画像が出力されるのに対して、 SaveDrawScreenToPNGで保存した際には抜け落ちてしまう領域が存在するというものです。 ダイアログに関してはすみません。ウィンドウ作成時にDPIを考慮するよう修正したのでメールにて送りました。 ファイルやプログラム機能の絡む部分はメール本文にて説明させていただきましたので、そちらを参照して頂ければと思います。
メンテ
Re: Spine描画時の補間に関して ( No.13 )
名前:管理人 日時:2024/09/26 01:07

すみません、本日時間が確保できずまだ更新版のプログラムを拝見できていないのですが、 SaveDrawScreenToJPG や SaveDrawScreenToBMP と同じように透明情報が無い画像として pngファイルを保存されたいとのことでしたら、以下のように関数 MakeScreen でアルファチャンネルの 無い仮画面を作成して使用することで解決することができます 〜〜〜〜〜グローバル変数定義に追加する記述〜〜〜〜〜 // 仮画面のグラフィックハンドル int TempScreen; 〜〜〜〜〜初期化処理に追加する記述〜〜〜〜〜 // 仮画面の作成 TempScreen = MakeScreen( 画面の幅, 画面の高さ, FALSE ); 〜〜〜〜〜描画処理に追加する記述〜〜〜〜〜 // 裏画面の代わりに仮画面を描画対象にする SetDrawScreen( TempScreen ); ====描画処理==== ===Sキーが押されたら SaveDrawScreenToPNG する処理=== // 描画先を裏画面にする SetDrawScreen( DX_SCREEN_BACK ); // 仮画面を裏画面に描画する DrawGraph( 0, 0, TempScreen, FALSE ); 〜〜〜〜〜画面サイズを変える処理に追加する記述〜〜〜〜〜 // 画面サイズを変更 SetGraphMode( 画面の幅, 画面の高さ, 32); // 仮画面も作り直す DeleteGraph( TempScreen ); TempScreen = MakeScreen( 画面の幅, 画面の高さ, FALSE ); よろしければお試しください m(_ _)m
メンテ
Re: Spine描画時の補間に関して ( No.14 )
名前:Ingaan 日時:2024/09/26 23:35

いいえ、透明情報は欲しいのですが、意図していない箇所が透明になることが問題でした。 それと、原因は分かりました。Spine側でspBlendMode::SP_BLEND_MODE_MULTIPLYとして指定されているスロットが問題で、 画素は最終的に(186, 171, 160, 0)のように、色情報はあるのですが、αは0のため出力時に透明になるようでした。 ========== SP_BLEND_MODE_MULTIPLYの混成計算式 ========== dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA)) dstA = dstA そこでspBlendMode::SP_BLEND_MODE_MULTIPLY指定のスロットに対しては、 (1)RGBはDX_BLENDMODE_SPINE_MULTIPLYを基調とし、 (2)αはDX_BLENDMODE_SPINE_NORMALを基調とする、 次のような混成法で描画するようにしたら、画面通りのPNGとなりました。 DxLib::SetDrawCustomBlendMode ( TRUE, DX_BLEND_DEST_COLOR, DX_BLEND_INV_SRC_ALPHA, DX_BLENDOP_ADD, DX_BLEND_ONE, DX_BLEND_INV_SRC_ALPHA, DX_BLENDOP_ADD, 255 ); (本当は重ね塗りの領域に対して常にNormalよりMultiplyが先に描画されるような順番だといいんでしょうけど、 スロットの配列順がそうなっていないんですよね…)
メンテ
Re: Spine描画時の補間に関して ( No.15 )
名前:管理人 日時:2024/09/27 00:37

なるほど、MULTIPLY が原因だったのですね、問題が解決したようで何よりです 頂いたプログラムを拝見したところ、高DPIでも Setting のダイアログが正常に表示されました これで全ての問題が解決したという認識で問題ないでしょうか?
メンテ

Page: 1 |

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

   クッキー保存