アトラスの縁を拡張

格子タイルの縁を伸ばし、新しい座標JSONを出力。

タイルの間の細い線やすき間は、GPUがタイルの矩形のすぐ外のテクセルをサンプリングしたときに出ます。線形フィルタリング、ミップマップ、整数でない位置のカメラが、隣のタイルや空のすき間を読んでしまうのです。縁の拡張は各タイルのいちばん外側のピクセルを外側の縁にコピーし、タイルの外に落ちたサンプルもタイル自身の色を読むようにして直します。このページはグリッドのシートの全タイルを拡張し(既定2px、0〜16)padded-atlas.pngを作り、タイルは余白 = 拡張幅、間隔 = 拡張幅 × 2に置かれます。先にエンジンを確認してください。Godot 4のTileSetはすでに内部で1pxの余白を付けています。

画像をここにドロップ複数のファイルをまとめて処理できます
アップロードなし · この端末で処理

タイルの間に線が出る理由

タイルマップはすべてのタイルをアトラスの矩形1つから描きます。最近傍フィルターでカメラが整数ピクセル上にあれば、画面の各ピクセルは矩形内のテクセル1つを読み、にじみません。線形フィルターは最も近い4つのテクセルを混ぜるので、縁のサンプルは色の最大半分を隣のテクセルから取ります。ミップマップは段階ごとに2 × 2のブロックを平均するので小さく描くほど隣が混ざり、整数でない拡大率やカメラ位置はサンプルをその縁に動かします。

余白(padding)と拡張(extrude)は別の対策です。余白(TexturePackerのshape padding)は矩形の間に透明なピクセルを残すので、隣は読まなくなりますが空のすき間を読み、それが暗い線や透けた線になります。拡張は縁のピクセルを外へ繰り返すので(TexturePacker:"repeats the sprite's pixels at the border; sprite's size is not changed")、入り込むのもタイル自身の色です。縁どうしがぴったり接するべきタイルなら、線を隠すのは拡張です。

すでにこれを行うエンジンもあります。Godot 4のTileSetAtlasSource.use_texture_paddingは既定でオンで、タイルごとに1ピクセル余分に囲んだ内部テクスチャを作るので、Godot 4のTileSetにはたいていこの作業は不要です。Tiledは拡張済みのタイルセットを使えるようmarginとspacingに対応し、PhaserのaddTilesetImageはtileMarginとtileSpacingを受け取ります。拡張するとこの2つの数値が変わり、それを忘れるのが最もよくある新しい問題です。

例:203 × 186のシートを2px拡張

シートは16 × 16のタイルが12 × 11枚、間隔1pxです。出力でのピクセル位置:

元        203 × 186:16 × 16のタイルが12 × 11枚、余白0、間隔1
拡張2     → セルごとに 16 + 2 × 2 = 20px → padded-atlas.png 12 × 20 = 240 × 11 × 20 = 220
13番      1列、1行:元 17,17 → アトラス x = 1 × 20 + 2 = 22, y = 22(ピクセル22〜37)
縁        x 20〜21はタイルの0列目を繰り返し、x 38〜39は15列目を繰り返す;2 × 2の角は角のピクセルを繰り返す
エンジン  余白2、間隔4 → Tiled margin 2 / spacing 4 · Phaser addTilesetImage(name, key, 16, 16, 2, 4) · Godot margins (2, 2), separation (4, 4)
余白だけ  同じ4pxを透明のままにすると:37番と38番のテクセルの中間の線形サンプルはタイル50%、空50%

元のシートの1pxの間隔は消えます。アトラスをグリッドから配置し直すためです。同じZIPのmetadata.jsonは元の範囲(13番は17,17)を保つので、余白アトラスには余白・間隔の値を使ってください。

結果の確認

  • padded-atlas.pngを開きます。サイズは列数 × (タイル + 2 × 拡張) × 行数 × (タイル + 2 × 拡張)で、0番のタイルが(拡張, 拡張)から始まるはずです。
  • タイル1つの縁を拡大します。縁のピクセルはすべて、そのタイルの最も近い縁のピクセルと同じはずです。
  • エンジンで余白 = 拡張、間隔 = 2 × 拡張にし、カメラをタイルの境目の上で小数単位で動かしたり拡大したりします。線が出ないはずです。

