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

Đang mở Phù hợp với người mới
#7,423 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 3 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
1/5
Thời gian dự kiến
Dưới một giờ
Mức phù hợp với người mới
80/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
javascript
Lĩnh vực
computer-graphics

Hướng nghiên cứu

src/renderer/webgl/shaders/src/TilemapGPULayer.vert dòng 24 (được build vào TilemapGPULayer-vert.js) tính outTileStride từ .zz (margin) thay vì .ww (spacing); đọc dòng đó cùng với getFrameCorner trong fragment shader để xác nhận rằng stride cấp dữ liệu cho việc đặt tile. Sửa component, build lại shader bundle và chạy ví dụ HTML của issue với margin 2 / spacing 4 để dải trắng của hàng GPU thẳng hàng sát như hàng TilemapLayer.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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.

Ngôn ngữ chính
JavaScript
Star
40.7k
Fork
7.2k
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của phaserjs/phaser

Tất cả issue của phaserjs/phaser

Issue tương tự

Thêm issue về JavaScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.