summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/geometry/sprite_atlas.hpp1
-rw-r--r--include/mbgl/shader/pattern_shader.hpp24
-rw-r--r--include/mbgl/util/mat3.hpp40
-rw-r--r--src/renderer/painter_fill.cpp99
-rw-r--r--src/shader/pattern.fragment.glsl11
-rw-r--r--src/shader/pattern.vertex.glsl3
-rw-r--r--src/shader/pattern_shader.cpp54
-rw-r--r--src/util/mat3.cpp51
8 files changed, 181 insertions, 102 deletions
diff --git a/include/mbgl/geometry/sprite_atlas.hpp b/include/mbgl/geometry/sprite_atlas.hpp
index dc2378c2fb..bc123abe13 100644
--- a/include/mbgl/geometry/sprite_atlas.hpp
+++ b/include/mbgl/geometry/sprite_atlas.hpp
@@ -49,6 +49,7 @@ public:
inline float getHeight() const { return height; }
inline float getTextureWidth() const { return width * pixelRatio; }
inline float getTextureHeight() const { return height * pixelRatio; }
+ inline float getPixelRatio() const { return pixelRatio; }
private:
void allocate();
diff --git a/include/mbgl/shader/pattern_shader.hpp b/include/mbgl/shader/pattern_shader.hpp
index b1b49b54df..e574b755dc 100644
--- a/include/mbgl/shader/pattern_shader.hpp
+++ b/include/mbgl/shader/pattern_shader.hpp
@@ -11,33 +11,33 @@ public:
void bind(char *offset);
- void setColor(const std::array<float, 4>& color);
- void setOffset(const std::array<float, 2>& offset);
- void setPatternSize(const std::array<float, 2>& pattern_size);
void setPatternTopLeft(const std::array<float, 2>& pattern_tl);
void setPatternBottomRight(const std::array<float, 2>& pattern_br);
+ void setOpacity(float opacity);
+ void setImage(int image);
void setMix(float mix);
+ void setPatternMatrix(const std::array<float, 9> &patternmatrix);
private:
int32_t a_pos = -1;
- std::array<float, 4> color = {{}};
- int32_t u_color = -1;
-
- std::array<float, 2> offset = {{}};
- int32_t u_offset = -1;
-
- std::array<float, 2> pattern_size = {{}};
- int32_t u_pattern_size = -1;
-
std::array<float, 2> pattern_tl = {{}};
int32_t u_pattern_tl = -1;
std::array<float, 2> pattern_br = {{}};
int32_t u_pattern_br = -1;
+ float opacity = 0;
+ int32_t u_opacity = -1;
+
+ int image = 0;
+ int32_t u_image = -1;
+
float mix = 0;
int32_t u_mix = -1;
+
+ std::array<float, 9> patternmatrix = {{}};
+ int32_t u_patternmatrix = -1;
};
}
diff --git a/include/mbgl/util/mat3.hpp b/include/mbgl/util/mat3.hpp
new file mode 100644
index 0000000000..d44b1435d3
--- /dev/null
+++ b/include/mbgl/util/mat3.hpp
@@ -0,0 +1,40 @@
+// This is an incomplete port of http://glmatrix.net/
+//
+// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the
+// use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim
+// that you wrote the original software. If you use this software in a
+// product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+#ifndef MBGL_UTIL_MAT3
+#define MBGL_UTIL_MAT3
+
+#include <array>
+
+namespace mbgl {
+
+typedef std::array<float, 9> mat3;
+
+namespace matrix {
+
+void identity(mat3& out);
+void scale(mat3& out, const mat3& a, float x, float y);
+
+}
+}
+
+#endif
diff --git a/src/renderer/painter_fill.cpp b/src/renderer/painter_fill.cpp
index f99cc93bbf..fe08d4c2fa 100644
--- a/src/renderer/painter_fill.cpp
+++ b/src/renderer/painter_fill.cpp
@@ -6,6 +6,7 @@
#include <mbgl/map/sprite.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/util/std.hpp>
+#include <mbgl/util/mat3.hpp>
using namespace mbgl;
@@ -28,13 +29,10 @@ void Painter::renderFill(FillBucket& bucket, const FillProperties& properties, c
stroke_color[3] *= properties.opacity;
}
- bool outline = properties.antialias && properties.stroke_color != properties.fill_color;
- bool fringeline = properties.antialias && properties.stroke_color == properties.fill_color;
- if (fringeline) {
- outline = true;
- stroke_color = fill_color;
- }
+ const bool pattern = properties.image.size();
+ bool outline = properties.antialias && !pattern && properties.stroke_color != properties.fill_color;
+ bool fringeline = properties.antialias && !pattern && properties.stroke_color == properties.fill_color;
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
@@ -52,66 +50,59 @@ void Painter::renderFill(FillBucket& bucket, const FillProperties& properties, c
}});
depthRange(strata, 1.0f);
bucket.drawVertices(*outlineShader);
- } else if (fringeline) {
- // // We're only drawing to the first seven bits (== support a maximum of
- // // 127 overlapping polygons in one place before we get rendering errors).
- // glStencilMask(0x3F);
- // glClear(GL_STENCIL_BUFFER_BIT);
-
- // // Draw front facing triangles. Wherever the 0x80 bit is 1, we are
- // // increasing the lower 7 bits by one if the triangle is a front-facing
- // // triangle. This means that all visible polygons should be in CCW
- // // orientation, while all holes (see below) are in CW orientation.
- // glStencilFunc(GL_EQUAL, 0x80, 0x80);
-
- // // When we do a nonzero fill, we count the number of times a pixel is
- // // covered by a counterclockwise polygon, and subtract the number of
- // // times it is "uncovered" by a clockwise polygon.
- // glStencilOp(GL_KEEP, GL_KEEP, GL_INCR_WRAP);
}
- if ((fill_color[3] >= 1.0f) == (pass == RenderPass::Opaque)) {
+ if (pattern) {
+ // Image fill.
Sprite &sprite = *map.getSprite();
- if (properties.image.size() && sprite) {
+ if (pass == RenderPass::Translucent && sprite) {
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
- Rect<uint16_t> imagePos = spriteAtlas.getImage(properties.image, sprite);
-
-
- float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
- float mix = std::fmod(map.getState().getZoom(), 1.0);
-
- std::array<float, 2> imageSize = {{
- imagePos.w * factor,
- imagePos.h * factor
- }
- };
-
- std::array<float, 2> offset = {{
- (float)std::fmod(id.x * 4096, imageSize[0]),
- (float)std::fmod(id.y * 4096, imageSize[1])
- }
- };
+ const Rect<uint16_t> pos = spriteAtlas.getImage(properties.image, sprite);
+
+ // `repeating` indicates that the image will be used in a repeating pattern
+ // repeating pattern images are assumed to have a 1px padding that mirrors the opposite edge
+ // positions for repeating images are adjusted to exclude the edge
+ const int repeating = 1;
+ const std::array<float, 2> size {{
+ float(pos.w) / spriteAtlas.getPixelRatio(),
+ float(pos.h) / spriteAtlas.getPixelRatio(),
+ }};
+ const std::array<float, 2> tl {{
+ (float(pos.x + repeating) / spriteAtlas.getWidth()),
+ (float(pos.y + repeating) / spriteAtlas.getHeight()),
+ }};
+ const std::array<float, 2> br {{
+ (float(pos.x + pos.w - 2 * repeating) / spriteAtlas.getWidth()),
+ (float(pos.y + pos.h - 2 * repeating) / spriteAtlas.getHeight()),
+ }};
+ const float mix = std::fmod(float(map.getState().getZoom()), 1.0f);
+
+ const float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
+
+ mat3 patternMatrix;
+ matrix::identity(patternMatrix);
+ matrix::scale(patternMatrix, patternMatrix, 1.0f / (size[0] * factor), 1.0f / (size[1] * factor));
useProgram(patternShader->program);
patternShader->setMatrix(vtxMatrix);
- patternShader->setOffset(offset);
- patternShader->setPatternSize(imageSize);
- patternShader->setPatternTopLeft({{
- float(imagePos.x) / spriteAtlas.getWidth(),
- float(imagePos.y) / spriteAtlas.getHeight(),
- }});
- patternShader->setPatternBottomRight({{
- float(imagePos.x + imagePos.w) / spriteAtlas.getWidth(),
- float(imagePos.y + imagePos.h) / spriteAtlas.getHeight(),
- }});
- patternShader->setColor(fill_color);
+ patternShader->setPatternTopLeft(tl);
+ patternShader->setPatternBottomRight(br);
+ patternShader->setOpacity(properties.opacity);
+ patternShader->setImage(0);
patternShader->setMix(mix);
+ patternShader->setPatternMatrix(patternMatrix);
+
+ glActiveTexture(GL_TEXTURE0);
spriteAtlas.bind(true);
// Draw the actual triangles into the color & stencil buffer.
- depthRange(strata + strata_epsilon, 1.0f);
+ depthRange(strata, 1.0f);
bucket.drawElements(*patternShader);
- } else {
+ }
+ }
+ else {
+ // No image fill.
+ if ((fill_color[3] >= 1.0f) == (pass == RenderPass::Opaque)) {
// Only draw the fill when it's either opaque and we're drawing opaque
// fragments or when it's translucent and we're drawing translucent
// fragments
diff --git a/src/shader/pattern.fragment.glsl b/src/shader/pattern.fragment.glsl
index 850c7afaff..ba6aed3023 100644
--- a/src/shader/pattern.fragment.glsl
+++ b/src/shader/pattern.fragment.glsl
@@ -1,19 +1,15 @@
-uniform vec4 u_color;
-
-uniform vec2 u_offset;
-uniform vec2 u_pattern_size;
+uniform float u_opacity;
uniform vec2 u_pattern_tl;
uniform vec2 u_pattern_br;
uniform float u_mix;
-
uniform sampler2D u_image;
varying vec2 v_pos;
void main() {
- vec2 imagecoord = mod((v_pos + u_offset) / u_pattern_size, 1.0);
+ vec2 imagecoord = mod(v_pos, 1.0);
vec2 pos = mix(u_pattern_tl, u_pattern_br, imagecoord);
vec4 color1 = texture2D(u_image, pos);
@@ -21,6 +17,5 @@ void main() {
vec2 pos2 = mix(u_pattern_tl, u_pattern_br, imagecoord2);
vec4 color2 = texture2D(u_image, pos2);
- vec4 color = mix(color1, color2, u_mix);
- gl_FragColor = color + u_color * (1.0 - color.a);
+ gl_FragColor = mix(color1, color2, u_mix) * u_opacity;
}
diff --git a/src/shader/pattern.vertex.glsl b/src/shader/pattern.vertex.glsl
index eeee39930f..f2de884ead 100644
--- a/src/shader/pattern.vertex.glsl
+++ b/src/shader/pattern.vertex.glsl
@@ -1,10 +1,11 @@
uniform mat4 u_matrix;
+uniform mat3 u_patternmatrix;
attribute vec2 a_pos;
varying vec2 v_pos;
void main() {
- v_pos = a_pos;
gl_Position = u_matrix * vec4(a_pos, 0, 1);
+ v_pos = (u_patternmatrix * vec3(a_pos, 1)).xy;
}
diff --git a/src/shader/pattern_shader.cpp b/src/shader/pattern_shader.cpp
index f3943b964e..ec604290a6 100644
--- a/src/shader/pattern_shader.cpp
+++ b/src/shader/pattern_shader.cpp
@@ -19,21 +19,21 @@ PatternShader::PatternShader()
a_pos = glGetAttribLocation(program, "a_pos");
u_matrix = glGetUniformLocation(program, "u_matrix");
- u_color = glGetUniformLocation(program, "u_color");
- u_offset = glGetUniformLocation(program, "u_offset");
- u_pattern_size = glGetUniformLocation(program, "u_pattern_size");
u_pattern_tl = glGetUniformLocation(program, "u_pattern_tl");
u_pattern_br = glGetUniformLocation(program, "u_pattern_br");
+ u_opacity = glGetUniformLocation(program, "u_opacity");
+ u_image = glGetUniformLocation(program, "u_image");
u_mix = glGetUniformLocation(program, "u_mix");
+ u_patternmatrix = glGetUniformLocation(program, "u_patternmatrix");
// fprintf(stderr, "PatternShader:\n");
// fprintf(stderr, " - u_matrix: %d\n", u_matrix);
- // fprintf(stderr, " - u_color: %d\n", u_color);
- // fprintf(stderr, " - u_offset: %d\n", u_offset);
- // fprintf(stderr, " - u_pattern_size: %d\n", u_pattern_size);
// fprintf(stderr, " - u_pattern_tl: %d\n", u_pattern_tl);
// fprintf(stderr, " - u_pattern_br: %d\n", u_pattern_br);
+ // fprintf(stderr, " - u_opacity: %d\n", u_opacity);
+ // fprintf(stderr, " - u_image: %d\n", u_image);
// fprintf(stderr, " - u_mix: %d\n", u_mix);
+ // fprintf(stderr, " - u_patternmatrix: %d\n", u_patternmatrix);
}
void PatternShader::bind(char *offset) {
@@ -41,27 +41,6 @@ void PatternShader::bind(char *offset) {
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
}
-void PatternShader::setColor(const std::array<float, 4>& new_color) {
- if (color != new_color) {
- glUniform4fv(u_color, 1, new_color.data());
- color = new_color;
- }
-}
-
-void PatternShader::setOffset(const std::array<float, 2>& new_offset) {
- if (offset != new_offset) {
- glUniform2fv(u_offset, 1, new_offset.data());
- offset = new_offset;
- }
-}
-
-void PatternShader::setPatternSize(const std::array<float, 2>& new_pattern_size) {
- if (pattern_size != new_pattern_size) {
- glUniform2fv(u_pattern_size, 1, new_pattern_size.data());
- pattern_size = new_pattern_size;
- }
-}
-
void PatternShader::setPatternTopLeft(const std::array<float, 2>& new_pattern_tl) {
if (pattern_tl != new_pattern_tl) {
glUniform2fv(u_pattern_tl, 1, new_pattern_tl.data());
@@ -76,6 +55,20 @@ void PatternShader::setPatternBottomRight(const std::array<float, 2>& new_patter
}
}
+void PatternShader::setOpacity(float new_opacity) {
+ if (opacity != new_opacity) {
+ glUniform1f(u_opacity, new_opacity);
+ opacity = new_opacity;
+ }
+}
+
+void PatternShader::setImage(int new_image) {
+ if (image != new_image) {
+ glUniform1i(u_image, new_image);
+ image = new_image;
+ }
+}
+
void PatternShader::setMix(float new_mix) {
if (mix != new_mix) {
glUniform1f(u_mix, new_mix);
@@ -83,3 +76,10 @@ void PatternShader::setMix(float new_mix) {
}
}
+void PatternShader::setPatternMatrix(const std::array<float, 9>& new_patternmatrix) {
+ if (patternmatrix != new_patternmatrix) {
+ glUniformMatrix3fv(u_patternmatrix, 1, GL_FALSE, new_patternmatrix.data());
+ patternmatrix = new_patternmatrix;
+ }
+}
+
diff --git a/src/util/mat3.cpp b/src/util/mat3.cpp
new file mode 100644
index 0000000000..38858d2385
--- /dev/null
+++ b/src/util/mat3.cpp
@@ -0,0 +1,51 @@
+// This is an incomplete port of http://glmatrix.net/
+//
+// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the
+// use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim
+// that you wrote the original software. If you use this software in a
+// product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+#include <mbgl/util/mat3.hpp>
+
+#include <cmath>
+
+using namespace mbgl;
+
+void matrix::identity(mat3& out) {
+ out[0] = 1.0f;
+ out[1] = 0.0f;
+ out[2] = 0.0f;
+ out[3] = 0.0f;
+ out[4] = 1.0f;
+ out[5] = 0.0f;
+ out[6] = 0.0f;
+ out[7] = 0.0f;
+ out[8] = 1.0f;
+}
+
+void matrix::scale(mat3& out, const mat3& a, const float x, const float y) {
+ out[0] = x * a[0];
+ out[1] = x * a[1];
+ out[2] = x * a[2];
+ out[3] = y * a[3];
+ out[4] = y * a[4];
+ out[5] = y * a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+}