From da06a5205679f19498bcc3fd3f57b53e36bb4bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 13 Feb 2014 16:21:51 +0100 Subject: [PATCH] cut down on redundant gl uniform changes --- include/llmr/map/transform.hpp | 6 +- include/llmr/renderer/shader-line.hpp | 38 +++++++++--- include/llmr/renderer/shader-linejoin.hpp | 23 ++++++-- include/llmr/renderer/shader-outline.hpp | 11 ++-- include/llmr/renderer/shader-pattern.hpp | 33 ++++++++--- include/llmr/renderer/shader-plain.hpp | 6 +- include/llmr/renderer/shader.hpp | 8 +-- src/renderer/painter.cpp | 71 +++++++++++++---------- src/renderer/shader-line.cpp | 44 +++++++++++++- src/renderer/shader-linejoin.cpp | 28 +++++++++ src/renderer/shader-pattern.cpp | 43 ++++++++++++++ src/renderer/shader.cpp | 2 +- src/shader/outline.vertex.glsl | 3 +- src/shader/plain.vertex.glsl | 3 +- src/shader/shaders.cpp | 4 +- 15 files changed, 249 insertions(+), 74 deletions(-) diff --git a/include/llmr/map/transform.hpp b/include/llmr/map/transform.hpp index 0118659dd..064aa5551 100644 --- a/include/llmr/map/transform.hpp +++ b/include/llmr/map/transform.hpp @@ -56,10 +56,10 @@ public: uint32_t height = 0; // physical (framebuffer) dimensions - uint32_t fb_width = 0; - uint32_t fb_height = 0; + float fb_width = 0; + float fb_height = 0; - double pixelRatio = 1; + float pixelRatio = 1; private: double x = 0, y = 0; // pixel values of the map center in the current scale diff --git a/include/llmr/renderer/shader-line.hpp b/include/llmr/renderer/shader-line.hpp index 47a46f628..6d6d79b72 100644 --- a/include/llmr/renderer/shader-line.hpp +++ b/include/llmr/renderer/shader-line.hpp @@ -11,18 +11,38 @@ public: void bind(char *offset); - int32_t a_pos; - int32_t a_extrude; - // int32_t a_linesofar; + void setExtrudeMatrix(const std::array& exmatrix); + void setColor(const std::array& color); + void setLineWidth(const std::array& linewidth); + void setRatio(float ratio); + void setDashArray(const std::array& dasharray); + void setDebug(float debug); - int32_t u_exmatrix; - int32_t u_linewidth; - int32_t u_color; - int32_t u_ratio; - int32_t u_dasharray; - int32_t u_debug; +private: + int32_t a_pos = -1; + int32_t a_extrude = -1; + // int32_t a_linesofar = -1; + + std::array exmatrix = {}; + int32_t u_exmatrix = -1; + + std::array color = {}; + int32_t u_color = -1; + + std::array linewidth = {}; + int32_t u_linewidth = -1; + + float ratio = 0; + int32_t u_ratio = -1; + + std::array dasharray = {}; + int32_t u_dasharray = -1; + + float debug = 0; + int32_t u_debug = -1; }; + } #endif diff --git a/include/llmr/renderer/shader-linejoin.hpp b/include/llmr/renderer/shader-linejoin.hpp index e553f2cb2..5aa30be5f 100644 --- a/include/llmr/renderer/shader-linejoin.hpp +++ b/include/llmr/renderer/shader-linejoin.hpp @@ -11,12 +11,25 @@ public: void bind(char *offset); - int32_t a_pos; + void setColor(const std::array& color); + void setWorld(const std::array& world); + void setLineWidth(const std::array& linewidth); + void setSize(float size); - int32_t u_world; - int32_t u_linewidth; - int32_t u_color; - int32_t u_size; +private: + int32_t a_pos = -1; + + std::array color = {}; + int32_t u_color = -1; + + std::array world = {}; + int32_t u_world = -1; + + std::array linewidth = {}; + int32_t u_linewidth = -1; + + float size = 0; + int32_t u_size = -1; }; } diff --git a/include/llmr/renderer/shader-outline.hpp b/include/llmr/renderer/shader-outline.hpp index 7d76500ca..5d05978cc 100644 --- a/include/llmr/renderer/shader-outline.hpp +++ b/include/llmr/renderer/shader-outline.hpp @@ -13,14 +13,15 @@ public: void setColor(const std::array& color); void setWorld(const std::array& world); + private: - int32_t a_pos; + int32_t a_pos = -1; - std::array color; - int32_t u_color; + std::array color = {}; + int32_t u_color = -1; - std::array world; - int32_t u_world; + std::array world = {}; + int32_t u_world = -1; }; } diff --git a/include/llmr/renderer/shader-pattern.hpp b/include/llmr/renderer/shader-pattern.hpp index d7b43a2c9..c26919569 100644 --- a/include/llmr/renderer/shader-pattern.hpp +++ b/include/llmr/renderer/shader-pattern.hpp @@ -11,14 +11,33 @@ public: void bind(char *offset); - int32_t a_pos; - int32_t u_color; - int32_t u_offset; - int32_t u_pattern_size; - int32_t u_pattern_tl; - int32_t u_pattern_br; - int32_t u_mix; + void setColor(const std::array& color); + void setOffset(const std::array& offset); + void setPatternSize(const std::array& pattern_size); + void setPatternTopLeft(const std::array& pattern_tl); + void setPatternBottomRight(const std::array& pattern_br); + void setMix(float mix); +private: + int32_t a_pos = -1; + + std::array color = {}; + int32_t u_color = -1; + + std::array offset = {}; + int32_t u_offset = -1; + + std::array pattern_size = {}; + int32_t u_pattern_size = -1; + + std::array pattern_tl = {}; + int32_t u_pattern_tl = -1; + + std::array pattern_br = {}; + int32_t u_pattern_br = -1; + + float mix = 0; + int32_t u_mix = -1; }; } diff --git a/include/llmr/renderer/shader-plain.hpp b/include/llmr/renderer/shader-plain.hpp index 859aa0e32..ae7d8d598 100644 --- a/include/llmr/renderer/shader-plain.hpp +++ b/include/llmr/renderer/shader-plain.hpp @@ -15,10 +15,10 @@ public: void setColor(const std::array& color); private: - int32_t a_pos; + int32_t a_pos = -1; - std::array color; - int32_t u_color; + std::array color = {}; + int32_t u_color = -1; }; } diff --git a/include/llmr/renderer/shader.hpp b/include/llmr/renderer/shader.hpp index a6a4c512a..294a5e69b 100644 --- a/include/llmr/renderer/shader.hpp +++ b/include/llmr/renderer/shader.hpp @@ -2,8 +2,8 @@ #define LLMR_RENDERER_SHADER #include +#include #include -#include namespace llmr { @@ -14,14 +14,14 @@ public: bool valid; uint32_t program; - void setMatrix(const mat4& matrix); + void setMatrix(const std::array& matrix); private: bool compileShader(uint32_t *shader, uint32_t type, const char *source); protected: - int32_t u_matrix; - mat4 matrix; + std::array matrix = {}; + int32_t u_matrix = -1; }; } diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index f8a4a86cb..73f96a55f 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -248,7 +248,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons } // Draw the entire line - outlineShader->setWorld({{ (float)transform.fb_width, (float)transform.fb_height }}); + outlineShader->setWorld({{ transform.fb_width, transform.fb_height }}); bucket.drawVertices(*outlineShader); } @@ -259,23 +259,27 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons // Draw texture fill ImagePosition imagePos = style.sprite->getPosition(properties.image, true); - double factor = 8.0 / pow(2, transform.getIntegerZoom() - id.z); - double mix = fmod(transform.getZoom(), 1.0); - vec2 imageSize { imagePos.size.x * factor, imagePos.size.y * factor }; + float factor = 8.0 / pow(2, transform.getIntegerZoom() - id.z); + float mix = fmod(transform.getZoom(), 1.0); - vec2 offset { - fmod(id.x * 4096, imageSize.x), - fmod(id.y * 4096, imageSize.y) - }; + std::array imageSize = {{ + imagePos.size.x * factor, + imagePos.size.y * factor + }}; + + std::array offset = {{ + (float)fmod(id.x * 4096, imageSize[0]), + (float)fmod(id.y * 4096, imageSize[1]) + }}; useProgram(patternShader->program); patternShader->setMatrix(matrix); - glUniform2f(patternShader->u_pattern_size, imageSize.x, imageSize.y); - glUniform2f(patternShader->u_offset, offset.x, offset.y); - glUniform2f(patternShader->u_pattern_tl, imagePos.tl.x, imagePos.tl.y); - glUniform2f(patternShader->u_pattern_br, imagePos.br.x, imagePos.br.y); - glUniform4fv(patternShader->u_color, 1, fill_color.data()); - glUniform1f(patternShader->u_mix, mix); + patternShader->setOffset(offset); + patternShader->setPatternSize(imageSize); + patternShader->setPatternTopLeft({{ imagePos.tl.x, imagePos.tl.y }}); + patternShader->setPatternBottomRight({{ imagePos.br.x, imagePos.br.y }}); + patternShader->setColor(fill_color); + patternShader->setMix(mix); style.sprite->bind(true); // Draw a rectangle that covers the entire viewport. @@ -303,13 +307,13 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons if (bucket.empty()) return; if (properties.hidden) return; - double width = properties.width; - double offset = properties.offset / 2; + float width = properties.width; + float offset = properties.offset / 2; // These are the radii of the line. We are limiting it to 16, which will result // in a point size of 64 on retina. - double inset = fmin((fmax(-1, offset - width / 2 - 0.5) + 1), 16.0f); - double outset = fmin(offset + width / 2 + 0.5, 16.0f); + float inset = fmin((fmax(-1, offset - width / 2 - 0.5) + 1), 16.0f); + float outset = fmin(offset + width / 2 + 0.5, 16.0f); Color color = properties.color; color[0] *= properties.opacity; @@ -321,14 +325,21 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons if (bucket.hasPoints() && outset > 1.0f) { useProgram(linejoinShader->program); linejoinShader->setMatrix(matrix); - glUniform4fv(linejoinShader->u_color, 1, color.data()); - glUniform2f(linejoinShader->u_world, transform.fb_width / 2, transform.fb_height / 2); - glUniform2f(linejoinShader->u_linewidth, (outset - 0.25) * transform.pixelRatio, (inset - 0.25) * transform.pixelRatio); + linejoinShader->setColor(color); + linejoinShader->setWorld({{ + transform.fb_width * 0.5f, + transform.fb_height * 0.5f + }}); + linejoinShader->setLineWidth({{ + ((outset - 0.25f) * transform.pixelRatio), + ((inset - 0.25f) * transform.pixelRatio) + }}); + float pointSize = ceil(transform.pixelRatio * outset * 2.0); #if defined(GL_ES_VERSION_2_0) - glUniform1f(linejoinShader->u_size, ceil(transform.pixelRatio * outset * 2.0)); + linejoinShader->setSize(pointSize); #else - glPointSize(ceil(transform.pixelRatio * outset * 2.0)); + glPointSize(pointSize); #endif bucket.drawPoints(*linejoinShader); @@ -352,16 +363,16 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons } else { useProgram(lineShader->program); lineShader->setMatrix(matrix); - glUniformMatrix4fv(lineShader->u_exmatrix, 1, GL_FALSE, exMatrix.data()); + lineShader->setExtrudeMatrix(exMatrix); // TODO: Move this to transform? - const double tilePixelRatio = transform.getScale() / (1 << transform.getIntegerZoom()) / 8; + const float tilePixelRatio = transform.getScale() / (1 << transform.getIntegerZoom()) / 8; - glUniform2f(lineShader->u_dasharray, 1, -1); - glUniform2f(lineShader->u_linewidth, outset, inset); - glUniform1f(lineShader->u_ratio, tilePixelRatio); - glUniform4fv(lineShader->u_color, 1, color.data()); - glUniform1f(lineShader->u_debug, 0); + lineShader->setDashArray({{ 1, -1 }}); + lineShader->setLineWidth({{ outset, inset }}); + lineShader->setRatio(tilePixelRatio); + lineShader->setColor(color); + lineShader->setDebug(0); bucket.drawLines(*lineShader); } } diff --git a/src/renderer/shader-line.cpp b/src/renderer/shader-line.cpp index e6d2d2f15..1db69247e 100644 --- a/src/renderer/shader-line.cpp +++ b/src/renderer/shader-line.cpp @@ -47,4 +47,46 @@ void LineShader::bind(char *offset) { glEnableVertexAttribArray(a_extrude); glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 4); -} \ No newline at end of file +} + +void LineShader::setExtrudeMatrix(const std::array& new_exmatrix) { + if (exmatrix != new_exmatrix) { + glUniformMatrix4fv(u_exmatrix, 1, GL_FALSE, new_exmatrix.data()); + exmatrix = new_exmatrix; + } +} + +void LineShader::setColor(const std::array& new_color) { + if (color != new_color) { + glUniform4fv(u_color, 1, new_color.data()); + color = new_color; + } +} + +void LineShader::setLineWidth(const std::array& new_linewidth) { + if (linewidth != new_linewidth) { + glUniform2fv(u_linewidth, 1, new_linewidth.data()); + linewidth = new_linewidth; + } +} + +void LineShader::setRatio(float new_ratio) { + if (ratio != new_ratio) { + glUniform1f(u_ratio, new_ratio); + ratio = new_ratio; + } +} + +void LineShader::setDashArray(const std::array& new_dasharray) { + if (dasharray != new_dasharray) { + glUniform2fv(u_dasharray, 1, new_dasharray.data()); + dasharray = new_dasharray; + } +} + +void LineShader::setDebug(float new_debug) { + if (debug != new_debug) { + glUniform1f(u_debug, new_debug); + debug = new_debug; + } +} diff --git a/src/renderer/shader-linejoin.cpp b/src/renderer/shader-linejoin.cpp index 9f89bc2d7..7e07d4c4b 100644 --- a/src/renderer/shader-linejoin.cpp +++ b/src/renderer/shader-linejoin.cpp @@ -37,3 +37,31 @@ void LinejoinShader::bind(char *offset) { // Note: We're referring to the vertices in a line array, which are 8 bytes long! glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset); } + +void LinejoinShader::setColor(const std::array& new_color) { + if (color != new_color) { + glUniform4fv(u_color, 1, new_color.data()); + color = new_color; + } +} + +void LinejoinShader::setWorld(const std::array& new_world) { + if (world != new_world) { + glUniform2fv(u_world, 1, new_world.data()); + world = new_world; + } +} + +void LinejoinShader::setLineWidth(const std::array& new_linewidth) { + if (linewidth != new_linewidth) { + glUniform2fv(u_linewidth, 1, new_linewidth.data()); + linewidth = new_linewidth; + } +} + +void LinejoinShader::setSize(float new_size) { + if (size != new_size) { + glUniform1f(u_size, new_size); + size = new_size; + } +} diff --git a/src/renderer/shader-pattern.cpp b/src/renderer/shader-pattern.cpp index 877b67664..2904fd4c4 100644 --- a/src/renderer/shader-pattern.cpp +++ b/src/renderer/shader-pattern.cpp @@ -40,3 +40,46 @@ void PatternShader::bind(char *offset) { glEnableVertexAttribArray(a_pos); glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset); } + +void PatternShader::setColor(const std::array& new_color) { + if (color != new_color) { + glUniform4fv(u_color, 1, new_color.data()); + color = new_color; + } +} + +void PatternShader::setOffset(const std::array& new_offset) { + if (offset != new_offset) { + glUniform2fv(u_offset, 1, new_offset.data()); + offset = new_offset; + } +} + +void PatternShader::setPatternSize(const std::array& 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& new_pattern_tl) { + if (pattern_tl != new_pattern_tl) { + glUniform2fv(u_pattern_tl, 1, new_pattern_tl.data()); + pattern_tl = new_pattern_tl; + } +} + +void PatternShader::setPatternBottomRight(const std::array& new_pattern_br) { + if (pattern_br != new_pattern_br) { + glUniform2fv(u_pattern_br, 1, new_pattern_br.data()); + pattern_br = new_pattern_br; + } +} + +void PatternShader::setMix(float new_mix) { + if (mix != new_mix) { + glUniform1f(u_mix, new_mix); + mix = new_mix; + } +} + diff --git a/src/renderer/shader.cpp b/src/renderer/shader.cpp index b913b665b..cdb8e9a9f 100644 --- a/src/renderer/shader.cpp +++ b/src/renderer/shader.cpp @@ -143,7 +143,7 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) { } -void Shader::setMatrix(const mat4& newMatrix) { +void Shader::setMatrix(const std::array& newMatrix) { if (matrix != newMatrix) { glUniformMatrix4fv(u_matrix, 1, GL_FALSE, newMatrix.data()); matrix = newMatrix; diff --git a/src/shader/outline.vertex.glsl b/src/shader/outline.vertex.glsl index c3d608fd7..60db8e45d 100644 --- a/src/shader/outline.vertex.glsl +++ b/src/shader/outline.vertex.glsl @@ -8,8 +8,7 @@ void main() { // If the x coordinate is the maximum integer, we move the z coordinates out // of the view plane so that the triangle gets clipped. This makes it easier // for us to create degenerate triangle strips. - float z = step(32767.0, a_pos.x) * 2.0; - gl_Position = u_matrix * vec4(a_pos, z, 1); + gl_Position = u_matrix * vec4(a_pos, 0, 1); v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world; } diff --git a/src/shader/plain.vertex.glsl b/src/shader/plain.vertex.glsl index ef8225231..866c3cd2f 100644 --- a/src/shader/plain.vertex.glsl +++ b/src/shader/plain.vertex.glsl @@ -3,6 +3,5 @@ attribute vec2 a_pos; uniform mat4 u_matrix; void main() { - float z = step(32767.0, a_pos.x) * 2.0; - gl_Position = u_matrix * vec4(a_pos, z, 1); + gl_Position = u_matrix * vec4(a_pos, 0, 1); } diff --git a/src/shader/shaders.cpp b/src/shader/shaders.cpp index b832804ed..ba64eb82a 100644 --- a/src/shader/shaders.cpp +++ b/src/shader/shaders.cpp @@ -13,7 +13,7 @@ const shader_source llmr::shaders[SHADER_COUNT] = { "uniform vec4 u_color;\nuniform vec2 u_linewidth;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_linewidth.t) or when fading out\n // (v_linewidth.s)\n float alpha = clamp(min(dist - (u_linewidth.t - 1.0), u_linewidth.s - dist), 0.0, 1.0);\n gl_FragColor = u_color * alpha;\n}\n", }, { - "attribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n\n v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;\n}\n", + "attribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n\n v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;\n}\n", "uniform vec4 u_color;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = smoothstep(1.0, 0.0, dist);\n gl_FragColor = u_color * alpha;\n}\n", }, { @@ -21,7 +21,7 @@ const shader_source llmr::shaders[SHADER_COUNT] = { "uniform vec4 u_color;\n\nuniform vec2 u_offset;\nuniform vec2 u_pattern_size;\nuniform vec2 u_pattern_tl;\nuniform vec2 u_pattern_br;\nuniform float u_mix;\n\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos;\n\nvoid main() {\n\n vec2 imagecoord = mod((v_pos + u_offset) / u_pattern_size, 1.0);\n vec2 pos = mix(u_pattern_tl, u_pattern_br, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord2 = mod(imagecoord * 2.0, 1.0);\n vec2 pos2 = mix(u_pattern_tl, u_pattern_br, imagecoord2);\n vec4 color2 = texture2D(u_image, pos2);\n\n vec4 color = mix(color1, color2, u_mix);\n gl_FragColor = color + u_color * (1.0 - color.a);\n}\n", }, { - "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n}\n", + "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n", "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n", } };