Skip to content

Commit 040bf6a

Browse files
astojiljgithub-actions[bot]
authored andcommitted
[GLJS-1669] Fix pulsating zoom flickering of dashed lines (internal-10764)
GitOrigin-RevId: 64b8879215c915fb4a42fe575dc8c411106675d8
1 parent 9c01595 commit 040bf6a

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

src/render/draw_line.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ export default function drawLine(painter: Painter, sourceCache: SourceCache, lay
141141
}
142142
}
143143

144+
// Cache line-width evaluation per bucket zoom for dash anchoring to avoid evaluating per tile.
145+
const floorwidthByZoom: Record<number, number> = {};
146+
144147
const renderTiles = (coords: OverscaledTileID[], baseDefines: DynamicDefinesType[], depthMode: DepthMode, stencilMode3D: StencilMode, elevated: boolean, firstPass: boolean) => {
145148
for (const coord of coords) {
146149
const tile = sourceCache.getTile(coord);
@@ -225,6 +228,25 @@ export default function drawLine(painter: Painter, sourceCache: SourceCache, lay
225228
const matrix = isDraping ? coord.projMatrix : null;
226229
const lineWidthScale = unitInMeters ? (1.0 / bucket.tileToMeter) / pixelsToTileUnits(tile, 1, painter.transform.zoom) : 1.0;
227230
const lineFloorWidthScale = unitInMeters ? (1.0 / bucket.tileToMeter) / pixelsToTileUnits(tile, 1, Math.floor(painter.transform.zoom)) : 1.0;
231+
232+
// Avoid dash flickering while loading ideal tiles on zoom level traversal.
233+
// Override the floorwidth paint property to use width evaluated at bucket zoom
234+
// instead of camera zoom. This ensures stable dash texture coordinates when an
235+
// overscaled lower-zoom tile is temporarily rendered. Restore after draw.
236+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
237+
const widthProperty: {value: {kind: string; value: number}} | null = dasharray ? (layer.paint as any)._values['line-floorwidth'] : null;
238+
let savedFloorwidth: number | undefined;
239+
if (widthProperty && widthProperty.value.kind === 'constant') {
240+
const bz = bucket.zoom;
241+
if (!(bz in floorwidthByZoom)) {
242+
floorwidthByZoom[bz] = Math.max(0.01, layer.widthExpression().evaluate({zoom: bz}));
243+
}
244+
savedFloorwidth = widthProperty.value.value;
245+
const floorZoom = Math.floor(painter.transform.zoom);
246+
const zoomDiff = floorZoom - tile.tileID.overscaledZ;
247+
widthProperty.value.value = floorwidthByZoom[bz] * Math.pow(2, zoomDiff);
248+
}
249+
228250
const uniformValues: UniformValues<LineUniformsType | LinePatternUniformsType> = image ?
229251
linePatternUniformValues(painter, tile, layer, matrix, pixelRatio, lineWidthScale, lineFloorWidthScale, [trimStart, trimEnd], groundShadowFactor, patternTransition) :
230252
lineUniformValues(painter, tile, layer, matrix, bucket.lineClipsArray.length, pixelRatio, lineWidthScale, lineFloorWidthScale, [trimStart, trimEnd], groundShadowFactor);
@@ -329,6 +351,10 @@ export default function drawLine(painter: Painter, sourceCache: SourceCache, lay
329351
}
330352
renderLine(elevated ? stencilMode3D : painter.stencilModeForClipping(coord));
331353
}
354+
// Restore floorwidth paint property after draw
355+
if (savedFloorwidth !== undefined) {
356+
widthProperty.value.value = savedFloorwidth;
357+
}
332358
}
333359
};
334360

0 commit comments

Comments
 (0)