From 1be972eb15fb53fa07b3154fb93bbcf742888b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Sun, 1 Jun 2014 17:43:12 +0200 Subject: Allow property functions for prerender properties, but tie them to the tile's zoom level instead of the map zoom level fixes #253 --- bin/style.js | 21 ++++++++++------- include/llmr/renderer/painter.hpp | 6 ++--- include/llmr/renderer/prerendered_texture.hpp | 7 ++++-- include/llmr/style/properties.hpp | 33 ++++++++++++++++++++------- src/renderer/painter_fill.cpp | 20 ++++++++-------- src/renderer/painter_prerender.cpp | 12 +++++----- src/renderer/prerendered_texture.cpp | 17 +++++--------- src/style/style.cpp | 19 ++++----------- src/style/style_parser.cpp | 6 ++--- 9 files changed, 75 insertions(+), 66 deletions(-) diff --git a/bin/style.js b/bin/style.js index ffa326525a..eb2994fdf9 100644 --- a/bin/style.js +++ b/bin/style.js @@ -1819,6 +1819,11 @@ module.exports = { "stops", {"z": 16, "val": 10}, {"z": 17, "val": 11} + ], + "hillshade_prerender_size": [ + "stops", + {"z": 13, "val": 1024 }, + {"z": 14, "val": 512 } ] }, "classes": [ @@ -1973,7 +1978,7 @@ module.exports = { "color": "#103", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", @@ -1988,7 +1993,7 @@ module.exports = { "color": "#206", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", @@ -2003,7 +2008,7 @@ module.exports = { "color": "#fffff3", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", @@ -2018,7 +2023,7 @@ module.exports = { "color": "#ffd", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", @@ -2785,7 +2790,7 @@ module.exports = { "color": "#103", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", @@ -2799,7 +2804,7 @@ module.exports = { "color": "#206", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", @@ -2813,7 +2818,7 @@ module.exports = { "color": "#fdfdad", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", @@ -2828,7 +2833,7 @@ module.exports = { "color": "#ffe1b7", "antialias": false, "prerender": true, - "prerender-size": 1024, + "prerender-size": "hillshade_prerender_size", "prerender-blur": 1, "opacity": [ "stops", diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp index 0345c9c00c..104f4c9bd5 100644 --- a/include/llmr/renderer/painter.hpp +++ b/include/llmr/renderer/painter.hpp @@ -85,9 +85,9 @@ public: void renderText(TextBucket& bucket, const std::string& layer_name, const Tile::ID& id); void renderRaster(RasterBucket& bucket, const std::string& layer_name, const Tile::ID& id); - void preparePrerender(const GenericProperties &properties); - void finishPrerender(const GenericProperties &properties); - void renderPrerenderedTexture(Bucket &bucket, const GenericProperties &properties); + void preparePrerender(PrerenderedTexture &texture); + void finishPrerender(PrerenderedTexture &texture); + void renderPrerenderedTexture(PrerenderedTexture &texture, const GenericProperties &properties); void resize(); diff --git a/include/llmr/renderer/prerendered_texture.hpp b/include/llmr/renderer/prerendered_texture.hpp index 4b163ac70c..b109e397c3 100644 --- a/include/llmr/renderer/prerendered_texture.hpp +++ b/include/llmr/renderer/prerendered_texture.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace llmr { @@ -10,7 +11,7 @@ class Painter; class PrerenderedTexture : private util::noncopyable { public: - PrerenderedTexture(uint16_t size); + PrerenderedTexture(const PrerenderProperties &properties); ~PrerenderedTexture(); void bindTexture(); @@ -21,8 +22,10 @@ public: void blur(Painter& painter, uint16_t passes); +public: + const PrerenderProperties properties; + private: - const uint16_t size; GLint previous_fbo = 0; GLuint fbo = 0; GLuint texture = 0; diff --git a/include/llmr/style/properties.hpp b/include/llmr/style/properties.hpp index d0bc3b2d47..96e49b7e89 100644 --- a/include/llmr/style/properties.hpp +++ b/include/llmr/style/properties.hpp @@ -93,10 +93,16 @@ struct GenericClass { boost::optional translateAnchor; boost::optional opacity; boost::optional opacity_transition; - boost::optional prerender; - boost::optional prerenderBuffer; - boost::optional prerenderSize; - boost::optional prerenderBlur; + float prerender = false; + boost::optional prerenderBuffer; + boost::optional prerenderSize; + boost::optional prerenderBlur; +}; + +struct PrerenderProperties { + float buffer = 1.0f / 32.0f; + uint16_t size = 256; + uint16_t blur = 0; }; struct GenericProperties { @@ -104,10 +110,21 @@ struct GenericProperties { std::array translate = {{ 0, 0 }}; TranslateAnchor translateAnchor = TranslateAnchor::Map; float opacity = 1.0; - bool prerender = false; - float prerenderBuffer = 1.0f / 32.0f; - uint16_t prerenderSize = 256; - uint16_t prerenderBlur = 0; + bool prerender; + + // These are unresolved properties because the value here is per tile, so it might differ. + boost::optional prerenderBuffer; + boost::optional prerenderSize; + boost::optional prerenderBlur; + + // Obtains prerender properties by integer zoom level. + inline PrerenderProperties getPrerenderProperties(int8_t z) const { + PrerenderProperties props; + if (prerenderBuffer) props.buffer = prerenderBuffer.get().evaluate(z); + if (prerenderSize) props.size = prerenderSize.get().evaluate(z); + if (prerenderBlur) props.blur = prerenderBlur.get().evaluate(z); + return props; + } virtual bool isVisible() const { if (!enabled) { return false; } diff --git a/src/renderer/painter_fill.cpp b/src/renderer/painter_fill.cpp index 0cc137013f..0d3a415115 100644 --- a/src/renderer/painter_fill.cpp +++ b/src/renderer/painter_fill.cpp @@ -152,18 +152,19 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons : defaultFillProperties; if (!properties.enabled) return; - if (properties.prerender) { if (pass == Translucent) { + + // Buffer value around the 0..4096 extent that will be drawn into the 256x256 pixel // texture. We later scale the texture so that the actual bounds will align with this // tile's bounds. The reason we do this is so that the - if (!bucket.prerendered) { - bucket.prerendered = std::make_unique(properties.prerenderSize); + const PrerenderProperties prerender = properties.getPrerenderProperties(id.z); + bucket.prerendered = std::make_unique(prerender); bucket.prerendered->bindFramebuffer(); - preparePrerender(properties); + preparePrerender(*bucket.prerendered); const FillProperties modifiedProperties = [&]{ FillProperties modifiedProperties = properties; @@ -173,7 +174,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons // When drawing the fill, we want to draw a buffer around too, so we // essentially downscale everyting, and then upscale it later when rendering. - const int buffer = 4096 * properties.prerenderBuffer; + const int buffer = prerender.buffer * 4096.0f; const mat4 vtxMatrix = [&]{ mat4 vtxMatrix; matrix::ortho(vtxMatrix, -buffer, 4096 + buffer, -4096 - buffer, buffer, 0, 1); @@ -187,17 +188,16 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons setTranslucent(); renderFill(bucket, modifiedProperties, id, vtxMatrix); - - if (properties.prerenderBlur > 0) { - bucket.prerendered->blur(*this, properties.prerenderBlur); + if (prerender.blur > 0) { + bucket.prerendered->blur(*this, prerender.blur); } // RESET STATE bucket.prerendered->unbindFramebuffer(); - finishPrerender(properties); + finishPrerender(*bucket.prerendered); } - renderPrerenderedTexture(bucket, properties); + renderPrerenderedTexture(*bucket.prerendered, properties); } } else { const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor); diff --git a/src/renderer/painter_prerender.cpp b/src/renderer/painter_prerender.cpp index 7d4f7f9d93..6d748c7c4e 100644 --- a/src/renderer/painter_prerender.cpp +++ b/src/renderer/painter_prerender.cpp @@ -2,7 +2,7 @@ using namespace llmr; -void Painter::preparePrerender(const GenericProperties &properties) { +void Painter::preparePrerender(PrerenderedTexture &texture) { glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); @@ -13,18 +13,18 @@ void Painter::preparePrerender(const GenericProperties &properties) { #endif glClear(GL_COLOR_BUFFER_BIT); - glViewport(0, 0, properties.prerenderSize, properties.prerenderSize); + glViewport(0, 0, texture.properties.size, texture.properties.size); } -void Painter::finishPrerender(const GenericProperties &properties) { +void Painter::finishPrerender(PrerenderedTexture &texture) { glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glViewport(0, 0, gl_viewport[0], gl_viewport[1]); } -void Painter::renderPrerenderedTexture(Bucket &bucket, const GenericProperties &properties) { - const int buffer = 4096 * properties.prerenderBuffer; +void Painter::renderPrerenderedTexture(PrerenderedTexture &texture, const GenericProperties &properties) { + const int buffer = texture.properties.buffer * 4096.0f; // draw the texture on a quad useProgram(rasterShader->program); @@ -37,7 +37,7 @@ void Painter::renderPrerenderedTexture(Bucket &bucket, const GenericProperties & rasterShader->setImage(0); rasterShader->setBuffer(buffer); rasterShader->setOpacity(properties.opacity); - bucket.prerendered->bindTexture(); + texture.bindTexture(); coveringRasterArray.bind(*rasterShader, tileStencilBuffer, BUFFER_OFFSET(0)); glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index()); } diff --git a/src/renderer/prerendered_texture.cpp b/src/renderer/prerendered_texture.cpp index 408f433bee..7fc27ec719 100644 --- a/src/renderer/prerendered_texture.cpp +++ b/src/renderer/prerendered_texture.cpp @@ -4,8 +4,8 @@ using namespace llmr; -PrerenderedTexture::PrerenderedTexture(uint16_t size) - : size(size) { +PrerenderedTexture::PrerenderedTexture(const PrerenderProperties &properties) + : properties(properties) { } PrerenderedTexture::~PrerenderedTexture() { @@ -28,11 +28,6 @@ void PrerenderedTexture::bindTexture() { } glBindTexture(GL_TEXTURE_2D, texture); - - // if (!mipmapped) { - // glGenerateMipmap(GL_TEXTURE_2D); - // mipmapped = true; - // } } void PrerenderedTexture::bindFramebuffer() { @@ -45,7 +40,7 @@ void PrerenderedTexture::bindFramebuffer() { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, properties.size, properties.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); } @@ -95,7 +90,7 @@ void PrerenderedTexture::blur(Painter& painter, uint16_t passes) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, properties.size, properties.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); @@ -113,7 +108,7 @@ void PrerenderedTexture::blur(Painter& painter, uint16_t passes) { #endif glClear(GL_COLOR_BUFFER_BIT); - painter.gaussianShader->setOffset({{ 1.0f / float(size), 0 }}); + painter.gaussianShader->setOffset({{ 1.0f / float(properties.size), 0 }}); glBindTexture(GL_TEXTURE_2D, original_texture); painter.coveringGaussianArray.bind(*painter.gaussianShader, painter.tileStencilBuffer, BUFFER_OFFSET(0)); glDrawArrays(GL_TRIANGLES, 0, (GLsizei)painter.tileStencilBuffer.index()); @@ -127,7 +122,7 @@ void PrerenderedTexture::blur(Painter& painter, uint16_t passes) { #endif glClear(GL_COLOR_BUFFER_BIT); - painter.gaussianShader->setOffset({{ 0, 1.0f / float(size) }}); + painter.gaussianShader->setOffset({{ 0, 1.0f / float(properties.size) }}); glBindTexture(GL_TEXTURE_2D, secondary_texture); painter.coveringGaussianArray.bind(*painter.gaussianShader, painter.tileStencilBuffer, BUFFER_OFFSET(0)); glDrawArrays(GL_TRIANGLES, 0, (GLsizei)painter.tileStencilBuffer.index()); diff --git a/src/style/style.cpp b/src/style/style.cpp index 9ae0b273f4..a0c8a1e57b 100644 --- a/src/style/style.cpp +++ b/src/style/style.cpp @@ -51,21 +51,10 @@ void Style::cascadeProperties(GenericProperties &properties, const GenericClass& } } - if (klass.prerender) { - properties.prerender = klass.prerender.get(); - } - - if (klass.prerenderBuffer) { - properties.prerenderBuffer = klass.prerenderBuffer.get(); - } - - if (klass.prerenderSize) { - properties.prerenderSize = klass.prerenderSize.get(); - } - - if (klass.prerenderBlur) { - properties.prerenderBlur = klass.prerenderBlur.get(); - } + properties.prerender = klass.prerender; + properties.prerenderBuffer = klass.prerenderBuffer; + properties.prerenderSize = klass.prerenderSize; + properties.prerenderBlur = klass.prerenderBlur; } diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 83d0eb2564..fb3ab59578 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -561,15 +561,15 @@ void StyleParser::parseGenericClass(GenericClass &klass, JSVal value) { } if (value.HasMember("prerender-buffer")) { - klass.prerenderBuffer = toNumber(parseValue(value["prerender-buffer"])); + klass.prerenderBuffer = parseFunction(value["prerender-buffer"]); } if (value.HasMember("prerender-size")) { - klass.prerenderSize = toNumber(parseValue(value["prerender-size"])); + klass.prerenderSize = parseFunction(value["prerender-size"]); } if (value.HasMember("prerender-blur")) { - klass.prerenderBlur = toNumber(parseValue(value["prerender-blur"])); + klass.prerenderBlur = parseFunction(value["prerender-blur"]); } } -- cgit v1.2.1