Disable icon scaling with offsets (#3928)

This commit is contained in:
yousifd
2026-04-23 20:30:25 +03:00
committed by GitHub
parent 9e2d167656
commit f75f3b7e8f
18 changed files with 242 additions and 43 deletions

View File

@@ -39,6 +39,7 @@ layout (std140) uniform SymbolDrawableUBO {
bool u_pitch_with_map;
bool u_is_size_zoom_constant;
bool u_is_size_feature_constant;
bool u_is_offset;
highp float u_size_t; // used to interpolate between zoom stops when size is a composite function
highp float u_size; // used when size is both zoom and feature constant
@@ -115,7 +116,9 @@ lowp float opacity = u_opacity;
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!u_is_offset) {
size *= perspective_ratio;
}
float fontScale = u_is_text_prop ? size / 24.0 : size;

View File

@@ -47,6 +47,7 @@ layout (std140) uniform SymbolDrawableUBO {
bool u_pitch_with_map;
bool u_is_size_zoom_constant;
bool u_is_size_feature_constant;
bool u_is_offset;
highp float u_size_t; // used to interpolate between zoom stops when size is a composite function
highp float u_size; // used when size is both zoom and feature constant
@@ -167,7 +168,9 @@ lowp float halo_blur = u_halo_blur;
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!u_is_offset) {
size *= perspective_ratio;
}
float fontScale = u_is_text_prop ? size / 24.0 : size;

View File

@@ -46,6 +46,7 @@ layout (std140) uniform SymbolDrawableUBO {
bool u_pitch_with_map;
bool u_is_size_zoom_constant;
bool u_is_size_feature_constant;
bool u_is_offset;
highp float u_size_t; // used to interpolate between zoom stops when size is a composite function
highp float u_size; // used when size is both zoom and feature constant
@@ -166,7 +167,9 @@ lowp float halo_blur = u_halo_blur;
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!u_is_offset) {
size *= perspective_ratio;
}
float fontScale = size / 24.0;

View File

@@ -29,19 +29,20 @@ struct alignas(16) SymbolDrawableUBO {
/* 216 */ /*bool*/ int pitch_with_map;
/* 220 */ /*bool*/ int is_size_zoom_constant;
/* 224 */ /*bool*/ int is_size_feature_constant;
/* 228 */ /*bool*/ int is_offset;
/* 228 */ float size_t;
/* 232 */ float size;
/* 232 */ float size_t;
/* 236 */ float size;
// Interpolations
/* 236 */ float fill_color_t;
/* 240 */ float halo_color_t;
/* 244 */ float opacity_t;
/* 248 */ float halo_width_t;
/* 252 */ float halo_blur_t;
/* 256 */
/* 240 */ float fill_color_t;
/* 244 */ float halo_color_t;
/* 248 */ float opacity_t;
/* 252 */ float halo_width_t;
/* 256 */ float halo_blur_t;
/* 260 */
};
static_assert(sizeof(SymbolDrawableUBO) == 16 * 16, "wrong size");
static_assert(sizeof(SymbolDrawableUBO) == 17 * 16, "wrong size");
struct alignas(16) SymbolTilePropsUBO {
/* 0 */ /*bool*/ int is_text;
@@ -171,7 +172,9 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!drawable.is_offset) {
size *= perspective_ratio;
}
const float fontScale = drawable.is_text_prop ? size / 24.0 : size;
@@ -348,7 +351,9 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!drawable.is_offset) {
size *= perspective_ratio;
}
const float fontScale = drawable.is_text_prop ? size / 24.0 : size;
@@ -583,7 +588,9 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!drawable.is_offset) {
size *= perspective_ratio;
}
const float fontScale = size / 24.0;

View File

