diff --git a/include/mbgl/renderer/painter.hpp b/include/mbgl/renderer/painter.hpp index db85d8703..26e1bd395 100644 --- a/include/mbgl/renderer/painter.hpp +++ b/include/mbgl/renderer/painter.hpp @@ -88,6 +88,7 @@ public: void renderLine(LineBucket& bucket, std::shared_ptr layer_desc, const Tile::ID& id, const mat4 &matrix); void renderSymbol(SymbolBucket& bucket, std::shared_ptr layer_desc, const Tile::ID& id, const mat4 &matrix); void renderRaster(RasterBucket& bucket, std::shared_ptr layer_desc, const Tile::ID& id, const mat4 &matrix); + std::array spinWeights(float spin_value); void preparePrerender(RasterBucket &bucket); diff --git a/include/mbgl/shader/raster_shader.hpp b/include/mbgl/shader/raster_shader.hpp index ec69fa723..11765413f 100644 --- a/include/mbgl/shader/raster_shader.hpp +++ b/include/mbgl/shader/raster_shader.hpp @@ -14,6 +14,10 @@ public: void setImage(int32_t image); void setOpacity(float opacity); void setBuffer(float buffer); + void setBrightness(float brightness_low, float brightness_high); + void setSaturation(float saturation_factor); + void setContrast(float contrast_factor); + void setSpin(std::array spin_weights); private: int32_t a_pos = -1; @@ -26,6 +30,22 @@ private: float buffer = 0; int32_t u_buffer = -1; + + float brightness_low = 0; + int32_t u_brightness_low = -1; + + float brightness_high = 0; + int32_t u_brightness_high = -1; + + float saturation_factor = 0; + int32_t u_saturation_factor = -1; + + float contrast_factor = 1; + int32_t u_contrast_factor = -1; + + std::array spin_weights = {{}}; + int32_t u_spin_weights = -1; + }; } diff --git a/include/mbgl/style/property_key.hpp b/include/mbgl/style/property_key.hpp index 7d2498176..aee5db038 100644 --- a/include/mbgl/style/property_key.hpp +++ b/include/mbgl/style/property_key.hpp @@ -55,6 +55,7 @@ enum class PropertyKey { RasterOpacity, RasterHueRotate, + RasterBrightness, // for transitions only RasterBrightnessLow, RasterBrightnessHigh, RasterSaturation, diff --git a/src/renderer/painter_prerender.cpp b/src/renderer/painter_prerender.cpp index f17014b62..1a5433692 100644 --- a/src/renderer/painter_prerender.cpp +++ b/src/renderer/painter_prerender.cpp @@ -34,6 +34,10 @@ void Painter::renderPrerenderedTexture(RasterBucket &bucket, const mat4 &matrix, rasterShader->setImage(0); rasterShader->setBuffer(buffer); rasterShader->setOpacity(properties.opacity); + rasterShader->setBrightness(properties.brightness[0], properties.brightness[1]); + rasterShader->setSaturation(properties.saturation); + rasterShader->setContrast(properties.contrast); + rasterShader->setSpin(spinWeights(properties.hue_rotate)); bucket.texture.bindTexture(); coveringRasterArray.bind(*rasterShader, tileStencilBuffer, BUFFER_OFFSET(0)); glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index()); diff --git a/src/renderer/painter_raster.cpp b/src/renderer/painter_raster.cpp index b6d1a34b7..b67b4b553 100644 --- a/src/renderer/painter_raster.cpp +++ b/src/renderer/painter_raster.cpp @@ -66,6 +66,10 @@ void Painter::renderRaster(RasterBucket& bucket, std::shared_ptr lay rasterShader->setMatrix(matrix); rasterShader->setBuffer(0); rasterShader->setOpacity(properties.opacity); + rasterShader->setBrightness(properties.brightness[0], properties.brightness[1]); + rasterShader->setSaturation(properties.saturation); + rasterShader->setContrast(properties.contrast); + rasterShader->setSpin(spinWeights(properties.hue_rotate)); glDepthRange(strata + strata_epsilon, 1.0f); @@ -75,3 +79,15 @@ void Painter::renderRaster(RasterBucket& bucket, std::shared_ptr lay } } + +std::array Painter::spinWeights(float spin) { + spin *= M_PI / 180; + float s = std::sin(spin); + float c = std::cos(spin); + std::array spin_weights = {{ + (2 * c + 1) / 3, + (-std::sqrt(3.0f) * s - c + 1) / 3, + (std::sqrt(3.0f) * s - c + 1) / 3 + }}; + return spin_weights; +} diff --git a/src/shader/raster.fragment.glsl b/src/shader/raster.fragment.glsl index feb0a58f0..d56a5b590 100644 --- a/src/shader/raster.fragment.glsl +++ b/src/shader/raster.fragment.glsl @@ -3,6 +3,34 @@ uniform float u_opacity; varying vec2 v_pos; +uniform float u_brightness_low; +uniform float u_brightness_high; + +uniform float u_saturation_factor; +uniform float u_contrast_factor; +uniform vec3 u_spin_weights; + void main() { - gl_FragColor = texture2D(u_image, v_pos) * u_opacity; + + vec4 color = texture2D(u_image, v_pos) * u_opacity; + vec3 rgb = color.rgb; + + // spin + rgb = vec3( + dot(rgb, u_spin_weights.xyz), + dot(rgb, u_spin_weights.zxy), + dot(rgb, u_spin_weights.yzx)); + + // saturation + float average = (color.r + color.g + color.b) / 3.0; + rgb += (average - rgb) * u_saturation_factor; + + // contrast + rgb = (rgb - 0.5) * u_contrast_factor + 0.5; + + // brightness + vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low); + vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high); + + gl_FragColor = vec4(mix(u_high_vec, u_low_vec, rgb), color.a); } diff --git a/src/shader/raster_shader.cpp b/src/shader/raster_shader.cpp index 1a21a2edc..51b328fa8 100644 --- a/src/shader/raster_shader.cpp +++ b/src/shader/raster_shader.cpp @@ -24,6 +24,11 @@ RasterShader::RasterShader() u_image = glGetUniformLocation(program, "u_image"); u_opacity = glGetUniformLocation(program, "u_opacity"); u_buffer = glGetUniformLocation(program, "u_buffer"); + u_brightness_low = glGetUniformLocation(program, "u_brightness_low"); + u_brightness_high = glGetUniformLocation(program, "u_brightness_high"); + u_saturation_factor = glGetUniformLocation(program, "u_saturation_factor"); + u_contrast_factor = glGetUniformLocation(program, "u_contrast_factor"); + u_spin_weights = glGetUniformLocation(program, "u_spin_weights"); // fprintf(stderr, "RasterShader:\n"); // fprintf(stderr, " - u_matrix: %d\n", u_matrix); @@ -57,3 +62,45 @@ void RasterShader::setBuffer(float new_buffer) { buffer = new_buffer; } } + +void RasterShader::setBrightness(float new_brightness_low, float new_brightness_high) { + if (brightness_low != new_brightness_low) { + glUniform1f(u_brightness_low, new_brightness_low); + brightness_low = new_brightness_low; + } + if (brightness_high != new_brightness_high) { + glUniform1f(u_brightness_high, new_brightness_high); + brightness_high = new_brightness_high; + } +} + +void RasterShader::setSaturation(float new_saturation_factor) { + if (saturation_factor != new_saturation_factor) { + if (new_saturation_factor > 0) { + new_saturation_factor = 1 - 1 / (1.001 - new_saturation_factor); + } else { + new_saturation_factor = -new_saturation_factor; + } + glUniform1f(u_saturation_factor, new_saturation_factor); + saturation_factor = new_saturation_factor; + } +} + +void RasterShader::setContrast(float new_contrast_factor) { + if (contrast_factor != new_contrast_factor) { + if (new_contrast_factor > 0) { + new_contrast_factor = 1 / (1 - new_contrast_factor); + } else { + new_contrast_factor = 1 + new_contrast_factor; + } + glUniform1f(u_contrast_factor, new_contrast_factor); + contrast_factor = new_contrast_factor; + } +} + +void RasterShader::setSpin(std::array new_spin_weights) { + if (spin_weights != new_spin_weights) { + glUniform3fv(u_spin_weights, 1, new_spin_weights.data()); + spin_weights = new_spin_weights; + } +} \ No newline at end of file diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 67d3f81a0..43790e21b 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -631,15 +631,12 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) { parseOptionalProperty>("composite-opacity", Key::CompositeOpacity, klass, value); parseOptionalProperty("transition-composite-opacity", Key::CompositeOpacity, klass, value); -// TODO edit these?: parseOptionalProperty>("raster-opacity", Key::RasterOpacity, klass, value); parseOptionalProperty("transition-raster-opacity", Key::RasterOpacity, klass, value); parseOptionalProperty>("raster-hue-rotate", Key::RasterHueRotate, klass, value); parseOptionalProperty("transition-raster-hue-rotate", Key::RasterHueRotate, klass, value); - parseOptionalProperty>("raster-brightness-low", Key::RasterBrightnessLow, klass, value); - parseOptionalProperty("transition-raster-brightness-low", Key::RasterBrightnessLow, klass, value); - parseOptionalProperty>("raster-brightness-high", Key::RasterBrightnessHigh, klass, value); - parseOptionalProperty("transition-raster-brightness-high", Key::RasterBrightnessHigh, klass, value); + parseOptionalProperty>("raster-brightness", { Key::RasterBrightnessLow, Key::RasterBrightnessHigh }, klass, value); + parseOptionalProperty("transition-raster-brightness", Key::RasterBrightness, klass, value); parseOptionalProperty>("raster-saturation", Key::RasterSaturation, klass, value); parseOptionalProperty("transition-raster-saturation", Key::RasterSaturation, klass, value); parseOptionalProperty>("raster-contrast", Key::RasterContrast, klass, value);