Skip to content

Commit 4a15e60

Browse files
ibesoragithub-actions[bot]
authored andcommitted
Support different interpolate zoom expressions on appearances (internal-14509)
GitOrigin-RevId: 1cc50f15d83d8d7a8014cea23ebacbb84f7cf9eb
1 parent 8a6ddda commit 4a15e60

9 files changed

Lines changed: 362 additions & 77 deletions

File tree

src/data/bucket/symbol_properties_ubo.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import type Context from '../../gl/context';
99
* the shader's SymbolPropertyHeader struct). These constants name its dword slots:
1010
*
1111
* [HEADER_DATA_DRIVEN_MASK] bitmask: 1 = property goes in the per-feature data-driven block
12-
* [HEADER_ZOOM_DEPENDENT_MASK] bitmask: 1 = property uses zoom interpolation (composite kind)
12+
* [HEADER_ZOOM_DEPENDENT_MASK] low 16 bits: 1 = property uses zoom interpolation (composite kind).
13+
* high 16 bits (>> HEADER_APPEARANCE_ZOOM_STOPS_SHIFT): 1 = appearances
14+
* override this property with differing zoom stops, so its zoom range
15+
* [zm, zM] is stored per feature in the data-driven block
1316
* [HEADER_BLOCK_SIZE_VEC4] size of the data-driven block in vec4 units (0 when no DD props)
1417
* [HEADER_OFFSETS + i] dword offset of property i within the data-driven block
1518
* (only meaningful when property i's data-driven bit is set)
@@ -22,6 +25,9 @@ export const HEADER_ZOOM_DEPENDENT_MASK = 1;
2225
export const HEADER_BLOCK_SIZE_VEC4 = 2;
2326
export const HEADER_OFFSETS = 3;
2427

28+
// Bit shift for the appearance-zoom-stops flags packed into the high half of the HEADER_ZOOM_DEPENDENT_MASK dword.
29+
export const HEADER_APPEARANCE_ZOOM_STOPS_SHIFT = 16;
30+
2531
/**
2632
* A packed value for writing into the UBO's data-driven properties array.
2733
*
@@ -56,10 +62,13 @@ export class SymbolPropertiesUBO {
5662
// Flat evaluation buffer layout — per-property start offset in a Float32Array(EVAL_FLAT_TOTAL).
5763
// fill_color[0..3], halo_color[4..7], opacity[8..9], halo_width[10..11],
5864
// halo_blur[12..13], emissive_strength[14..15], occlusion_opacity[16..17],
59-
// z_offset[18..19], translate[20..23].
65+
// z_offset[18..19], translate[20..23]
66+
// Each property also gets a 2-slot [zm, zM] zoom range starting at EVAL_FLAT_ZOOM_OFFSETS[i]
67+
// ([24,25] … [40,41]); only written for appearance-zoom-stops properties.
6068
// Colors and translate always use 4 slots; scalars always use 2 (second = 0 for non-zoom).
6169
static readonly EVAL_FLAT_OFFSETS: readonly number[] = [0, 4, 8, 10, 12, 14, 16, 18, 20];
62-
static readonly EVAL_FLAT_TOTAL = 24;
70+
static readonly EVAL_FLAT_ZOOM_OFFSETS: readonly number[] = [24, 26, 28, 30, 32, 34, 36, 38, 40];
71+
static readonly EVAL_FLAT_TOTAL = 42;
6372

6473
// The block-indices buffer is a pure identity mapping (blockIndices[i] = i): dedup currently
6574
// happens at the vertex-attribute level (duplicate features get the same index written into the
@@ -167,9 +176,10 @@ export class SymbolPropertiesUBO {
167176
}
168177
const dataDrivenMask = h[HEADER_DATA_DRIVEN_MASK];
169178
const zoomDependentMask = h[HEADER_ZOOM_DEPENDENT_MASK];
179+
const appearanceZoomStopsMask = zoomDependentMask >>> HEADER_APPEARANCE_ZOOM_STOPS_SHIFT;
170180
for (let i = 0; i < 9; i++) {
171181
if ((dataDrivenMask & (1 << i)) === 0) continue;
172-
this._copyFromFlat(base + h[HEADER_OFFSETS + i], i, flat, SymbolPropertiesUBO.EVAL_FLAT_OFFSETS[i], zoomDependentMask);
182+
this._copyFromFlat(base + h[HEADER_OFFSETS + i], i, flat, SymbolPropertiesUBO.EVAL_FLAT_OFFSETS[i], zoomDependentMask, appearanceZoomStopsMask);
173183
}
174184
// Track dword range touched so upload() can do a partial bufferSubData.
175185
if (this._propsDirtyMin === -1 || base < this._propsDirtyMin) this._propsDirtyMin = base;
@@ -201,14 +211,25 @@ export class SymbolPropertiesUBO {
201211
*
202212
* Colors (propIdx < 2) and zoom-dep translate always copy 4 dwords.
203213
* Non-zoom translate and zoom-dep scalars copy 2 dwords. Non-zoom scalars copy 1 dword.
214+
*
215+
* Appearance-zoom-stops properties additionally carry a [zm, zM] pair, written after
216+
* the value data: at relative dwords +4/+5 for colors/translate (the next vec4) and +2/+3 for
217+
* scalars (the third/fourth dword of the value's vec4).
204218
*/
205-
private _copyFromFlat(dwordOffset: number, propIdx: number, flat: Float32Array, flatOffset: number, zoomDependentMask: number): void {
219+
private _copyFromFlat(dwordOffset: number, propIdx: number, flat: Float32Array, flatOffset: number, zoomDependentMask: number, appearanceZoomStopsMask: number): void {
206220
const isColor = propIdx < 2;
207221
const isVec2 = propIdx === 8;
208222
const isZoomDep = (zoomDependentMask & (1 << propIdx)) !== 0;
209223
const count = isColor || (isVec2 && isZoomDep) ? 4 : (isVec2 || isZoomDep) ? 2 : 1;
210224

211-
for (let k = 0; k < count; k++) this.propertiesData[dwordOffset + k] = flat[flatOffset + k];
225+
this.propertiesData.set(flat.subarray(flatOffset, flatOffset + count), dwordOffset);
226+
227+
if ((appearanceZoomStopsMask & (1 << propIdx)) !== 0) {
228+
const zoomRel = isColor || isVec2 ? 4 : 2;
229+
const zStart = SymbolPropertiesUBO.EVAL_FLAT_ZOOM_OFFSETS[propIdx];
230+
this.propertiesData[dwordOffset + zoomRel] = flat[zStart];
231+
this.propertiesData[dwordOffset + zoomRel + 1] = flat[zStart + 1];
232+
}
212233
}
213234

214235
/**

0 commit comments

Comments
 (0)