diff options
author | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-05-22 16:41:40 +0300 |
---|---|---|
committer | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-05-24 10:54:06 +0300 |
commit | aa3a7cf02f2b5d0b99bec9d335c9681dcfa38426 (patch) | |
tree | 08d9826c1b419960a1e7a03b6fefb6d21aeab923 /src/mbgl/renderer/layers/render_symbol_layer.cpp | |
parent | d8e9acd0f510a811f5c1fa87738be646ff83b715 (diff) | |
download | qtlocation-mapboxgl-aa3a7cf02f2b5d0b99bec9d335c9681dcfa38426.tar.gz |
[core] SymbolBucket updates complete at placement stage
`RenderSymbolLayer` does not have to update dynamic vertices of its buckets, this logic is moved to placement (which is already updates opacity vertices).
* fixes clustering of labels when text variable placement enabled - as assignes `usesVariablePlacement` per bucket
* simplifies the code in `RenderSymbolLayer` (the `RenderSymbolLayer::upload()` is now omitted).
* symbol buckets are not modified after orchestration finishes
Diffstat (limited to 'src/mbgl/renderer/layers/render_symbol_layer.cpp')
-rw-r--r-- | src/mbgl/renderer/layers/render_symbol_layer.cpp | 157 |
1 files changed, 5 insertions, 152 deletions
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 7fc0e08b41..dc67dea7e3 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -15,9 +15,7 @@ #include <mbgl/tile/geometry_tile.hpp> #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> -#include <mbgl/text/placement.hpp> #include <mbgl/gfx/cull_face_mode.hpp> -#include <mbgl/layout/symbol_projection.hpp> #include <mbgl/layout/symbol_layout.hpp> #include <mbgl/layout/symbol_layout.hpp> #include <mbgl/util/math.hpp> @@ -29,16 +27,6 @@ namespace mbgl { using namespace style; namespace { -Point<float> calculateVariableRenderShift(style::SymbolAnchorType anchor, float width, float height, float radialOffset, float textBoxScale, float renderTextSize) { - AnchorAlignment alignment = AnchorAlignment::getAnchorAlignment(anchor); - float shiftX = -(alignment.horizontalAlign - 0.5f) * width; - float shiftY = -(alignment.verticalAlign - 0.5f) * height; - Point<float> offset = SymbolLayout::evaluateRadialOffset(anchor, radialOffset); - return Point<float>( - (shiftX / textBoxScale + offset.x) * renderTextSize, - (shiftY / textBoxScale + offset.y) * renderTextSize - ); -} style::SymbolPropertyValues iconPropertyValues(const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_, const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) { @@ -116,122 +104,6 @@ struct RenderableSegment { } }; -void uploadIcon(gfx::UploadPass& uploadPass, - UploadParameters& uploadParameters, - const RenderTile& tile, - const LayerRenderData& renderData) { - assert(tile.tile.kind == Tile::Kind::Geometry); - auto& bucket = static_cast<SymbolBucket&>(*renderData.bucket); - const auto& layout = bucket.layout; - - const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point && - layout.get<IconRotationAlignment>() == AlignmentType::Map; - - if (alongLine) { - const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties); - reprojectLineLabels(bucket.icon.dynamicVertices, bucket.icon.placedSymbols, tile.matrix, - iconPropertyValues(evaluated, layout), tile, *bucket.iconSizeBinder, - uploadParameters.state); - - uploadPass.updateVertexBuffer(*bucket.icon.dynamicVertexBuffer, - std::move(bucket.icon.dynamicVertices)); - } -} - -void uploadText(gfx::UploadPass& uploadPass, - UploadParameters& uploadParameters, - const RenderTile& tile, - const LayerRenderData& renderData, - bool& hasVariablePlacement) { - assert(tile.tile.kind == Tile::Kind::Geometry); - auto& bucket = static_cast<SymbolBucket&>(*renderData.bucket); - const auto& layout = bucket.layout; - - const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point && - layout.get<TextRotationAlignment>() == AlignmentType::Map; - - if (alongLine) { - const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties); - reprojectLineLabels(bucket.text.dynamicVertices, - bucket.text.placedSymbols, - tile.matrix, - textPropertyValues(evaluated, layout), - tile, - *bucket.textSizeBinder, - uploadParameters.state); - - uploadPass.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); - } else if (!layout.get<TextVariableAnchor>().empty()) { - bucket.text.dynamicVertices.clear(); - - hasVariablePlacement = false; - - const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(uploadParameters.state.getZoom()); - const float tileScale = std::pow(2, uploadParameters.state.getZoom() - tile.tile.id.overscaledZ); - const bool rotateWithMap = layout.get<TextRotationAlignment>() == AlignmentType::Map; - const bool pitchWithMap = layout.get<TextPitchAlignment>() == AlignmentType::Map; - const float pixelsToTileUnits = tile.id.pixelsToTileUnits(1.0, uploadParameters.state.getZoom()); - const auto labelPlaneMatrix = getLabelPlaneMatrix(tile.matrix, pitchWithMap, rotateWithMap, uploadParameters.state, pixelsToTileUnits); - - for (const PlacedSymbol& symbol : bucket.text.placedSymbols) { - optional<VariableOffset> variableOffset; - if (!symbol.hidden && symbol.crossTileID != 0u) { - auto it = uploadParameters.variableOffsets.find(symbol.crossTileID); - if (it != uploadParameters.variableOffsets.end()) { - hasVariablePlacement |= true; - variableOffset = it->second; - } - } - - if (!variableOffset) { - // These symbols are from a justification that is not being used, or a label that wasn't placed - // so we don't need to do the extra math to figure out what incremental shift to apply. - hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices); - } else { - const Point<float> tileAnchor = symbol.anchorPoint; - const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix); - const float perspectiveRatio = 0.5f + 0.5f * (uploadParameters.state.getCameraToCenterDistance() / projectedAnchor.second); - float renderTextSize = evaluateSizeForFeature(partiallyEvaluatedSize, symbol) * perspectiveRatio / util::ONE_EM; - if (pitchWithMap) { - // Go from size in pixels to equivalent size in tile units - renderTextSize *= bucket.tilePixelRatio / tileScale; - } - - auto shift = calculateVariableRenderShift( - (*variableOffset).anchor, - (*variableOffset).width, - (*variableOffset).height, - (*variableOffset).radialOffset, - (*variableOffset).textBoxScale, - renderTextSize); - - // Usual case is that we take the projected anchor and add the pixel-based shift - // calculated above. In the (somewhat weird) case of pitch-aligned text, we add an equivalent - // tile-unit based shift to the anchor before projecting to the label plane. - Point<float> shiftedAnchor; - if (pitchWithMap) { - shiftedAnchor = project(Point<float>(tileAnchor.x + shift.x, tileAnchor.y + shift.y), - labelPlaneMatrix).first; - } else { - if (rotateWithMap) { - auto rotated = util::rotate(shift, -uploadParameters.state.getPitch()); - shiftedAnchor = Point<float>(projectedAnchor.first.x + rotated.x, - projectedAnchor.first.y + rotated.y); - } else { - shiftedAnchor = Point<float>(projectedAnchor.first.x + shift.x, - projectedAnchor.first.y + shift.y); - } - } - - for (std::size_t i = 0; i < symbol.glyphOffsets.size(); i++) { - addDynamicAttributes(shiftedAnchor, 0, bucket.text.dynamicVertices); - } - } - } - uploadPass.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); - } -} - template <typename DrawFn> void drawIcon(const DrawFn& draw, const RenderTile& tile, @@ -314,8 +186,7 @@ void drawText(const DrawFn& draw, const LayerRenderData& renderData, SegmentsWrapper textSegments, const SymbolBucket::PaintProperties& bucketPaintProperties, - const PaintParameters& parameters, - bool hasVariablePlacement) { + const PaintParameters& parameters) { assert(tile.tile.kind == Tile::Kind::Geometry); auto& geometryTile = static_cast<GeometryTile&>(tile.tile); auto& bucket = static_cast<SymbolBucket&>(*renderData.bucket); @@ -335,7 +206,7 @@ void drawText(const DrawFn& draw, if (values.hasHalo) { draw(parameters.programs.getSymbolLayerPrograms().symbolGlyph, - SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePlacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), + SymbolSDFTextProgram::layoutUniformValues(true, bucket.hasVariablePlacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.text, textSegments, bucket.textSizeBinder, @@ -350,7 +221,7 @@ void drawText(const DrawFn& draw, if (values.hasFill) { draw(parameters.programs.getSymbolLayerPrograms().symbolGlyph, - SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePlacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), + SymbolSDFTextProgram::layoutUniformValues(true, bucket.hasVariablePlacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.text, textSegments, bucket.textSizeBinder, @@ -413,24 +284,6 @@ bool RenderSymbolLayer::hasCrossfade() const { return false; } -void RenderSymbolLayer::upload(gfx::UploadPass& uploadPass, UploadParameters& uploadParameters) { - for (const RenderTile& tile : renderTiles) { - const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl); - if (!renderData) { - continue; - } - - auto& bucket = static_cast<SymbolBucket&>(*renderData->bucket); - if (bucket.hasIconData()) { - uploadIcon(uploadPass, uploadParameters, tile, *renderData); - } - - if (bucket.hasTextData()) { - uploadText(uploadPass, uploadParameters, tile, *renderData, hasVariablePlacement); - } - } -} - void RenderSymbolLayer::render(PaintParameters& parameters) { if (parameters.pass == RenderPass::Opaque) { return; @@ -537,7 +390,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { if (sortFeaturesByKey) { addRenderables(bucket.text.segments, true /*isText*/); } else { - drawText(draw, tile, *renderData, std::ref(bucket.text.segments), bucketPaintProperties, parameters, hasVariablePlacement); + drawText(draw, tile, *renderData, std::ref(bucket.text.segments), bucketPaintProperties, parameters); } } @@ -619,7 +472,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { if (sortFeaturesByKey) { for (auto& renderable : renderableSegments) { if (renderable.isText) { - drawText(draw, renderable.tile, renderable.renderData, renderable.segment, renderable.bucketPaintProperties, parameters, hasVariablePlacement); + drawText(draw, renderable.tile, renderable.renderData, renderable.segment, renderable.bucketPaintProperties, parameters); } else { drawIcon(draw, renderable.tile, renderable.renderData, renderable.segment, renderable.bucketPaintProperties, parameters); } |