トラブルシューティング

症状考えられる原因確認方法対処
カメラが動く・拡大するときだけ線がちらつく小数の位置と線形フィルターがタイルの境目をまたいでサンプリングしているカメラを整数ピクセルの位置で止めると線が消えるアトラスを拡張するか、最近傍フィルターと整数ピクセルのカメラ位置を使う
マップを縮小したときだけ線が出るミップマップが隣のタイルを含むブロックを平均しているタイルセットのテクスチャのミップマップを切ると線が消えるもっと拡張する(2〜4px)か、2Dタイルマップのミップマップを切る
拡張した後、すべてのタイルに隣のタイルが見えるエンジンがまだ古い余白・間隔を使っている余白アトラスでは0番のタイルが(拡張, 拡張)から始まるはず余白 = 拡張、間隔 = 2 × 拡張にする(拡張2 → 2と4)
タイルの透明な部分の周りに暗い縁が出る完全に透明なピクセルの下の色が黒で、フィルターがそれを混ぜる。拡張はタイルの外側にピクセルを足すだけ縁の近くの透明ピクセルのRGBを確認エッジブリードで透明ピクセルの下の色を埋める
最近傍フィルターでミップマップなしでもすき間が残るタイル自体が離れて配置されている:マップの位置や倍率が整数ピクセルでないタイルの位置とカメラの倍率を確認マップかカメラを直す。アトラスで直せる範囲外で、Nerulioでも変えられない

バージョンと出典

docs/TILE-LAB.mdとtests/recipes-browser.pyで測定しました。1pxのタイル2 × 1枚のシートを1px拡張すると縁のピクセルが分離した6 × 3のアトラスになり、8pxのタイル・余白1・間隔2のシートは36 × 24のアトラスになってタイルのピクセル6 × 64個と左端のピクセル6 × 8個が元と一致しました。32 × 32のシートの余白3、1 × 1・1 × 16・16 × 1のセルの余白2で、基準の拡張結果とバイト一致しました(Chromium・Firefox)。例の位置は同じ配置関数で計算し直しています。エンジンの動作はGodot 4.7、Tiled、Phaser、TexturePackerの公式ドキュメントに基づきます。

参照した公式ドキュメント

使用例

元の図形サンプル · 96 × 64
元の図形サンプル · 96 × 64
処理後のサンプル · 108 × 72
処理後のサンプル · 108 × 72

このツールで作成した例です。ZIPツールはプレビューを表示します。すべてのファイルはダウンロードしたZIPで確認してください。

アトラスの縁を拡張

格子タイルの縁を伸ばし、新しい座標JSONを出力。

使い方

  1. 画像を追加
  2. 設定を調整して結果を確認
  3. 新しいファイルを保存

対応形式

PNG / JPG / WebP / AVIF / HEIC → PNG + JSON (ZIP) — 入力のデコードはブラウザ対応と追加エンジンに依存します。

このツールでできること

格子タイルの縁を伸ばし、新しい座標JSONを出力。

処理方式と検証状況

advanced · nine-blit nearest edge extrusion. 品質検証中です。Pro・Flagship水準はまだ実証されていません。

書き出す前に

格子タイルのみ。出力寸法とUV位置は変わり、UVベイクは行いません。

よくある質問

このツールにはどのような制限がありますか?

格子タイルのみ。出力寸法とUV位置は変わり、UVベイクは行いません。

ファイルはアップロードされますか?

このツールで開いたファイルはアップロードせず端末で処理します。コミュニティの投稿に明示的に添付する画像は別途アップロードされます。一部のエンジンやモデルは外部から取得するため、IPアドレスなどの接続情報は配信元に伝わります。

作業は自動保存されますか?

いいえ。画像と編集状態はこのタブに保持され、メディア出力は端末の一時保存を利用する場合があります。言語を変えても作業は残りますが、再読み込み、タブを閉じる操作、別のページへの移動で失われることがあります。