diff options
Diffstat (limited to 'src/mbgl/renderer/painters')
-rw-r--r-- | src/mbgl/renderer/painters/painter_background.cpp | 83 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_circle.cpp | 57 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_clipping.cpp | 37 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_debug.cpp | 162 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_fill.cpp | 141 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_fill_extrusion.cpp | 86 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_line.cpp | 91 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_raster.cpp | 89 | ||||
-rw-r--r-- | src/mbgl/renderer/painters/painter_symbol.cpp | 166 |
9 files changed, 912 insertions, 0 deletions
diff --git a/src/mbgl/renderer/painters/painter_background.cpp b/src/mbgl/renderer/painters/painter_background.cpp new file mode 100644 index 0000000000..577d7d6cda --- /dev/null +++ b/src/mbgl/renderer/painters/painter_background.cpp @@ -0,0 +1,83 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/layers/render_background_layer.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/style/layers/background_layer_impl.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/fill_program.hpp> +#include <mbgl/util/tile_cover.hpp> + +namespace mbgl { + +using namespace style; + +void Painter::renderBackground(PaintParameters& parameters, const RenderBackgroundLayer& layer) { + // Note that for bottommost layers without a pattern, the background color is drawn with + // glClear rather than this method. + const BackgroundPaintProperties::PossiblyEvaluated& background = layer.evaluated; + + style::FillPaintProperties::PossiblyEvaluated properties; + properties.get<FillPattern>() = background.get<BackgroundPattern>(); + properties.get<FillOpacity>() = { background.get<BackgroundOpacity>() }; + properties.get<FillColor>() = { background.get<BackgroundColor>() }; + + const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + + if (!background.get<BackgroundPattern>().to.empty()) { + optional<ImagePosition> imagePosA = imageManager->getPattern(background.get<BackgroundPattern>().from); + optional<ImagePosition> imagePosB = imageManager->getPattern(background.get<BackgroundPattern>().to); + + if (!imagePosA || !imagePosB) + return; + + imageManager->bind(context, 0); + + for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) { + parameters.programs.fillPattern.get(properties).draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillPatternUniforms::values( + matrixForTile(tileID), + context.viewport.getCurrentValue().size, + imageManager->getPixelSize(), + *imagePosA, + *imagePosB, + background.get<BackgroundPattern>(), + tileID, + state + ), + tileVertexBuffer, + quadTriangleIndexBuffer, + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() + ); + } + } else { + for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) { + parameters.programs.fill.get(properties).draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillProgram::UniformValues { + uniforms::u_matrix::Value{ matrixForTile(tileID) }, + uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, + }, + tileVertexBuffer, + quadTriangleIndexBuffer, + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() + ); + } + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_circle.cpp b/src/mbgl/renderer/painters/painter_circle.cpp new file mode 100644 index 0000000000..58e384979d --- /dev/null +++ b/src/mbgl/renderer/painters/painter_circle.cpp @@ -0,0 +1,57 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/buckets/circle_bucket.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/layers/render_circle_layer.hpp> +#include <mbgl/style/layers/circle_layer_impl.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/circle_program.hpp> +#include <mbgl/gl/context.hpp> + +namespace mbgl { + +using namespace style; + +void Painter::renderCircle(PaintParameters& parameters, + CircleBucket& bucket, + const RenderCircleLayer& layer, + const RenderTile& tile) { + if (pass == RenderPass::Opaque) { + return; + } + + const CirclePaintProperties::PossiblyEvaluated& properties = layer.evaluated; + const bool scaleWithMap = properties.get<CirclePitchScale>() == CirclePitchScaleType::Map; + + parameters.programs.circle.get(properties).draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + frame.mapMode == MapMode::Still + ? stencilModeForClipping(tile.clip) + : gl::StencilMode::disabled(), + colorModeForRenderPass(), + CircleProgram::UniformValues { + uniforms::u_matrix::Value{ + tile.translatedMatrix(properties.get<CircleTranslate>(), + properties.get<CircleTranslateAnchor>(), + state) + }, + uniforms::u_scale_with_map::Value{ scaleWithMap }, + uniforms::u_extrude_scale::Value{ scaleWithMap + ? std::array<float, 2> {{ + pixelsToGLUnits[0] * state.getCameraToCenterDistance(), + pixelsToGLUnits[1] * state.getCameraToCenterDistance() + }} + : pixelsToGLUnits } + }, + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_clipping.cpp b/src/mbgl/renderer/painters/painter_clipping.cpp new file mode 100644 index 0000000000..cad092594e --- /dev/null +++ b/src/mbgl/renderer/painters/painter_clipping.cpp @@ -0,0 +1,37 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/fill_program.hpp> +#include <mbgl/util/clip_id.hpp> + +namespace mbgl { + +void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& clip) { + static const style::FillPaintProperties::PossiblyEvaluated properties {}; + static const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + programs->fill.get(properties).draw( + context, + gl::Triangles(), + gl::DepthMode::disabled(), + gl::StencilMode { + gl::StencilMode::Always(), + static_cast<int32_t>(clip.reference.to_ulong()), + 0b11111111, + gl::StencilMode::Keep, + gl::StencilMode::Keep, + gl::StencilMode::Replace + }, + gl::ColorMode::disabled(), + FillProgram::UniformValues { + uniforms::u_matrix::Value{ matrixForTile(tileID) }, + uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, + }, + tileVertexBuffer, + quadTriangleIndexBuffer, + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() + ); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_debug.cpp b/src/mbgl/renderer/painters/painter_debug.cpp new file mode 100644 index 0000000000..ee76aee54c --- /dev/null +++ b/src/mbgl/renderer/painters/painter_debug.cpp @@ -0,0 +1,162 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/buckets/debug_bucket.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/map/view.hpp> +#include <mbgl/tile/tile.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/fill_program.hpp> +#include <mbgl/util/string.hpp> +#include <mbgl/gl/debugging.hpp> +#include <mbgl/util/color.hpp> + +namespace mbgl { + +using namespace style; + +void Painter::renderTileDebug(const RenderTile& renderTile) { + if (frame.debugOptions == MapDebugOptions::NoDebug) + return; + + MBGL_DEBUG_GROUP(context, std::string { "debug " } + util::toString(renderTile.id)); + + static const style::Properties<>::PossiblyEvaluated properties {}; + static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + + auto draw = [&] (Color color, const auto& vertexBuffer, const auto& indexBuffer, const auto& segments, auto drawMode) { + programs->debug.draw( + context, + drawMode, + gl::DepthMode::disabled(), + stencilModeForClipping(renderTile.clip), + gl::ColorMode::unblended(), + DebugProgram::UniformValues { + uniforms::u_matrix::Value{ renderTile.matrix }, + uniforms::u_color::Value{ color } + }, + vertexBuffer, + indexBuffer, + segments, + paintAttibuteData, + properties, + state.getZoom() + ); + }; + + if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) { + Tile& tile = renderTile.tile; + if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() || + tile.debugBucket->complete != tile.isComplete() || + !(tile.debugBucket->modified == tile.modified) || + !(tile.debugBucket->expires == tile.expires) || + tile.debugBucket->debugMode != frame.debugOptions) { + tile.debugBucket = std::make_unique<DebugBucket>( + tile.id, tile.isRenderable(), tile.isComplete(), tile.modified, + tile.expires, frame.debugOptions, context); + } + + draw(Color::white(), + *tile.debugBucket->vertexBuffer, + *tile.debugBucket->indexBuffer, + tile.debugBucket->segments, + gl::Lines { 4.0f * frame.pixelRatio }); + + draw(Color::black(), + *tile.debugBucket->vertexBuffer, + *tile.debugBucket->indexBuffer, + tile.debugBucket->segments, + gl::Lines { 2.0f * frame.pixelRatio }); + } + + if (frame.debugOptions & MapDebugOptions::TileBorders) { + draw(Color::red(), + tileVertexBuffer, + tileBorderIndexBuffer, + tileBorderSegments, + gl::LineStrip { 4.0f * frame.pixelRatio }); + } +} + +void Painter::renderTileDebug(const mat4& matrix) { + if (frame.debugOptions == MapDebugOptions::NoDebug) + return; + + static const style::Properties<>::PossiblyEvaluated properties {}; + static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + + if (frame.debugOptions & MapDebugOptions::TileBorders) { + programs->debug.draw( + context, + gl::LineStrip { 4.0f * frame.pixelRatio }, + gl::DepthMode::disabled(), + gl::StencilMode::disabled(), + gl::ColorMode::unblended(), + DebugProgram::UniformValues { + uniforms::u_matrix::Value{ matrix }, + uniforms::u_color::Value{ Color::red() } + }, + tileVertexBuffer, + tileBorderIndexBuffer, + tileBorderSegments, + paintAttibuteData, + properties, + state.getZoom() + ); + } +} + +#ifndef NDEBUG +void Painter::renderClipMasks(PaintParameters&) { + context.setStencilMode(gl::StencilMode::disabled()); + context.setDepthMode(gl::DepthMode::disabled()); + context.setColorMode(gl::ColorMode::unblended()); + context.program = 0; + +#if not MBGL_USE_GLES2 + // Reset the value in case someone else changed it, or it's dirty. + context.pixelTransferStencil = gl::value::PixelTransferStencil::Default; + + // Read the stencil buffer + const auto viewport = context.viewport.getCurrentValue(); + auto image = + context.readFramebuffer<AlphaImage, gl::TextureFormat::Stencil>(viewport.size, false); + + // Scale the Stencil buffer to cover the entire color space. + auto it = image.data.get(); + auto end = it + viewport.size.width * viewport.size.height; + const auto factor = 255.0f / *std::max_element(it, end); + for (; it != end; ++it) { + *it *= factor; + } + + context.pixelZoom = { 1, 1 }; + context.rasterPos = { -1, -1, 0, 1 }; + context.drawPixels(image); +#endif // MBGL_USE_GLES2 +} + +void Painter::renderDepthBuffer(PaintParameters&) { + context.setStencilMode(gl::StencilMode::disabled()); + context.setDepthMode(gl::DepthMode::disabled()); + context.setColorMode(gl::ColorMode::unblended()); + context.program = 0; + +#if not MBGL_USE_GLES2 + // Scales the values in the depth buffer so that they cover the entire grayscale range. This + // makes it easier to spot tiny differences. + const float base = 1.0f / (1.0f - depthRangeSize); + context.pixelTransferDepth = { base, 1.0f - base }; + + // Read the stencil buffer + auto viewport = context.viewport.getCurrentValue(); + auto image = + context.readFramebuffer<AlphaImage, gl::TextureFormat::Depth>(viewport.size, false); + + context.pixelZoom = { 1, 1 }; + context.rasterPos = { -1, -1, 0, 1 }; + context.drawPixels(image); +#endif // MBGL_USE_GLES2 +} +#endif // NDEBUG + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_fill.cpp b/src/mbgl/renderer/painters/painter_fill.cpp new file mode 100644 index 0000000000..3a0bfed454 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_fill.cpp @@ -0,0 +1,141 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/buckets/fill_bucket.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/layers/render_fill_layer.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/style/layers/fill_layer_impl.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/fill_program.hpp> +#include <mbgl/util/convert.hpp> + +namespace mbgl { + +using namespace style; + +void Painter::renderFill(PaintParameters& parameters, + FillBucket& bucket, + const RenderFillLayer& layer, + const RenderTile& tile) { + const FillPaintProperties::PossiblyEvaluated& properties = layer.evaluated; + + if (!properties.get<FillPattern>().from.empty()) { + if (pass != RenderPass::Translucent) { + return; + } + + optional<ImagePosition> imagePosA = imageManager->getPattern(properties.get<FillPattern>().from); + optional<ImagePosition> imagePosB = imageManager->getPattern(properties.get<FillPattern>().to); + + if (!imagePosA || !imagePosB) { + return; + } + + imageManager->bind(context, 0); + + auto draw = [&] (uint8_t sublayer, + auto& program, + const auto& drawMode, + const auto& indexBuffer, + const auto& segments) { + program.get(properties).draw( + context, + drawMode, + depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite), + stencilModeForClipping(tile.clip), + colorModeForRenderPass(), + FillPatternUniforms::values( + tile.translatedMatrix(properties.get<FillTranslate>(), + properties.get<FillTranslateAnchor>(), + state), + context.viewport.getCurrentValue().size, + imageManager->getPixelSize(), + *imagePosA, + *imagePosB, + properties.get<FillPattern>(), + tile.id, + state + ), + *bucket.vertexBuffer, + indexBuffer, + segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); + }; + + draw(0, + parameters.programs.fillPattern, + gl::Triangles(), + *bucket.triangleIndexBuffer, + bucket.triangleSegments); + + if (!properties.get<FillAntialias>() || !layer.unevaluated.get<FillOutlineColor>().isUndefined()) { + return; + } + + draw(2, + parameters.programs.fillOutlinePattern, + gl::Lines { 2.0f }, + *bucket.lineIndexBuffer, + bucket.lineSegments); + } else { + auto draw = [&] (uint8_t sublayer, + auto& program, + const auto& drawMode, + const auto& indexBuffer, + const auto& segments) { + program.get(properties).draw( + context, + drawMode, + depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite), + stencilModeForClipping(tile.clip), + colorModeForRenderPass(), + FillProgram::UniformValues { + uniforms::u_matrix::Value{ + tile.translatedMatrix(properties.get<FillTranslate>(), + properties.get<FillTranslateAnchor>(), + state) + }, + uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, + }, + *bucket.vertexBuffer, + indexBuffer, + segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); + }; + + if (properties.get<FillAntialias>() && !layer.unevaluated.get<FillOutlineColor>().isUndefined() && pass == RenderPass::Translucent) { + draw(2, + parameters.programs.fillOutline, + gl::Lines { 2.0f }, + *bucket.lineIndexBuffer, + bucket.lineSegments); + } + + // 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 ((properties.get<FillColor>().constantOr(Color()).a >= 1.0f + && properties.get<FillOpacity>().constantOr(0) >= 1.0f) == (pass == RenderPass::Opaque)) { + draw(1, + parameters.programs.fill, + gl::Triangles(), + *bucket.triangleIndexBuffer, + bucket.triangleSegments); + } + + if (properties.get<FillAntialias>() && layer.unevaluated.get<FillOutlineColor>().isUndefined() && pass == RenderPass::Translucent) { + draw(2, + parameters.programs.fillOutline, + gl::Lines { 2.0f }, + *bucket.lineIndexBuffer, + bucket.lineSegments); + } + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_fill_extrusion.cpp b/src/mbgl/renderer/painters/painter_fill_extrusion.cpp new file mode 100644 index 0000000000..165476944b --- /dev/null +++ b/src/mbgl/renderer/painters/painter_fill_extrusion.cpp @@ -0,0 +1,86 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/fill_extrusion_program.hpp> +#include <mbgl/util/constants.hpp> +#include <mbgl/util/convert.hpp> + +namespace mbgl { + +using namespace style; + +void Painter::renderFillExtrusion(PaintParameters& parameters, + FillExtrusionBucket& bucket, + const RenderFillExtrusionLayer& layer, + const RenderTile& tile) { + const FillExtrusionPaintProperties::PossiblyEvaluated& properties = layer.evaluated; + + if (pass == RenderPass::Opaque) { + return; + } + + if (!properties.get<FillExtrusionPattern>().from.empty()) { + optional<ImagePosition> imagePosA = imageManager->getPattern(properties.get<FillExtrusionPattern>().from); + optional<ImagePosition> imagePosB = imageManager->getPattern(properties.get<FillExtrusionPattern>().to); + + if (!imagePosA || !imagePosB) { + return; + } + + imageManager->bind(context, 0); + + parameters.programs.fillExtrusionPattern.get(properties).draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadWrite), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillExtrusionPatternUniforms::values( + tile.translatedClipMatrix(properties.get<FillExtrusionTranslate>(), + properties.get<FillExtrusionTranslateAnchor>(), + state), + imageManager->getPixelSize(), + *imagePosA, + *imagePosB, + properties.get<FillExtrusionPattern>(), + tile.id, + state, + -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, + evaluatedLight + ), + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.triangleSegments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom()); + + } else { + parameters.programs.fillExtrusion.get(properties).draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadWrite), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillExtrusionUniforms::values( + tile.translatedClipMatrix(properties.get<FillExtrusionTranslate>(), + properties.get<FillExtrusionTranslateAnchor>(), + state), + state, + evaluatedLight + ), + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.triangleSegments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom()); + }; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_line.cpp b/src/mbgl/renderer/painters/painter_line.cpp new file mode 100644 index 0000000000..58f4131d96 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_line.cpp @@ -0,0 +1,91 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/buckets/line_bucket.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/layers/render_line_layer.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/style/layers/line_layer_impl.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/line_program.hpp> +#include <mbgl/geometry/line_atlas.hpp> + +namespace mbgl { + +using namespace style; + +void Painter::renderLine(PaintParameters& parameters, + LineBucket& bucket, + const RenderLineLayer& layer, + const RenderTile& tile) { + if (pass == RenderPass::Opaque) { + return; + } + + const RenderLinePaintProperties::PossiblyEvaluated& properties = layer.evaluated; + + auto draw = [&] (auto& program, auto&& uniformValues) { + program.get(properties).draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + stencilModeForClipping(tile.clip), + colorModeForRenderPass(), + std::move(uniformValues), + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); + }; + + if (!properties.get<LineDasharray>().from.empty()) { + const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round + ? LinePatternCap::Round : LinePatternCap::Square; + LinePatternPos posA = lineAtlas->getDashPosition(properties.get<LineDasharray>().from, cap); + LinePatternPos posB = lineAtlas->getDashPosition(properties.get<LineDasharray>().to, cap); + + lineAtlas->bind(context, 0); + + draw(parameters.programs.lineSDF, + LineSDFProgram::uniformValues( + properties, + frame.pixelRatio, + tile, + state, + pixelsToGLUnits, + posA, + posB, + lineAtlas->getSize().width)); + + } else if (!properties.get<LinePattern>().from.empty()) { + optional<ImagePosition> posA = imageManager->getPattern(properties.get<LinePattern>().from); + optional<ImagePosition> posB = imageManager->getPattern(properties.get<LinePattern>().to); + + if (!posA || !posB) + return; + + imageManager->bind(context, 0); + + draw(parameters.programs.linePattern, + LinePatternProgram::uniformValues( + properties, + tile, + state, + pixelsToGLUnits, + imageManager->getPixelSize(), + *posA, + *posB)); + + } else { + draw(parameters.programs.line, + LineProgram::uniformValues( + properties, + tile, + state, + pixelsToGLUnits)); + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_raster.cpp b/src/mbgl/renderer/painters/painter_raster.cpp new file mode 100644 index 0000000000..56e38ae8f4 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_raster.cpp @@ -0,0 +1,89 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/buckets/raster_bucket.hpp> +#include <mbgl/renderer/layers/render_raster_layer.hpp> +#include <mbgl/style/layers/raster_layer_impl.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/raster_program.hpp> + +namespace mbgl { + +using namespace style; + +static float saturationFactor(float saturation) { + if (saturation > 0) { + return 1 - 1 / (1.001 - saturation); + } else { + return -saturation; + } +} + +static float contrastFactor(float contrast) { + if (contrast > 0) { + return 1 / (1 - contrast); + } else { + return 1 + contrast; + } +} + +static std::array<float, 3> spinWeights(float spin) { + spin *= util::DEG2RAD; + float s = std::sin(spin); + float c = std::cos(spin); + std::array<float, 3> spin_weights = {{ + (2 * c + 1) / 3, + (-std::sqrt(3.0f) * s - c + 1) / 3, + (std::sqrt(3.0f) * s - c + 1) / 3 + }}; + return spin_weights; +} + +void Painter::renderRaster(PaintParameters& parameters, + RasterBucket& bucket, + const RenderRasterLayer& layer, + const mat4& matrix, + bool useBucketBuffers = false) { + if (pass != RenderPass::Translucent) + return; + if (!bucket.hasData()) + return; + + const RasterPaintProperties::PossiblyEvaluated& properties = layer.evaluated; + const RasterProgram::PaintPropertyBinders paintAttributeData(properties, 0); + + assert(bucket.texture); + context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear); + context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear); + + parameters.programs.raster.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + RasterProgram::UniformValues { + uniforms::u_matrix::Value{ matrix }, + uniforms::u_image0::Value{ 0 }, + uniforms::u_image1::Value{ 1 }, + uniforms::u_opacity::Value{ properties.get<RasterOpacity>() }, + uniforms::u_fade_t::Value{ 1 }, + uniforms::u_brightness_low::Value{ properties.get<RasterBrightnessMin>() }, + uniforms::u_brightness_high::Value{ properties.get<RasterBrightnessMax>() }, + uniforms::u_saturation_factor::Value{ saturationFactor(properties.get<RasterSaturation>()) }, + uniforms::u_contrast_factor::Value{ contrastFactor(properties.get<RasterContrast>()) }, + uniforms::u_spin_weights::Value{ spinWeights(properties.get<RasterHueRotate>()) }, + uniforms::u_buffer_scale::Value{ 1.0f }, + uniforms::u_scale_parent::Value{ 1.0f }, + uniforms::u_tl_parent::Value{ std::array<float, 2> {{ 0.0f, 0.0f }} }, + }, + useBucketBuffers ? *bucket.vertexBuffer : rasterVertexBuffer, + useBucketBuffers ? *bucket.indexBuffer : quadTriangleIndexBuffer, + useBucketBuffers ? bucket.segments : rasterSegments, + paintAttributeData, + properties, + state.getZoom() + ); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_symbol.cpp b/src/mbgl/renderer/painters/painter_symbol.cpp new file mode 100644 index 0000000000..d3a505aa3f --- /dev/null +++ b/src/mbgl/renderer/painters/painter_symbol.cpp @@ -0,0 +1,166 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/buckets/symbol_bucket.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/layers/render_symbol_layer.hpp> +#include <mbgl/style/layers/symbol_layer_impl.hpp> +#include <mbgl/text/glyph_atlas.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/programs/symbol_program.hpp> +#include <mbgl/programs/collision_box_program.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/tile/geometry_tile.hpp> + +#include <cmath> + +namespace mbgl { + +using namespace style; + +void Painter::renderSymbol(PaintParameters& parameters, + SymbolBucket& bucket, + const RenderSymbolLayer& layer, + const RenderTile& tile) { + if (pass == RenderPass::Opaque) { + return; + } + + const auto& layout = bucket.layout; + + frameHistory.bind(context, 1); + + auto draw = [&] (auto& program, + auto&& uniformValues, + const auto& buffers, + const auto& symbolSizeBinder, + const SymbolPropertyValues& values_, + const auto& binders, + const auto& paintProperties) + { + // We clip symbols to their tile extent in still mode. + const bool needsClipping = frame.mapMode == MapMode::Still; + + program.get(paintProperties).draw( + context, + gl::Triangles(), + values_.pitchAlignment == AlignmentType::Map + ? depthModeForSublayer(0, gl::DepthMode::ReadOnly) + : gl::DepthMode::disabled(), + needsClipping + ? stencilModeForClipping(tile.clip) + : gl::StencilMode::disabled(), + colorModeForRenderPass(), + std::move(uniformValues), + *buffers.vertexBuffer, + *symbolSizeBinder, + *buffers.indexBuffer, + buffers.segments, + binders, + paintProperties, + state.getZoom() + ); + }; + + assert(dynamic_cast<GeometryTile*>(&tile.tile)); + GeometryTile& geometryTile = static_cast<GeometryTile&>(tile.tile); + + if (bucket.hasIconData()) { + auto values = layer.iconPropertyValues(layout); + auto paintPropertyValues = layer.iconPaintProperties(); + + const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; + const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || state.getPitch() != 0; + + context.bindTexture(*geometryTile.iconAtlasTexture, 0, + bucket.sdfIcons || state.isChanging() || iconScaled || iconTransformed + ? gl::TextureFilter::Linear : gl::TextureFilter::Nearest); + + const Size texsize = geometryTile.iconAtlasTexture->size; + + if (bucket.sdfIcons) { + if (values.hasHalo) { + draw(parameters.programs.symbolIconSDF, + SymbolSDFIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), + bucket.icon, + bucket.iconSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); + } + + if (values.hasFill) { + draw(parameters.programs.symbolIconSDF, + SymbolSDFIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), + bucket.icon, + bucket.iconSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); + } + } else { + draw(parameters.programs.symbolIcon, + SymbolIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state), + bucket.icon, + bucket.iconSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); + } + } + + if (bucket.hasTextData()) { + context.bindTexture(*geometryTile.glyphAtlasTexture, 0, gl::TextureFilter::Linear); + + auto values = layer.textPropertyValues(layout); + auto paintPropertyValues = layer.textPaintProperties(); + + const Size texsize = geometryTile.glyphAtlasTexture->size; + + if (values.hasHalo) { + draw(parameters.programs.symbolGlyph, + SymbolSDFTextProgram::uniformValues(true, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), + bucket.text, + bucket.textSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).second, + paintPropertyValues); + } + + if (values.hasFill) { + draw(parameters.programs.symbolGlyph, + SymbolSDFTextProgram::uniformValues(true, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), + bucket.text, + bucket.textSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).second, + paintPropertyValues); + } + } + + if (bucket.hasCollisionBoxData()) { + static const style::Properties<>::PossiblyEvaluated properties {}; + static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); + + programs->collisionBox.draw( + context, + gl::Lines { 1.0f }, + gl::DepthMode::disabled(), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + CollisionBoxProgram::UniformValues { + uniforms::u_matrix::Value{ tile.matrix }, + uniforms::u_scale::Value{ std::pow(2.0f, float(state.getZoom() - tile.tile.id.overscaledZ)) }, + uniforms::u_zoom::Value{ float(state.getZoom() * 10) }, + uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) }, + }, + *bucket.collisionBox.vertexBuffer, + *bucket.collisionBox.indexBuffer, + bucket.collisionBox.segments, + paintAttributeData, + properties, + state.getZoom() + ); + } +} + +} // namespace mbgl |