diff options
author | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-07-08 12:31:42 +0300 |
---|---|---|
committer | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-07-08 12:31:42 +0300 |
commit | c1e4bf91f8c3e490336e9722f8e3d8bd63979c6f (patch) | |
tree | 7281b8b96b64318b5a1d59b7845a1dfa4ea7adb8 | |
parent | b481469394a7c55ec43aeaec5a19622a2fae7df5 (diff) | |
download | qtlocation-mapboxgl-c1e4bf91f8c3e490336e9722f8e3d8bd63979c6f.tar.gz |
[core] Renderer for RenderFillLayer and RenderFillExtrusionLayer
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp | 321 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp | 6 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_layer.cpp | 362 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_layer.hpp | 3 |
4 files changed, 352 insertions, 340 deletions
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index 29002d8bdf..cdaefb6b0e 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -31,6 +31,169 @@ RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable<style::FillExtrusio RenderFillExtrusionLayer::~RenderFillExtrusionLayer() = default; +LayerRenderer RenderFillExtrusionLayer::createRenderer() { + const bool drawPattern = !unevaluated.get<FillExtrusionPattern>().isUndefined(); + return [drawPattern](PaintParameters& parameters, const LayerRenderItem& renderItem) { + if (parameters.pass != RenderPass::Translucent) { + return; + } + const auto& renderTiles = renderItem.renderTiles; + const auto& baseImpl = *renderItem.evaluatedProperties->baseImpl; + const auto& evaluated = getEvaluated<FillExtrusionLayerProperties>(renderItem.evaluatedProperties); + const auto& crossfade = getCrossfade<FillExtrusionLayerProperties>(renderItem.evaluatedProperties); + + if (evaluated.get<FillExtrusionOpacity>() == 0) { + return; + } + + const auto depthMode = parameters.depthModeFor3D(); + + auto draw = [&](auto& programInstance, + const auto& evaluated_, + const auto& crossfade_, + const gfx::StencilMode& stencilMode, + const gfx::ColorMode& colorMode, + const auto& tileBucket, + const auto& uniformValues, + const optional<ImagePosition>& patternPositionA, + const optional<ImagePosition>& patternPositionB, + const auto& textureBindings, + const std::string& uniqueName) { + const auto& paintPropertyBinders = tileBucket.paintPropertyBinders.at(baseImpl.id); + paintPropertyBinders.setPatternParameters(patternPositionA, patternPositionB, crossfade_); + + const auto allUniformValues = programInstance.computeAllUniformValues( + uniformValues, + paintPropertyBinders, + evaluated_, + parameters.state.getZoom() + ); + const auto allAttributeBindings = programInstance.computeAllAttributeBindings( + *tileBucket.vertexBuffer, + paintPropertyBinders, + evaluated_ + ); + + renderItem.checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); + + programInstance.draw( + parameters.context, + *parameters.renderPass, + gfx::Triangles(), + depthMode, + stencilMode, + colorMode, + gfx::CullFaceMode::backCCW(), + *tileBucket.indexBuffer, + tileBucket.triangleSegments, + allUniformValues, + allAttributeBindings, + textureBindings, + baseImpl.id + "/" + uniqueName); + }; + + if (!drawPattern) { + // Draw solid color extrusions + auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) { + for (const RenderTile& tile : renderTiles) { + const LayerRenderData* renderData = tile.getLayerRenderData(baseImpl); + if (!renderData) { + continue; + } + auto& bucket = static_cast<FillExtrusionBucket&>(*renderData->bucket); + draw( + parameters.programs.getFillExtrusionLayerPrograms().fillExtrusion, + evaluated, + crossfade, + stencilMode_, + colorMode_, + bucket, + FillExtrusionProgram::layoutUniformValues( + tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), + evaluated.get<FillExtrusionTranslateAnchor>(), + parameters.state), + parameters.state, + evaluated.get<FillExtrusionOpacity>(), + parameters.evaluatedLight, + evaluated.get<FillExtrusionVerticalGradient>() + ), + {}, + {}, + FillExtrusionProgram::TextureBindings{}, + name + ); + } + }; + + if (evaluated.get<FillExtrusionOpacity>() == 1) { + // Draw opaque extrusions + drawTiles(gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), "color"); + } else { + // Draw transparent buildings in two passes so that only the closest surface is drawn. + // First draw all the extrusions into only the depth buffer. No colors are drawn. + drawTiles(gfx::StencilMode::disabled(), gfx::ColorMode::disabled(), "depth"); + + // Then draw all the extrusions a second time, only coloring fragments if they have the + // same depth value as the closest fragment in the previous pass. Use the stencil buffer + // to prevent the second draw in cases where we have coincident polygons. + drawTiles(parameters.stencilModeFor3D(), parameters.colorModeForRenderPass(), "color"); + } + } else { + // Draw textured extrusions + const auto fillPatternValue = evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<std::basic_string<char> >{"", ""}); + auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) { + for (const RenderTile& tile : renderTiles) { + const LayerRenderData* renderData = tile.getLayerRenderData(baseImpl); + if (!renderData) { + continue; + } + auto& bucket = static_cast<FillExtrusionBucket&>(*renderData->bucket); + optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from); + optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to); + + draw( + parameters.programs.getFillExtrusionLayerPrograms().fillExtrusionPattern, + evaluated, + crossfade, + stencilMode_, + colorMode_, + bucket, + FillExtrusionPatternProgram::layoutUniformValues( + tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), + evaluated.get<FillExtrusionTranslateAnchor>(), + parameters.state), + tile.getIconAtlasTexture().size, + crossfade, + tile.id, + parameters.state, + evaluated.get<FillExtrusionOpacity>(), + -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, + parameters.pixelRatio, + parameters.evaluatedLight, + evaluated.get<FillExtrusionVerticalGradient>() + ), + patternPosA, + patternPosB, + FillExtrusionPatternProgram::TextureBindings{ + textures::image::Value{ tile.getIconAtlasTexture().getResource(), gfx::TextureFilterType::Linear }, + }, + name + ); + } + }; + + // Draw transparent buildings in two passes so that only the closest surface is drawn. + // First draw all the extrusions into only the depth buffer. No colors are drawn. + drawTiles(gfx::StencilMode::disabled(), gfx::ColorMode::disabled(), "depth"); + + // Then draw all the extrusions a second time, only coloring fragments if they have the + // same depth value as the closest fragment in the previous pass. Use the stencil buffer + // to prevent the second draw in cases where we have coincident polygons. + drawTiles(parameters.stencilModeFor3D(), parameters.colorModeForRenderPass(), "color"); + } + }; +} + void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters) { unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } @@ -55,164 +218,6 @@ bool RenderFillExtrusionLayer::hasCrossfade() const { return getCrossfade<FillExtrusionLayerProperties>(evaluatedProperties).t != 1; } -void RenderFillExtrusionLayer::render(PaintParameters& parameters) { - if (parameters.pass != RenderPass::Translucent) { - return; - } - - const auto& evaluated = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).evaluated; - const auto& crossfade = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).crossfade; - if (evaluated.get<FillExtrusionOpacity>() == 0) { - return; - } - - const auto depthMode = parameters.depthModeFor3D(); - - auto draw = [&](auto& programInstance, - const auto& evaluated_, - const auto& crossfade_, - const gfx::StencilMode& stencilMode, - const gfx::ColorMode& colorMode, - const auto& tileBucket, - const auto& uniformValues, - const optional<ImagePosition>& patternPositionA, - const optional<ImagePosition>& patternPositionB, - const auto& textureBindings, - const std::string& uniqueName) { - const auto& paintPropertyBinders = tileBucket.paintPropertyBinders.at(getID()); - paintPropertyBinders.setPatternParameters(patternPositionA, patternPositionB, crossfade_); - - const auto allUniformValues = programInstance.computeAllUniformValues( - uniformValues, - paintPropertyBinders, - evaluated_, - parameters.state.getZoom() - ); - const auto allAttributeBindings = programInstance.computeAllAttributeBindings( - *tileBucket.vertexBuffer, - paintPropertyBinders, - evaluated_ - ); - - checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - - programInstance.draw( - parameters.context, - *parameters.renderPass, - gfx::Triangles(), - depthMode, - stencilMode, - colorMode, - gfx::CullFaceMode::backCCW(), - *tileBucket.indexBuffer, - tileBucket.triangleSegments, - allUniformValues, - allAttributeBindings, - textureBindings, - getID() + "/" + uniqueName); - }; - - if (unevaluated.get<FillExtrusionPattern>().isUndefined()) { - // Draw solid color extrusions - auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) { - for (const RenderTile& tile : renderTiles) { - const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); - if (!renderData) { - continue; - } - auto& bucket = static_cast<FillExtrusionBucket&>(*renderData->bucket); - draw( - parameters.programs.getFillExtrusionLayerPrograms().fillExtrusion, - evaluated, - crossfade, - stencilMode_, - colorMode_, - bucket, - FillExtrusionProgram::layoutUniformValues( - tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), - evaluated.get<FillExtrusionTranslateAnchor>(), - parameters.state), - parameters.state, - evaluated.get<FillExtrusionOpacity>(), - parameters.evaluatedLight, - evaluated.get<FillExtrusionVerticalGradient>() - ), - {}, - {}, - FillExtrusionProgram::TextureBindings{}, - name - ); - } - }; - - if (evaluated.get<FillExtrusionOpacity>() == 1) { - // Draw opaque extrusions - drawTiles(gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), "color"); - } else { - // Draw transparent buildings in two passes so that only the closest surface is drawn. - // First draw all the extrusions into only the depth buffer. No colors are drawn. - drawTiles(gfx::StencilMode::disabled(), gfx::ColorMode::disabled(), "depth"); - - // Then draw all the extrusions a second time, only coloring fragments if they have the - // same depth value as the closest fragment in the previous pass. Use the stencil buffer - // to prevent the second draw in cases where we have coincident polygons. - drawTiles(parameters.stencilModeFor3D(), parameters.colorModeForRenderPass(), "color"); - } - } else { - // Draw textured extrusions - const auto fillPatternValue = evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<std::basic_string<char> >{"", ""}); - auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) { - for (const RenderTile& tile : renderTiles) { - const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); - if (!renderData) { - continue; - } - auto& bucket = static_cast<FillExtrusionBucket&>(*renderData->bucket); - optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from); - optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to); - - draw( - parameters.programs.getFillExtrusionLayerPrograms().fillExtrusionPattern, - evaluated, - crossfade, - stencilMode_, - colorMode_, - bucket, - FillExtrusionPatternProgram::layoutUniformValues( - tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), - evaluated.get<FillExtrusionTranslateAnchor>(), - parameters.state), - tile.getIconAtlasTexture().size, - crossfade, - tile.id, - parameters.state, - evaluated.get<FillExtrusionOpacity>(), - -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, - parameters.pixelRatio, - parameters.evaluatedLight, - evaluated.get<FillExtrusionVerticalGradient>() - ), - patternPosA, - patternPosB, - FillExtrusionPatternProgram::TextureBindings{ - textures::image::Value{ tile.getIconAtlasTexture().getResource(), gfx::TextureFilterType::Linear }, - }, - name - ); - } - }; - - // Draw transparent buildings in two passes so that only the closest surface is drawn. - // First draw all the extrusions into only the depth buffer. No colors are drawn. - drawTiles(gfx::StencilMode::disabled(), gfx::ColorMode::disabled(), "depth"); - - // Then draw all the extrusions a second time, only coloring fragments if they have the - // same depth value as the closest fragment in the previous pass. Use the stencil buffer - // to prevent the second draw in cases where we have coincident polygons. - drawTiles(parameters.stencilModeFor3D(), parameters.colorModeForRenderPass(), "color"); - } -} - bool RenderFillExtrusionLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp index 9118601581..3410814444 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -3,7 +3,6 @@ #include <mbgl/renderer/render_layer.hpp> #include <mbgl/style/layers/fill_extrusion_layer_impl.hpp> #include <mbgl/style/layers/fill_extrusion_layer_properties.hpp> -#include <mbgl/gfx/offscreen_texture.hpp> namespace mbgl { @@ -13,11 +12,12 @@ public: ~RenderFillExtrusionLayer() override; private: + LayerRenderer createRenderer() override; void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; - void render(PaintParameters&) override; + void render(PaintParameters&) override {} bool queryIntersectsFeature( const GeometryCoordinates&, @@ -29,8 +29,6 @@ private: // Paint properties style::FillExtrusionPaintProperties::Unevaluated unevaluated; - - std::unique_ptr<gfx::OffscreenTexture> renderTexture; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index c549b338df..2d36a71812 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -32,6 +32,191 @@ RenderFillLayer::RenderFillLayer(Immutable<style::FillLayer::Impl> _impl) RenderFillLayer::~RenderFillLayer() = default; +LayerRenderer RenderFillLayer::createRenderer() { + bool drawPattern = !unevaluated.get<FillPattern>().isUndefined(); + bool hasOutlineColor = !unevaluated.get<FillOutlineColor>().isUndefined(); + + return [hasOutlineColor, drawPattern](PaintParameters& parameters, const LayerRenderItem& renderItem) { + const auto& renderTiles = renderItem.renderTiles; + const auto& baseImpl = *renderItem.evaluatedProperties->baseImpl; + + if (!drawPattern) { + parameters.renderTileClippingMasks(renderTiles); + for (const RenderTile& tile : renderTiles) { + const LayerRenderData* renderData = tile.getLayerRenderData(baseImpl); + if (!renderData) { + continue; + } + auto& bucket = static_cast<FillBucket&>(*renderData->bucket); + const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties); + + auto draw = [&] (auto& programInstance, + const auto& drawMode, + const auto& depthMode, + const auto& indexBuffer, + const auto& segments, + auto&& textureBindings) { + const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(baseImpl.id); + + const auto allUniformValues = programInstance.computeAllUniformValues( + FillProgram::LayoutUniformValues { + uniforms::matrix::Value( + tile.translatedMatrix(evaluated.get<FillTranslate>(), + evaluated.get<FillTranslateAnchor>(), + parameters.state) + ), + uniforms::world::Value( parameters.backend.getDefaultRenderable().getSize() ), + }, + paintPropertyBinders, + evaluated, + parameters.state.getZoom() + ); + const auto allAttributeBindings = programInstance.computeAllAttributeBindings( + *bucket.vertexBuffer, + paintPropertyBinders, + evaluated + ); + + renderItem.checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); + + programInstance.draw( + parameters.context, + *parameters.renderPass, + drawMode, + depthMode, + parameters.stencilModeForClipping(tile.id), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + indexBuffer, + segments, + allUniformValues, + allAttributeBindings, + std::move(textureBindings), + baseImpl.id + ); + }; + + // Only draw the fill when it's opaque and we're drawing opaque fragments, + // or when it's translucent and we're drawing translucent fragments. + if (bucket.triangleIndexBuffer && + (evaluated.get<FillColor>().constantOr(Color()).a >= 1.0f && + evaluated.get<FillOpacity>().constantOr(0) >= 1.0f) == (parameters.pass == RenderPass::Opaque)) { + draw(parameters.programs.getFillLayerPrograms().fill, + gfx::Triangles(), + parameters.depthModeForSublayer(1, parameters.pass == RenderPass::Opaque + ? gfx::DepthMaskType::ReadWrite + : gfx::DepthMaskType::ReadOnly), + *bucket.triangleIndexBuffer, + bucket.triangleSegments, + FillProgram::TextureBindings{}); + } + + if (evaluated.get<FillAntialias>() && parameters.pass == RenderPass::Translucent) { + draw(parameters.programs.getFillLayerPrograms().fillOutline, + gfx::Lines{ 2.0f }, + parameters.depthModeForSublayer( + hasOutlineColor ? 0u : 2u, + gfx::DepthMaskType::ReadOnly), + *bucket.lineIndexBuffer, + bucket.lineSegments, + FillOutlineProgram::TextureBindings{}); + } + } + } else { + if (parameters.pass != RenderPass::Translucent) { + return; + } + + parameters.renderTileClippingMasks(renderTiles); + + for (const RenderTile& tile : renderTiles) { + const LayerRenderData* renderData = tile.getLayerRenderData(baseImpl); + if (!renderData) { + continue; + } + auto& bucket = static_cast<FillBucket&>(*renderData->bucket); + const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties); + const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties); + + const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<std::basic_string<char>>{"", ""}); + optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from); + optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to); + + auto draw = [&] (auto& programInstance, + const auto& drawMode, + const auto& depthMode, + const auto& indexBuffer, + const auto& segments, + auto&& textureBindings) { + const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(baseImpl.id); + paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); + + const auto allUniformValues = programInstance.computeAllUniformValues( + FillPatternProgram::layoutUniformValues( + tile.translatedMatrix(evaluated.get<FillTranslate>(), + evaluated.get<FillTranslateAnchor>(), + parameters.state), + parameters.backend.getDefaultRenderable().getSize(), + tile.getIconAtlasTexture().size, + crossfade, + tile.id, + parameters.state, + parameters.pixelRatio + ), + paintPropertyBinders, + evaluated, + parameters.state.getZoom() + ); + const auto allAttributeBindings = programInstance.computeAllAttributeBindings( + *bucket.vertexBuffer, + paintPropertyBinders, + evaluated + ); + + renderItem.checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); + + programInstance.draw( + parameters.context, + *parameters.renderPass, + drawMode, + depthMode, + parameters.stencilModeForClipping(tile.id), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + indexBuffer, + segments, + allUniformValues, + allAttributeBindings, + std::move(textureBindings), + baseImpl.id + ); + }; + + if (bucket.triangleIndexBuffer) { + draw(parameters.programs.getFillLayerPrograms().fillPattern, + gfx::Triangles(), + parameters.depthModeForSublayer(1, gfx::DepthMaskType::ReadWrite), + *bucket.triangleIndexBuffer, + bucket.triangleSegments, + FillPatternProgram::TextureBindings{ + textures::image::Value{ tile.getIconAtlasTexture().getResource(), gfx::TextureFilterType::Linear }, + }); + } + if (evaluated.get<FillAntialias>() && !hasOutlineColor) { + draw(parameters.programs.getFillLayerPrograms().fillOutlinePattern, + gfx::Lines { 2.0f }, + parameters.depthModeForSublayer(2, gfx::DepthMaskType::ReadOnly), + *bucket.lineIndexBuffer, + bucket.lineSegments, + FillOutlinePatternProgram::TextureBindings{ + textures::image::Value{ tile.getIconAtlasTexture().getResource(), gfx::TextureFilterType::Linear }, + }); + } + } + } + }; +} + void RenderFillLayer::transition(const TransitionParameters& parameters) { unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } @@ -72,183 +257,6 @@ bool RenderFillLayer::hasCrossfade() const { return getCrossfade<FillLayerProperties>(evaluatedProperties).t != 1; } -void RenderFillLayer::render(PaintParameters& parameters) { - if (unevaluated.get<FillPattern>().isUndefined()) { - parameters.renderTileClippingMasks(renderTiles); - for (const RenderTile& tile : renderTiles) { - const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); - if (!renderData) { - continue; - } - auto& bucket = static_cast<FillBucket&>(*renderData->bucket); - const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties); - - auto draw = [&] (auto& programInstance, - const auto& drawMode, - const auto& depthMode, - const auto& indexBuffer, - const auto& segments, - auto&& textureBindings) { - const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); - - const auto allUniformValues = programInstance.computeAllUniformValues( - FillProgram::LayoutUniformValues { - uniforms::matrix::Value( - tile.translatedMatrix(evaluated.get<FillTranslate>(), - evaluated.get<FillTranslateAnchor>(), - parameters.state) - ), - uniforms::world::Value( parameters.backend.getDefaultRenderable().getSize() ), - }, - paintPropertyBinders, - evaluated, - parameters.state.getZoom() - ); - const auto allAttributeBindings = programInstance.computeAllAttributeBindings( - *bucket.vertexBuffer, - paintPropertyBinders, - evaluated - ); - - checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - - programInstance.draw( - parameters.context, - *parameters.renderPass, - drawMode, - depthMode, - parameters.stencilModeForClipping(tile.id), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - indexBuffer, - segments, - allUniformValues, - allAttributeBindings, - std::move(textureBindings), - getID() - ); - }; - - // Only draw the fill when it's opaque and we're drawing opaque fragments, - // or when it's translucent and we're drawing translucent fragments. - if (bucket.triangleIndexBuffer && - (evaluated.get<FillColor>().constantOr(Color()).a >= 1.0f && - evaluated.get<FillOpacity>().constantOr(0) >= 1.0f) == (parameters.pass == RenderPass::Opaque)) { - draw(parameters.programs.getFillLayerPrograms().fill, - gfx::Triangles(), - parameters.depthModeForSublayer(1, parameters.pass == RenderPass::Opaque - ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly), - *bucket.triangleIndexBuffer, - bucket.triangleSegments, - FillProgram::TextureBindings{}); - } - - if (evaluated.get<FillAntialias>() && parameters.pass == RenderPass::Translucent) { - draw(parameters.programs.getFillLayerPrograms().fillOutline, - gfx::Lines{ 2.0f }, - parameters.depthModeForSublayer( - unevaluated.get<FillOutlineColor>().isUndefined() ? 2 : 0, - gfx::DepthMaskType::ReadOnly), - *bucket.lineIndexBuffer, - bucket.lineSegments, - FillOutlineProgram::TextureBindings{}); - } - } - } else { - if (parameters.pass != RenderPass::Translucent) { - return; - } - - parameters.renderTileClippingMasks(renderTiles); - - for (const RenderTile& tile : renderTiles) { - const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); - if (!renderData) { - continue; - } - auto& bucket = static_cast<FillBucket&>(*renderData->bucket); - const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties); - const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties); - - const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<std::basic_string<char>>{"", ""}); - optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from); - optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to); - - auto draw = [&] (auto& programInstance, - const auto& drawMode, - const auto& depthMode, - const auto& indexBuffer, - const auto& segments, - auto&& textureBindings) { - const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); - paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); - - const auto allUniformValues = programInstance.computeAllUniformValues( - FillPatternProgram::layoutUniformValues( - tile.translatedMatrix(evaluated.get<FillTranslate>(), - evaluated.get<FillTranslateAnchor>(), - parameters.state), - parameters.backend.getDefaultRenderable().getSize(), - tile.getIconAtlasTexture().size, - crossfade, - tile.id, - parameters.state, - parameters.pixelRatio - ), - paintPropertyBinders, - evaluated, - parameters.state.getZoom() - ); - const auto allAttributeBindings = programInstance.computeAllAttributeBindings( - *bucket.vertexBuffer, - paintPropertyBinders, - evaluated - ); - - checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - - programInstance.draw( - parameters.context, - *parameters.renderPass, - drawMode, - depthMode, - parameters.stencilModeForClipping(tile.id), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - indexBuffer, - segments, - allUniformValues, - allAttributeBindings, - std::move(textureBindings), - getID() - ); - }; - - if (bucket.triangleIndexBuffer) { - draw(parameters.programs.getFillLayerPrograms().fillPattern, - gfx::Triangles(), - parameters.depthModeForSublayer(1, gfx::DepthMaskType::ReadWrite), - *bucket.triangleIndexBuffer, - bucket.triangleSegments, - FillPatternProgram::TextureBindings{ - textures::image::Value{ tile.getIconAtlasTexture().getResource(), gfx::TextureFilterType::Linear }, - }); - } - if (evaluated.get<FillAntialias>() && unevaluated.get<FillOutlineColor>().isUndefined()) { - draw(parameters.programs.getFillLayerPrograms().fillOutlinePattern, - gfx::Lines { 2.0f }, - parameters.depthModeForSublayer(2, gfx::DepthMaskType::ReadOnly), - *bucket.lineIndexBuffer, - bucket.lineSegments, - FillOutlinePatternProgram::TextureBindings{ - textures::image::Value{ tile.getIconAtlasTexture().getResource(), gfx::TextureFilterType::Linear }, - }); - } - } - } -} - bool RenderFillLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp index 79adc9dab4..dda4bdd372 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -15,11 +15,12 @@ public: ~RenderFillLayer() override; private: + LayerRenderer createRenderer() override; void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; - void render(PaintParameters&) override; + void render(PaintParameters&) override {} bool queryIntersectsFeature( const GeometryCoordinates&, |