TilemapGPULayer steps between tiles by the tileset's margin instead of its spacing
メンテナーはふだん 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
mastertoday) - 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 はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
phaserjs/phaser のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 80/100
メンテナーはふだん 3 日以内に返信
-
Type definition for TilemapLayer.getTileAt is wrong対応中かも @hkbughk が 34 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 3 日以内に返信
-
Shader.preDestroy leaks its ShaderQuad's vertex buffer and VAO on every create/destroy cycle (4.2.1)対応中かも @k1epg01ng129-eng が 32 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
メンテナーはふだん 3 日以内に返信
-
Black opaque background on transparent Phaser.Text textures in Phaser 4.2.1 on older iOS WebGL対応中かも @SamuelMalmfors が 14 日前に担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
phaserjs/phaser#7392 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
flipY renders tile incorrectly対応中かも @vtxe02023274 が 26 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 3 日以内に返信
phaserjs/phaser の issue をすべて見る
似ている issue
-
Out of order / duplicate key error shows the key bytes as decimal or UTF-8, not hex対応中かも @bardrop が今日担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 86/100
-
`remix-hook-form/middleware` imports `unstable_createContext`, breaking on `react-router` >= 7.9.0オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
code-forge-io/remix-hook-form#189 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
webtorrent/webtorrent#3131 ·