速度でぼやけてレンダリングされるスプライト


9

ゲームにベロシティを追加した後、テクスチャがぴくぴく動いているように感じます。最終的にスクリーンショットでキャプチャするまで、それは私の目だと思いました。

ここに画像の説明を入力してください

左側はゲームでレンダリングするものです。右側は元のスプライトを貼り付けたものです。(これは6倍に拡大したPhotoshopのスクリーンショットです。)

エッジがエイリアシングしていることに注意してください。サブピクセルレンダリングのように見えます。実際、整数値を使用して描画するように私のスプライト(intとして位置と速度を持っている)を強制しなかった場合、MonoGameが浮動小数点値で描画していることを誓います。しかし、そうではありません。

これらがぼやけて表示される原因は何ですか?速度を適用しないと発生しません。

正確には、私のSpriteComponentクラスにはVector2 Positionフィールドがあります。を呼び出すときDraw、私は基本的new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))にポジションに使用します。

以前、静止オブジェクトでさえジッターするバグがありPositionましたints。これは、直線ベクトルを使用し、値をに丸めなかったためです。ラウンドの代わりにFloor/ を使用するCeilingと、スプライトはシンク/ホバーします(いずれの方法でも1ピクセルの違いがあります)が、ぼやけて描画されます。


1
これは、適用されているテクスチャフィルタリングに関連していますか?
OriginalDaemon

シェーダーのコードはありますか?一部の人々は、ピクセルを中央に配置するために両方の軸に半分のピクセルを追加します。確かではありませんが、これはDirectXのみのことだと思います。
William Mariager

3
フィルタリングの非アクティブ化は、解決策ではなく回避策です。
Archy

1
レンダリングは速度について何も認識しないため、SpriteBatch.Drawへのパスの位置、サイズなどが異なるか、速度を追加する前にエラーが発生しました。どのようにSpriteBatch.Drawを正確に呼び出しますか?
Archy

1
@ ashes999この呼び出しをデバッグして、this.X、this.Y、this.originを確認しましたか?this.originは何に設定されていますか?このDraw呼び出しが同じ場合、基本的にレンダリング結果が異なることはありません。
Archy

回答:


3

まあ、これは恥ずかしいです。

整数の位置ではなく、浮動小数点の位置を使用して描画していることがわかりました。アーキーは彼のコメントで私を正しい道に向けました@ashes999 did you debug this call and checked this.X, this.Y and this.origin?

traceステートメントを追加するとすぐに、何もトレースされていないことに気付きました。私のSpriteComponentクラスは整数値を正しく使用していることがわかりましたが、SpriteSheetComponentまだrawのfloat値を使用していますVector2 Position

テクスチャフィルタリングとクランプを試したわけではありませんが、ソースイメージと同じ幅と高さ(スケーリングなし)で2Dイメージを描画していたため、これらが正しく変更されなかったのではないかと疑いました。


1
完了しました。見つかりました。
Archy

2

XNAは、ピクセルの中心を位置として使用するDirectX9を使用します。これは、描画クラスのVector2ベースのオーバーロードを使用するときに顕著です。(.5、.5)を引くと問題が解決すると思います。

詳細はこちら。


int, int引数としてVector2を渡すため、技術的にこれを行うことはできません。その上、動いているオブジェクトがないときは、物事は完全にうまく見えます。
ashes999

オブジェクトが動いているとはどういう意味ですか?XNAにはモーションの概念がなく、ユーザーが指示した場所にも描画されます。その一連の静止したスナップショット。とにかく四角形に丸めるので、四角形のオーバーロードを使用してみてください。
ClassicThunder

独自の速度の実装があります。速度に応じてフロートとして増加SpriteComponentするVector2位置があります。描画するVector2と、positionXとYの整数(丸め)バージョンで新しいバージョンを作成します。速度のない静止オブジェクトは問題なく表示されるため、これは問題ではありません。
ashes999

したがって、位置ベクトルpと速度ベクトルvがあると言って、それらをp + = vのように追加し、丸められた値を使用してpのコピーを作成します。そして、この描画の異なる値は、描画呼び出しが同じであるにもかかわらず、前のp + = vと同じ位置を持っているのですか?それは意味がないからです。
ClassicThunder

うん、それは@Archyが言っていることでもあります。デバッグしてもう一度確認してみましょう。中に追加p += vUpdate、でレンダリングしnew Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y)))ます。
ashes999

2

レンダリングは速度について何も認識していないため、位置、サイズなど、SpriteBatch.Drawへのパスが異なるか、速度を追加する前にエラーが発生しました。どのようにSpriteBatch.Drawを正確に呼び出しますか?

この呼び出しをデバッグして、this.X、this.Y、this.originを確認しましたか?this.originは何に設定されていますか?このDraw呼び出しが同じである場合、速度によるレンダリング結果が異なる方法は基本的にありません。


1

問題は、テクスチャフィルタリングがオンになっている可能性があります。それが何を意味するのかわからない場合は、2ピクセル幅の画像がある場合を考えてください。最初のピクセルは黒で、2番目のピクセルは白です。このテクスチャを拡大すると、テクスチャフィルタリングがオンの場合、テクスチャがぼやけ、黒と白のピクセル間の領域がグラデーショングレー色を使用していることがわかります。

フィルタリングがある場合とない場合の古典的なゲームの例は、DoomにはなかったのにフィルタリングがあったSuper Mario 64です。

速度を使用しない場合、テクスチャの中心がXNA(または基になるAPIが使用されている)が色を取得するサンプルポイントになるように、スプライトが配置される可能性があります。フロート速度で移動すると、スプライトの位置が変化するため、サンプルポイントがピクセルの中心と直接一致しない場合があるため、最も近いピクセルの平均である色がレンダリングに使用されます。

スプライトを画面上で非常に大きくレンダリングするだけで、フィルタリングがオンになっていることを確認できます。ぼやけている場合は、それが問題です。

レンダリングでピクセルパーフェクトな精度が必要な場合は、位置の浮動小数点値をどこかに保存する必要がありますが、レンダリングするオブジェクトの位置には整数値を使用します...または、もちろん、フィルタリングをオフにすることもできますあなたのゲームがそれを必要としない場合。

これも読んでみてください。


私の質問で述べたように、を呼び出すときは、すでに位置と元の画像サイズに整数を使用していますDraw。そのため、どのようになるかはわかりませんが、大規模にレンダリングして、テクスチャフィルタリングをオフにすると効果があるかどうかを確認します。
ashes999

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.