From 87a70c47930d79017816b8ac7ae1bb06eb6446c9 Mon Sep 17 00:00:00 2001 From: Lauren Budorick Date: Mon, 19 Jun 2017 14:27:43 -0700 Subject: [PATCH] [core] Enable property functions for line-width (#9250) --- include/mbgl/annotation/annotation.hpp | 2 +- .../conversion/make_property_setters.hpp | 2 +- .../mbgl/style/data_driven_property_value.hpp | 2 +- .../mbgl/style/function/camera_function.hpp | 1 + .../style/function/composite_function.hpp | 1 + .../mbgl/style/function/source_function.hpp | 1 + include/mbgl/style/layers/line_layer.hpp | 6 +- mapbox-gl-js | 2 +- .../style/layers/PropertyFactory.java | 10 +- .../testapp/style/LineLayerTest.java | 112 ++++++++++++++++++ platform/darwin/src/MGLLineStyleLayer.h | 9 ++ platform/darwin/src/MGLLineStyleLayer.mm | 6 +- platform/darwin/src/MGLSymbolStyleLayer.h | 6 +- .../darwin/test/MGLLineStyleLayerTests.mm | 30 ++++- src/mbgl/programs/attributes.hpp | 5 + src/mbgl/programs/line_program.cpp | 14 +-- src/mbgl/programs/line_program.hpp | 19 ++- src/mbgl/programs/uniforms.hpp | 2 + src/mbgl/renderer/buckets/line_bucket.cpp | 2 +- .../data_driven_property_evaluator.hpp | 10 +- .../renderer/layers/render_line_layer.cpp | 17 +-- .../renderer/layers/render_line_layer.hpp | 14 ++- src/mbgl/renderer/paint_property_binder.hpp | 6 +- src/mbgl/renderer/painter.cpp | 2 +- src/mbgl/renderer/painters/painter_line.cpp | 3 +- .../possibly_evaluated_property_value.hpp | 12 +- .../property_evaluation_parameters.hpp | 10 +- src/mbgl/shaders/line.cpp | 18 ++- src/mbgl/shaders/line_pattern.cpp | 18 ++- src/mbgl/shaders/line_sdf.cpp | 59 ++++++++- src/mbgl/style/layers/line_layer.cpp | 6 +- .../style/layers/line_layer_properties.hpp | 2 +- src/mbgl/style/properties.hpp | 13 +- 33 files changed, 340 insertions(+), 82 deletions(-) diff --git a/include/mbgl/annotation/annotation.hpp b/include/mbgl/annotation/annotation.hpp index 2a938fb75..96e06ca22 100644 --- a/include/mbgl/annotation/annotation.hpp +++ b/include/mbgl/annotation/annotation.hpp @@ -31,7 +31,7 @@ class LineAnnotation { public: ShapeAnnotationGeometry geometry; style::DataDrivenPropertyValue opacity { 1.0f }; - style::PropertyValue width { 1.0f }; + style::DataDrivenPropertyValue width { 1.0f }; style::DataDrivenPropertyValue color { Color::black() }; }; diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp index 582ac7079..eaea2e89d 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp +++ b/include/mbgl/style/conversion/make_property_setters.hpp @@ -99,7 +99,7 @@ auto makePaintPropertySetters() { result["line-translate-transition"] = &setTransition; result["line-translate-anchor"] = &setProperty, &LineLayer::setLineTranslateAnchor>; result["line-translate-anchor-transition"] = &setTransition; - result["line-width"] = &setProperty, &LineLayer::setLineWidth>; + result["line-width"] = &setProperty, &LineLayer::setLineWidth>; result["line-width-transition"] = &setTransition; result["line-gap-width"] = &setProperty, &LineLayer::setLineGapWidth>; result["line-gap-width-transition"] = &setTransition; diff --git a/include/mbgl/style/data_driven_property_value.hpp b/include/mbgl/style/data_driven_property_value.hpp index 090ee0f59..5d7c59636 100644 --- a/include/mbgl/style/data_driven_property_value.hpp +++ b/include/mbgl/style/data_driven_property_value.hpp @@ -49,7 +49,7 @@ public: bool isZoomConstant() const { return !value.template is>() && !value.template is>(); } - + template auto match(Ts&&... ts) const { return value.match(std::forward(ts)...); diff --git a/include/mbgl/style/function/camera_function.hpp b/include/mbgl/style/function/camera_function.hpp index 1b03cc8cf..0fd5bcb07 100644 --- a/include/mbgl/style/function/camera_function.hpp +++ b/include/mbgl/style/function/camera_function.hpp @@ -35,6 +35,7 @@ public: } Stops stops; + bool useIntegerZoom = false; }; } // namespace style diff --git a/include/mbgl/style/function/composite_function.hpp b/include/mbgl/style/function/composite_function.hpp index c3de0726c..43599cd33 100644 --- a/include/mbgl/style/function/composite_function.hpp +++ b/include/mbgl/style/function/composite_function.hpp @@ -135,6 +135,7 @@ public: std::string property; Stops stops; optional defaultValue; + bool useIntegerZoom = false; private: T evaluateFinal(const CoveringRanges& ranges, const Value& value, T finalDefaultValue) const { diff --git a/include/mbgl/style/function/source_function.hpp b/include/mbgl/style/function/source_function.hpp index f6601d9ea..2872c63a6 100644 --- a/include/mbgl/style/function/source_function.hpp +++ b/include/mbgl/style/function/source_function.hpp @@ -53,6 +53,7 @@ public: std::string property; Stops stops; optional defaultValue; + bool useIntegerZoom = false; }; } // namespace style diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp index c643ad110..0b49690fd 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -80,9 +80,9 @@ public: void setLineTranslateAnchorTransition(const TransitionOptions&); TransitionOptions getLineTranslateAnchorTransition() const; - static PropertyValue getDefaultLineWidth(); - PropertyValue getLineWidth() const; - void setLineWidth(PropertyValue); + static DataDrivenPropertyValue getDefaultLineWidth(); + DataDrivenPropertyValue getLineWidth() const; + void setLineWidth(DataDrivenPropertyValue); void setLineWidthTransition(const TransitionOptions&); TransitionOptions getLineWidthTransition() const; diff --git a/mapbox-gl-js b/mapbox-gl-js index a222ef16b..09bec658e 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit a222ef16b5a34b15a52e7c722dcdfceafdc62af4 +Subproject commit 09bec658e3f8de18a7964f5633aea9716dcb3919 diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java index e4ea9676f..73896b790 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java @@ -322,11 +322,11 @@ public class PropertyFactory { /** * Stroke thickness. * - * @param the zoom parameter type - * @param function a wrapper {@link CameraFunction} for Float + * @param the function input type + * @param function a wrapper function for Float * @return property wrapper around a Float function */ - public static PropertyValue> lineWidth(CameraFunction function) { + public static PropertyValue> lineWidth(Function function) { return new PaintPropertyValue<>("line-width", function); } @@ -1676,7 +1676,7 @@ public class PropertyFactory { } /** - * Scale factor for icon. 1 is original size, 3 triples the size. + * Scales the original size of the icon by the provided factor. The new pixel size of the image will be the original pixel size multiplied by {@link PropertyFactory#iconSize}. 1 is the original size; 3 triples the size of the image. * * @param value a Float value * @return property wrapper around Float @@ -1688,7 +1688,7 @@ public class PropertyFactory { /** - * Scale factor for icon. 1 is original size, 3 triples the size. + * Scales the original size of the icon by the provided factor. The new pixel size of the image will be the original pixel size multiplied by {@link PropertyFactory#iconSize}. 1 is the original size; 3 triples the size of the image. * * @param the function input type * @param function a wrapper function for Float diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java index 1c23dd366..c10c908c8 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java @@ -696,6 +696,118 @@ public class LineLayerTest extends BaseActivityTest { assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size()); } + @Test + public void testLineWidthAsIdentitySourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("line-width"); + assertNotNull(layer); + + // Set + layer.setProperties( + lineWidth(property("FeaturePropertyA", Stops.identity())) + ); + + // Verify + assertNotNull(layer.getLineWidth()); + assertNotNull(layer.getLineWidth().getFunction()); + assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty()); + assertEquals(IdentityStops.class, layer.getLineWidth().getFunction().getStops().getClass()); + } + + @Test + public void testLineWidthAsExponentialSourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("line-width"); + assertNotNull(layer); + + // Set + layer.setProperties( + lineWidth( + property( + "FeaturePropertyA", + exponential( + stop(0.3f, lineWidth(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getLineWidth()); + assertNotNull(layer.getLineWidth().getFunction()); + assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass()); + } + + @Test + public void testLineWidthAsCategoricalSourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("line-width"); + assertNotNull(layer); + + // Set + layer.setProperties( + lineWidth( + property( + "FeaturePropertyA", + categorical( + stop(1.0f, lineWidth(0.3f)) + ) + ).withDefaultValue(lineWidth(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getLineWidth()); + assertNotNull(layer.getLineWidth().getFunction()); + assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty()); + assertEquals(CategoricalStops.class, layer.getLineWidth().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue()); + } + + @Test + public void testLineWidthAsCompositeFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("line-width"); + assertNotNull(layer); + + // Set + layer.setProperties( + lineWidth( + composite( + "FeaturePropertyA", + exponential( + stop(0, 0.3f, lineWidth(0.9f)) + ).withBase(0.5f) + ).withDefaultValue(lineWidth(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getLineWidth()); + assertNotNull(layer.getLineWidth().getFunction()); + assertEquals(CompositeFunction.class, layer.getLineWidth().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineWidth().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass()); + assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size()); + + ExponentialStops, Float> stops = + (ExponentialStops, Float>) layer.getLineWidth().getFunction().getStops(); + Stop, Float> stop = stops.iterator().next(); + assertEquals(0f, stop.in.zoom, 0.001); + assertEquals(0.3f, stop.in.value, 0.001f); + assertEquals(0.9f, stop.out, 0.001f); + } + @Test public void testLineGapWidthTransition() { validateTestSetup(); diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index 38513652c..4a96b11ab 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -543,6 +543,15 @@ MGL_EXPORT * `MGLCameraStyleFunction` with an interpolation mode of: * `MGLInterpolationModeExponential` * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue *lineWidth; diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index 8b90efd0c..9be166772 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -480,7 +480,7 @@ namespace mbgl { - (void)setLineWidth:(MGLStyleValue *)lineWidth { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toInterpolatablePropertyValue(lineWidth); + auto mbglValue = MGLStyleValueTransformer().toDataDrivenPropertyValue(lineWidth); self.rawLayer->setLineWidth(mbglValue); } @@ -489,9 +489,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getLineWidth(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer().toStyleValue(self.rawLayer->getDefaultLineWidth()); + return MGLStyleValueTransformer().toDataDrivenStyleValue(self.rawLayer->getDefaultLineWidth()); } - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return MGLStyleValueTransformer().toDataDrivenStyleValue(propertyValue); } - (void)setLineWidthTransition:(MGLTransition )transition { diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index b6c637232..5df995aa0 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -533,7 +533,11 @@ MGL_EXPORT @property (nonatomic, null_resettable) MGLStyleValue *iconRotationAlignment; /** - Scale factor for icon. 1 is original size, 3 triples the size. + Scales the original size of the icon by the provided factor. The new point size + of the image will be the original point size multiplied by `iconSize`. 1 is the + original size; 3 triples the size of the image. + + This property is measured in factor of the original icon sizes. The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm index 1e9295952..be7d9a675 100644 --- a/platform/darwin/test/MGLLineStyleLayerTests.mm +++ b/platform/darwin/test/MGLLineStyleLayerTests.mm @@ -713,7 +713,7 @@ MGLStyleValue *constantStyleValue = [MGLStyleValue valueWithRawValue:@0xff]; layer.lineWidth = constantStyleValue; - mbgl::style::PropertyValue propertyValue = { 0xff }; + mbgl::style::DataDrivenPropertyValue propertyValue = { 0xff }; XCTAssertEqual(rawLayer->getLineWidth(), propertyValue, @"Setting lineWidth to a constant value should update line-width."); XCTAssertEqualObjects(layer.lineWidth, constantStyleValue, @@ -730,6 +730,29 @@ XCTAssertEqualObjects(layer.lineWidth, functionStyleValue, @"lineWidth should round-trip camera functions."); + functionStyleValue = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil]; + layer.lineWidth = functionStyleValue; + + mbgl::style::ExponentialStops exponentialStops = { {{18, 0xff}}, 1.0 }; + propertyValue = mbgl::style::SourceFunction { "keyName", exponentialStops }; + + XCTAssertEqual(rawLayer->getLineWidth(), propertyValue, + @"Setting lineWidth to a source function should update line-width."); + XCTAssertEqualObjects(layer.lineWidth, functionStyleValue, + @"lineWidth should round-trip source functions."); + + functionStyleValue = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil]; + layer.lineWidth = functionStyleValue; + + std::map innerStops { {18, 0xff} }; + mbgl::style::CompositeExponentialStops compositeStops { { {10.0, innerStops} }, 1.0 }; + + propertyValue = mbgl::style::CompositeFunction { "keyName", compositeStops }; + + XCTAssertEqual(rawLayer->getLineWidth(), propertyValue, + @"Setting lineWidth to a composite function should update line-width."); + XCTAssertEqualObjects(layer.lineWidth, functionStyleValue, + @"lineWidth should round-trip composite functions."); layer.lineWidth = nil; @@ -737,11 +760,6 @@ @"Unsetting lineWidth should return line-width to the default value."); XCTAssertEqualObjects(layer.lineWidth, defaultStyleValue, @"lineWidth should return the default value after being unset."); - - functionStyleValue = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.lineWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); - functionStyleValue = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.lineWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); // Transition property test layer.lineWidthTransition = transitionTest; auto toptions = rawLayer->getLineWidthTransition(); diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp index a0b2b93e1..8f2751080 100644 --- a/src/mbgl/programs/attributes.hpp +++ b/src/mbgl/programs/attributes.hpp @@ -96,6 +96,11 @@ struct a_width { using Type = gl::Attribute; }; +struct a_floorwidth { + static auto name() { return "a_floorwidth"; } + using Type = gl::Attribute; +}; + struct a_height { static auto name() { return "a_height"; } using Type = gl::Attribute; diff --git a/src/mbgl/programs/line_program.cpp b/src/mbgl/programs/line_program.cpp index 86645588c..db5c916d3 100644 --- a/src/mbgl/programs/line_program.cpp +++ b/src/mbgl/programs/line_program.cpp @@ -13,7 +13,7 @@ using namespace style; static_assert(sizeof(LineLayoutVertex) == 8, "expected LineLayoutVertex size"); template -Values makeValues(const LinePaintProperties::PossiblyEvaluated& properties, +Values makeValues(const RenderLinePaintProperties::PossiblyEvaluated& properties, const RenderTile& tile, const TransformState& state, const std::array& pixelsToGLUnits, @@ -25,7 +25,6 @@ Values makeValues(const LinePaintProperties::PossiblyEvaluated& properties, properties.get(), state) }, - uniforms::u_width::Value{ properties.get() }, uniforms::u_ratio::Value{ 1.0f / tile.id.pixelsToTileUnits(1.0, state.getZoom()) }, uniforms::u_gl_units_to_pixels::Value{{{ 1.0f / pixelsToGLUnits[0], 1.0f / pixelsToGLUnits[1] }}}, std::forward(args)... @@ -33,7 +32,7 @@ Values makeValues(const LinePaintProperties::PossiblyEvaluated& properties, } LineProgram::UniformValues -LineProgram::uniformValues(const LinePaintProperties::PossiblyEvaluated& properties, +LineProgram::uniformValues(const RenderLinePaintProperties::PossiblyEvaluated& properties, const RenderTile& tile, const TransformState& state, const std::array& pixelsToGLUnits) { @@ -46,17 +45,16 @@ LineProgram::uniformValues(const LinePaintProperties::PossiblyEvaluated& propert } LineSDFProgram::UniformValues -LineSDFProgram::uniformValues(const LinePaintProperties::PossiblyEvaluated& properties, +LineSDFProgram::uniformValues(const RenderLinePaintProperties::PossiblyEvaluated& properties, float pixelRatio, const RenderTile& tile, const TransformState& state, const std::array& pixelsToGLUnits, const LinePatternPos& posA, const LinePatternPos& posB, - float dashLineWidth, float atlasWidth) { - const float widthA = posA.width * properties.get().fromScale * dashLineWidth; - const float widthB = posB.width * properties.get().toScale * dashLineWidth; + const float widthA = posA.width * properties.get().fromScale; + const float widthB = posB.width * properties.get().toScale; std::array scaleA {{ 1.0f / tile.id.pixelsToTileUnits(widthA, state.getIntegerZoom()), @@ -84,7 +82,7 @@ LineSDFProgram::uniformValues(const LinePaintProperties::PossiblyEvaluated& prop } LinePatternProgram::UniformValues -LinePatternProgram::uniformValues(const LinePaintProperties::PossiblyEvaluated& properties, +LinePatternProgram::uniformValues(const RenderLinePaintProperties::PossiblyEvaluated& properties, const RenderTile& tile, const TransformState& state, const std::array& pixelsToGLUnits, diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp index fadd35102..ed4a09bf1 100644 --- a/src/mbgl/programs/line_program.hpp +++ b/src/mbgl/programs/line_program.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include @@ -20,7 +20,6 @@ class ImagePosition; namespace uniforms { MBGL_DEFINE_UNIFORM_SCALAR(float, u_ratio); -MBGL_DEFINE_UNIFORM_SCALAR(float, u_width); MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_a); MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_b); MBGL_DEFINE_UNIFORM_SCALAR(float, u_sdfgamma); @@ -41,10 +40,9 @@ class LineProgram : public Program< LineLayoutAttributes, gl::Uniforms< uniforms::u_matrix, - uniforms::u_width, uniforms::u_ratio, uniforms::u_gl_units_to_pixels>, - style::LinePaintProperties> + RenderLinePaintProperties> { public: using Program::Program; @@ -91,7 +89,7 @@ public: */ static const int8_t extrudeScale = 63; - static UniformValues uniformValues(const style::LinePaintProperties::PossiblyEvaluated&, + static UniformValues uniformValues(const RenderLinePaintProperties::PossiblyEvaluated&, const RenderTile&, const TransformState&, const std::array& pixelsToGLUnits); @@ -103,7 +101,6 @@ class LinePatternProgram : public Program< LineLayoutAttributes, gl::Uniforms< uniforms::u_matrix, - uniforms::u_width, uniforms::u_ratio, uniforms::u_gl_units_to_pixels, uniforms::u_pattern_tl_a, @@ -115,12 +112,12 @@ class LinePatternProgram : public Program< uniforms::u_texsize, uniforms::u_fade, uniforms::u_image>, - style::LinePaintProperties> + RenderLinePaintProperties> { public: using Program::Program; - static UniformValues uniformValues(const style::LinePaintProperties::PossiblyEvaluated&, + static UniformValues uniformValues(const RenderLinePaintProperties::PossiblyEvaluated&, const RenderTile&, const TransformState&, const std::array& pixelsToGLUnits, @@ -135,7 +132,6 @@ class LineSDFProgram : public Program< LineLayoutAttributes, gl::Uniforms< uniforms::u_matrix, - uniforms::u_width, uniforms::u_ratio, uniforms::u_gl_units_to_pixels, uniforms::u_patternscale_a, @@ -145,19 +141,18 @@ class LineSDFProgram : public Program< uniforms::u_mix, uniforms::u_sdfgamma, uniforms::u_image>, - style::LinePaintProperties> + RenderLinePaintProperties> { public: using Program::Program; - static UniformValues uniformValues(const style::LinePaintProperties::PossiblyEvaluated&, + static UniformValues uniformValues(const RenderLinePaintProperties::PossiblyEvaluated&, float pixelRatio, const RenderTile&, const TransformState&, const std::array& pixelsToGLUnits, const LinePatternPos& posA, const LinePatternPos& posB, - float dashLineWidth, float atlasWidth); }; diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp index bec8fbe9f..f1b2c2fb5 100644 --- a/src/mbgl/programs/uniforms.hpp +++ b/src/mbgl/programs/uniforms.hpp @@ -27,6 +27,8 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_halo_blur); MBGL_DEFINE_UNIFORM_SCALAR(Color, u_outline_color); MBGL_DEFINE_UNIFORM_SCALAR(float, u_height); MBGL_DEFINE_UNIFORM_SCALAR(float, u_base); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_width); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_floorwidth); MBGL_DEFINE_UNIFORM_SCALAR(float, u_gapwidth); MBGL_DEFINE_UNIFORM_SCALAR(float, u_offset); MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world); diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index ab9cfe937..3af3cd63d 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -480,7 +480,7 @@ static float get(const RenderLineLayer& layer, const std::map(); + float lineWidth = get(layer, paintPropertyBinders); float gapWidth = get(layer, paintPropertyBinders); if (gapWidth) { diff --git a/src/mbgl/renderer/data_driven_property_evaluator.hpp b/src/mbgl/renderer/data_driven_property_evaluator.hpp index 6406b3478..79ecd0d49 100644 --- a/src/mbgl/renderer/data_driven_property_evaluator.hpp +++ b/src/mbgl/renderer/data_driven_property_evaluator.hpp @@ -24,12 +24,18 @@ public: } ResultType operator()(const style::CameraFunction& function) const { - return ResultType(function.evaluate(parameters.z)); + if (!parameters.useIntegerZoom) { + return ResultType(function.evaluate(parameters.z)); + } else { + return ResultType(function.evaluate(floor(parameters.z))); + } } template ResultType operator()(const Function& function) const { - return ResultType(function); + auto returnFunction = function; + returnFunction.useIntegerZoom = parameters.useIntegerZoom; + return ResultType(returnFunction); } private: diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 076ee77af..5998c1f2f 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -24,16 +24,18 @@ void RenderLineLayer::transition(const TransitionParameters& parameters) { } void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { - // for scaling dasharrays - auto dashArrayParams = parameters; - dashArrayParams.z = std::floor(dashArrayParams.z); - dashLineWidth = unevaluated.evaluate(dashArrayParams); + style::Properties::Unevaluated extra; + extra.get() = unevaluated.get(); - evaluated = unevaluated.evaluate(parameters); + auto dashArrayParams = parameters; + dashArrayParams.useIntegerZoom = true; + + evaluated = RenderLinePaintProperties::PossiblyEvaluated( + unevaluated.evaluate(parameters).concat(extra.evaluate(dashArrayParams))); passes = (evaluated.get().constantOr(1.0) > 0 && evaluated.get().constantOr(Color::black()).a > 0 - && evaluated.get() > 0) + && evaluated.get().constantOr(1.0) > 0) ? RenderPass::Translucent : RenderPass::None; } @@ -102,7 +104,8 @@ bool RenderLineLayer::queryIntersectsFeature( } float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const { - float lineWidth = evaluated.get(); + float lineWidth = evaluated.get() + .evaluate(feature, zoom, style::LineWidth::defaultValue()); float gapWidth = evaluated.get() .evaluate(feature, zoom, style::LineGapWidth::defaultValue()); if (gapWidth) { diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp index 04ba74553..77551b6b7 100644 --- a/src/mbgl/renderer/layers/render_line_layer.hpp +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -3,9 +3,18 @@ #include #include #include +#include namespace mbgl { +struct LineFloorwidth : style::DataDrivenPaintProperty { + static float defaultValue() { return 1; } +}; + +class RenderLinePaintProperties : public style::ConcatenateProperties< + style::LinePaintProperties::PropertyTypes, + TypeList>::Type {}; + class RenderLineLayer: public RenderLayer { public: RenderLineLayer(Immutable); @@ -26,13 +35,10 @@ public: // Paint properties style::LinePaintProperties::Unevaluated unevaluated; - style::LinePaintProperties::PossiblyEvaluated evaluated; + RenderLinePaintProperties::PossiblyEvaluated evaluated; const style::LineLayer::Impl& impl() const; - // Special case - float dashLineWidth = 1; - private: float getLineWidth(const GeometryTileFeature&, const float) const; }; diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index 8ac6ce8cf..f78147fc8 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -217,7 +217,11 @@ public: } float interpolationFactor(float currentZoom) const override { - return util::interpolationFactor(1.0f, { rangeOfCoveringRanges.min.zoom, rangeOfCoveringRanges.max.zoom }, currentZoom); + if (function.useIntegerZoom) { + return util::interpolationFactor(1.0f, { rangeOfCoveringRanges.min.zoom, rangeOfCoveringRanges.max.zoom }, std::floor(currentZoom)); + } else { + return util::interpolationFactor(1.0f, { rangeOfCoveringRanges.min.zoom, rangeOfCoveringRanges.max.zoom }, currentZoom); + } } T uniformValue(const PossiblyEvaluatedPropertyValue& currentValue) const override { diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index edec98047..5a70243a5 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -328,7 +328,7 @@ void Painter::renderPass(PaintParameters& parameters, mat4 viewportMat; matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); - const Properties<>::PossiblyEvaluated properties{}; + const Properties<>::PossiblyEvaluated properties; parameters.programs.extrusionTexture.draw( context, gl::Triangles(), gl::DepthMode::disabled(), gl::StencilMode::disabled(), diff --git a/src/mbgl/renderer/painters/painter_line.cpp b/src/mbgl/renderer/painters/painter_line.cpp index 49fee3692..58f4131d9 100644 --- a/src/mbgl/renderer/painters/painter_line.cpp +++ b/src/mbgl/renderer/painters/painter_line.cpp @@ -21,7 +21,7 @@ void Painter::renderLine(PaintParameters& parameters, return; } - const LinePaintProperties::PossiblyEvaluated& properties = layer.evaluated; + const RenderLinePaintProperties::PossiblyEvaluated& properties = layer.evaluated; auto draw = [&] (auto& program, auto&& uniformValues) { program.get(properties).draw( @@ -57,7 +57,6 @@ void Painter::renderLine(PaintParameters& parameters, pixelsToGLUnits, posA, posB, - layer.dashLineWidth, lineAtlas->getSize().width)); } else if (!properties.get().from.empty()) { diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp index a0bcec2bf..8a5dfbe4e 100644 --- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp +++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp @@ -19,7 +19,9 @@ private: public: PossiblyEvaluatedPropertyValue() = default; - PossiblyEvaluatedPropertyValue(Value v) : value(std::move(v)) {} + PossiblyEvaluatedPropertyValue(Value v, bool useIntegerZoom_ = false) + : value(std::move(v)), + useIntegerZoom(useIntegerZoom_) {} bool isConstant() const { return value.template is(); @@ -48,10 +50,16 @@ public: return function.evaluate(feature, defaultValue); }, [&] (const style::CompositeFunction& function) { - return function.evaluate(zoom, feature, defaultValue); + if (useIntegerZoom) { + return function.evaluate(floor(zoom), feature, defaultValue); + } else { + return function.evaluate(zoom, feature, defaultValue); + } } ); } + + bool useIntegerZoom; }; namespace util { diff --git a/src/mbgl/renderer/property_evaluation_parameters.hpp b/src/mbgl/renderer/property_evaluation_parameters.hpp index 39b663bdb..da6a4a089 100644 --- a/src/mbgl/renderer/property_evaluation_parameters.hpp +++ b/src/mbgl/renderer/property_evaluation_parameters.hpp @@ -11,20 +11,24 @@ public: : z(z_), now(Clock::time_point::max()), zoomHistory(), - defaultFadeDuration(0) {} + defaultFadeDuration(0), + useIntegerZoom(false) {} PropertyEvaluationParameters(ZoomHistory zoomHistory_, TimePoint now_, - Duration defaultFadeDuration_) + Duration defaultFadeDuration_, + bool useIntegerZoom_ = false) : z(zoomHistory_.lastZoom), now(std::move(now_)), zoomHistory(std::move(zoomHistory_)), - defaultFadeDuration(std::move(defaultFadeDuration_)) {} + defaultFadeDuration(std::move(defaultFadeDuration_)), + useIntegerZoom(useIntegerZoom_) {} float z; TimePoint now; ZoomHistory zoomHistory; Duration defaultFadeDuration; + bool useIntegerZoom; }; } // namespace mbgl diff --git a/src/mbgl/shaders/line.cpp b/src/mbgl/shaders/line.cpp index dce604625..1eb92c4b7 100644 --- a/src/mbgl/shaders/line.cpp +++ b/src/mbgl/shaders/line.cpp @@ -26,7 +26,6 @@ attribute vec4 a_data; uniform mat4 u_matrix; uniform mediump float u_ratio; -uniform mediump float u_width; uniform vec2 u_gl_units_to_pixels; varying vec2 v_normal; @@ -72,6 +71,13 @@ attribute lowp vec2 a_offset; uniform lowp float u_offset; #endif +#ifndef HAS_UNIFORM_u_width +uniform lowp float a_width_t; +attribute mediump vec2 a_width; +#else +uniform mediump float u_width; +#endif + void main() { #ifndef HAS_UNIFORM_u_color @@ -104,6 +110,12 @@ void main() { lowp float offset = u_offset; #endif +#ifndef HAS_UNIFORM_u_width + mediump float width = unpack_mix_vec2(a_width, a_width_t); +#else + mediump float width = u_width; +#endif + vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; @@ -119,11 +131,11 @@ void main() { // these transformations used to be applied in the JS and native code bases. // moved them into the shader for clarity and simplicity. gapwidth = gapwidth / 2.0; - float width = u_width / 2.0; + float halfwidth = width / 2.0; offset = -1.0 * offset; float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0); - float outset = gapwidth + width * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; + float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; // Scale the extrusion vector down to a normal and then up by the line width // of this vertex. diff --git a/src/mbgl/shaders/line_pattern.cpp b/src/mbgl/shaders/line_pattern.cpp index ded4c7682..222042a13 100644 --- a/src/mbgl/shaders/line_pattern.cpp +++ b/src/mbgl/shaders/line_pattern.cpp @@ -28,7 +28,6 @@ attribute vec4 a_data; uniform mat4 u_matrix; uniform mediump float u_ratio; -uniform mediump float u_width; uniform vec2 u_gl_units_to_pixels; varying vec2 v_normal; @@ -67,6 +66,13 @@ attribute mediump vec2 a_gapwidth; uniform mediump float u_gapwidth; #endif +#ifndef HAS_UNIFORM_u_width +uniform lowp float a_width_t; +attribute mediump vec2 a_width; +#else +uniform mediump float u_width; +#endif + void main() { #ifndef HAS_UNIFORM_u_blur @@ -93,6 +99,12 @@ void main() { mediump float gapwidth = u_gapwidth; #endif +#ifndef HAS_UNIFORM_u_width + mediump float width = unpack_mix_vec2(a_width, a_width_t); +#else + mediump float width = u_width; +#endif + vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE; @@ -108,11 +120,11 @@ void main() { // these transformations used to be applied in the JS and native code bases. // moved them into the shader for clarity and simplicity. gapwidth = gapwidth / 2.0; - float width = u_width / 2.0; + float halfwidth = width / 2.0; offset = -1.0 * offset; float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0); - float outset = gapwidth + width * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; + float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; // Scale the extrusion vector down to a normal and then up by the line width // of this vertex. diff --git a/src/mbgl/shaders/line_sdf.cpp b/src/mbgl/shaders/line_sdf.cpp index b37bf688d..168f4ca98 100644 --- a/src/mbgl/shaders/line_sdf.cpp +++ b/src/mbgl/shaders/line_sdf.cpp @@ -33,7 +33,6 @@ uniform float u_tex_y_a; uniform vec2 u_patternscale_b; uniform float u_tex_y_b; uniform vec2 u_gl_units_to_pixels; -uniform mediump float u_width; varying vec2 v_normal; varying vec2 v_width2; @@ -80,6 +79,22 @@ attribute lowp vec2 a_offset; uniform lowp float u_offset; #endif +#ifndef HAS_UNIFORM_u_width +uniform lowp float a_width_t; +attribute mediump vec2 a_width; +varying mediump float width; +#else +uniform mediump float u_width; +#endif + +#ifndef HAS_UNIFORM_u_floorwidth +uniform lowp float a_floorwidth_t; +attribute lowp vec2 a_floorwidth; +varying lowp float floorwidth; +#else +uniform lowp float u_floorwidth; +#endif + void main() { #ifndef HAS_UNIFORM_u_color @@ -112,6 +127,18 @@ void main() { lowp float offset = u_offset; #endif +#ifndef HAS_UNIFORM_u_width + width = unpack_mix_vec2(a_width, a_width_t); +#else + mediump float width = u_width; +#endif + +#ifndef HAS_UNIFORM_u_floorwidth + floorwidth = unpack_mix_vec2(a_floorwidth, a_floorwidth_t); +#else + lowp float floorwidth = u_floorwidth; +#endif + vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE; @@ -127,11 +154,11 @@ void main() { // these transformations used to be applied in the JS and native code bases. // moved them into the shader for clarity and simplicity. gapwidth = gapwidth / 2.0; - float width = u_width / 2.0; + float halfwidth = width / 2.0; offset = -1.0 * offset; float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0); - float outset = gapwidth + width * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; + float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; // Scale the extrusion vector down to a normal and then up by the line width // of this vertex. @@ -156,8 +183,8 @@ void main() { float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels); v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective; - v_tex_a = vec2(a_linesofar * u_patternscale_a.x, normal.y * u_patternscale_a.y + u_tex_y_a); - v_tex_b = vec2(a_linesofar * u_patternscale_b.x, normal.y * u_patternscale_b.y + u_tex_y_b); + v_tex_a = vec2(a_linesofar * u_patternscale_a.x / floorwidth, normal.y * u_patternscale_a.y + u_tex_y_a); + v_tex_b = vec2(a_linesofar * u_patternscale_b.x / floorwidth, normal.y * u_patternscale_b.y + u_tex_y_b); v_width2 = vec2(outset, inset); } @@ -194,6 +221,18 @@ varying lowp float opacity; uniform lowp float u_opacity; #endif +#ifndef HAS_UNIFORM_u_width +varying mediump float width; +#else +uniform mediump float u_width; +#endif + +#ifndef HAS_UNIFORM_u_floorwidth +varying lowp float floorwidth; +#else +uniform lowp float u_floorwidth; +#endif + void main() { #ifdef HAS_UNIFORM_u_color @@ -208,6 +247,14 @@ void main() { lowp float opacity = u_opacity; #endif +#ifdef HAS_UNIFORM_u_width + mediump float width = u_width; +#endif + +#ifdef HAS_UNIFORM_u_floorwidth + lowp float floorwidth = u_floorwidth; +#endif + // Calculate the distance of the pixel from the line in pixels. float dist = length(v_normal) * v_width2.s; @@ -220,7 +267,7 @@ void main() { float sdfdist_a = texture2D(u_image, v_tex_a).a; float sdfdist_b = texture2D(u_image, v_tex_b).a; float sdfdist = mix(sdfdist_a, sdfdist_b, u_mix); - alpha *= smoothstep(0.5 - u_sdfgamma, 0.5 + u_sdfgamma, sdfdist); + alpha *= smoothstep(0.5 - u_sdfgamma / floorwidth, 0.5 + u_sdfgamma / floorwidth, sdfdist); gl_FragColor = color * (alpha * opacity); diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp index cf3f81f61..6fbdf1956 100644 --- a/src/mbgl/style/layers/line_layer.cpp +++ b/src/mbgl/style/layers/line_layer.cpp @@ -267,15 +267,15 @@ TransitionOptions LineLayer::getLineTranslateAnchorTransition() const { return impl().paint.template get().options; } -PropertyValue LineLayer::getDefaultLineWidth() { +DataDrivenPropertyValue LineLayer::getDefaultLineWidth() { return { 1 }; } -PropertyValue LineLayer::getLineWidth() const { +DataDrivenPropertyValue LineLayer::getLineWidth() const { return impl().paint.template get().value; } -void LineLayer::setLineWidth(PropertyValue value) { +void LineLayer::setLineWidth(DataDrivenPropertyValue value) { if (value == getLineWidth()) return; auto impl_ = mutableImpl(); diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp index 7930ed113..b2c7f3199 100644 --- a/src/mbgl/style/layers/line_layer_properties.hpp +++ b/src/mbgl/style/layers/line_layer_properties.hpp @@ -48,7 +48,7 @@ struct LineTranslateAnchor : PaintProperty { static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; } }; -struct LineWidth : PaintProperty { +struct LineWidth : DataDrivenPaintProperty { static float defaultValue() { return 1; } }; diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp index 24ac03054..e42beac97 100644 --- a/src/mbgl/style/properties.hpp +++ b/src/mbgl/style/properties.hpp @@ -130,7 +130,10 @@ public: class PossiblyEvaluated : public Tuple { public: - using Tuple::Tuple; + template + PossiblyEvaluated(Us&&... us) + : Tuple(std::forward(us)...) { + } template static T evaluate(float, const GeometryTileFeature&, const T& t, const T&) { @@ -214,5 +217,13 @@ public: }; }; +template +struct ConcatenateProperties; + +template +struct ConcatenateProperties, TypeList> { + using Type = Properties; +}; + } // namespace style } // namespace mbgl