@@ -18,19 +18,20 @@ struct alignas(16) SymbolDrawableUBO {
/* 216 */ /*bool*/ int pitch_with_map;
/* 220 */ /*bool*/ int is_size_zoom_constant;
/* 224 */ /*bool*/ int is_size_feature_constant;
/* 228 */ /*bool*/ int is_offset;
/* 228 */ float size_t;
/* 232 */ float size;
/* 232 */ float size_t;
/* 236 */ float size;
// Interpolations
/* 236 */ float fill_color_t;
/* 240 */ float halo_color_t;
/* 244 */ float opacity_t;
/* 248 */ float halo_width_t;
/* 252 */ float halo_blur_t;
/* 256 */
/* 240 */ float fill_color_t;
/* 244 */ float halo_color_t;
/* 248 */ float opacity_t;
/* 252 */ float halo_width_t;
/* 256 */ float halo_blur_t;
/* 260 */
};
static_assert(sizeof(SymbolDrawableUBO) == 16 * 16);
static_assert(sizeof(SymbolDrawableUBO) == 17 * 16);
struct alignas(16) SymbolTilePropsUBO {
/* 0 */ /*bool*/ int is_text;

View File

@@ -52,6 +52,7 @@ struct SymbolDrawableUBO {
bool pitch_with_map;
bool is_size_zoom_constant;
bool is_size_feature_constant;
bool is_offset;
float size_t;
float size;
@@ -106,7 +107,9 @@ void main() {
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!drawable.is_offset) {
size *= perspective_ratio;
}
const float fontScale = drawable.is_text_prop ? size / 24.0 : size;
@@ -256,6 +259,7 @@ struct SymbolDrawableUBO {
bool pitch_with_map;
bool is_size_zoom_constant;
bool is_size_feature_constant;
bool is_offset;
float size_t;
float size;
@@ -335,7 +339,9 @@ void main() {
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!drawable.is_offset) {
size *= perspective_ratio;
}
const float fontScale = drawable.is_text_prop ? size / 24.0 : size;
@@ -563,6 +569,7 @@ struct SymbolDrawableUBO {
bool pitch_with_map;
bool is_size_zoom_constant;
bool is_size_feature_constant;
bool is_offset;
float size_t;
float size;
@@ -644,7 +651,9 @@ void main() {
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!drawable.is_offset) {
size *= perspective_ratio;
}
const float fontScale = size / 24.0;

View File

@@ -41,6 +41,7 @@ struct SymbolDrawableUBO {
pitch_with_map: u32,
is_size_zoom_constant: u32,
is_size_feature_constant: u32,
is_offset: u32,
size_t: f32,
size: f32,
@@ -175,7 +176,9 @@ fn main(in: VertexInput) -> VertexOutput {
);
let perspective_ratio = clamp(0.5 + 0.5 * distance_ratio, 0.0, 4.0);
if (drawable.is_offset == 0u) {
size *= perspective_ratio;
}
let is_text = drawable.is_text_prop != 0u;
let fontScale = select(size, size / 24.0, is_text);
@@ -348,7 +351,9 @@ fn main(in: VertexInput) -> VertexOutput {
);
let perspective_ratio = clamp(0.5 + 0.5 * distance_ratio, 0.0, 4.0);
if (drawable.is_offset == 0u) {
size *= perspective_ratio;
}
let is_text = drawable.is_text_prop != 0u;
let fontScale = select(size, size / 24.0, is_text);
@@ -597,7 +602,9 @@ fn main(in: VertexInput) -> VertexOutput {
);
let perspective_ratio = clamp(0.5 + 0.5 * distance_ratio, 0.0, 4.0);
if (drawable.is_offset == 0u) {
size *= perspective_ratio;
}
let fontScale = size / 24.0;

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -0,0 +1,125 @@
{
"version": 8,
"metadata": {
"test": {
"height": 1048
}
},
"pitch": 60,
"center": [-118.78224, 39.32157],
"zoom": 14,
"sources": {
"geojson": {
"type": "geojson",
"data": {
"type": "LineString",
"coordinates": [
[
-118.78156097142148,
39.47488496583114
],
[
-118.7823961479745,
39.28832054802072
]
]
}
}
},
"sprite": "local://sprites/almccon",
"layers": [
{
"id": "background",
"type": "background",
"layout": {"visibility": "visible"},
"paint": {"background-color": "rgba(204, 204, 204, 1)"}
},
{
"id": "streets",
"type": "line",
"source": "geojson",
"layout": {
"visibility": "visible",
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "rgba(32, 32, 32, 1)",
"line-width": 150
}
},
{
"id": "road-lane-dashes-right",
"type": "line",
"source": "geojson",
"layout": {"line-cap": "round", "line-join": "round"},
"paint": {
"line-color": "hsl(0, 0%, 100%)",
"line-dasharray": [4, 12],
"line-offset": 7
}
},
{
"id": "road-lane-dashes-left",
"type": "line",
"source": "geojson",
"layout": {"line-cap": "round", "line-join": "round"},
"paint": {
"line-color": "hsl(0, 0%, 100%)",
"line-dasharray": [4, 12],
"line-offset": -7
}
},
{
"id": "road-arrows-center",
"type": "symbol",
"source": "geojson",
"layout": {
"icon-allow-overlap": true,
"icon-image": "through",
"icon-offset": [0, 0],
"icon-rotate": 90,
"icon-rotation-alignment": "map",
"icon-pitch-alignment": "map",
"icon-size": 1,
"symbol-placement": "line",
"symbol-spacing": 300
},
"paint": {"icon-opacity": 0.8}
},
{
"id": "road-arrows-right",
"type": "symbol",
"source": "geojson",
"layout": {
"icon-allow-overlap": true,
"icon-image": "through",
"icon-offset": [50.339999999999996, 0],
"icon-rotate": 90,
"icon-rotation-alignment": "map",
"icon-pitch-alignment": "map",
"icon-size": 1,
"symbol-placement": "line",
"symbol-spacing": 300
},
"paint": {"icon-opacity": 0.8}
},
{
"id": "road-arrows-left",
"type": "symbol",
"source": "geojson",
"layout": {
"icon-allow-overlap": true,
"icon-image": "through",
"icon-offset": [-53.339999999999996, 0],
"icon-rotate": 90,
"icon-rotation-alignment": "map",
"icon-pitch-alignment": "map",
"icon-size": 1,
"symbol-placement": "line",
"symbol-spacing": 300
},
"paint": {"icon-opacity": 0.8}
}
]
}

View File

@@ -0,0 +1,23 @@
{
"through": {
"width": 48,
"height": 64,
"x": 531,
"y": 64,
"pixelRatio": 1
},
"through;right": {
"width": 48,
"height": 64,
"x": 579,
"y": 64,
"pixelRatio": 1
},
"through;slight_right": {
"width": 48,
"height": 64,
"x": 627,
"y": 64,
"pixelRatio": 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -29,6 +29,7 @@ layout (std140) uniform SymbolDrawableUBO {
bool u_pitch_with_map;
bool u_is_size_zoom_constant;
bool u_is_size_feature_constant;
bool u_is_offset;
highp float u_size_t; // used to interpolate between zoom stops when size is a composite function
highp float u_size; // used when size is both zoom and feature constant
@@ -98,7 +99,9 @@ void main() {
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!u_is_offset) {
size *= perspective_ratio;
}
float fontScale = u_is_text_prop ? size / 24.0 : size;

View File

@@ -37,6 +37,7 @@ layout (std140) uniform SymbolDrawableUBO {
bool u_pitch_with_map;
bool u_is_size_zoom_constant;
bool u_is_size_feature_constant;
bool u_is_offset;
highp float u_size_t; // used to interpolate between zoom stops when size is a composite function
highp float u_size; // used when size is both zoom and feature constant
@@ -122,7 +123,9 @@ void main() {
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!u_is_offset) {
size *= perspective_ratio;
}
float fontScale = u_is_text_prop ? size / 24.0 : size;

View File

@@ -36,6 +36,7 @@ layout (std140) uniform SymbolDrawableUBO {
bool u_pitch_with_map;
bool u_is_size_zoom_constant;
bool u_is_size_feature_constant;
bool u_is_offset;
highp float u_size_t; // used to interpolate between zoom stops when size is a composite function
highp float u_size; // used when size is both zoom and feature constant
@@ -121,7 +122,9 @@ void main() {
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
4.0);
if (!u_is_offset) {
size *= perspective_ratio;
}
float fontScale = size / 24.0;

View File

@@ -19,14 +19,16 @@ struct SymbolDrawableData : public DrawableData {
const style::AlignmentType pitchAlignment_,
const style::AlignmentType rotationAlignment_,
const style::SymbolPlacementType placement_,
const style::IconTextFitType textFit_)
const style::IconTextFitType textFit_,
const bool isOffset_)
: isHalo(isHalo_),
bucketVariablePlacement(bucketVariablePlacement_),
symbolType(symbolType_),
pitchAlignment(pitchAlignment_),
rotationAlignment(rotationAlignment_),
placement(placement_),
textFit(textFit_) {}
textFit(textFit_),
isOffset(isOffset_) {}
~SymbolDrawableData() override = default;
const bool isHalo;
@@ -36,6 +38,7 @@ struct SymbolDrawableData : public DrawableData {
const style::AlignmentType rotationAlignment;
const style::SymbolPlacementType placement;
const style::IconTextFitType textFit;
const bool isOffset;
};
using UniqueSymbolDrawableData = std::unique_ptr<SymbolDrawableData>;

View File

@@ -512,9 +512,11 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
});
}
const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get<SymbolSortKey>().isUndefined();
const auto& layout = impl_cast(baseImpl).layout;
const bool sortFeaturesByKey = !layout.get<SymbolSortKey>().isUndefined();
std::multiset<SegmentGroup> renderableSegments;
std::unique_ptr<gfx::DrawableBuilder> builder;
const bool isOffset = !layout.get<IconOffset>().isUndefined();
const auto currentZoom = static_cast<float>(state.getZoom());
const auto layerPrefix = getID() + "/";
@@ -560,8 +562,9 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
return;
}
const auto& layout = *bucket.layout;
const auto values = isText ? textPropertyValues(evaluated, layout) : iconPropertyValues(evaluated, layout);
const auto& bucketLayout = *bucket.layout;
const auto values = isText ? textPropertyValues(evaluated, bucketLayout)
: iconPropertyValues(evaluated, bucketLayout);
const std::string suffix = isText ? "text/" : "icon/";
const auto addVertices = [&collisionBuilder](const auto& vertices) {
@@ -708,8 +711,9 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderable.renderData.layerProperties);
auto& bucketPaintProperties = bucket.paintProperties.at(getID());
const auto& layout = *bucket.layout;
const auto values = isText ? textPropertyValues(evaluated, layout) : iconPropertyValues(evaluated, layout);
const auto& bucketLayout = *bucket.layout;
const auto values = isText ? textPropertyValues(evaluated, bucketLayout)
: iconPropertyValues(evaluated, bucketLayout);
const auto& atlases = tile.getAtlasTextures();
if (!atlases) {
@@ -759,7 +763,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
textSizeIsZoomConstant);
}
if (!isText && !tileInfo.iconTweaker) {
const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear;
const bool iconScaled = bucketLayout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear;
tileInfo.iconTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(atlases,
idSymbolImageIconTexture,
idSymbolImageTexture,
@@ -819,8 +823,9 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
/*.symbolType=*/renderable.type,
/*.pitchAlignment=*/values.pitchAlignment,
/*.rotationAlignment=*/values.rotationAlignment,
/*.placement=*/layout.get<SymbolPlacement>(),
/*.textFit=*/layout.get<IconTextFit>()));
/*.placement=*/bucketLayout.get<SymbolPlacement>(),
/*.textFit=*/bucketLayout.get<IconTextFit>(),
/*.isOffset=*/isOffset));
tileLayerGroup->addDrawable(passes, tileID, std::move(drawable));
++stats.drawablesAdded;

View File

@@ -181,6 +181,7 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamete
.pitch_with_map = (symbolData.pitchAlignment == style::AlignmentType::Map),
.is_size_zoom_constant = size.isZoomConstant,
.is_size_feature_constant = size.isFeatureConstant,
.is_offset = symbolData.isOffset,
.size_t = size.sizeT,
.size = size.size,