Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.1 ) |
- 名前:Ketty 日時:2025/01/18 21:37
初心者さん
こんにちは(^^)Kettyといいます。
初心者さんがあげられた今回のご質問は、
私が過去に管理人様に相談させていただいたのものと同じ内容だと思いましたので、
下記に当時のスレッドと、その際の解決策を挙げさせていただきます。
↓バイリニア補間とLoadDivGraph
https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=view&no=3519
※先頭のhを半角にしてください。
また、解決策としては、下記の2つになります。
(1)LoadDivGraphを使用する場合は1コマ毎の一番外の1ドットを使わないようにする
(2)あらかじめ別の描画先スクリーンを用意しておいて、そこにニアレストで敷き詰めて描画した結果を、バイリニアでfloat系座標指定で描画する
よろしければご参考までにどうぞ。
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.2 ) |
- 名前:初心者 日時:2025/01/18 22:36
Kettyさんご返信ありがとうございます。
過去に同様の質問をされていたのですね。
私なりに調べたつもりではありましたが見落としていたようです。
失礼いたしました。
解決策を拝見したところ、どちらも一長一短のように見受けられますがKettyさんはどちらを利用されていますか?
おすすめ等ありましたらご意見をお聞かせください。
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.3 ) |
- 名前:Ketty 日時:2025/01/18 23:26
初心者さん
どうも(^^)Kettyです。
>どちらも一長一短のように見受けられますがKettyさんはどちらを利用されていますか?
私のケースをお答えさせていただきますね。
私は、スプライト(キャラクター)の画像はだいたい(1)で対応するようにしており、
背景とかマップチップを扱う場合は(2)で対応してます。
いくつかのチップを並べて表現するようなスプライト(キャラクター)の場合は、(2)にすることもあります。
ちなみに、(2)のための一時描画先のスクリーンは、
ゲーム起動時に、1つか2つだけあらかじめMakeScreen関数で作っておいて、
そのハンドルをゲーム内で共通して使いまわせるようにグローバルな扱いにしてます。
そうすると、メモリ消費も抑えられると思いますので。
もっと他にいいやり方があるかもしれませんが、私もまだまだ初級者の域を出てませんので、いまのところそんな感じで作ってます。
初心者さんのご参考になれば幸いです。
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.4 ) |
- 名前:初心者 日時:2025/01/19 01:05
ご返信ありがとうございます。
(1)の文言通りに周囲1pxを利用しないのが容易な方法だと見受けられますが、16x16pxマップチップ等、他のチップとのなめらかな連結が重要な場合、採用しづらいと考えました。
そこでチップの周り1pxを透過ピクセルで囲った画像で(1)を実験してみたのですが、周囲の透過ピクセルとブレンドされてしまい、周囲がぼやけてしまいました。
チップ外周を外周と同じ色のピクセルで囲うことでこのぼやけは解消可能だと思いますが、あまりにも手間なのが気がかりです。
Kettyさんはどのように(1)を実装されていますか?
▼検証用コード▼
用意する画像を 2 × 2 のグリッド上に分かれた 36px × 36px の画像に変更し検証しました。
また、コードも読み込み部分に変更を加えました。
変更前 `DxLib::LoadDivGraphF(TEXT("res/image.png"), ROWS * COLS, COLS, ROWS, RAW_SIZE, RAW_SIZE, handles.data());`
変更後 `DxLib::LoadDivGraphF(TEXT("res/image.png"), ROWS * COLS, COLS, ROWS, RAW_SIZE, RAW_SIZE, handles.data(), 0, RAW_SIZE + 2.f, RAW_SIZE + 2.f);`
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.5 ) |
- 名前:Ketty 日時:2025/01/19 09:29
初心者さん
こんにちは(^^)Kettyです。
下記に回答させていただきますね。
初心者さんの質問の意図をくみ取り損ねているかもしれませんのでその際はご指摘ください。
>Kettyさんはどのように(1)を実装されていますか?
私は、(1)については、1チップサイズが64*64で、周囲1pxを透明色255,0,255に塗りつぶした画像をLoadDivGraphで分割ロードしてますが、
画面内には、いずれかのチップ1枚ずつしか表示しないので、にじみは発生しません。
つまり、複数チップを組み合わせて敷き詰めて表示する場合は、(2)で対応しています。
あと、以下は、憶測で回答させていただきますね(的外れでしたらすみません)
>周囲の透過ピクセルとブレンドされてしまい、周囲がぼやけてしまいました。
それは乗算済みアルファで解決できることではないでしょうか?
その件についても、さきほど私がお伝えした過去に投降したスレッドにて管理人様からご助言いただいてますのでご覧ください。
管理人様からのご助言を抜粋すると、
「透過色を指定する際、この色を白や赤また彩やかな色を指定するとドットの輪郭にその色が浮き上がってしまう」
については『乗算済みアルファ』という手法を用いることで解決することができます
とのことです。
乗算済みアルファというものについては下記で管理人様が詳しく説明してくださっています。
https://dxlib.xsrv.jp/lecture/PremulAlpha/PremulAlpha.html
※先頭のhを半角にしてください。
ご参考になれば幸いです。
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.6 ) |
- 名前:初心者 日時:2025/01/19 14:50
ご返信ありがとうございます。
まず、前回の投稿内容について一部謝罪、訂正させていただきます。
> 他のチップとのなめらかな連結が重要な場合、採用しづらいと考えました。
(1)を利用する画像の選定について述べていますが、Kettyさんの返信内容(背景とかマップチップを扱う場合は(2)で対応してます。)で書かれていることを無視した内容となっています。
寝ぼけていたのだと思われます。失礼いたしました。
> 周囲の透過ピクセルとブレンドされてしまい、周囲がぼやけてしまいました。
と記述しましたが、背景色を白にして実験したところ、実際には周囲1pxが灰色に縁取られてしまうという現象でした。
(灰色の背景色で実験していたため、周囲1pxが半透明になったと勘違いしてしまいました。)
▼乗算済みアルファについて▼
私は透過色を利用せず、画素単位で透明度を指定していました。(調べたところPNG32と呼ばれる形式のようです。)
ですので乗算済みアルファは関係ないものと考えていましたが、`SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255)`を適用すると改善されました。
ただ、これでも周囲1pxの透明度が下がってしまいます。(気にならないレベルではありますが…)
Kettyさんはこの点をどう解消されていますか?
また、気になる点として、乗算済みアルファのページには
> 通常のバイリニアフィルタリング描画をした際に完全透明部分との境界に完全透明部分のピクセルの色がうっすら表示されてしまう問題の解消
と書かれていますが、完全透明部分のピクセル色は存在しないはずで、試しにアルファ値を変えずに透明部分のRGBを0,0,0からff,ff,ffへ変更してみましたが、変わらず灰色に縁どられてしまいました。
これは何故でしょうか?ご存じでしたらご教示ください。
よければ管理人様にもお伺いしたいです。
▼(1)を利用する画像の選定基準について▼
連結しない画像で(1)を利用されているということでよろしいでしょうか?
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.7 ) |
- 名前:Ketty 日時:2025/01/19 16:42
初心者さん
(^^)Kettyです。
>私は透過色を利用せず、画素単位で透明度を指定していました。(調べたところPNG32と呼ばれる形式のようです。)
>ただ、これでも周囲1pxの透明度が下がってしまいます。(気にならないレベルではありますが…)
>Kettyさんはこの点をどう解消されていますか?
透過pngのことをおっしゃっているのだと思いますが、
よく考えたら私は透過pngをマップチップ的に敷き詰めることをした実績がないですね。
(透明ピクセルを持たない画像ファイルしか扱ってないです)
初心者さんから、再現する画像ファイル(仮画像でもかまいません)と、最小限のソースコードをご提示いただけないでしょうか?
その方が他の人からのレスもつきやすいと思います(^^)
>連結しない画像で(1)を利用されているということでよろしいでしょうか?
私が(1)に使っているのは、キャラクターの歩行のアニメーションパターンのチップとかのことです。
例えば、RPGツクールとかによくある
0:垂直立ち→1:右足を前に出す→2:垂直立ち→3:左足を前に出す
のようなパターンを1枚の画像ファイル内にまとめているようなのをご想像ください。
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.8 ) |
- 名前:初心者 日時:2025/01/19 18:55
ご返信ありがとうございます。
拙いコードではありますが、検証用のコードは以下になります。
コメントにもある通り「上下キーで補間法」を「左右キーでブレンド法」を「数字キーで利用する画像」を変更できます。
利用する画像は下記URLからダウンロードし、プロジェクト以下の `./res/` ディレクトリに保存して実行してください。
h ttps://76.gigafile.nu/0320-9c5da9b7808315dd17781945374dd0d9
```C++
#include <vector>
#define DX_NON_USING_NAMESPACE_DXLIB
#include <DxLib.h>
int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) {
static constexpr float RAW_SIZE = 16.f; // 画像内の各チップサイズ
static constexpr float DRAW_SIZE = 64.f; // 描画サイズ
static constexpr float DRAW_MARGIN = 8.f; // 描画時の間隔
static constexpr std::size_t ROWS = 2; // 画像内のチップ数(Y軸方向)
static constexpr std::size_t COLS = 2; // 画像内のチップ数(X軸方向)
DxLib::ChangeWindowMode(true);
if (DxLib::DxLib_Init() == -1) {
return 0;
}
std::vector<int> handles(ROWS * COLS);
DxLib::SetDrawMode(DX_DRAWMODE_NEAREST);
DxLib::LoadDivGraphF(TEXT("res/32x32.png"), ROWS * COLS, COLS, ROWS, RAW_SIZE, RAW_SIZE, handles.data());
unsigned int bgColor = 0;
bool toWhite = true;
enum class DrawMode {
eNearest,
eBilinear,
} drawMode = DrawMode::eNearest;
enum class Blend {
eNoBlend,
ePMAAlpha,
} blend = Blend::eNoBlend;
enum class Image {
e32x32,
e34x34,
e36x36,
} image = Image::e32x32;
while (DxLib::ProcessMessage() == 0 && DxLib::CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
// 上キーを押すとNearest補間
if (DxLib::CheckHitKey(KEY_INPUT_UP)) {
DxLib::SetDrawMode(DX_DRAWMODE_NEAREST);
drawMode = DrawMode::eNearest;
}
// 下キーを押すとBilinear補間
else if (DxLib::CheckHitKey(KEY_INPUT_DOWN)) {
DxLib::SetDrawMode(DX_DRAWMODE_BILINEAR);
drawMode = DrawMode::eBilinear;
}
// 左キーを押すとノーブレンド
if (DxLib::CheckHitKey(KEY_INPUT_LEFT)) {
DxLib::SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
blend = Blend::eNoBlend;
}
// 右キーを押すと乗算済みアルファブレンド
else if (DxLib::CheckHitKey(KEY_INPUT_RIGHT)) {
DxLib::SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255);
blend = Blend::ePMAAlpha;
}
// そのまま敷き詰めた画像を利用する
if (DxLib::CheckHitKey(KEY_INPUT_1)) {
DxLib::LoadDivGraph(TEXT("res/32x32.png"), ROWS * COLS, COLS, ROWS, RAW_SIZE, RAW_SIZE, handles.data());
image = Image::e32x32;
}
// 右端と下端を透明ピクセルで囲った画像を利用する
else if (DxLib::CheckHitKey(KEY_INPUT_2)) {
DxLib::LoadDivGraph(TEXT("res/34x34.png"), ROWS * COLS, COLS, ROWS, RAW_SIZE, RAW_SIZE, handles.data(), false, RAW_SIZE + 1.f, RAW_SIZE + 1.f);
image = Image::e34x34;
}
// 上下左右を透明ピクセルで囲った画像を利用する(ただし左上から分割するので、上端と左端に透明ピクセルが存在する)
else if (DxLib::CheckHitKey(KEY_INPUT_3)) {
DxLib::LoadDivGraph(TEXT("res/36x36.png"), ROWS * COLS, COLS, ROWS, RAW_SIZE, RAW_SIZE, handles.data(), false, RAW_SIZE + 2.f, RAW_SIZE + 2.f);
image = Image::e36x36;
}
// 背景色の更新
if (toWhite) {
bgColor += 0x020202;
if (bgColor > 0xffffff) {
bgColor = 0xffffff;
toWhite = false;
}
}
else {
bgColor -= 0x020202;
if (bgColor > 0xffffff) {
bgColor = 0x000000;
toWhite = true;
}
}
DxLib::ClearDrawScreen();
DxLib::DrawBoxAA(.0f, .0f, 640.f, 480.f, bgColor, true);
DxLib::DrawString(200, 16, drawMode == DrawMode::eNearest ? TEXT("DrawMode: Nearest") : TEXT("DrawMode: Bilinear"), 0x000000);
DxLib::DrawString(200, 64, drawMode == DrawMode::eNearest ? TEXT("DrawMode: Nearest") : TEXT("DrawMode: Bilinear"), 0xffffff);
DxLib::DrawString(200, 32, blend == Blend::eNoBlend ? TEXT("Blend: NoBlend") : TEXT("Blend: PMA Alpha"), 0x000000);
DxLib::DrawString(200, 80, blend == Blend::eNoBlend ? TEXT("Blend: NoBlend") : TEXT("Blend: PMA Alpha"), 0xffffff);
DxLib::DrawString(200, 48, image == Image::e32x32 ? TEXT("Image: 32x32") : image == Image::e34x34 ? TEXT("Image: 34x34") : TEXT("Image: 36x36"), 0x000000);
DxLib::DrawString(200, 96, image == Image::e32x32 ? TEXT("Image: 32x32") : image == Image::e34x34 ? TEXT("Image: 34x34") : TEXT("Image: 36x36"), 0xffffff);
for (int x = 0; x < COLS; ++x) {
for (int y = 0; y < ROWS; ++y) {
const auto handle = handles[std::size_t(x + y * COLS)];
DxLib::DrawRotaGraph3F(
x * (DRAW_SIZE + DRAW_MARGIN) + DRAW_MARGIN,
y * (DRAW_SIZE + DRAW_MARGIN) + DRAW_MARGIN,
.0f,
.0f,
DRAW_SIZE / RAW_SIZE,
DRAW_SIZE / RAW_SIZE,
.0f,
handles[std::size_t(x + y * COLS)],
true
);
}
}
DxLib::ScreenFlip();
}
DxLib::DxLib_End();
return 0;
}
```
 |
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.9 ) |
- 名前:初心者 日時:2025/01/19 19:05
▼No.8で挙げた検証用コードに関して▼
表題の件は「DrawMode: Bilinear, Image: 32x32」で確認していいただけます。(ブレンドは問いません)
周り1pxを透過ピクセルで囲った画像がぼやける件は「DrawMode: Bilinear, Image: 34x34」で確認していただけます。
この状態でブレンドモードを切り替えて頂くと、「No.6 : ▼乗算済みアルファについて▼」の内容が確認できるかと思います。
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.10 ) |
- 名前:Ketty 日時:2025/01/19 21:33
初心者さん
(^^)Kettyです。
resディレクトリとソースコードをダウンロードさせていただきました。
そして、まず、「表題の件」の「にじみ」は私の手元でも再現できました。
つぎに、「No.6 : ▼乗算済みアルファについて▼」の内容までは現時点で言及できませんが、取り急ぎで気になった点をお伝えします。
それは、どうも初心者さんがやりたいことは、(2)の方法じゃないと不可能なのではないかということです。
DrawDivGraph、DrawRotaGraphいずれもがfloat系であることから、小数誤差を避けられないと思うからです。
拡大(exRate)も使われているようですし。
なので、ひとまず(2)の疑似コードを記載しますのでお手すきの際にお試し下さい。
(引き続き調べてみますが、たぶん画像ファイルを加工するよりはラクだと思います)
// int系で画像ロードする
DxLib::LoadDivGraph((TEXT("res/32x32.png"), /*・・・*/, handles.data());
// 仮スクリーンをつくる
int tempScreen = DxLib::MakeScreen(640, 480, TRUE);
// ↓↓↓ここからメインループ
// 描画先を仮スクリーンにする
DxLib::SetDrawScreen(tempScreen);
// ここではニアレストにする
DxLib::SetDrawMode(DX_DRAWMODE_NEAREST);
// 乗算済みアルファにする
DxLib::SetDrawBlendMode(DX_BLENDMODE_PMA_ALPHA, 255);
// 仮スクリーンにint系で描画する
for (int x = 0; x < COLS; ++x) {
for (int y = 0; y < ROWS; ++y) {
const auto handle = handles[std::size_t(x + y * COLS)];
DxLib::DrawGraph(/*・・・*/, handle, TRUE);
}
}
// 乗算済みアルファ解除
DxLib::SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
// 描画先を裏画面に戻す
DxLib::SetDrawScreen(DX_SCREEN_BACK);
// ここでバイリニアにする
DxLib::SetDrawMode(DX_DRAWMODE_BILINEAR);
// 仮スクリーンの内容をfloat系指定で拡大とかもして描画する
DxLib::DrawExtendGraphF(/*・・・*/, tempScreen, TRUE);
DxLib::ScreenFlip();
// ↑↑↑ここまでメインループ
初心者さんのご意向をくみ違えていたらすみません(^^;
 |
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.11 ) |
- 名前:初心者 日時:2025/01/20 20:11
ご返信ありがとうございます。
> (2)の方法じゃないと不可能なのではないかということです。
私も薄々思っていたのですが、やはりそうですよね…
マップチップ等の連結する画像はご提示いただいたコードを参考に(2)の方法で実装したいと思います。
表題の件はこれにて解決とさせていただきます。
お付き合いいただきありがとうございました。
最後にお聞きしたいのですが、Kettyさんが(1)の方法で描画されている画像は1チップサイズが64x64とのことですが、その画像の上下左右端1px(周囲1pxではなく、64x64内の1px)は透明色のピクセルでしょうか?
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.12 ) |
- 名前:Ketty 日時:2025/01/20 20:48
初心者さん
(^^)Kettyです。
>その画像の上下左右端1px(周囲1pxではなく、64x64内の1px)は透明色のピクセルでしょうか?
その部分は、R:255,G:0,B:255という色を持っています。
画面に表示する際には、DxLib::SetTransColor(255, 0, 255); することで透明にしています。
念のため、分かりやすく、私が扱っている画像ファイルのイメージを共有させていただきます。
https://ibb.co/bLRMv2m
※先頭のhを半角にしてください
これは、1チップ64x64を4枚並べたものですが、
緑の部分に絵を描いて、ピンクの部分(64x64内枠の1px)には絵を描かないようにしています。
引き続き頑張ってください(^^
|
Re: DrawRotaGraph3 の描画結果がにじんでしまう。 ( No.13 ) |
- 名前:初心者(解決済み) 日時:2025/01/20 23:15
ご返信ありがとうございます。
ご丁寧に画像ファイルまで送っていただきありがとうございます。
参考にさせていただきます。
今後ともよろしくお願いいたします。(^^
|
|