0.2.6-dev: merge claude/r37-impostor — GitHub #542: impostor boxes from each skeleton's measured clip bounds (idle core, played clips within limits, the rest drawn directly while they play), every slot drawn inside its own scissor, frozen models posed at their clip's first frame, PIXI's pooled batch buffers (no Apple GPU stall from the per-slot flushes); golden: unchanged
# Conflicts: # CHANGELOG.md # docs/design/client.md # docs/history/0.2.6.md
This commit is contained in:
commit
a1f0d1bb6e
12 files changed
+1469
-27
No files matched your search
+10
-1
@@ -112,7 +112,8 @@
|
||||
// Assault prep = the boss field).
|
||||
// Battle device boxes (`ctx.createBox`) follow the board layer (switchableBox), so a 3D ⇄ 2D switch keeps crates.
|
||||
// Crowds and clipped Spine skeletons render through the shared impostor atlas (render/impostor.js), flushed once per
|
||||
// frame before the main pass.
|
||||
// frame before the main pass; each frame also measures queued Spine clips within a small time budget
|
||||
// (spine.js stepClipBounds: the impostor boxes, GitHub #542).
|
||||
// canPlace: `(uid, target, piece) => bool` (the game UI's form: target = {area:'board',row,col}|{area:'hand',idx})
|
||||
// or `(piece, row, col, target) => bool` (functions declaring ≥ 3 parameters). Throwing ⇒ illegal.
|
||||
// Piece shape (DESIGN §8.3): { uid, kind: 'chess'|'item'|'token', id, golden, tier, items: [{uid,id}], count, ownerUid }.
|
||||
@@ -134,6 +135,7 @@ import { backdropTextures, shadowTexture, refreshTierChips, refreshDownLabels, s
|
||||
import { TILE_H, TIER_COLORS, COLORS } from './style.js';
|
||||
import { loadBoardArt } from './boardArt.js';
|
||||
import { ImpostorAtlas } from './impostor.js';
|
||||
import { stepClipBounds } from './spine.js';
|
||||
import { loadThree, loadBoardPack, loadScenePack, webgl2Available, boardArtListed } from './board3d/load.js';
|
||||
import { BoardScene } from './board3d/scene.js';
|
||||
import { unionAreas } from './board3d/layout.js';
|
||||
@@ -199,6 +201,12 @@ export async function createFieldView(host, options = {}) {
|
||||
let view = null;
|
||||
let onAbort;
|
||||
try {
|
||||
// a vertex buffer of its own for every batch flush of a frame (PIXI's own setting on iOS) instead of uploading the one
|
||||
// shared buffer again: the impostor atlas flushes once per redrawn slot (render/impostor.js: each slot is clipped by its
|
||||
// own scissor rect, GitHub #542), and with those flushes the re-uploads stalled Apple GPUs — on an Apple M4 (Chrome,
|
||||
// ANGLE Metal) a 120-unit crowd at 1920 × 1080 ran at 42–58 fps instead of 60 (DPR 1 and 2, by the machine's load);
|
||||
// a buffer per flush costs ≈ 0.3 ms of render CPU there
|
||||
if (P.BatchRenderer && 'canUploadSameBuffer' in P.BatchRenderer) P.BatchRenderer.canUploadSameBuffer = false;
|
||||
const app = new P.Application({
|
||||
// MSAA only where it pays: dense (DPR ≥ 1.5) screens are sharp enough without it and it would cost 4× the fill
|
||||
// transparent: the 3D board canvas shows through (the 2D board paints an opaque backdrop itself)
|
||||
@@ -1820,6 +1828,7 @@ export async function createFieldView(host, options = {}) {
|
||||
if (leader && !leaderHidden) leader.view.update(dt, cam, clock);
|
||||
tiles.update(dt);
|
||||
fx.update(dt);
|
||||
stepClipBounds();
|
||||
impostors.flush();
|
||||
} catch (err) {
|
||||
if (!frame.warned) { frame.warned = true; console.error('[render] frame failed', err); }
|
||||
|
||||
Reference in new issue
Block a user