diff options
Diffstat (limited to 'src/mbgl/renderer/painter_line.cpp')
-rw-r--r-- | src/mbgl/renderer/painter_line.cpp | 173 |
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)); } } |