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

未关闭 适合新手
#7,423 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 3 天内回复

还没有人认领这个 Issue。

评估

难度
1/5
预计耗时
1 小时以内
新手友好度
80/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
javascript

调研方向

src/renderer/webgl/shaders/src/TilemapGPULayer.vert 第 24 行(构建到 TilemapGPULayer-vert.js 中)从 .zz(margin)而不是 .ww(spacing)计算 outTileStride;请结合片段着色器中的 getFrameCorner 阅读该行,以确认 stride 会参与 tile 放置。修改该组件,重新构建 shader bundle,并使用 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. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

phaserjs/phaser 的其他 Issue

查看 phaserjs/phaser 的全部 Issue

相似的 Issue

更多 JavaScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。