summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/painter_line.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/painter_line.cpp')
-rw-r--r--src/mbgl/renderer/painter_line.cpp173
1 files changed, 48 insertions, 125 deletions
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 9880564ddc..9fa6b15559 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -5,9 +5,9 @@
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/line_uniforms.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
-#include <mbgl/util/mat2.hpp>
namespace mbgl {
@@ -17,150 +17,73 @@ void Painter::renderLine(PaintParameters& parameters,
LineBucket& bucket,
const LineLayer& layer,
const RenderTile& tile) {
- // Abort early.
- if (pass == RenderPass::Opaque) return;
-
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
+ if (pass == RenderPass::Opaque) {
+ return;
+ }
const auto& properties = layer.impl->paint;
- const auto& layout = bucket.layout;
-
- // the distance over which the line edge fades out.
- // Retina devices need a smaller distance to avoid aliasing.
- float antialiasing = 1.0 / frame.pixelRatio;
-
- float blur = properties.lineBlur + antialiasing;
-
- const Color color = properties.lineColor;
- const float opacity = properties.lineOpacity;
- const float ratio = 1.0 / tile.id.pixelsToTileUnits(1.0, state.getZoom());
-
- mat2 antialiasingMatrix;
- matrix::identity(antialiasingMatrix);
- matrix::scale(antialiasingMatrix, antialiasingMatrix, 1.0, std::cos(state.getPitch()));
- matrix::rotate(antialiasingMatrix, antialiasingMatrix, state.getAngle());
- // calculate how much longer the real world distance is at the top of the screen
- // than at the middle of the screen.
- float topedgelength = std::sqrt(std::pow(state.getSize().height, 2.0f) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2.0f)));
- float x = state.getSize().height / 2.0f * std::tan(state.getPitch());
- float extra = (topedgelength + x) / topedgelength - 1.0f;
-
- mat4 vtxMatrix = tile.translatedMatrix(properties.lineTranslate,
- properties.lineTranslateAnchor,
- state);
-
- setDepthSublayer(0);
-
- auto& linesdfShader = parameters.shaders.lineSDF;
- auto& linepatternShader = parameters.shaders.linePattern;
- auto& lineShader = parameters.shaders.line;
+ auto draw = [&] (auto& shader, auto&& uniformValues) {
+ context.draw({
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ shader,
+ std::move(uniformValues),
+ gl::Segmented<gl::Triangles>(
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments
+ )
+ });
+ };
if (!properties.lineDasharray.value.from.empty()) {
- context.program = linesdfShader.getID();
-
- linesdfShader.u_matrix = vtxMatrix;
- linesdfShader.u_linewidth = properties.lineWidth / 2;
- linesdfShader.u_gapwidth = properties.lineGapWidth / 2;
- linesdfShader.u_antialiasing = antialiasing / 2;
- linesdfShader.u_ratio = ratio;
- linesdfShader.u_blur = blur;
- linesdfShader.u_color = color;
- linesdfShader.u_opacity = opacity;
-
- const LinePatternCap cap =
- layout.lineCap == LineCapType::Round ? LinePatternCap::Round : LinePatternCap::Square;
+ const LinePatternCap cap = bucket.layout.lineCap == LineCapType::Round
+ ? LinePatternCap::Round : LinePatternCap::Square;
LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, cap);
LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, cap);
- const float widthA = posA.width * properties.lineDasharray.value.fromScale * layer.impl->dashLineWidth;
- const float widthB = posB.width * properties.lineDasharray.value.toScale * layer.impl->dashLineWidth;
-
- float scaleXA = 1.0 / tile.id.pixelsToTileUnits(widthA, state.getIntegerZoom());
- float scaleYA = -posA.height / 2.0;
- float scaleXB = 1.0 / tile.id.pixelsToTileUnits(widthB, state.getIntegerZoom());
- float scaleYB = -posB.height / 2.0;
-
- linesdfShader.u_patternscale_a = {{ scaleXA, scaleYA }};
- linesdfShader.u_tex_y_a = posA.y;
- linesdfShader.u_patternscale_b = {{ scaleXB, scaleYB }};
- linesdfShader.u_tex_y_b = posB.y;
- linesdfShader.u_sdfgamma = lineAtlas->width / (std::min(widthA, widthB) * 256.0 * frame.pixelRatio) / 2;
- linesdfShader.u_mix = properties.lineDasharray.value.t;
- linesdfShader.u_extra = extra;
- linesdfShader.u_offset = -properties.lineOffset;
- linesdfShader.u_antialiasingmatrix = antialiasingMatrix;
-
- linesdfShader.u_image = 0;
lineAtlas->bind(context, 0);
- bucket.drawLineSDF(linesdfShader, context, paintMode());
+ draw(parameters.shaders.lineSDF,
+ LineSDFUniforms::values(
+ properties,
+ frame.pixelRatio,
+ tile,
+ state,
+ posA,
+ posB,
+ layer.impl->dashLineWidth,
+ lineAtlas->width));
} else if (!properties.linePattern.value.from.empty()) {
- optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
+ optional<SpriteAtlasPosition> posA = spriteAtlas->getPosition(
properties.linePattern.value.from, SpritePatternMode::Repeating);
- optional<SpriteAtlasPosition> imagePosB =
- spriteAtlas->getPosition(properties.linePattern.value.to, SpritePatternMode::Repeating);
+ optional<SpriteAtlasPosition> posB = spriteAtlas->getPosition(
+ properties.linePattern.value.to, SpritePatternMode::Repeating);
- if (!imagePosA || !imagePosB)
+ if (!posA || !posB)
return;
- context.program = linepatternShader.getID();
-
- linepatternShader.u_matrix = vtxMatrix;
- linepatternShader.u_linewidth = properties.lineWidth / 2;
- linepatternShader.u_gapwidth = properties.lineGapWidth / 2;
- linepatternShader.u_antialiasing = antialiasing / 2;
- linepatternShader.u_ratio = ratio;
- linepatternShader.u_blur = blur;
-
- linepatternShader.u_pattern_size_a = {{
- tile.id.pixelsToTileUnits((*imagePosA).size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
- (*imagePosA).size[1]
- }};
- linepatternShader.u_pattern_tl_a = (*imagePosA).tl;
- linepatternShader.u_pattern_br_a = (*imagePosA).br;
-
- linepatternShader.u_pattern_size_b = {{
- tile.id.pixelsToTileUnits((*imagePosB).size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
- (*imagePosB).size[1]
- }};
- linepatternShader.u_pattern_tl_b = (*imagePosB).tl;
- linepatternShader.u_pattern_br_b = (*imagePosB).br;
-
- linepatternShader.u_fade = properties.linePattern.value.t;
- linepatternShader.u_opacity = properties.lineOpacity;
- linepatternShader.u_extra = extra;
- linepatternShader.u_offset = -properties.lineOffset;
- linepatternShader.u_antialiasingmatrix = antialiasingMatrix;
-
- linepatternShader.u_image = 0;
spriteAtlas->bind(true, context, 0);
- bucket.drawLinePatterns(linepatternShader, context, paintMode());
+ draw(parameters.shaders.linePattern,
+ LinePatternUniforms::values(
+ properties,
+ frame.pixelRatio,
+ tile,
+ state,
+ *posA,
+ *posB));
} else {
- context.program = lineShader.getID();
-
- lineShader.u_matrix = vtxMatrix;
- lineShader.u_linewidth = properties.lineWidth / 2;
- lineShader.u_gapwidth = properties.lineGapWidth / 2;
- lineShader.u_antialiasing = antialiasing / 2;
- lineShader.u_ratio = ratio;
- lineShader.u_blur = blur;
- lineShader.u_extra = extra;
- lineShader.u_offset = -properties.lineOffset;
- lineShader.u_antialiasingmatrix = antialiasingMatrix;
-
- lineShader.u_color = color;
- lineShader.u_opacity = opacity;
-
- bucket.drawLines(lineShader, context, paintMode());
+ draw(parameters.shaders.line,
+ LineColorUniforms::values(
+ properties,
+ frame.pixelRatio,
+ tile,
+ state));
}
}