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

Aperta Adatta ai principianti
#7,423 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
1/5
Tempo stimato
Meno di un'ora
Idoneità per principianti
80/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
javascript

Direzione di ricerca

src/renderer/webgl/shaders/src/TilemapGPULayer.vert riga 24 (compilata in TilemapGPULayer-vert.js) calcola outTileStride da .zz (margin) invece di .ww (spacing); leggi quella riga insieme a getFrameCorner nel fragment shader per confermare che lo stride alimenta il posizionamento delle tile. Modifica il componente, ricostruisci il bundle degli shader ed esegui l'esempio HTML dell'issue con margin 2 / spacing 4 in modo che la striscia bianca della riga GPU sia allineata a filo come la riga TilemapLayer.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.

Lingua principale
JavaScript
Stelle
40.7k
Fork
7.2k
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di phaserjs/phaser

Tutte le issue di phaserjs/phaser

Issue simili

Altre issue su JavaScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.