LoginSignup
1
2

【完全解決】2Dのスプライト描画で隙間や変な線、隣の色が出る問題

Last updated at Posted at 2024-04-19

対象者

2Dのスプライト描画に悩まされていて、本質を知りたい人向けです。
正しく解説されている記事を見つけられなかったので、執筆に至りました。

原因

  • 描画位置がずれている。
  • カメラの位置がずれている。
    ※DirectX, OpenGL, Unity, UEどれも原因は一緒

補足

  • ゲームエンジンやライブラリの不具合ではない。
  • 補間方法の指定は関係ない。
  • 1ピクセル大きく描画しても解決している訳ではない。
  • テクスチャ周辺を透明ピクセルで埋めても解決はしていない。

どうしたらいいの?

描画位置とカメラの位置をずれないようにする。

なんでずれるの?

作り手が気づいてない&本質を理解できておらず発生しています。

解説

ディスプレイはピクセルという単位で描かれています。
大切なことなので、もう一度いいます。ディスプレイはピクセル単位です。

ピクセルを扱う座標は整数です。
もう一度いいますね。ピクセルは整数です。

3x3ピクセルの画像
3x3.png

この画像の中心座標は(1,1)です。※赤い部分
3x3g.png

次に大切なことを言います。ゲームエンジン/ライブラリは浮動小数で座標を扱います。
もう一度いいますね。ゲームエンジン/ライブラリは浮動小数です。

3x3背景の中に2x2のスプライトを中心に描画するとこうなります。
3x3b.png

これはピクセル領域から「はみ出ている」ので描画できません!
んじゃどうなるの?

パターン1 切り捨て
スプライトを並べた時に隙間が出来たり、欠けたりする原因はこれ
3x3c.png

パターン2 混ざる
UVのサンプリングに影響を与えて隣の色が出たり、変な色になる原因はこれ。
3x3d.png

本質はこれのどちらかです。
小数の具合に応じて、切り捨てられたり混じったり変化します。
なので、動かしてから隙間が出たりする訳です。

どうしたらいいの?

ピクセルでぴったり表示できる座標にする。
これだけです…本当にこれだけ…
3x3f.png

偶数ピクセル数の画像を描画するときは、描画位置を整数化つまりintキャストを実施して+0.5もしくは-0.5を行えばよいです。※どちらにずらすかはお好みで

奇数ピクセルの画像を描画するときは、描画位置の整数化が必要になります。
当然のことですが、幅/高さが偶数・偶奇か判定して、それぞれ計算しなければなりません。

同様にカメラの位置もずれてはいけません。こちらも気をつけましょう。

カメラの位置に応じて偶数時・奇数時の計算式が逆になりますのでご注意ください。
※整数か0.5刻みかによって違う

参考(Unity)

正常系
ピクセルぴったりにすると補間方法の違いも影響を受けていません。
正確には補間されていますが、計算結果が同じ値になります。
(高速化の観点ではニアレストネイバーの方がよいです)
image.png

異常系(GameObjectを正常に表示できない位置にずらす)
色が混じっていることが分かりますね。
補間方法が効いており、真ん中の部分がバイリニアだと隣の色が混じっています。

一見するとニアレストネイバー(Unityではポイント)が綺麗に見えるため
解決すると勘違いされる部分です。
image.png

スライスするとバイリニアは隣の色を拾って問題になることが分かりやすいですね。
内側1ピクセルスライスしたらよいとか、1ピクセル大きくすればよい、もしくは空ければよいと言われる部分です。
image.png

位置を変えれば、ニアレストネイバーでも隣の色を拾うので、何の解決にもなっていません。
image.png

異常系(カメラを正常に表示できない位置にずらす)
オブジェクトの位置が正常でも、カメラの位置がずれてると台無しです。
同様の問題が発生します。
image.png

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2