From 30de793c2ab2f864af3e524be24f917f6897634a Mon Sep 17 00:00:00 2001 From: Chris Loer Date: Thu, 9 Nov 2017 13:24:43 -0800 Subject: [core] Update shaders/tests from GL JS. --- src/mbgl/programs/attributes.hpp | 2 + src/mbgl/programs/collision_box_program.hpp | 158 ++++++++++++++++++++--- src/mbgl/programs/programs.hpp | 4 +- src/mbgl/programs/symbol_program.cpp | 12 +- src/mbgl/programs/symbol_program.hpp | 34 +++-- src/mbgl/programs/uniforms.hpp | 1 + src/mbgl/renderer/layers/render_symbol_layer.cpp | 74 ++++++++--- src/mbgl/shaders/collision_box.cpp | 67 +++------- src/mbgl/shaders/collision_circle.cpp | 83 ++++++++++++ src/mbgl/shaders/collision_circle.hpp | 16 +++ src/mbgl/shaders/preludes.cpp | 4 + src/mbgl/shaders/symbol_icon.cpp | 24 ++-- src/mbgl/shaders/symbol_sdf.cpp | 54 +++----- 13 files changed, 378 insertions(+), 155 deletions(-) create mode 100644 src/mbgl/shaders/collision_circle.cpp create mode 100644 src/mbgl/shaders/collision_circle.hpp (limited to 'src') diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp index d023ec7d83..437ae2195c 100644 --- a/src/mbgl/programs/attributes.hpp +++ b/src/mbgl/programs/attributes.hpp @@ -30,6 +30,8 @@ MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_anchor_pos); MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos); MBGL_DEFINE_ATTRIBUTE(int16_t, 3, a_normal); MBGL_DEFINE_ATTRIBUTE(uint16_t, 1, a_edgedistance); +MBGL_DEFINE_ATTRIBUTE(uint8_t, 1, a_fade_opacity); +MBGL_DEFINE_ATTRIBUTE(uint8_t, 2, a_placed); template struct a_data { diff --git a/src/mbgl/programs/collision_box_program.hpp b/src/mbgl/programs/collision_box_program.hpp index ba99e0c087..46f65a905a 100644 --- a/src/mbgl/programs/collision_box_program.hpp +++ b/src/mbgl/programs/collision_box_program.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -11,37 +12,34 @@ namespace mbgl { -namespace uniforms { -MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale); -MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom); -} // namespace uniforms - -using CollisionBoxAttributes = gl::Attributes< +using CollisionBoxLayoutAttributes = gl::Attributes< attributes::a_pos, attributes::a_anchor_pos, - attributes::a_extrude, - attributes::a_data>; + attributes::a_extrude>; + +struct CollisionBoxDynamicAttributes : gl::Attributes { + static Vertex vertex(bool placed, bool notUsed) { + return Vertex { + {{ static_cast(placed), static_cast(notUsed) }} + }; + } +}; class CollisionBoxProgram : public Program< shaders::collision_box, gl::Line, - CollisionBoxAttributes, + gl::ConcatenateAttributes, gl::Uniforms< uniforms::u_matrix, - uniforms::u_scale, - uniforms::u_zoom, - uniforms::u_maxzoom, - uniforms::u_collision_y_stretch, - uniforms::u_camera_to_center_distance, - uniforms::u_pitch, - uniforms::u_fadetexture>, + uniforms::u_extrude_scale, + uniforms::u_camera_to_center_distance>, style::Properties<>> { public: using Program::Program; - static LayoutVertex vertex(Point a, Point anchor, Point o, float maxzoom, float placementZoom) { - return LayoutVertex { + static CollisionBoxLayoutAttributes::Vertex vertex(Point a, Point anchor, Point o) { + return CollisionBoxLayoutAttributes::Vertex { {{ static_cast(a.x), static_cast(a.y) @@ -53,13 +51,133 @@ public: {{ static_cast(::round(o.x)), static_cast(::round(o.y)) + }} + }; + } + + template + void draw(gl::Context& context, + DrawMode drawMode, + gl::DepthMode depthMode, + gl::StencilMode stencilMode, + gl::ColorMode colorMode, + const UniformValues& uniformValues, + const gl::VertexBuffer& layoutVertexBuffer, + const gl::VertexBuffer& dynamicVertexBuffer, + const gl::IndexBuffer& indexBuffer, + const SegmentVector& segments, + const PaintPropertyBinders& paintPropertyBinders, + const typename PaintProperties::PossiblyEvaluated& currentProperties, + float currentZoom, + const std::string& layerID) { + typename AllUniforms::Values allUniformValues = uniformValues + .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties)); + + typename Attributes::Bindings allAttributeBindings = CollisionBoxLayoutAttributes::bindings(layoutVertexBuffer) + .concat(CollisionBoxDynamicAttributes::bindings(dynamicVertexBuffer)) + .concat(paintPropertyBinders.attributeBindings(currentProperties)); + + assert(layoutVertexBuffer.vertexCount == dynamicVertexBuffer.vertexCount); + + for (auto& segment : segments) { + auto vertexArrayIt = segment.vertexArrays.find(layerID); + + if (vertexArrayIt == segment.vertexArrays.end()) { + vertexArrayIt = segment.vertexArrays.emplace(layerID, context.createVertexArray()).first; + } + + program.draw( + context, + std::move(drawMode), + std::move(depthMode), + std::move(stencilMode), + std::move(colorMode), + allUniformValues, + vertexArrayIt->second, + Attributes::offsetBindings(allAttributeBindings, segment.vertexOffset), + indexBuffer, + segment.indexOffset, + segment.indexLength); + } + } + +}; + + +class CollisionCircleProgram : public Program< + shaders::collision_circle, + gl::Triangle, + gl::ConcatenateAttributes, + gl::Uniforms< + uniforms::u_matrix, + uniforms::u_extrude_scale, + uniforms::u_camera_to_center_distance>, + style::Properties<>> +{ +public: + using Program::Program; + + static CollisionBoxLayoutAttributes::Vertex vertex(Point a, Point anchor, Point o) { + return CollisionBoxLayoutAttributes::Vertex { + {{ + static_cast(a.x), + static_cast(a.y) + }}, + {{ + static_cast(anchor.x), + static_cast(anchor.y) }}, {{ - static_cast(maxzoom * 10), - static_cast(placementZoom * 10) + static_cast(::round(o.x)), + static_cast(::round(o.y)) }} }; } + + template + void draw(gl::Context& context, + DrawMode drawMode, + gl::DepthMode depthMode, + gl::StencilMode stencilMode, + gl::ColorMode colorMode, + const UniformValues& uniformValues, + const gl::VertexBuffer& layoutVertexBuffer, + const gl::VertexBuffer& dynamicVertexBuffer, + const gl::IndexBuffer& indexBuffer, + const SegmentVector& segments, + const PaintPropertyBinders& paintPropertyBinders, + const typename PaintProperties::PossiblyEvaluated& currentProperties, + float currentZoom, + const std::string& layerID) { + typename AllUniforms::Values allUniformValues = uniformValues + .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties)); + + typename Attributes::Bindings allAttributeBindings = CollisionBoxLayoutAttributes::bindings(layoutVertexBuffer) + .concat(CollisionBoxDynamicAttributes::bindings(dynamicVertexBuffer)) + .concat(paintPropertyBinders.attributeBindings(currentProperties)); + + for (auto& segment : segments) { + auto vertexArrayIt = segment.vertexArrays.find(layerID); + + if (vertexArrayIt == segment.vertexArrays.end()) { + vertexArrayIt = segment.vertexArrays.emplace(layerID, context.createVertexArray()).first; + } + + program.draw( + context, + std::move(drawMode), + std::move(depthMode), + std::move(stencilMode), + std::move(colorMode), + allUniformValues, + vertexArrayIt->second, + Attributes::offsetBindings(allAttributeBindings, segment.vertexOffset), + indexBuffer, + segment.indexOffset, + segment.indexLength); + } + } + }; using CollisionBoxVertex = CollisionBoxProgram::LayoutVertex; diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp index 37ced32745..d769defaaf 100644 --- a/src/mbgl/programs/programs.hpp +++ b/src/mbgl/programs/programs.hpp @@ -32,7 +32,8 @@ public: symbolIconSDF(context, programParameters), symbolGlyph(context, programParameters), debug(context, programParameters), - collisionBox(context, programParameters) { + collisionBox(context, programParameters), + collisionCircle(context, programParameters) { } ProgramMap circle; @@ -53,6 +54,7 @@ public: DebugProgram debug; CollisionBoxProgram collisionBox; + CollisionCircleProgram collisionCircle; }; } // namespace mbgl diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp index 58174ff8a7..84a7a53f1d 100644 --- a/src/mbgl/programs/symbol_program.cpp +++ b/src/mbgl/programs/symbol_program.cpp @@ -37,6 +37,7 @@ Values makeValues(const bool isText, const bool alongLine, const RenderTile& tile, const TransformState& state, + const float symbolFadeChange, Args&&... args) { std::array extrudeScale; @@ -82,9 +83,8 @@ Values makeValues(const bool isText, uniforms::u_extrude_scale::Value{ extrudeScale }, uniforms::u_texsize::Value{ texsize }, uniforms::u_texture::Value{ 0 }, - uniforms::u_fadetexture::Value{ 1 }, + uniforms::u_fade_change::Value{ symbolFadeChange }, uniforms::u_is_text::Value{ isText }, - uniforms::u_collision_y_stretch::Value{ tile.tile.yStretch() }, uniforms::u_camera_to_center_distance::Value{ state.getCameraToCenterDistance() }, uniforms::u_pitch::Value{ state.getPitch() }, uniforms::u_pitch_with_map::Value{ pitchWithMap }, @@ -102,7 +102,8 @@ SymbolIconProgram::uniformValues(const bool isText, const std::array& pixelsToGLUnits, const bool alongLine, const RenderTile& tile, - const TransformState& state) + const TransformState& state, + const float symbolFadeChange) { return makeValues( isText, @@ -111,7 +112,8 @@ SymbolIconProgram::uniformValues(const bool isText, pixelsToGLUnits, alongLine, tile, - state + state, + symbolFadeChange ); } @@ -124,6 +126,7 @@ typename SymbolSDFProgram::UniformValues SymbolSDFProgram::UniformValues SymbolSDFProgram { - static Vertex vertex(Point anchorPoint, float labelAngle, float labelminzoom) { + static Vertex vertex(Point anchorPoint, float labelAngle) { return Vertex { {{ anchorPoint.x, anchorPoint.y, - static_cast(mbgl::attributes::packUint8Pair( - static_cast(std::fmod(labelAngle + 2 * M_PI, 2 * M_PI) / (2 * M_PI) * 255), - static_cast(labelminzoom * 10))) + labelAngle }} }; } }; + +struct SymbolOpacityAttributes : gl::Attributes { + static Vertex vertex(bool placed, float opacity) { + return Vertex { + {{ static_cast((static_cast(opacity * 127) << 1) | static_cast(placed)) }} + }; + } +}; struct ZoomEvaluatedSize { bool isZoomConstant; @@ -247,7 +253,7 @@ public: using LayoutAttributes = LayoutAttrs; using LayoutVertex = typename LayoutAttributes::Vertex; - using LayoutAndSizeAttributes = gl::ConcatenateAttributes; + using LayoutAndSizeAttributes = gl::ConcatenateAttributes>; using PaintProperties = PaintProps; using PaintPropertyBinders = typename PaintProperties::Binders; @@ -281,6 +287,7 @@ public: const UniformValues& uniformValues, const gl::VertexBuffer& layoutVertexBuffer, const gl::VertexBuffer& dynamicLayoutVertexBuffer, + const gl::VertexBuffer& opacityVertexBuffer, const SymbolSizeBinder& symbolSizeBinder, const gl::IndexBuffer& indexBuffer, const SegmentVector& segments, @@ -294,8 +301,12 @@ public: typename Attributes::Bindings allAttributeBindings = LayoutAttributes::bindings(layoutVertexBuffer) .concat(SymbolDynamicLayoutAttributes::bindings(dynamicLayoutVertexBuffer)) + .concat(SymbolOpacityAttributes::bindings(opacityVertexBuffer)) .concat(paintPropertyBinders.attributeBindings(currentProperties)); + assert(layoutVertexBuffer.vertexCount == dynamicLayoutVertexBuffer.vertexCount && + layoutVertexBuffer.vertexCount == opacityVertexBuffer.vertexCount); + for (auto& segment : segments) { auto vertexArrayIt = segment.vertexArrays.find(layerID); @@ -330,9 +341,8 @@ class SymbolIconProgram : public SymbolProgram< uniforms::u_extrude_scale, uniforms::u_texsize, uniforms::u_texture, - uniforms::u_fadetexture, + uniforms::u_fade_change, uniforms::u_is_text, - uniforms::u_collision_y_stretch, uniforms::u_camera_to_center_distance, uniforms::u_pitch, uniforms::u_pitch_with_map, @@ -350,7 +360,8 @@ public: const std::array& pixelsToGLUnits, const bool alongLine, const RenderTile&, - const TransformState&); + const TransformState&, + const float symbolFadeChange); }; enum class SymbolSDFPart { @@ -370,9 +381,8 @@ class SymbolSDFProgram : public SymbolProgram< uniforms::u_extrude_scale, uniforms::u_texsize, uniforms::u_texture, - uniforms::u_fadetexture, + uniforms::u_fade_change, uniforms::u_is_text, - uniforms::u_collision_y_stretch, uniforms::u_camera_to_center_distance, uniforms::u_pitch, uniforms::u_pitch_with_map, @@ -394,9 +404,8 @@ public: uniforms::u_extrude_scale, uniforms::u_texsize, uniforms::u_texture, - uniforms::u_fadetexture, + uniforms::u_fade_change, uniforms::u_is_text, - uniforms::u_collision_y_stretch, uniforms::u_camera_to_center_distance, uniforms::u_pitch, uniforms::u_pitch_with_map, @@ -420,6 +429,7 @@ public: const bool alongLine, const RenderTile&, const TransformState&, + const float SymbolFadeChange, const SymbolSDFPart); }; diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp index 285d243251..184f42e504 100644 --- a/src/mbgl/programs/uniforms.hpp +++ b/src/mbgl/programs/uniforms.hpp @@ -36,6 +36,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world); MBGL_DEFINE_UNIFORM_SCALAR(Size, u_texsize); MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map); MBGL_DEFINE_UNIFORM_SCALAR(float, u_camera_to_center_distance); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade_change); MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale); diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 1376e8a3d8..abc8391c40 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -92,7 +92,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { const auto& paintProperties) { // We clip symbols to their tile extent in still mode. - const bool needsClipping = parameters.mapMode == MapMode::Still; + const bool needsClipping = false; // TODO parameters.mapMode == MapMode::Still; program.get(paintProperties).draw( parameters.context, @@ -107,6 +107,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { std::move(uniformValues), *buffers.vertexBuffer, *buffers.dynamicVertexBuffer, + *buffers.opacityVertexBuffer, *symbolSizeBinder, *buffers.indexBuffer, buffers.segments, @@ -134,8 +135,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { values, tile, *bucket.iconSizeBinder, - parameters.state, - parameters.frameHistory); + parameters.state); parameters.context.updateVertexBuffer(*bucket.icon.dynamicVertexBuffer, std::move(bucket.icon.dynamicVertices)); } @@ -152,7 +152,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (bucket.sdfIcons) { if (values.hasHalo) { draw(parameters.programs.symbolIconSDF, - SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Halo), + SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.icon, bucket.iconSizeBinder, values, @@ -162,7 +162,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (values.hasFill) { draw(parameters.programs.symbolIconSDF, - SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Fill), + SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.icon, bucket.iconSizeBinder, values, @@ -171,7 +171,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { } } else { draw(parameters.programs.symbolIcon, - SymbolIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state), + SymbolIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange), bucket.icon, bucket.iconSizeBinder, values, @@ -196,8 +196,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { values, tile, *bucket.textSizeBinder, - parameters.state, - parameters.frameHistory); + parameters.state); parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); } @@ -206,7 +205,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (values.hasHalo) { draw(parameters.programs.symbolGlyph, - SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Halo), + SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.text, bucket.textSizeBinder, values, @@ -216,7 +215,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (values.hasFill) { draw(parameters.programs.symbolGlyph, - SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Fill), + SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.text, bucket.textSizeBinder, values, @@ -229,23 +228,27 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { static const style::Properties<>::PossiblyEvaluated properties {}; static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); + auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); + auto scale = std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ)); + std::array extrudeScale = + {{ + parameters.pixelsToGLUnits[0] / (pixelRatio * scale), + parameters.pixelsToGLUnits[1] / (pixelRatio * scale) + + }}; parameters.programs.collisionBox.draw( parameters.context, gl::Lines { 1.0f }, gl::DepthMode::disabled(), - parameters.stencilModeForClipping(tile.clip), + gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), CollisionBoxProgram::UniformValues { uniforms::u_matrix::Value{ tile.matrix }, - uniforms::u_scale::Value{ std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ)) }, - uniforms::u_zoom::Value{ float(parameters.state.getZoom() * 10) }, - uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) }, - uniforms::u_collision_y_stretch::Value{ tile.tile.yStretch() }, - uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() }, - uniforms::u_pitch::Value{ parameters.state.getPitch() }, - uniforms::u_fadetexture::Value{ 1 } + uniforms::u_extrude_scale::Value{ extrudeScale }, + uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() } }, *bucket.collisionBox.vertexBuffer, + *bucket.collisionBox.dynamicVertexBuffer, *bucket.collisionBox.indexBuffer, bucket.collisionBox.segments, paintAttributeData, @@ -254,6 +257,41 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { getID() ); } + if (bucket.hasCollisionCircleData()) { + static const style::Properties<>::PossiblyEvaluated properties {}; + static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); + + auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); + auto scale = std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ)); + std::array extrudeScale = + {{ + parameters.pixelsToGLUnits[0] / (pixelRatio * scale), + parameters.pixelsToGLUnits[1] / (pixelRatio * scale) + + }}; + + parameters.programs.collisionCircle.draw( + parameters.context, + gl::Triangles(), + gl::DepthMode::disabled(), + gl::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + CollisionBoxProgram::UniformValues { + uniforms::u_matrix::Value{ tile.matrix }, + uniforms::u_extrude_scale::Value{ extrudeScale }, + uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() } + }, + *bucket.collisionCircle.vertexBuffer, + *bucket.collisionCircle.dynamicVertexBuffer, + *bucket.collisionCircle.indexBuffer, + bucket.collisionCircle.segments, + paintAttributeData, + properties, + parameters.state.getZoom(), + getID() + ); + + } } } diff --git a/src/mbgl/shaders/collision_box.cpp b/src/mbgl/shaders/collision_box.cpp index 07fa94e338..9d11640bf4 100644 --- a/src/mbgl/shaders/collision_box.cpp +++ b/src/mbgl/shaders/collision_box.cpp @@ -10,77 +10,50 @@ const char* collision_box::vertexSource = R"MBGL_SHADER( attribute vec2 a_pos; attribute vec2 a_anchor_pos; attribute vec2 a_extrude; -attribute vec2 a_data; +attribute vec2 a_placed; uniform mat4 u_matrix; -uniform float u_scale; -uniform float u_pitch; -uniform float u_collision_y_stretch; +uniform vec2 u_extrude_scale; uniform float u_camera_to_center_distance; -varying float v_max_zoom; -varying float v_placement_zoom; -varying float v_perspective_zoom_adjust; -varying vec2 v_fade_tex; +varying float v_placed; +varying float v_notUsed; void main() { vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1); highp float camera_to_anchor_distance = projectedPoint.w; - highp float collision_perspective_ratio = 1.0 + 0.5 * ((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0); + highp float collision_perspective_ratio = 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance); - highp float incidence_stretch = camera_to_anchor_distance / (u_camera_to_center_distance * cos(u_pitch)); - highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch); + gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0); + gl_Position.xy += a_extrude * u_extrude_scale * gl_Position.w * collision_perspective_ratio; - gl_Position = u_matrix * vec4(a_pos + a_extrude * collision_perspective_ratio * collision_adjustment / u_scale, 0.0, 1.0); - - v_max_zoom = a_data.x; - v_placement_zoom = a_data.y; - - v_perspective_zoom_adjust = floor(log2(collision_perspective_ratio * collision_adjustment) * 10.0); - v_fade_tex = vec2((v_placement_zoom + v_perspective_zoom_adjust) / 255.0, 0.0); + v_placed = a_placed.x; + v_notUsed = a_placed.y; } )MBGL_SHADER"; const char* collision_box::fragmentSource = R"MBGL_SHADER( -uniform float u_zoom; -// u_maxzoom is derived from the maximum scale considered by the CollisionTile -// Labels with placement zoom greater than this value will not be placed, -// regardless of perspective effects. -uniform float u_maxzoom; -uniform sampler2D u_fadetexture; - -// v_max_zoom is a collision-box-specific value that controls when line-following -// collision boxes are used. -varying float v_max_zoom; -varying float v_placement_zoom; -varying float v_perspective_zoom_adjust; -varying vec2 v_fade_tex; + +varying float v_placed; +varying float v_notUsed; void main() { float alpha = 0.5; - // Green = no collisions, label is showing - gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0) * alpha; + // Red = collision, hide label + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * alpha; - // Red = collision, label hidden - if (texture2D(u_fadetexture, v_fade_tex).a < 1.0) { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * alpha; + // Blue = no collision, label is showing + if (v_placed > 0.5) { + gl_FragColor = vec4(0.0, 0.0, 1.0, 0.5) * alpha; } - // Faded black = this collision box is not used at this zoom (for curved labels) - if (u_zoom >= v_max_zoom + v_perspective_zoom_adjust) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) * alpha * 0.25; - } - - // Faded blue = the placement scale for this label is beyond the CollisionTile - // max scale, so it's impossible for this label to show without collision detection - // being run again (the label's glyphs haven't even been added to the symbol bucket) - if (v_placement_zoom >= u_maxzoom) { - gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0) * alpha * 0.2; + if (v_notUsed > 0.5) { + // This box not used, fade it out + gl_FragColor *= .1; } } - )MBGL_SHADER"; } // namespace shaders diff --git a/src/mbgl/shaders/collision_circle.cpp b/src/mbgl/shaders/collision_circle.cpp new file mode 100644 index 0000000000..1e85d99a33 --- /dev/null +++ b/src/mbgl/shaders/collision_circle.cpp @@ -0,0 +1,83 @@ +// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED. + +#include + +namespace mbgl { +namespace shaders { + +const char* collision_circle::name = "collision_circle"; +const char* collision_circle::vertexSource = R"MBGL_SHADER( +attribute vec2 a_pos; +attribute vec2 a_anchor_pos; +attribute vec2 a_extrude; +attribute vec2 a_placed; + +uniform mat4 u_matrix; +uniform vec2 u_extrude_scale; +uniform float u_camera_to_center_distance; + +varying float v_placed; +varying float v_notUsed; +varying float v_radius; + +varying vec2 v_extrude; +varying vec2 v_extrude_scale; + +void main() { + vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1); + highp float camera_to_anchor_distance = projectedPoint.w; + highp float collision_perspective_ratio = 0.5 + 0.5 * (camera_to_anchor_distance / u_camera_to_center_distance); + + gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0); + + highp float padding_factor = 1.2; // Pad the vertices slightly to make room for anti-alias blur + gl_Position.xy += a_extrude * u_extrude_scale * padding_factor * gl_Position.w / collision_perspective_ratio; + + v_placed = a_placed.x; + v_notUsed = a_placed.y; + v_radius = abs(a_extrude.y); // We don't pitch the circles, so both units of the extrusion vector are equal in magnitude to the radius + + v_extrude = a_extrude * padding_factor; + v_extrude_scale = u_extrude_scale * u_camera_to_center_distance / collision_perspective_ratio; +} + +)MBGL_SHADER"; +const char* collision_circle::fragmentSource = R"MBGL_SHADER( + +varying float v_placed; +varying float v_notUsed; +varying float v_radius; +varying vec2 v_extrude; +varying vec2 v_extrude_scale; + +void main() { + float alpha = 0.5; + + // Red = collision, hide label + vec4 color = vec4(1.0, 0.0, 0.0, 1.0) * alpha; + + // Blue = no collision, label is showing + if (v_placed > 0.5) { + color = vec4(0.0, 0.0, 1.0, 0.5) * alpha; + } + + if (v_notUsed > 0.5) { + // This box not used, fade it out + color *= .2; + } + + float extrude_scale_length = length(v_extrude_scale); + float extrude_length = length(v_extrude) * extrude_scale_length; + float stroke_width = 3.0; + float radius = v_radius * extrude_scale_length; + + float distance_to_edge = abs(extrude_length - radius); + float opacity_t = smoothstep(-stroke_width, 0.0, -distance_to_edge); + + gl_FragColor = opacity_t * color; +} + +)MBGL_SHADER"; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/collision_circle.hpp b/src/mbgl/shaders/collision_circle.hpp new file mode 100644 index 0000000000..12b1bcd445 --- /dev/null +++ b/src/mbgl/shaders/collision_circle.hpp @@ -0,0 +1,16 @@ +// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED. + +#pragma once + +namespace mbgl { +namespace shaders { + +class collision_circle { +public: + static const char* name; + static const char* vertexSource; + static const char* fragmentSource; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/preludes.cpp b/src/mbgl/shaders/preludes.cpp index feb185a684..6baa488a10 100644 --- a/src/mbgl/shaders/preludes.cpp +++ b/src/mbgl/shaders/preludes.cpp @@ -34,6 +34,10 @@ vec2 unpack_float(const float packedValue) { return vec2(v0, packedIntValue - v0 * 256); } +vec2 unpack_opacity(const float packedOpacity) { + int intOpacity = int(packedOpacity) / 2; + return vec2(float(intOpacity) / 127.0, mod(packedOpacity, 2.0)); +} // To minimize the number of attributes needed, we encode a 4-component // color into a pair of floats (i.e. a vec2) as follows: diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp index 1e96194738..f5c2bbe22d 100644 --- a/src/mbgl/shaders/symbol_icon.cpp +++ b/src/mbgl/shaders/symbol_icon.cpp @@ -12,6 +12,7 @@ const float PI = 3.141592653589793; attribute vec4 a_pos_offset; attribute vec4 a_data; attribute vec3 a_projected_pos; +attribute float a_fade_opacity; uniform bool u_is_size_zoom_constant; uniform bool u_is_size_feature_constant; @@ -21,7 +22,7 @@ uniform highp float u_camera_to_center_distance; uniform highp float u_pitch; uniform bool u_rotate_symbol; uniform highp float u_aspect_ratio; -uniform highp float u_collision_y_stretch; +uniform float u_fade_change; #ifndef HAS_UNIFORM_u_opacity @@ -43,7 +44,7 @@ uniform bool u_pitch_with_map; uniform vec2 u_texsize; varying vec2 v_tex; -varying vec2 v_fade_tex; +varying float v_fade_opacity; void main() { @@ -60,9 +61,7 @@ void main() { vec2 a_tex = a_data.xy; vec2 a_size = a_data.zw; - highp vec2 angle_labelminzoom = unpack_float(a_projected_pos[2]); - highp float segment_angle = -angle_labelminzoom[0] / 255.0 * 2.0 * PI; - mediump float a_labelminzoom = angle_labelminzoom[1]; + highp float segment_angle = -a_projected_pos[2]; float size; if (!u_is_size_zoom_constant && !u_is_size_feature_constant) { @@ -106,19 +105,14 @@ void main() { gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 64.0 * fontScale), 0.0, 1.0); v_tex = a_tex / u_texsize; - // See comments in symbol_sdf.vertex - highp float incidence_stretch = camera_to_anchor_distance / (u_camera_to_center_distance * cos(u_pitch)); - highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch); - - highp float collision_perspective_ratio = 1.0 + 0.5*((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0); - highp float perspective_zoom_adjust = floor(log2(collision_perspective_ratio * collision_adjustment) * 10.0); - v_fade_tex = vec2((a_labelminzoom + perspective_zoom_adjust) / 255.0, 0.0); + vec2 fade_opacity = unpack_opacity(a_fade_opacity); + float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change; + v_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change)); } )MBGL_SHADER"; const char* symbol_icon::fragmentSource = R"MBGL_SHADER( uniform sampler2D u_texture; -uniform sampler2D u_fadetexture; #ifndef HAS_UNIFORM_u_opacity @@ -129,7 +123,7 @@ uniform lowp float u_opacity; varying vec2 v_tex; -varying vec2 v_fade_tex; +varying float v_fade_opacity; void main() { @@ -138,7 +132,7 @@ void main() { #endif - lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * opacity; + lowp float alpha = opacity * v_fade_opacity; gl_FragColor = texture2D(u_texture, v_tex) * alpha; #ifdef OVERDRAW_INSPECTOR diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp index a4427f31ab..441eaf7aac 100644 --- a/src/mbgl/shaders/symbol_sdf.cpp +++ b/src/mbgl/shaders/symbol_sdf.cpp @@ -12,6 +12,7 @@ const float PI = 3.141592653589793; attribute vec4 a_pos_offset; attribute vec4 a_data; attribute vec3 a_projected_pos; +attribute float a_fade_opacity; // contents of a_size vary based on the type of property value // used for {text,icon}-size. @@ -81,12 +82,12 @@ uniform highp float u_pitch; uniform bool u_rotate_symbol; uniform highp float u_aspect_ratio; uniform highp float u_camera_to_center_distance; -uniform highp float u_collision_y_stretch; +uniform float u_fade_change; uniform vec2 u_texsize; -varying vec4 v_data0; -varying vec2 v_data1; +varying vec2 v_data0; +varying vec3 v_data1; void main() { @@ -131,9 +132,7 @@ void main() { vec2 a_tex = a_data.xy; vec2 a_size = a_data.zw; - highp vec2 angle_labelminzoom = unpack_float(a_projected_pos[2]); - highp float segment_angle = -angle_labelminzoom[0] / 255.0 * 2.0 * PI; - mediump float a_labelminzoom = angle_labelminzoom[1]; + highp float segment_angle = -a_projected_pos[2]; float size; if (!u_is_size_zoom_constant && !u_is_size_feature_constant) { @@ -185,31 +184,12 @@ void main() { float gamma_scale = gl_Position.w; vec2 tex = a_tex / u_texsize; - // incidence_stretch is the ratio of how much y space a label takes up on a tile while drawn perpendicular to the viewport vs - // how much space it would take up if it were drawn flat on the tile - // Using law of sines, camera_to_anchor/sin(ground_angle) = camera_to_center/sin(incidence_angle) - // sin(incidence_angle) = 1/incidence_stretch - // Incidence angle 90 -> head on, sin(incidence_angle) = 1, no incidence stretch - // Incidence angle 1 -> very oblique, sin(incidence_angle) =~ 0, lots of incidence stretch - // ground_angle = u_pitch + PI/2 -> sin(ground_angle) = cos(u_pitch) - // This 2D calculation is only exactly correct when gl_Position.x is in the center of the viewport, - // but it's a close enough approximation for our purposes - highp float incidence_stretch = camera_to_anchor_distance / (u_camera_to_center_distance * cos(u_pitch)); - // incidence_stretch only applies to the y-axis, but without re-calculating the collision tile, we can't - // adjust the size of only one axis. So, we do a crude approximation at placement time to get the aspect ratio - // about right, and then do the rest of the adjustment here: there will be some extra padding on the x-axis, - // but hopefully not too much. - // Never make the adjustment less than 1.0: instead of allowing collisions on the x-axis, be conservative on - // the y-axis. - highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch); - - // Floor to 1/10th zoom to dodge precision issues that can cause partially hidden labels - highp float collision_perspective_ratio = 1.0 + 0.5*((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0); - highp float perspective_zoom_adjust = floor(log2(collision_perspective_ratio * collision_adjustment) * 10.0); - vec2 fade_tex = vec2((a_labelminzoom + perspective_zoom_adjust) / 255.0, 0.0); - - v_data0 = vec4(tex.x, tex.y, fade_tex.x, fade_tex.y); - v_data1 = vec2(gamma_scale, size); + vec2 fade_opacity = unpack_opacity(a_fade_opacity); + float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change; + float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change)); + + v_data0 = vec2(tex.x, tex.y); + v_data1 = vec3(gamma_scale, size, interpolated_fade_opacity); } )MBGL_SHADER"; @@ -255,12 +235,11 @@ uniform lowp float u_halo_blur; uniform sampler2D u_texture; -uniform sampler2D u_fadetexture; uniform highp float u_gamma_scale; uniform bool u_is_text; -varying vec4 v_data0; -varying vec2 v_data1; +varying vec2 v_data0; +varying vec3 v_data1; void main() { @@ -290,9 +269,9 @@ void main() { vec2 tex = v_data0.xy; - vec2 fade_tex = v_data0.zw; float gamma_scale = v_data1.x; float size = v_data1.y; + float fade_opacity = v_data1[2]; float fontScale = u_is_text ? size / 24.0 : size; @@ -306,11 +285,10 @@ void main() { } lowp float dist = texture2D(u_texture, tex).a; - lowp float fade_alpha = texture2D(u_fadetexture, fade_tex).a; highp float gamma_scaled = gamma * gamma_scale; - highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist) * fade_alpha; + highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist); - gl_FragColor = color * (alpha * opacity); + gl_FragColor = color * (alpha * opacity * fade_opacity); #ifdef OVERDRAW_INSPECTOR gl_FragColor = vec4(1.0); -- cgit v1.2.1