mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix(globe): Navara sprites keep a full rewrite when a commit follows it
A sprite/point set uploads its instances by update range. When the camera went far enough to move the set's origin, update() rewrote every instance (relative to the new origin) — and a commit later in the same frame cleared the ranges and kept only its own, so the GPU never got the rewrite: the instances not committed again drew offset by the origin move (a military glyph at the orbit pose drew 45 px from its point after the global → city → orbit sequence; the CPU picks, the probe and Cesium had it in place). Ranges now add up until three uploads them (it clears them after the upload). Found by the military side-by-side (11b); flights' sprites had the same exposure since 10b.
This commit is contained in:
1 parent
0b8cb855fa
commit
65e30546dd
2 files changed
+35
-1
No files matched your search
@@ -262,7 +262,9 @@ export function createMoverMesh(
|
||||
[colorAttribute, 4],
|
||||
[uvAttribute, 4],
|
||||
]) {
|
||||
value.clearUpdateRanges();
|
||||
// Ranges add up until three uploads them (and clears them): a
|
||||
// partial commit after a full rewrite in the same frame (an origin
|
||||
// move) must not drop the rewrite — sprites drew offset by the move.
|
||||
value.addUpdateRange(from * size, (to - from) * size);
|
||||
value.needsUpdate = true;
|
||||
}
|
||||
|
||||
@@ -112,3 +112,35 @@ test('points have no atlas and draw a disc', () => {
|
||||
assert.equal(mover.uniforms.uGevOutlinePx.value, 1);
|
||||
mover.dispose();
|
||||
});
|
||||
|
||||
test('an origin move uploads every instance even when a commit follows in the same frame', () => {
|
||||
const store = createMoverStore(spriteOptions);
|
||||
const mover = createMoverMesh(spriteOptions, store);
|
||||
for (let index = 0; index < 4; index++)
|
||||
store.set(index, { position: { x: 6_378_137 + index * 10, y: 0, z: 0 } });
|
||||
store.setCount(4);
|
||||
mover.commit(store.dirty());
|
||||
store.clean();
|
||||
// The GPU took that upload (three clears the ranges after it).
|
||||
mover.mesh.instanceMatrix.clearUpdateRanges();
|
||||
// The camera went far: the origin moves and every instance is rewritten...
|
||||
assert.equal(
|
||||
mover.update({
|
||||
cameraPosition: { x: 6_378_137 + 2_000_000, y: 0, z: 0 },
|
||||
cameraHeight: 2_000_000,
|
||||
fovDeg: 60,
|
||||
viewportHeightPx: 800,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
// ...then one instance changes before the frame is drawn.
|
||||
store.set(2, { rotation: 1 });
|
||||
mover.commit(store.dirty());
|
||||
store.clean();
|
||||
const ranges = mover.mesh.instanceMatrix.updateRanges;
|
||||
const covered = new Set();
|
||||
for (const { start, count } of ranges)
|
||||
for (let i = start; i < start + count; i++) covered.add(i);
|
||||
for (let i = 0; i < 4 * 16; i++)
|
||||
assert.ok(covered.has(i), `instance float ${i} is uploaded`);
|
||||
});
|
||||
Reference in new issue
Block a user