From c86f558e9d608ac19ca5b26ea8f72e2dc43c07c0 Mon Sep 17 00:00:00 2001 From: Molly Lloyd Date: Wed, 20 Apr 2016 15:21:44 -0700 Subject: [core] port outlinepattern for fill-pattern anti-aliasing from gl-js to native add outlinepattern shader class to relevant files add outlinepattern code to painter_fill.cpp add outlinepattern code to fill_bucket refactor painter_fill, fix tests fix merge conflicts and setDepthSublayer update render test to no antialiasing so travis will be happy --- package.json | 2 +- src/mbgl/renderer/fill_bucket.cpp | 13 +++++++++ src/mbgl/renderer/fill_bucket.hpp | 4 ++- src/mbgl/renderer/painter.cpp | 2 ++ src/mbgl/renderer/painter.hpp | 2 ++ src/mbgl/renderer/painter_fill.cpp | 41 ++++++++++++++++++++++++++- src/mbgl/shader/outlinepattern.fragment.glsl | 30 ++++++++++++++++++++ src/mbgl/shader/outlinepattern.vertex.glsl | 21 ++++++++++++++ src/mbgl/shader/outlinepattern_shader.cpp | 21 ++++++++++++++ src/mbgl/shader/outlinepattern_shader.hpp | 32 +++++++++++++++++++++ test/fixtures/map/offline/expected.png | Bin 47842 -> 62976 bytes test/fixtures/map/offline/style.json | 3 +- 12 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 src/mbgl/shader/outlinepattern.fragment.glsl create mode 100644 src/mbgl/shader/outlinepattern.vertex.glsl create mode 100644 src/mbgl/shader/outlinepattern_shader.cpp create mode 100644 src/mbgl/shader/outlinepattern_shader.hpp diff --git a/package.json b/package.json index c7d82f1e15..62c1a7940a 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ }, "devDependencies": { "aws-sdk": "^2.3.5", - "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#1e0d988e187a6c9a7a74fa8d7feb9c66c2258123", + "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#d974ec6b3748a258f8ddd7528e049493390177b4", "node-gyp": "^3.3.1", "request": "^2.72.0", "tape": "^4.5.1" diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp index 1388c6dfb7..48d9ae88aa 100644 --- a/src/mbgl/renderer/fill_bucket.cpp +++ b/src/mbgl/renderer/fill_bucket.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -245,3 +246,15 @@ void FillBucket::drawVertices(OutlineShader& shader, gl::GLObjectStore& glObject elements_index += group->elements_length * lineElementsBuffer.itemSize; } } + +void FillBucket::drawVertices(OutlinePatternShader& shader, gl::GLObjectStore& glObjectStore) { + GLbyte* vertex_index = BUFFER_OFFSET(0); + GLbyte* elements_index = BUFFER_OFFSET(0); + for (auto& group : lineGroups) { + assert(group); + group->array[1].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, glObjectStore); + MBGL_CHECK_ERROR(glDrawElements(GL_LINES, group->elements_length * 2, GL_UNSIGNED_SHORT, elements_index)); + vertex_index += group->vertex_length * vertexBuffer.itemSize; + elements_index += group->elements_length * lineElementsBuffer.itemSize; + } +} diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp index 61a3b986ba..bd6a9a9cf4 100644 --- a/src/mbgl/renderer/fill_bucket.hpp +++ b/src/mbgl/renderer/fill_bucket.hpp @@ -16,6 +16,7 @@ namespace mbgl { class FillVertexBuffer; class OutlineShader; +class OutlinePatternShader; class PlainShader; class PatternShader; @@ -26,7 +27,7 @@ class FillBucket : public Bucket { static void free(void *userData, void *ptr); typedef ElementGroup<2> TriangleGroup; - typedef ElementGroup<1> LineGroup; + typedef ElementGroup<2> LineGroup; public: FillBucket(); @@ -43,6 +44,7 @@ public: void drawElements(PlainShader&, gl::GLObjectStore&); void drawElements(PatternShader&, gl::GLObjectStore&); void drawVertices(OutlineShader&, gl::GLObjectStore&); + void drawVertices(OutlinePatternShader&, gl::GLObjectStore&); private: TESSalloc *allocator; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 552859343b..1fbce82c03 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ Painter::Painter(const TransformState& state_, gl::GLObjectStore& glObjectStore_ plainShader = std::make_unique(glObjectStore); outlineShader = std::make_unique(glObjectStore); + outlinePatternShader = std::make_unique(glObjectStore); lineShader = std::make_unique(glObjectStore); linesdfShader = std::make_unique(glObjectStore); linepatternShader = std::make_unique(glObjectStore); diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 5dc87f9c9f..2fa5c02604 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -53,6 +53,7 @@ class BackgroundLayer; class SDFShader; class PlainShader; class OutlineShader; +class OutlinePatternShader; class LineShader; class LinejoinShader; class LineSDFShader; @@ -190,6 +191,7 @@ private: std::unique_ptr plainShader; std::unique_ptr outlineShader; + std::unique_ptr outlinePatternShader; std::unique_ptr lineShader; std::unique_ptr linesdfShader; std::unique_ptr linepatternShader; diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 0452b532ac..0808cd2ac1 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -108,6 +109,44 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI // Draw the actual triangles into the color & stencil buffer. setDepthSublayer(0); bucket.drawElements(*patternShader, glObjectStore); + + if (properties.fillAntialias && stroke_color == fill_color) { + config.program = outlinePatternShader->getID(); + outlinePatternShader->u_matrix = vtxMatrix; + config.lineWidth = 2.0f; + + // Draw the entire line + outlinePatternShader->u_world = {{ + static_cast(frame.framebufferSize[0]), + static_cast(frame.framebufferSize[1]) + }}; + + outlinePatternShader->u_pattern_tl_a = (*posA).tl; + outlinePatternShader->u_pattern_br_a = (*posA).br; + outlinePatternShader->u_pattern_tl_b = (*posB).tl; + outlinePatternShader->u_pattern_br_b = (*posB).br; + outlinePatternShader->u_opacity = properties.fillOpacity; + outlinePatternShader->u_image = 0; + outlinePatternShader->u_mix = properties.fillPattern.value.t; + + outlinePatternShader->u_patternscale_a = {{ + 1.0f / id.pixelsToTileUnits(imageSizeScaledA[0], state.getIntegerZoom()), + 1.0f / id.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom()) + }}; + outlinePatternShader->u_patternscale_b = {{ + 1.0f / id.pixelsToTileUnits(imageSizeScaledB[0], state.getIntegerZoom()), + 1.0f / id.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom()) + }}; + + outlinePatternShader->u_offset_a = std::array{{offsetAx, offsetAy}}; + outlinePatternShader->u_offset_b = std::array{{offsetBx, offsetBy}}; + + config.activeTexture = GL_TEXTURE0; + spriteAtlas->bind(true, glObjectStore); + + setDepthSublayer(2); + bucket.drawVertices(*outlinePatternShader, glObjectStore); + } } } else { @@ -135,7 +174,7 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI config.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio! outlineShader->u_color = fill_color; - + // Draw the entire line outlineShader->u_world = {{ static_cast(frame.framebufferSize[0]), diff --git a/src/mbgl/shader/outlinepattern.fragment.glsl b/src/mbgl/shader/outlinepattern.fragment.glsl new file mode 100644 index 0000000000..dd1efd63e6 --- /dev/null +++ b/src/mbgl/shader/outlinepattern.fragment.glsl @@ -0,0 +1,30 @@ +uniform float u_opacity; +uniform vec2 u_pattern_tl_a; +uniform vec2 u_pattern_br_a; +uniform vec2 u_pattern_tl_b; +uniform vec2 u_pattern_br_b; +uniform float u_mix; + +uniform sampler2D u_image; + +varying vec2 v_pos_a; +varying vec2 v_pos_b; +varying vec2 v_pos; + +void main() { + vec2 imagecoord = mod(v_pos_a, 1.0); + vec2 pos = mix(u_pattern_tl_a, u_pattern_br_a, imagecoord); + vec4 color1 = texture2D(u_image, pos); + + vec2 imagecoord_b = mod(v_pos_b, 1.0); + vec2 pos2 = mix(u_pattern_tl_b, u_pattern_br_b, imagecoord_b); + vec4 color2 = texture2D(u_image, pos2); + + // find distance to outline for alpha interpolation + + float dist = length(v_pos - gl_FragCoord.xy); + float alpha = smoothstep(1.0, 0.0, dist); + + + gl_FragColor = mix(color1, color2, u_mix) * alpha * u_opacity; +} \ No newline at end of file diff --git a/src/mbgl/shader/outlinepattern.vertex.glsl b/src/mbgl/shader/outlinepattern.vertex.glsl new file mode 100644 index 0000000000..e31b77b560 --- /dev/null +++ b/src/mbgl/shader/outlinepattern.vertex.glsl @@ -0,0 +1,21 @@ +uniform vec2 u_patternscale_a; +uniform vec2 u_patternscale_b; +uniform vec2 u_offset_a; +uniform vec2 u_offset_b; + +attribute vec2 a_pos; + +uniform mat4 u_matrix; +uniform vec2 u_world; + +varying vec2 v_pos_a; +varying vec2 v_pos_b; +varying vec2 v_pos; + + +void main() { + gl_Position = u_matrix * vec4(a_pos, 0, 1); + v_pos_a = u_patternscale_a * a_pos + u_offset_a; + v_pos_b = u_patternscale_b * a_pos + u_offset_b; + v_pos = (gl_Position.xy/gl_Position.w + 1.0) / 2.0 * u_world; +} diff --git a/src/mbgl/shader/outlinepattern_shader.cpp b/src/mbgl/shader/outlinepattern_shader.cpp new file mode 100644 index 0000000000..44b76b74c0 --- /dev/null +++ b/src/mbgl/shader/outlinepattern_shader.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +#include + +using namespace mbgl; + +OutlinePatternShader::OutlinePatternShader(gl::GLObjectStore& glObjectStore) + : Shader( + "outlinepattern", + shaders::outlinepattern::vertex, shaders::outlinepattern::fragment, + glObjectStore + ) { +} + +void OutlinePatternShader::bind(GLbyte *offset) { + MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos)); + MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset)); +} diff --git a/src/mbgl/shader/outlinepattern_shader.hpp b/src/mbgl/shader/outlinepattern_shader.hpp new file mode 100644 index 0000000000..eed3839fd3 --- /dev/null +++ b/src/mbgl/shader/outlinepattern_shader.hpp @@ -0,0 +1,32 @@ +#ifndef MBGL_SHADER_SHADER_OUTLINEPATTERN +#define MBGL_SHADER_SHADER_OUTLINEPATTERN + +#include +#include + +namespace mbgl { + +class OutlinePatternShader : public Shader { +public: + OutlinePatternShader(gl::GLObjectStore&); + + void bind(GLbyte *offset) final; + + UniformMatrix<4> u_matrix = {"u_matrix", *this}; + Uniform> u_pattern_tl_a = {"u_pattern_tl_a", *this}; + Uniform> u_pattern_br_a = {"u_pattern_br_a", *this}; + Uniform> u_pattern_tl_b = {"u_pattern_tl_b", *this}; + Uniform> u_pattern_br_b = {"u_pattern_br_b", *this}; + Uniform u_opacity = {"u_opacity", *this}; + Uniform u_mix = {"u_mix", *this}; + Uniform u_image = {"u_image", *this}; + Uniform> u_patternscale_a = {"u_patternscale_a", *this}; + Uniform> u_patternscale_b = {"u_patternscale_b", *this}; + Uniform> u_offset_a = {"u_offset_a", *this}; + Uniform> u_offset_b = {"u_offset_b", *this}; + Uniform> u_world = {"u_world", *this}; +}; + +} // namespace mbgl + +#endif \ No newline at end of file diff --git a/test/fixtures/map/offline/expected.png b/test/fixtures/map/offline/expected.png index 1b1c2be4c6..c7bfb79fbf 100644 Binary files a/test/fixtures/map/offline/expected.png and b/test/fixtures/map/offline/expected.png differ diff --git a/test/fixtures/map/offline/style.json b/test/fixtures/map/offline/style.json index 978df3aae3..e92dc2fb0a 100644 --- a/test/fixtures/map/offline/style.json +++ b/test/fixtures/map/offline/style.json @@ -21,7 +21,8 @@ "source": "mapbox", "source-layer": "water", "paint": { - "fill-pattern": "noise" + "fill-pattern": "noise", + "fill-antialias": false } }, { "id": "admin", -- cgit v1.2.1