TilemapGPULayer steps between tiles by the tileset's margin instead of its spacing

オープン 初心者向け
#7,423 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 3 日以内に返信

まだ誰も着手していません。

評価

難易度
1/5
見積もり時間
1時間未満
初心者へのやさしさ
80/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
javascript

調査の方向性

src/renderer/webgl/shaders/src/TilemapGPULayer.vert の 24 行目(TilemapGPULayer-vert.js にビルドされる)は、outTileStride を .ww(spacing)ではなく .zz(margin)から計算しています。フラグメントシェーダー内の getFrameCorner と併せてその行を読み、stride がタイル配置に影響していることを確認してください。コンポーネントを変更し、シェーダーバンドルを再ビルドし、margin 2 / spacing 4 で issue の HTML 例を実行して、GPU 行の白い筋が TilemapLayer 行と同じようにぴったり揃うようにしてください。

索引モデルが issue の本文から書いたものです。

説明

Version

  • Phaser Version: 4.2.1 (also on master today)
  • Operating system: Linux
  • Browser: Chrome 149 (WebGL 2 via ANGLE)

Description

TilemapGPULayer steps from one tile to the next in the tileset by the tileset's margin instead of its spacing. In src/renderer/webgl/shaders/src/TilemapGPULayer.vert (TilemapGPULayer-vert.js, line 24):

outTileStride = uTileWidthHeightMarginSpacing.xy + uTileWidthHeightMarginSpacing.zz;

.zz is the margin; .ww is the spacing. The fragment shader then places a tile at index * outTileStride + margin (getFrameCorner), so whenever margin ≠ spacing, tile n is sampled n × (spacing − margin) pixels to the left of where it is. With the common extruded layout (margin 2, spacing 4, i.e. 2 px of extrusion round every tile), each tile along a row is sampled 2 px further off than the last: the layer shows a growing sliver of the gap or the neighbouring tile, which reads as seams or a dotted grid.

When margin = spacing (including both 0) the bug doesn't show, which is probably why it hasn't been reported. It may be part of what's seen in #7317, which uses tilesets with margin and spacing. I saw the comment there that margin and spacing shouldn't be needed with TilemapGPULayer, but the shaders do read both, and TilemapLayer handles the same tileset correctly, so either fixing the stride or warning that margin/spacing are unsupported would help.

Expected: a TilemapGPULayer draws the same tiles as a TilemapLayer with the same tileset.
Actual: tile n is offset by n × (spacing − margin) px.

Fix (tested against the example below with a patched dist/phaser.js):

outTileStride = uTileWidthHeightMarginSpacing.xy + uTileWidthHeightMarginSpacing.ww;

Example Test Code

A tileset of four tiles with margin 2 and spacing 4, each a colour with a white stripe down its left edge. Top row: TilemapGPULayer; bottom row: TilemapLayer. In the GPU row the white stripe moves 2 px right per tile index, with a dark gap opening to its left; in the TilemapLayer row it's flush on every tile. (The GPU layer is at 0,0 because of a separate position bug, #7422.)

<!doctype html>
<html><body style="margin:0">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.min.js"></script>
<script>
const TILE = 32, MARGIN = 2, SPACING = 4, COLOURS = ['#e33', '#3c3', '#36f', '#fc2'];
class Demo extends Phaser.Scene {
  create() {
    const tex = this.textures.createCanvas('tiles', MARGIN * 2 + COLOURS.length * TILE + (COLOURS.length - 1) * SPACING, TILE + MARGIN * 2);
    const ctx = tex.getContext();
    COLOURS.forEach((colour, i) => {
      const x = MARGIN + i * (TILE + SPACING);
      ctx.fillStyle = colour; ctx.fillRect(x, MARGIN, TILE, TILE);
      ctx.fillStyle = '#fff'; ctx.fillRect(x, MARGIN, 4, TILE);
    });
    tex.refresh();
    const data = [[0, 1, 2, 3, 0, 1, 2, 3]];
    for (const [gpu, y] of [[true, 0], [false, 60]]) {
      const map = this.make.tilemap({ data, tileWidth: TILE, tileHeight: TILE });
      map.createLayer(0, map.addTilesetImage('tiles', 'tiles', TILE, TILE, MARGIN, SPACING), 0, y, gpu);
    }
  }
}
new Phaser.Game({ type: Phaser.WEBGL, width: 300, height: 100, backgroundColor: '#222', scene: Demo });
</script>
</body></html>

Additional Information

Workaround until it's fixed: lay the tileset out with margin equal to spacing (e.g. margin 4, spacing 4 for 2 px of extrusion each side), which gives the same stride either way.

主要言語
JavaScript
スター
40.7k
フォーク
7.2k
PR マージ指標
30日以内にマージされた PR はありません

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

phaserjs/phaser のほかの issue

phaserjs/phaser の issue をすべて見る

似ている issue

JavaScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。