Skip to content

Commit

Permalink
[GLJS-980] Global scale factor (internal-1809)
Browse files Browse the repository at this point in the history
  • Loading branch information
underoot committed Oct 25, 2024
1 parent f27c898 commit 5ab0e67
Show file tree
Hide file tree
Showing 38 changed files with 1,001 additions and 66 deletions.
4 changes: 3 additions & 1 deletion debug/render-test.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
fadeDuration = 0,
localIdeographFontFamily = false,
operations,
scaleFactor = 1,
...options
} = style.metadata.test;

Expand All @@ -56,7 +57,8 @@
localIdeographFontFamily,
interactive: false,
attributionControl: false,
performanceMetricsCollection: false
performanceMetricsCollection: false,
scaleFactor
});

map.removeControl(map._logoControl);
Expand Down
22 changes: 11 additions & 11 deletions src/data/bucket/symbol_bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ class SymbolBucket implements Bucket {
}
}

generateCollisionDebugBuffers(zoom: number, collisionBoxArray: CollisionBoxArray) {
generateCollisionDebugBuffers(zoom: number, collisionBoxArray: CollisionBoxArray, textScaleFactor: number) {
if (this.hasDebugData()) {
this.destroyDebugData();
}
Expand All @@ -1003,7 +1003,7 @@ class SymbolBucket implements Bucket {
this.iconCollisionBox = new CollisionBuffers(CollisionBoxLayoutArray, collisionBoxLayout.members, LineIndexArray);

const iconSize = symbolSize.evaluateSizeForZoom(this.iconSizeData, zoom);
const textSize = symbolSize.evaluateSizeForZoom(this.textSizeData, zoom);
const textSize = symbolSize.evaluateSizeForZoom(this.textSizeData, zoom, textScaleFactor);

for (let i = 0; i < this.symbolInstances.length; i++) {
const symbolInstance = this.symbolInstances.get(i);
Expand Down Expand Up @@ -1041,7 +1041,7 @@ class SymbolBucket implements Bucket {
array.emplaceBack(scale, -padding, padding, zOffset);
}

_updateTextDebugCollisionBoxes(size: any, zoom: number, collisionBoxArray: CollisionBoxArray, startIndex: number, endIndex: number, instance: SymbolInstance) {
_updateTextDebugCollisionBoxes(size: any, zoom: number, collisionBoxArray: CollisionBoxArray, startIndex: number, endIndex: number, instance: SymbolInstance, scaleFactor: number) {
for (let b = startIndex; b < endIndex; b++) {
const box: CollisionBox = (collisionBoxArray.get(b) as any);
const scale = this.getSymbolInstanceTextSize(size, instance, zoom, b);
Expand All @@ -1050,7 +1050,7 @@ class SymbolBucket implements Bucket {
}
}

_updateIconDebugCollisionBoxes(size: any, zoom: number, collisionBoxArray: CollisionBoxArray, startIndex: number, endIndex: number, instance: SymbolInstance) {
_updateIconDebugCollisionBoxes(size: any, zoom: number, collisionBoxArray: CollisionBoxArray, startIndex: number, endIndex: number, instance: SymbolInstance, iconScaleFactor: number) {
for (let b = startIndex; b < endIndex; b++) {
const box = (collisionBoxArray.get(b));
const scale = this.getSymbolInstanceIconSize(size, zoom, instance.placedIconSymbolIndex);
Expand All @@ -1059,23 +1059,23 @@ class SymbolBucket implements Bucket {
}
}

updateCollisionDebugBuffers(zoom: number, collisionBoxArray: CollisionBoxArray) {
updateCollisionDebugBuffers(zoom: number, collisionBoxArray: CollisionBoxArray, textScaleFactor: number, iconScaleFactor: number) {
if (!this.hasDebugData()) {
return;
}

if (this.hasTextCollisionBoxData()) this.textCollisionBox.collisionVertexArrayExt.clear();
if (this.hasIconCollisionBoxData()) this.iconCollisionBox.collisionVertexArrayExt.clear();

const iconSize = symbolSize.evaluateSizeForZoom(this.iconSizeData, zoom);
const textSize = symbolSize.evaluateSizeForZoom(this.textSizeData, zoom);
const iconSize = symbolSize.evaluateSizeForZoom(this.iconSizeData, zoom, iconScaleFactor);
const textSize = symbolSize.evaluateSizeForZoom(this.textSizeData, zoom, textScaleFactor);

for (let i = 0; i < this.symbolInstances.length; i++) {
const symbolInstance = this.symbolInstances.get(i);
this._updateTextDebugCollisionBoxes(textSize, zoom, collisionBoxArray, symbolInstance.textBoxStartIndex, symbolInstance.textBoxEndIndex, symbolInstance);
this._updateTextDebugCollisionBoxes(textSize, zoom, collisionBoxArray, symbolInstance.verticalTextBoxStartIndex, symbolInstance.verticalTextBoxEndIndex, symbolInstance);
this._updateIconDebugCollisionBoxes(iconSize, zoom, collisionBoxArray, symbolInstance.iconBoxStartIndex, symbolInstance.iconBoxEndIndex, symbolInstance);
this._updateIconDebugCollisionBoxes(iconSize, zoom, collisionBoxArray, symbolInstance.verticalIconBoxStartIndex, symbolInstance.verticalIconBoxEndIndex, symbolInstance);
this._updateTextDebugCollisionBoxes(textSize, zoom, collisionBoxArray, symbolInstance.textBoxStartIndex, symbolInstance.textBoxEndIndex, symbolInstance, textScaleFactor);
this._updateTextDebugCollisionBoxes(textSize, zoom, collisionBoxArray, symbolInstance.verticalTextBoxStartIndex, symbolInstance.verticalTextBoxEndIndex, symbolInstance, textScaleFactor);
this._updateIconDebugCollisionBoxes(iconSize, zoom, collisionBoxArray, symbolInstance.iconBoxStartIndex, symbolInstance.iconBoxEndIndex, symbolInstance, iconScaleFactor);
this._updateIconDebugCollisionBoxes(iconSize, zoom, collisionBoxArray, symbolInstance.verticalIconBoxStartIndex, symbolInstance.verticalIconBoxEndIndex, symbolInstance, iconScaleFactor);
}

if (this.hasTextCollisionBoxData() && this.textCollisionBox.collisionVertexBufferExt) {
Expand Down
16 changes: 11 additions & 5 deletions src/render/draw_symbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import SegmentVector from '../data/segment';
import * as symbolProjection from '../symbol/projection';
import * as symbolSize from '../symbol/symbol_size';
import {mat4, vec3, vec4} from 'gl-matrix';
import {clamp} from '../util/util';
const identityMat4 = mat4.create();
import StencilMode from '../gl/stencil_mode';
import DepthMode from '../gl/depth_mode';
Expand Down Expand Up @@ -66,6 +67,8 @@ function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: SymbolSt
const stencilMode = StencilMode.disabled;
const colorMode = painter.colorModeForRenderPass();
const variablePlacement = layer.layout.get('text-variable-anchor');
const textSizeScaleRange = layer.layout.get('text-size-scale-range');
const textScaleFactor = clamp(painter.scaleFactor, textSizeScaleRange[0], textSizeScaleRange[1]);

//Compute variable-offsets before painting since icons and text data positioning
//depend on each other in this case.
Expand All @@ -74,7 +77,8 @@ function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: SymbolSt

layer.layout.get('text-rotation-alignment'),
layer.layout.get('text-pitch-alignment'),
variableOffsets
variableOffsets,
textScaleFactor
);
}

Expand Down Expand Up @@ -143,7 +147,7 @@ function calculateVariableRenderShift(
);
}

function updateVariableAnchors(coords: Array<OverscaledTileID>, painter: Painter, layer: SymbolStyleLayer, sourceCache: SourceCache, rotationAlignment: Alignment, pitchAlignment: Alignment, variableOffsets: Partial<Record<CrossTileID, VariableOffset>>) {
function updateVariableAnchors(coords: Array<OverscaledTileID>, painter: Painter, layer: SymbolStyleLayer, sourceCache: SourceCache, rotationAlignment: Alignment, pitchAlignment: Alignment, variableOffsets: Partial<Record<CrossTileID, VariableOffset>>, textScaleFactor: number) {
const tr = painter.transform;
const rotateWithMap = rotationAlignment === 'map';
const pitchWithMap = pitchAlignment === 'map';
Expand All @@ -156,7 +160,7 @@ function updateVariableAnchors(coords: Array<OverscaledTileID>, painter: Painter
}

const sizeData = bucket.textSizeData;
const size = symbolSize.evaluateSizeForZoom(sizeData, tr.zoom);
const size = symbolSize.evaluateSizeForZoom(sizeData, tr.zoom, textScaleFactor);
const tileMatrix = getSymbolTileProjectionMatrix(coord, bucket.getProjection(), tr);

const pixelsToTileUnits = tr.calculatePixelsToTileUnitsMatrix(tile);
Expand Down Expand Up @@ -510,7 +514,9 @@ function drawLayerSymbols(
}

const texSize: [number, number] = tile.glyphAtlasTexture ? tile.glyphAtlasTexture.size : [0, 0];
const size = symbolSize.evaluateSizeForZoom(sizeData, tr.zoom);
const textSizeScaleRange = layer.layout.get('text-size-scale-range');
const textScaleFactor = clamp(painter.scaleFactor, textSizeScaleRange[0], textSizeScaleRange[1]);
const size = symbolSize.evaluateSizeForZoom(sizeData, tr.zoom, textScaleFactor);
const labelPlaneMatrixRendering = symbolProjection.getLabelPlaneMatrixForRendering(tileMatrix, tile.tileID.canonical, textPitchWithMap, textRotateWithMap, tr, bucket.getProjection(), s);
// labelPlaneMatrixInv is used for converting vertex pos to tile coordinates needed for sampling elevation.
const glCoordMatrix = symbolProjection.getGlCoordMatrix(tileMatrix, tile.tileID.canonical, textPitchWithMap, textRotateWithMap, tr, bucket.getProjection(), s);
Expand All @@ -537,7 +543,7 @@ function drawLayerSymbols(
const cameraUpVector = bucketIsGlobeProjection ? globeCameraUp : mercatorCameraUp;

const uniformValues = symbolUniformValues(sizeData.kind, size, rotateInShader, textPitchWithMap, painter,
matrix, uLabelPlaneMatrix, uglCoordMatrix, elevationFromSea, true, texSize, texSizeIcon, true, coord, globeToMercator, mercatorCenter, invMatrix, cameraUpVector, bucket.getProjection());
matrix, uLabelPlaneMatrix, uglCoordMatrix, elevationFromSea, true, texSize, texSizeIcon, true, coord, globeToMercator, mercatorCenter, invMatrix, cameraUpVector, bucket.getProjection(), null, null, textScaleFactor);

const atlasTexture = tile.glyphAtlasTexture ? tile.glyphAtlasTexture : null;
const atlasInterpolation = gl.LINEAR;
Expand Down
6 changes: 5 additions & 1 deletion src/render/painter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,9 @@ class Painter {

_clippingActiveLastFrame: boolean;

constructor(gl: WebGL2RenderingContext, contextCreateOptions: ContextOptions, transform: Transform, tp: ITrackedParameters) {
scaleFactor: number;

constructor(gl: WebGL2RenderingContext, contextCreateOptions: ContextOptions, transform: Transform, scaleFactor: number, tp: ITrackedParameters) {
this.context = new Context(gl, contextCreateOptions);

this.transform = transform;
Expand Down Expand Up @@ -345,6 +347,8 @@ class Painter {
this.emptyDepthTexture = new Texture(this.context, emptyDepth, gl.RGBA8);

this._clippingActiveLastFrame = false;

this.scaleFactor = scaleFactor;
}

updateTerrain(style: Style, adaptCameraAltitude: boolean) {
Expand Down
6 changes: 5 additions & 1 deletion src/render/program/symbol_program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export type SymbolUniformsType = {
['u_is_halo']: Uniform1i;
['u_icon_transition']: Uniform1f;
['u_color_adj_mat']: UniformMatrix4f;
['u_scale_factor']: Uniform1f;
};

export type SymbolDefinesType = 'PITCH_WITH_MAP_TERRAIN';
Expand Down Expand Up @@ -78,6 +79,7 @@ const symbolUniforms = (context: Context): SymbolUniformsType => ({
'u_is_halo': new Uniform1i(context),
'u_icon_transition': new Uniform1f(context),
'u_color_adj_mat': new UniformMatrix4f(context),
'u_scale_factor': new Uniform1f(context)
});

const identityMatrix = mat4.create();
Expand All @@ -104,6 +106,7 @@ const symbolUniformValues = (
projection: Projection,
colorAdjustmentMatrix?: mat4 | null,
transition?: number | null,
scaleFactor?: number | null
): UniformValues<SymbolUniformsType> => {
const transform = painter.transform;

Expand Down Expand Up @@ -138,7 +141,8 @@ const symbolUniformValues = (
'u_icon_transition': transition ? transition : 0.0,
'u_gamma_scale': pitchWithMap ? painter.transform.getCameraToCenterDistance(projection) * Math.cos(painter.terrain ? 0 : painter.transform._pitch) : 1,
'u_device_pixel_ratio': browser.devicePixelRatio,
'u_is_halo': +isHalo
'u_is_halo': +isHalo,
'u_scale_factor': scaleFactor ? scaleFactor : 1.0
};

if (projection.name === 'globe') {
Expand Down
5 changes: 3 additions & 2 deletions src/shaders/symbol.fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ uniform highp float u_gamma_scale;
uniform lowp float u_device_pixel_ratio;
uniform bool u_is_text;
uniform bool u_is_halo;
uniform lowp float u_scale_factor;
#ifdef ICON_TRANSITION
uniform float u_icon_transition;
#endif
Expand Down Expand Up @@ -76,8 +77,8 @@ void main() {
bool draw_halo = v_draw_halo > 0.0;
if (draw_halo) {
out_color = halo_color;
gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * u_gamma_scale);
buff = (6.0 - halo_width / fontScale) / SDF_PX;
gamma = (halo_blur * u_scale_factor * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * u_gamma_scale);
buff = (6.0 - halo_width * u_scale_factor / fontScale) / SDF_PX;
}

lowp float dist = texture(u_texture, v_tex_a).r;
Expand Down
1 change: 1 addition & 0 deletions src/source/geojson_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ class GeoJSONSource extends Evented<SourceEvents> implements ISource {
showCollisionBoxes: this.map.showCollisionBoxes,
promoteId: this.promoteId,
brightness: this.map.style ? (this.map.style.getBrightness() || 0.0) : 0.0,
scaleFactor: this.map.getScaleFactor(),
partial
};

Expand Down
3 changes: 2 additions & 1 deletion src/source/vector_tile_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ class VectorTileSource extends Evented<SourceEvents> implements ISource {
isSymbolTile: tile.isSymbolTile,
brightness: this.map.style ? (this.map.style.getBrightness() || 0.0) : 0.0,
extraShadowCaster: tile.isExtraShadowCaster,
tessellationStep: this.map._tessellationStep
tessellationStep: this.map._tessellationStep,
scaleFactor: this.map.getScaleFactor(),
};
params.request.collectResourceTiming = this._collectResourceTiming;

Expand Down
1 change: 1 addition & 0 deletions src/source/vector_tile_worker_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class VectorTileWorkerSource extends Evented implements WorkerSource {

if (loaded && loaded[uid]) {
const workerTile = loaded[uid];
workerTile.scaleFactor = params.scaleFactor;
workerTile.showCollisionBoxes = params.showCollisionBoxes;
workerTile.projection = params.projection;
workerTile.brightness = params.brightness;
Expand Down
1 change: 1 addition & 0 deletions src/source/worker_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export type WorkerTileParameters = RequestedTileParameters & {
collectResourceTiming?: boolean;
projection: Projection;
brightness: number;
scaleFactor: number;
extraShadowCaster?: boolean;
tessellationStep?: number // test purpose only;
partial?: boolean;
Expand Down
3 changes: 3 additions & 0 deletions src/source/worker_tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class WorkerTile {
projection: Projection;
tileTransform: TileTransform;
brightness: number;
scaleFactor: number;

status: 'parsing' | 'done';
data: VectorTile;
Expand Down Expand Up @@ -86,6 +87,7 @@ class WorkerTile {
this.brightness = params.brightness;
this.extraShadowCaster = !!params.extraShadowCaster;
this.tessellationStep = params.tessellationStep;
this.scaleFactor = params.scaleFactor;
}

parse(data: VectorTile, layerIndex: StyleLayerIndex, availableImages: Array<string>, actor: Actor, callback: WorkerTileCallback) {
Expand Down Expand Up @@ -258,6 +260,7 @@ class WorkerTile {
this.tileID.canonical,
this.tileZoom,
this.projection,
this.scaleFactor,
this.brightness);
} else if (bucket.hasPattern &&
(bucket instanceof LineBucket ||
Expand Down
50 changes: 50 additions & 0 deletions src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -2323,6 +2323,31 @@
},
"property-type": "data-driven"
},
"icon-size-scale-range": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0.8,
2
],
"doc": "Defines the minimum and maximum scaling factors for icon related properties like `icon-size`, `icon-halo-width`, `icon-halo-blur`",
"minimum": 0.1,
"maximum": 10,
"experimental": true,
"private": true,
"expression": {
"interpolated": false
},
"sdk-support": {
"basic functionality": {
"js": "3.8.0",
"android": "11.8.0",
"ios": "11.8.0"
}
},
"property-type": "data-constant"
},
"icon-text-fit": {
"type": "enum",
"values": {
Expand Down Expand Up @@ -2812,6 +2837,31 @@
},
"property-type": "data-driven"
},
"text-size-scale-range": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0.8,
2
],
"doc": "Defines the minimum and maximum scaling factors for text related properties like `text-size`, `text-max-width`, `text-halo-width`, `font-size`",
"minimum": 0.1,
"maximum": 10,
"experimental": true,
"private": true,
"expression": {
"interpolated": false
},
"sdk-support": {
"basic functionality": {
"js": "3.8.0",
"android": "11.8.0",
"ios": "11.8.0"
}
},
"property-type": "data-constant"
},
"text-max-width": {
"type": "number",
"default": 10,
Expand Down
8 changes: 8 additions & 0 deletions src/style-spec/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,10 @@ export type SymbolLayerSpecification = {
"icon-optional"?: PropertyValueSpecification<boolean>,
"icon-rotation-alignment"?: PropertyValueSpecification<"map" | "viewport" | "auto">,
"icon-size"?: DataDrivenPropertyValueSpecification<number>,
/**
* @experimental This property is experimental and subject to change in future versions.
*/
"icon-size-scale-range"?: ExpressionSpecification,
"icon-text-fit"?: DataDrivenPropertyValueSpecification<"none" | "width" | "height" | "both">,
"icon-text-fit-padding"?: DataDrivenPropertyValueSpecification<[number, number, number, number]>,
"icon-image"?: DataDrivenPropertyValueSpecification<ResolvedImageSpecification>,
Expand All @@ -530,6 +534,10 @@ export type SymbolLayerSpecification = {
"text-field"?: DataDrivenPropertyValueSpecification<FormattedSpecification>,
"text-font"?: DataDrivenPropertyValueSpecification<Array<string>>,
"text-size"?: DataDrivenPropertyValueSpecification<number>,
/**
* @experimental This property is experimental and subject to change in future versions.
*/
"text-size-scale-range"?: ExpressionSpecification,
"text-max-width"?: DataDrivenPropertyValueSpecification<number>,
"text-line-height"?: DataDrivenPropertyValueSpecification<number>,
"text-letter-spacing"?: DataDrivenPropertyValueSpecification<number>,
Expand Down
Loading

0 comments on commit 5ab0e67

Please sign in to comment.