cut down on redundant gl uniform changes

This commit is contained in:
Konstantin Käfer
2014-02-13 16:21:51 +01:00
parent f5846e1ebb
commit da06a52056
15 changed files with 249 additions and 74 deletions

View File

@@ -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

View File

@@ -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<float, 16>& exmatrix);
void setColor(const std::array<float, 4>& color);
void setLineWidth(const std::array<float, 2>& linewidth);
void setRatio(float ratio);
void setDashArray(const std::array<float, 2>& 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<float, 16> exmatrix = {};
int32_t u_exmatrix = -1;
std::array<float, 4> color = {};
int32_t u_color = -1;
std::array<float, 2> linewidth = {};
int32_t u_linewidth = -1;
float ratio = 0;
int32_t u_ratio = -1;
std::array<float, 2> dasharray = {};
int32_t u_dasharray = -1;
float debug = 0;
int32_t u_debug = -1;
};
}
#endif

View File

@@ -11,12 +11,25 @@ public:
void bind(char *offset);
int32_t a_pos;
void setColor(const std::array<float, 4>& color);
void setWorld(const std::array<float, 2>& world);
void setLineWidth(const std::array<float, 2>& 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<float, 4> color = {};
int32_t u_color = -1;
std::array<float, 2> world = {};
int32_t u_world = -1;
std::array<float, 2> linewidth = {};
int32_t u_linewidth = -1;
float size = 0;
int32_t u_size = -1;
};
}

View File

@@ -13,14 +13,15 @@ public:
void setColor(const std::array<float, 4>& color);
void setWorld(const std::array<float, 2>& world);
private:
int32_t a_pos;
int32_t a_pos = -1;
std::array<float, 4> color;
int32_t u_color;
std::array<float, 4> color = {};
int32_t u_color = -1;
std::array<float, 2> world;
int32_t u_world;
std::array<float, 2> world = {};
int32_t u_world = -1;
};
}

View File

@@ -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<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 setMix(float mix);
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 mix = 0;
int32_t u_mix = -1;
};
}

View File

@@ -15,10 +15,10 @@ public:
void setColor(const std::array<float, 4>& color);
private:
int32_t a_pos;
int32_t a_pos = -1;
std::array<float, 4> color;
int32_t u_color;
std::array<float, 4> color = {};
int32_t u_color = -1;
};
}

View File

@@ -2,8 +2,8 @@
#define LLMR_RENDERER_SHADER
#include <cstdint>
#include <array>
#include <llmr/util/noncopyable.hpp>
#include <llmr/util/mat4.hpp>
namespace llmr {
@@ -14,14 +14,14 @@ public:
bool valid;
uint32_t program;
void setMatrix(const mat4& matrix);
void setMatrix(const std::array<float, 16>& matrix);
private:
bool compileShader(uint32_t *shader, uint32_t type, const char *source);
protected:
int32_t u_matrix;
mat4 matrix;
std::array<float, 16> matrix = {};
int32_t u_matrix = -1;
};
}

View File

@@ -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<double> 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<double> offset {
fmod(id.x * 4096, imageSize.x),
fmod(id.y * 4096, imageSize.y)
};
std::array<float, 2> imageSize = {{
imagePos.size.x * factor,
imagePos.size.y * factor
}};
std::array<float, 2> 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);
}
}

View File

@@ -47,4 +47,46 @@ void LineShader::bind(char *offset) {
glEnableVertexAttribArray(a_extrude);
glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 4);
}
}
void LineShader::setExtrudeMatrix(const std::array<float, 16>& new_exmatrix) {
if (exmatrix != new_exmatrix) {
glUniformMatrix4fv(u_exmatrix, 1, GL_FALSE, new_exmatrix.data());
exmatrix = new_exmatrix;
}
}
void LineShader::setColor(const std::array<float, 4>& new_color) {
if (color != new_color) {
glUniform4fv(u_color, 1, new_color.data());
color = new_color;
}
}
void LineShader::setLineWidth(const std::array<float, 2>& 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<float, 2>& 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;
}
}

View File

@@ -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<float, 4>& new_color) {
if (color != new_color) {
glUniform4fv(u_color, 1, new_color.data());
color = new_color;
}
}
void LinejoinShader::setWorld(const std::array<float, 2>& new_world) {
if (world != new_world) {
glUniform2fv(u_world, 1, new_world.data());
world = new_world;
}
}
void LinejoinShader::setLineWidth(const std::array<float, 2>& 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;
}
}

View File

@@ -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<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());
pattern_tl = new_pattern_tl;
}
}
void PatternShader::setPatternBottomRight(const std::array<float, 2>& 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;
}
}

View File

@@ -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<float, 16>& newMatrix) {
if (matrix != newMatrix) {
glUniformMatrix4fv(u_matrix, 1, GL_FALSE, newMatrix.data());
matrix = newMatrix;

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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",
}
};