From 8d9fe37a6b9408d47ec4709d766cafdca290858f Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Mon, 3 Jul 2023 11:55:50 -0700 Subject: [PATCH] Topic/drawable extrusion (#1288) Co-authored-by: Alex Cristici --- CMakeLists.txt | 10 +- bazel/core.bzl | 9 +- include/mbgl/gfx/drawable.hpp | 43 +-- include/mbgl/gfx/drawable_atlases_tweaker.hpp | 39 +++ include/mbgl/gfx/drawable_builder.hpp | 36 ++- include/mbgl/gfx/drawable_tweaker.hpp | 1 + include/mbgl/gfx/vertex_attribute.hpp | 16 +- include/mbgl/gl/drawable_gl.hpp | 5 +- include/mbgl/gl/drawable_gl_tweaker.hpp | 27 -- include/mbgl/renderer/layer_tweaker.hpp | 4 + include/mbgl/renderer/render_target.hpp | 5 +- .../shaders/gl/drawable_fill_extrusion.hpp | 135 ++++++++ .../gl/drawable_fill_extrusion_pattern.hpp | 232 ++++++++++++++ include/mbgl/shaders/gl/fill_extrusion.hpp | 1 - .../shaders/gl/fill_extrusion_pattern.hpp | 20 +- .../mbgl/shaders/gl/fill_outline_pattern.hpp | 20 +- include/mbgl/shaders/gl/fill_pattern.hpp | 20 +- include/mbgl/shaders/gl/line_pattern.hpp | 21 +- include/mbgl/shaders/shader_manifest.hpp | 4 +- include/mbgl/shaders/shader_source.hpp | 2 + shaders/drawable.fill_extrusion.fragment.glsl | 9 + shaders/drawable.fill_extrusion.vertex.glsl | 92 ++++++ ...wable.fill_extrusion_pattern.fragment.glsl | 73 +++++ ...rawable.fill_extrusion_pattern.vertex.glsl | 99 ++++++ shaders/fill_extrusion.vertex.glsl | 1 - shaders/fill_extrusion_pattern.fragment.glsl | 4 +- shaders/fill_extrusion_pattern.vertex.glsl | 4 +- shaders/fill_outline_pattern.fragment.glsl | 4 +- shaders/fill_outline_pattern.vertex.glsl | 4 +- shaders/fill_pattern.fragment.glsl | 4 +- shaders/fill_pattern.vertex.glsl | 4 +- shaders/line_pattern.fragment.glsl | 5 +- shaders/line_pattern.vertex.glsl | 4 +- shaders/manifest.json | 14 + src/mbgl/gfx/context.hpp | 5 - src/mbgl/gfx/drawable_atlases_tweaker.cpp | 25 ++ src/mbgl/gfx/drawable_builder.cpp | 7 +- src/mbgl/gfx/drawable_tweaker.cpp | 0 src/mbgl/gl/context.cpp | 5 - src/mbgl/gl/context.hpp | 1 - src/mbgl/gl/drawable_gl.cpp | 33 +- src/mbgl/gl/drawable_gl_tweaker.cpp | 15 - src/mbgl/gl/layer_group_gl.cpp | 11 +- src/mbgl/gl/renderer_backend.cpp | 2 + src/mbgl/programs/fill_extrusion_program.cpp | 34 +- src/mbgl/programs/fill_extrusion_program.hpp | 9 +- src/mbgl/renderer/layer_tweaker.cpp | 7 +- .../renderer/layers/circle_layer_tweaker.cpp | 7 +- .../layers/fill_extrusion_layer_tweaker.cpp | 152 +++++++++ .../layers/fill_extrusion_layer_tweaker.hpp | 49 +++ .../renderer/layers/fill_layer_tweaker.cpp | 10 +- .../renderer/layers/fill_layer_tweaker.hpp | 2 +- .../renderer/layers/heatmap_layer_tweaker.cpp | 11 +- .../renderer/layers/line_layer_tweaker.cpp | 88 +++--- .../renderer/layers/raster_layer_tweaker.cpp | 35 ++- .../layers/render_fill_extrusion_layer.cpp | 290 +++++++++++++++++- .../layers/render_fill_extrusion_layer.hpp | 17 + .../renderer/layers/render_fill_layer.cpp | 64 ++-- .../renderer/layers/render_line_layer.cpp | 2 +- .../renderer/layers/render_symbol_layer.cpp | 63 ++-- .../renderer/layers/render_symbol_layer.hpp | 3 +- .../renderer/layers/symbol_layer_tweaker.cpp | 42 ++- .../renderer/layers/symbol_layer_tweaker.hpp | 2 + src/mbgl/renderer/paint_parameters.hpp | 7 +- src/mbgl/renderer/render_layer.cpp | 12 + src/mbgl/renderer/render_layer.hpp | 19 +- src/mbgl/renderer/renderer_impl.cpp | 127 ++++++-- 67 files changed, 1744 insertions(+), 383 deletions(-) create mode 100644 include/mbgl/gfx/drawable_atlases_tweaker.hpp delete mode 100644 include/mbgl/gl/drawable_gl_tweaker.hpp create mode 100644 include/mbgl/shaders/gl/drawable_fill_extrusion.hpp create mode 100644 include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp create mode 100644 shaders/drawable.fill_extrusion.fragment.glsl create mode 100644 shaders/drawable.fill_extrusion.vertex.glsl create mode 100644 shaders/drawable.fill_extrusion_pattern.fragment.glsl create mode 100644 shaders/drawable.fill_extrusion_pattern.vertex.glsl create mode 100644 src/mbgl/gfx/drawable_atlases_tweaker.cpp delete mode 100644 src/mbgl/gfx/drawable_tweaker.cpp delete mode 100644 src/mbgl/gl/drawable_gl_tweaker.cpp create mode 100644 src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp create mode 100644 src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1848a6bbc..1892a2f36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ if(MLN_DRAWABLE_RENDERER) ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_impl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_builder.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_tweaker.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_atlases_tweaker.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_block.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_buffer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_attribute.hpp @@ -153,12 +154,10 @@ if(MLN_DRAWABLE_RENDERER) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program_mtl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/identity.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/suppress_copies.hpp - ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/shader_program_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_builder.hpp - ${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_tweaker.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/layer_group_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/render_target_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_block_gl.hpp @@ -170,7 +169,7 @@ if(MLN_DRAWABLE_RENDERER) ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder_impl.hpp - ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_tweaker.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_atlases_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/line_drawable_data.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/shader_group.cpp @@ -188,6 +187,8 @@ if(MLN_DRAWABLE_RENDERER) ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/circle_layer_tweaker.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_layer_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_layer_tweaker.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/raster_layer_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/raster_layer_tweaker.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -200,7 +201,6 @@ if(MLN_DRAWABLE_RENDERER) ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_builder.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_impl.hpp - ${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/layer_group_gl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture2d.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform_block_gl.cpp @@ -1014,6 +1014,8 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_line_sdf.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline_pattern.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_pattern.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_extrusion.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_heatmap.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_heatmap_texture.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_raster.hpp diff --git a/bazel/core.bzl b/bazel/core.bzl index 86fcd4373..1aae21fab 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -844,6 +844,8 @@ MLN_OPENGL_HEADERS = [ "include/mbgl/shaders/gl/drawable_fill.hpp", "include/mbgl/shaders/gl/drawable_fill_outline.hpp", "include/mbgl/shaders/gl/drawable_fill_outline_pattern.hpp", + "include/mbgl/shaders/gl/drawable_fill_extrusion.hpp", + "include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp", "include/mbgl/shaders/gl/drawable_fill_pattern.hpp", "include/mbgl/shaders/gl/drawable_line_gradient.hpp", "include/mbgl/shaders/gl/drawable_line_pattern.hpp", @@ -883,7 +885,7 @@ MLN_DRAWABLES_SOURCE = [ "src/mbgl/gfx/drawable.cpp", "src/mbgl/gfx/drawable_builder.cpp", "src/mbgl/gfx/drawable_builder_impl.hpp", - "src/mbgl/gfx/drawable_tweaker.cpp", + "src/mbgl/gfx/drawable_atlases_tweaker.cpp", "src/mbgl/gfx/image_drawable_data.hpp", "src/mbgl/gfx/line_drawable_data.hpp", "src/mbgl/gfx/symbol_drawable_data.hpp", @@ -901,6 +903,8 @@ MLN_DRAWABLES_SOURCE = [ "src/mbgl/renderer/layers/circle_layer_tweaker.hpp", "src/mbgl/renderer/layers/fill_layer_tweaker.cpp", "src/mbgl/renderer/layers/fill_layer_tweaker.hpp", + "src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp", + "src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp", "src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp", "src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp", "src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp", @@ -918,7 +922,6 @@ MLN_DRAWABLES_SOURCE = [ "src/mbgl/gl/drawable_gl.cpp", "src/mbgl/gl/drawable_gl_builder.cpp", "src/mbgl/gl/drawable_gl_impl.hpp", - "src/mbgl/gl/drawable_gl_tweaker.cpp", "src/mbgl/gl/layer_group_gl.cpp", "src/mbgl/gl/render_target_gl.cpp", "src/mbgl/gl/texture2d.cpp", @@ -933,6 +936,7 @@ MLN_DRAWABLES_HEADERS = [ "include/mbgl/gfx/drawable_impl.hpp", "include/mbgl/gfx/drawable_builder.hpp", "include/mbgl/gfx/drawable_tweaker.hpp", + "include/mbgl/gfx/drawable_atlases_tweaker.hpp", "include/mbgl/gfx/uniform_block.hpp", "include/mbgl/gfx/uniform_buffer.hpp", "include/mbgl/gfx/vertex_attribute.hpp", @@ -948,7 +952,6 @@ MLN_DRAWABLES_HEADERS = [ "include/mbgl/shaders/gl/shader_program_gl.hpp", "include/mbgl/gl/drawable_gl.hpp", "include/mbgl/gl/drawable_gl_builder.hpp", - "include/mbgl/gl/drawable_gl_tweaker.hpp", "include/mbgl/gl/layer_group_gl.hpp", "include/mbgl/gl/render_target_gl.hpp", "include/mbgl/gl/uniform_block_gl.hpp", diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index b54740048..7c2dcc11e 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -50,7 +50,7 @@ public: const util::SimpleIdentity& getId() const { return uniqueID; } /// Draw the drawable - virtual void draw(const PaintParameters&) const = 0; + virtual void draw(PaintParameters&) const = 0; /// Drawable name is used for debugging and troubleshooting const std::string& getName() const { return name; } @@ -101,37 +101,38 @@ public: /// @param location A sampler location in the shader being used with this drawable. void setTexture(gfx::Texture2DPtr texture, int32_t location); - using TexSourceFunc = std::function; - - /// @brief Provide a function to get the current textures - void setTextureSource(TexSourceFunc value) { textureSource = std::move(value); } - const TexSourceFunc& getTextureSource() const { return textureSource; } - - /// @brief Provide all texture sources at once - void setTextureSources(std::vector); - /// Whether the drawble should be drawn bool getEnabled() const { return enabled; } void setEnabled(bool value) { enabled = value; } - /// Whether to do stenciling (based on the Tile ID) - bool getNeedsStencil() const { return needsStencil; } - void setNeedsStencil(bool value) { needsStencil = value; } + /// Whether to render to the color target + bool getEnableColor() const { return enableColor; } + void setEnableColor(bool value) { enableColor = value; } + + /// Whether to do stenciling (based on the Tile ID or 3D) + bool getEnableStencil() const { return enableStencil; } + void setEnableStencil(bool value) { enableStencil = value; } /// not used for anything yet DrawPriority getDrawPriority() const { return drawPriority; } void setDrawPriority(DrawPriority value) { drawPriority = value; } - /// Determines depth range within the layer + /// Determines depth range within the layer for 2D drawables int32_t getSubLayerIndex() const { return subLayerIndex; } void setSubLayerIndex(int32_t value) { subLayerIndex = value; } - const std::optional& getTileID() const { return tileID; } - void setTileID(const OverscaledTileID& value) { tileID = value; } - + /// Depth writability for 2D drawables DepthMaskType getDepthType() const { return depthType; } void setDepthType(DepthMaskType value) { depthType = value; } + /// Uses 3D depth mode + bool getIs3D() const { return is3D; } + void setIs3D(bool value) { is3D = value; } + + /// The ID of the tile that this drawable represents, if any + const std::optional& getTileID() const { return tileID; } + void setTileID(const OverscaledTileID& value) { tileID = value; } + const gfx::CullFaceMode& getCullFaceMode() const; void setCullFaceMode(const gfx::CullFaceMode&); @@ -148,6 +149,9 @@ public: /// Get the tweakers attached to this drawable const std::vector& getTweakers() const { return tweakers; } + void addTweaker(DrawableTweakerPtr value) { tweakers.emplace_back(std::move(value)); } + void setTweakers(std::vector value) { tweakers = std::move(value); } + void clearTweakers() { tweakers.clear(); } /// Get the uniform buffers attached to this drawable virtual const gfx::UniformBufferArray& getUniformBuffers() const = 0; @@ -168,7 +172,9 @@ public: protected: bool enabled = true; - bool needsStencil = false; + bool enableColor = true; + bool enableStencil = false; + bool is3D = false; std::string name; util::SimpleIdentity uniqueID; gfx::ShaderProgramBasePtr shader; @@ -184,7 +190,6 @@ protected: std::unique_ptr impl; Textures textures; - TexSourceFunc textureSource; std::vector tweakers; }; diff --git a/include/mbgl/gfx/drawable_atlases_tweaker.hpp b/include/mbgl/gfx/drawable_atlases_tweaker.hpp new file mode 100644 index 000000000..d014e220e --- /dev/null +++ b/include/mbgl/gfx/drawable_atlases_tweaker.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include +#include + +namespace mbgl { + +class TileAtlasTextures; +using TileAtlasTexturesPtr = std::shared_ptr; + +namespace gfx { + +class Drawable; + +/** + Tweaker that applies the latest values from a retained `TileAtlasTexturesPtr` + */ +class DrawableAtlasesTweaker : public gfx::DrawableTweaker { +public: + DrawableAtlasesTweaker(TileAtlasTexturesPtr atlases_, std::string iconName_, std::string glyphName_, bool isText_) + : atlases(std::move(atlases_)), + iconName(std::move(iconName_)), + glyphName(std::move(glyphName_)), + isText(isText_) {} + ~DrawableAtlasesTweaker() override = default; + + void execute(Drawable&, const PaintParameters&) override; + +protected: + TileAtlasTexturesPtr atlases; + std::string iconName; + std::string glyphName; + bool isText; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 51b2c322b..b4da32511 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -50,6 +50,10 @@ public: /// Get the ID of the drawable we're currently working on, if any util::SimpleIdentity getDrawableId(); + /// Whether the drawble should be drawn + bool getEnabled() const { return enabled; } + void setEnabled(bool value) { enabled = value; } + /// The pass on which we'll be rendered mbgl::RenderPass getRenderPass() const { return renderPass; } void setRenderPass(mbgl::RenderPass value) { renderPass = value; } @@ -58,10 +62,18 @@ public: DrawPriority getDrawPriority() const; void setDrawPriority(DrawPriority); - /// The layer index assigned to generated drawables + /// Determines depth range within the layer for 2D drawables int32_t getSubLayerIndex() const { return subLayerIndex; } void setSubLayerIndex(int32_t value) { subLayerIndex = value; } + /// Depth writability for 2D drawables + DepthMaskType getDepthType() const { return depthType; } + void setDepthType(DepthMaskType value) { depthType = value; } + + /// Uses 3D depth mode + bool getIs3D() const { return is3D; } + void setIs3D(bool value) { is3D = value; } + /// Set the draw priority on all drawables including those already generated void resetDrawPriority(DrawPriority); @@ -69,12 +81,13 @@ public: float getLineWidth() const { return lineWidth; } void setLineWidth(float value) { lineWidth = value; } - /// Whether to do stenciling (based on the Tile ID) - bool getNeedsStencil() const { return needsStencil; } - void setNeedsStencil(bool value) { needsStencil = value; } + /// Whether to render to the color target + bool getEnableColor() const { return enableColor; } + void setEnableColor(bool value) { enableColor = value; } - DepthMaskType getDepthType() const { return depthType; } - void setDepthType(DepthMaskType value) { depthType = value; } + /// Whether to do stenciling (based on the Tile ID or 3D) + bool getEnableStencil() const { return enableStencil; } + void setEnableStencil(bool value) { enableStencil = value; } const gfx::ColorMode& getColorMode() const; void setColorMode(const gfx::ColorMode& value); @@ -100,8 +113,8 @@ public: /// @param location A sampler location in the shader being used. void setTexture(const gfx::Texture2DPtr&, int32_t location); - /// @brief Provide a function to get the current texture - void setTextureSource(Drawable::TexSourceFunc value) { textureSource = std::move(value); } + void addTweaker(DrawableTweakerPtr value) { tweakers.emplace_back(std::move(value)); } + void clearTweakers() { tweakers.clear(); } /// Add a triangle void addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); @@ -156,7 +169,10 @@ protected: std::string drawableName; std::string vertexAttrName; mbgl::RenderPass renderPass; - bool needsStencil = false; + bool enabled = true; + bool enableColor = true; + bool enableStencil = false; + bool is3D = false; float lineWidth = 1.0f; DrawPriority drawPriority = 0; int32_t subLayerIndex = 0; @@ -166,7 +182,7 @@ protected: std::vector drawables; VertexAttributeArray vertexAttrs; gfx::Drawable::Textures textures; - Drawable::TexSourceFunc textureSource; + std::vector tweakers; struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/gfx/drawable_tweaker.hpp b/include/mbgl/gfx/drawable_tweaker.hpp index 7e4199adf..83e37a538 100644 --- a/include/mbgl/gfx/drawable_tweaker.hpp +++ b/include/mbgl/gfx/drawable_tweaker.hpp @@ -20,6 +20,7 @@ protected: public: virtual ~DrawableTweaker() = default; + /// Called just before rendering virtual void execute(Drawable&, const PaintParameters&) = 0; }; diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 714d1f12b..71069c55a 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -255,6 +255,14 @@ public: return propertiesAsUniforms; } + virtual void copy(const VertexAttributeArray& other) { + for (const auto& kv : other.attrs) { + if (kv.second) { + attrs.insert(std::make_pair(kv.first, copy(*kv.second))); + } + } + } + protected: const std::unique_ptr& add(std::string name, std::unique_ptr&& attr) { const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); @@ -270,14 +278,6 @@ protected: return std::make_unique(index, dataType, count, count); } - virtual void copy(const VertexAttributeArray& other) { - for (const auto& kv : other.attrs) { - if (kv.second) { - attrs.insert(std::make_pair(kv.first, copy(*kv.second))); - } - } - } - virtual std::unique_ptr copy(const gfx::VertexAttribute& attr) const { return std::make_unique(attr); } diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index 5d8070a4e..07be116ba 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -33,7 +33,7 @@ public: DrawableGL(std::string name); ~DrawableGL() override; - void draw(const PaintParameters&) const override; + void draw(PaintParameters&) const override; struct DrawSegmentGL; void setIndexData(std::vector indexes, std::vector segments); @@ -61,6 +61,9 @@ protected: DrawableGL(std::unique_ptr); private: + gfx::ColorMode makeColorMode(PaintParameters&) const; + gfx::StencilMode makeStencilMode(PaintParameters&) const; + void uploadTextures() const; void bindUniformBuffers() const; diff --git a/include/mbgl/gl/drawable_gl_tweaker.hpp b/include/mbgl/gl/drawable_gl_tweaker.hpp deleted file mode 100644 index c8113b003..000000000 --- a/include/mbgl/gl/drawable_gl_tweaker.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include - -namespace mbgl { - -namespace gfx { -class Drawable; -} - -namespace gl { - -/** - OpenGL-specific drawable tweaker - */ -class DrawableGLTweaker : public gfx::DrawableTweaker { -public: - DrawableGLTweaker() = default; - -public: - ~DrawableGLTweaker() override = default; - - void execute(gfx::Drawable&, const PaintParameters&) override; -}; - -} // namespace gl -} // namespace mbgl diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp index 5613d98b5..b9650e42e 100644 --- a/include/mbgl/renderer/layer_tweaker.hpp +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -36,11 +36,15 @@ public: virtual void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) = 0; protected: + /// Calculate matrices for this tile. + /// @param nearClipped If true, the near plane is moved further to enhance depth buffer precision. + /// @param inViewportPixelUnits If false, the translation is scaled based on the current zoom. static mat4 getTileMatrix(const UnwrappedTileID&, const RenderTree&, const TransformState&, const std::array& translation, style::TranslateAnchorType, + bool nearClipped, bool inViewportPixelUnits); protected: diff --git a/include/mbgl/renderer/render_target.hpp b/include/mbgl/renderer/render_target.hpp index 6c1713777..2219c820d 100644 --- a/include/mbgl/renderer/render_target.hpp +++ b/include/mbgl/renderer/render_target.hpp @@ -1,8 +1,9 @@ #pragma once -#include -#include +#include #include +#include +#include namespace mbgl { diff --git a/include/mbgl/shaders/gl/drawable_fill_extrusion.hpp b/include/mbgl/shaders/gl/drawable_fill_extrusion.hpp new file mode 100644 index 000000000..a4ebfe9ec --- /dev/null +++ b/include/mbgl/shaders/gl/drawable_fill_extrusion.hpp @@ -0,0 +1,135 @@ +// Generated code, do not modify this file! +#pragma once +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr const char* name = "FillExtrusionShader"; + static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; +layout (location = 1) in vec4 a_normal_ed; +out vec4 v_color; + +layout (std140) uniform FillExtrusionDrawableTilePropsUBO { + highp vec4 u_pattern_from; + highp vec4 u_pattern_to; +}; +layout (std140) uniform FillExtrusionInterpolateUBO { + highp float u_base_t; + highp float u_height_t; + highp float u_color_t; + highp float u_pattern_from_t; + highp float u_pattern_to_t; + highp float u_pad_interp1, u_pad_interp2, u_pad_interp3; +}; +layout (std140) uniform FillExtrusionDrawableUBO { + highp mat4 u_matrix; + highp vec4 u_scale; + highp vec2 u_texsize; + highp vec2 u_pixel_coord_upper; + highp vec2 u_pixel_coord_lower; + highp float u_height_factor; + highp float u_pad_drawable; +}; +layout (std140) uniform FillExtrusionDrawablePropsUBO { + highp vec4 u_color; + highp vec3 u_lightcolor; + highp float u_pad1; + highp vec3 u_lightpos; + highp float u_base; + highp float u_height; + highp float u_lightintensity; + highp float u_vertical_gradient; + highp float u_opacity; + highp float u_fade; + highp float u_pad_props2, u_pad_props3, u_pad_props4; +}; + +#ifndef HAS_UNIFORM_u_base +layout (location = 2) in highp vec2 a_base; +#endif +#ifndef HAS_UNIFORM_u_height +layout (location = 3) in highp vec2 a_height; +#endif +#ifndef HAS_UNIFORM_u_color +layout (location = 4) in highp vec4 a_color; +#endif + +void main() { + #ifndef HAS_UNIFORM_u_base +highp float base = unpack_mix_vec2(a_base, u_base_t); +#else +highp float base = u_base; +#endif + #ifndef HAS_UNIFORM_u_height +highp float height = unpack_mix_vec2(a_height, u_height_t); +#else +highp float height = u_height; +#endif + #ifndef HAS_UNIFORM_u_color +highp vec4 color = unpack_mix_color(a_color, u_color_t); +#else +highp vec4 color = u_color; +#endif + + vec3 normal = a_normal_ed.xyz; + + base = max(0.0, base); + height = max(0.0, height); + + float t = mod(normal.x, 2.0); + + gl_Position = u_matrix * vec4(a_pos, t > 0.0 ? height : base, 1); + + // Relative luminance (how dark/bright is the surface color?) + float colorvalue = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722; + + v_color = vec4(0.0, 0.0, 0.0, 1.0); + + // Add slight ambient lighting so no extrusions are totally black + vec4 ambientlight = vec4(0.03, 0.03, 0.03, 1.0); + color += ambientlight; + + // Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray + float directional = clamp(dot(normal / 16384.0, u_lightpos), 0.0, 1.0); + + // Adjust directional so that + // the range of values for highlight/shading is narrower + // with lower light intensity + // and with lighter/brighter surface colors + directional = mix((1.0 - u_lightintensity), max((1.0 - colorvalue + u_lightintensity), 1.0), directional); + + // Add gradient along z axis of side surfaces + if (normal.y != 0.0) { + // This avoids another branching statement, but multiplies by a constant of 0.84 if no vertical gradient, + // and otherwise calculates the gradient based on base + height + directional *= ( + (1.0 - u_vertical_gradient) + + (u_vertical_gradient * clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0))); + } + + // Assign final color based on surface + ambient light color, diffuse light directional, and light color + // with lower bounds adjusted to hue of light + // so that shading is tinted with the complementary (opposite) color to the light color + v_color.r += clamp(color.r * directional * u_lightcolor.r, mix(0.0, 0.3, 1.0 - u_lightcolor.r), 1.0); + v_color.g += clamp(color.g * directional * u_lightcolor.g, mix(0.0, 0.3, 1.0 - u_lightcolor.g), 1.0); + v_color.b += clamp(color.b * directional * u_lightcolor.b, mix(0.0, 0.3, 1.0 - u_lightcolor.b), 1.0); + v_color *= u_opacity; +} +)"; + static constexpr const char* fragment = R"(in vec4 v_color; + +void main() { + fragColor = v_color; + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp b/include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp new file mode 100644 index 000000000..3d912f6fe --- /dev/null +++ b/include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp @@ -0,0 +1,232 @@ +// Generated code, do not modify this file! +#pragma once +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr const char* name = "FillExtrusionPatternShader"; + static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; +layout (location = 1) in vec4 a_normal_ed; + +out vec2 v_pos_a; +out vec2 v_pos_b; +out vec4 v_lighting; + +layout (std140) uniform FillExtrusionDrawableTilePropsUBO { + highp vec4 u_pattern_from; + highp vec4 u_pattern_to; +}; +layout (std140) uniform FillExtrusionInterpolateUBO { + highp float u_base_t; + highp float u_height_t; + highp float u_color_t; + highp float u_pattern_from_t; + highp float u_pattern_to_t; + highp float u_pad_interp1, u_pad_interp2, u_pad_interp3; +}; +layout (std140) uniform FillExtrusionDrawableUBO { + highp mat4 u_matrix; + highp vec4 u_scale; + highp vec2 u_texsize; + highp vec2 u_pixel_coord_upper; + highp vec2 u_pixel_coord_lower; + highp float u_height_factor; + highp float u_pad_drawable; +}; +layout (std140) uniform FillExtrusionDrawablePropsUBO { + highp vec4 u_color; + highp vec3 u_lightcolor; + highp float u_pad1; + highp vec3 u_lightpos; + highp float u_base; + highp float u_height; + highp float u_lightintensity; + highp float u_vertical_gradient; + highp float u_opacity; + highp float u_fade; + highp float u_pad_props2, u_pad_props3, u_pad_props4; +}; + +#ifndef HAS_UNIFORM_u_base +layout (location = 2) in lowp vec2 a_base; +out lowp float base; +#endif +#ifndef HAS_UNIFORM_u_height +layout (location = 3) in lowp vec2 a_height; +out lowp float height; +#endif +#ifndef HAS_UNIFORM_u_pattern_from +layout (location = 4) in mediump vec4 a_pattern_from; +out mediump vec4 pattern_from; +#endif +#ifndef HAS_UNIFORM_u_pattern_to +layout (location = 5) in mediump vec4 a_pattern_to; +out mediump vec4 pattern_to; +#endif + +void main() { + #ifndef HAS_UNIFORM_u_base +base = unpack_mix_vec2(a_base, u_base_t); +#else +lowp float base = u_base; +#endif + #ifndef HAS_UNIFORM_u_height +height = unpack_mix_vec2(a_height, u_height_t); +#else +lowp float height = u_height; +#endif + #ifndef HAS_UNIFORM_u_pattern_from +pattern_from = a_pattern_from; +#else +mediump vec4 pattern_from = u_pattern_from; +#endif + #ifndef HAS_UNIFORM_u_pattern_to +pattern_to = a_pattern_to; +#else +mediump vec4 pattern_to = u_pattern_to; +#endif + + vec2 pattern_tl_a = pattern_from.xy; + vec2 pattern_br_a = pattern_from.zw; + vec2 pattern_tl_b = pattern_to.xy; + vec2 pattern_br_b = pattern_to.zw; + + float pixelRatio = u_scale.x; + float tileRatio = u_scale.y; + float fromScale = u_scale.z; + float toScale = u_scale.w; + + vec3 normal = a_normal_ed.xyz; + float edgedistance = a_normal_ed.w; + + vec2 display_size_a = vec2((pattern_br_a.x - pattern_tl_a.x) / pixelRatio, (pattern_br_a.y - pattern_tl_a.y) / pixelRatio); + vec2 display_size_b = vec2((pattern_br_b.x - pattern_tl_b.x) / pixelRatio, (pattern_br_b.y - pattern_tl_b.y) / pixelRatio); + + base = max(0.0, base); + height = max(0.0, height); + + float t = mod(normal.x, 2.0); + float z = t > 0.0 ? height : base; + + gl_Position = u_matrix * vec4(a_pos, z, 1); + + vec2 pos = normal.x == 1.0 && normal.y == 0.0 && normal.z == 16384.0 + ? a_pos // extrusion top + : vec2(edgedistance, z * u_height_factor); // extrusion side + + v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, fromScale * display_size_a, tileRatio, pos); + v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, toScale * display_size_b, tileRatio, pos); + + v_lighting = vec4(0.0, 0.0, 0.0, 1.0); + float directional = clamp(dot(normal / 16383.0, u_lightpos), 0.0, 1.0); + directional = mix((1.0 - u_lightintensity), max((0.5 + u_lightintensity), 1.0), directional); + + if (normal.y != 0.0) { + // This avoids another branching statement, but multiplies by a constant of 0.84 if no vertical gradient, + // and otherwise calculates the gradient based on base + height + directional *= ( + (1.0 - u_vertical_gradient) + + (u_vertical_gradient * clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0))); + } + + v_lighting.rgb += clamp(directional * u_lightcolor, mix(vec3(0.0), vec3(0.3), 1.0 - u_lightcolor), vec3(1.0)); + v_lighting *= u_opacity; +} +)"; + static constexpr const char* fragment = R"(in vec2 v_pos_a; +in vec2 v_pos_b; +in vec4 v_lighting; + +layout (std140) uniform FillExtrusionDrawableTilePropsUBO { + highp vec4 u_pattern_from; + highp vec4 u_pattern_to; +}; +layout (std140) uniform FillExtrusionInterpolateUBO { + highp float u_base_t; + highp float u_height_t; + highp float u_color_t; + highp float u_pattern_from_t; + highp float u_pattern_to_t; + highp float u_pad_interp1, u_pad_interp2, u_pad_interp3; +}; +layout (std140) uniform FillExtrusionDrawableUBO { + highp mat4 u_matrix; + highp vec4 u_scale; + highp vec2 u_texsize; + highp vec2 u_pixel_coord_upper; + highp vec2 u_pixel_coord_lower; + highp float u_height_factor; + highp float u_pad_drawable; +}; +layout (std140) uniform FillExtrusionDrawablePropsUBO { + highp vec4 u_color; + highp vec3 u_lightcolor; + highp float u_pad1; + highp vec3 u_lightpos; + highp float u_base; + highp float u_height; + highp float u_lightintensity; + highp float u_vertical_gradient; + highp float u_opacity; + highp float u_fade; + highp float u_pad_props2, u_pad_props3, u_pad_props4; +}; + +uniform sampler2D u_image; + +#ifndef HAS_UNIFORM_u_base +in lowp float base; +#endif +#ifndef HAS_UNIFORM_u_height +in lowp float height; +#endif +#ifndef HAS_UNIFORM_u_pattern_from +in mediump vec4 pattern_from; +#endif +#ifndef HAS_UNIFORM_u_pattern_to +in mediump vec4 pattern_to; +#endif + +void main() { + #ifdef HAS_UNIFORM_u_base +lowp float base = u_base; +#endif + #ifdef HAS_UNIFORM_u_height +lowp float height = u_height; +#endif + #ifdef HAS_UNIFORM_u_pattern_from +mediump vec4 pattern_from = u_pattern_from; +#endif + #ifdef HAS_UNIFORM_u_pattern_to +mediump vec4 pattern_to = u_pattern_to; +#endif + + vec2 pattern_tl_a = pattern_from.xy; + vec2 pattern_br_a = pattern_from.zw; + vec2 pattern_tl_b = pattern_to.xy; + vec2 pattern_br_b = pattern_to.zw; + + vec2 imagecoord = mod(v_pos_a, 1.0); + vec2 pos = mix(pattern_tl_a / u_texsize, pattern_br_a / u_texsize, imagecoord); + vec4 color1 = texture(u_image, pos); + + vec2 imagecoord_b = mod(v_pos_b, 1.0); + vec2 pos2 = mix(pattern_tl_b / u_texsize, pattern_br_b / u_texsize, imagecoord_b); + vec4 color2 = texture(u_image, pos2); + + vec4 mixedColor = mix(color1, color2, u_fade); + + fragColor = mixedColor * v_lighting; + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/fill_extrusion.hpp b/include/mbgl/shaders/gl/fill_extrusion.hpp index c1a490e3f..afe1936e1 100644 --- a/include/mbgl/shaders/gl/fill_extrusion.hpp +++ b/include/mbgl/shaders/gl/fill_extrusion.hpp @@ -31,7 +31,6 @@ layout (location = 3) in highp vec2 a_height; #else uniform highp float u_height; #endif - #ifndef HAS_UNIFORM_u_color uniform lowp float u_color_t; layout (location = 4) in highp vec4 a_color; diff --git a/include/mbgl/shaders/gl/fill_extrusion_pattern.hpp b/include/mbgl/shaders/gl/fill_extrusion_pattern.hpp index f309881b7..a24c7b906 100644 --- a/include/mbgl/shaders/gl/fill_extrusion_pattern.hpp +++ b/include/mbgl/shaders/gl/fill_extrusion_pattern.hpp @@ -43,17 +43,17 @@ uniform lowp float u_height; #endif #ifndef HAS_UNIFORM_u_pattern_from uniform lowp float u_pattern_from_t; -layout (location = 4) in lowp vec4 a_pattern_from; -out lowp vec4 pattern_from; +layout (location = 4) in mediump vec4 a_pattern_from; +out mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to uniform lowp float u_pattern_to_t; -layout (location = 5) in lowp vec4 a_pattern_to; -out lowp vec4 pattern_to; +layout (location = 5) in mediump vec4 a_pattern_to; +out mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif void main() { @@ -145,14 +145,14 @@ in lowp float height; uniform lowp float u_height; #endif #ifndef HAS_UNIFORM_u_pattern_from -in lowp vec4 pattern_from; +in mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to -in lowp vec4 pattern_to; +in mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif void main() { diff --git a/include/mbgl/shaders/gl/fill_outline_pattern.hpp b/include/mbgl/shaders/gl/fill_outline_pattern.hpp index 392264b75..ca6c80aec 100644 --- a/include/mbgl/shaders/gl/fill_outline_pattern.hpp +++ b/include/mbgl/shaders/gl/fill_outline_pattern.hpp @@ -29,17 +29,17 @@ uniform lowp float u_opacity; #endif #ifndef HAS_UNIFORM_u_pattern_from uniform lowp float u_pattern_from_t; -layout (location = 2) in lowp vec4 a_pattern_from; -out lowp vec4 pattern_from; +layout (location = 2) in mediump vec4 a_pattern_from; +out mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to uniform lowp float u_pattern_to_t; -layout (location = 3) in lowp vec4 a_pattern_to; -out lowp vec4 pattern_to; +layout (location = 3) in mediump vec4 a_pattern_to; +out mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif void main() { @@ -95,14 +95,14 @@ in lowp float opacity; uniform lowp float u_opacity; #endif #ifndef HAS_UNIFORM_u_pattern_from -in lowp vec4 pattern_from; +in mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to -in lowp vec4 pattern_to; +in mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif void main() { diff --git a/include/mbgl/shaders/gl/fill_pattern.hpp b/include/mbgl/shaders/gl/fill_pattern.hpp index 8219ffafe..40b7cb18e 100644 --- a/include/mbgl/shaders/gl/fill_pattern.hpp +++ b/include/mbgl/shaders/gl/fill_pattern.hpp @@ -27,17 +27,17 @@ uniform lowp float u_opacity; #endif #ifndef HAS_UNIFORM_u_pattern_from uniform lowp float u_pattern_from_t; -layout (location = 2) in lowp vec4 a_pattern_from; -out lowp vec4 pattern_from; +layout (location = 2) in mediump vec4 a_pattern_from; +out mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to uniform lowp float u_pattern_to_t; -layout (location = 3) in lowp vec4 a_pattern_to; -out lowp vec4 pattern_to; +layout (location = 3) in mediump vec4 a_pattern_to; +out mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif void main() { @@ -89,14 +89,14 @@ in lowp float opacity; uniform lowp float u_opacity; #endif #ifndef HAS_UNIFORM_u_pattern_from -in lowp vec4 pattern_from; +in mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to -in lowp vec4 pattern_to; +in mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif void main() { diff --git a/include/mbgl/shaders/gl/line_pattern.hpp b/include/mbgl/shaders/gl/line_pattern.hpp index 2f1ecedf1..46a3a0cd1 100644 --- a/include/mbgl/shaders/gl/line_pattern.hpp +++ b/include/mbgl/shaders/gl/line_pattern.hpp @@ -67,17 +67,17 @@ uniform mediump float u_width; #endif #ifndef HAS_UNIFORM_u_pattern_from uniform lowp float u_pattern_from_t; -layout (location = 7) in lowp vec4 a_pattern_from; -out lowp vec4 pattern_from; +layout (location = 7) in mediump vec4 a_pattern_from; +out mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to uniform lowp float u_pattern_to_t; -layout (location = 8) in lowp vec4 a_pattern_to; -out lowp vec4 pattern_to; +layout (location = 8) in mediump vec4 a_pattern_to; +out mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif void main() { @@ -180,14 +180,14 @@ in float v_linesofar; in float v_gamma_scale; #ifndef HAS_UNIFORM_u_pattern_from -in lowp vec4 pattern_from; +in mediump vec4 pattern_from; #else -uniform lowp vec4 u_pattern_from; +uniform mediump vec4 u_pattern_from; #endif #ifndef HAS_UNIFORM_u_pattern_to -in lowp vec4 pattern_to; +in mediump vec4 pattern_to; #else -uniform lowp vec4 u_pattern_to; +uniform mediump vec4 u_pattern_to; #endif #ifndef HAS_UNIFORM_u_blur in lowp float blur; @@ -207,7 +207,6 @@ mediump vec4 pattern_from = u_pattern_from; #ifdef HAS_UNIFORM_u_pattern_to mediump vec4 pattern_to = u_pattern_to; #endif - #ifdef HAS_UNIFORM_u_blur lowp float blur = u_blur; #endif diff --git a/include/mbgl/shaders/shader_manifest.hpp b/include/mbgl/shaders/shader_manifest.hpp index f2acb593a..3bda7348d 100644 --- a/include/mbgl/shaders/shader_manifest.hpp +++ b/include/mbgl/shaders/shader_manifest.hpp @@ -14,12 +14,14 @@ #include #include #include +#include +#include #include #include #include #include -#include #include +#include #include #include #include diff --git a/include/mbgl/shaders/shader_source.hpp b/include/mbgl/shaders/shader_source.hpp index df63ef01e..be0f60e8a 100644 --- a/include/mbgl/shaders/shader_source.hpp +++ b/include/mbgl/shaders/shader_source.hpp @@ -20,6 +20,8 @@ enum class BuiltIn { LineShader, FillPatternShader, FillOutlinePatternShader, + FillExtrusionShader, + FillExtrusionPatternShader, HeatmapShader, HeatmapTextureShader, RasterShader, diff --git a/shaders/drawable.fill_extrusion.fragment.glsl b/shaders/drawable.fill_extrusion.fragment.glsl new file mode 100644 index 000000000..c7913c30e --- /dev/null +++ b/shaders/drawable.fill_extrusion.fragment.glsl @@ -0,0 +1,9 @@ +in vec4 v_color; + +void main() { + fragColor = v_color; + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} diff --git a/shaders/drawable.fill_extrusion.vertex.glsl b/shaders/drawable.fill_extrusion.vertex.glsl new file mode 100644 index 000000000..13b599bdd --- /dev/null +++ b/shaders/drawable.fill_extrusion.vertex.glsl @@ -0,0 +1,92 @@ +layout (location = 0) in vec2 a_pos; +layout (location = 1) in vec4 a_normal_ed; +out vec4 v_color; + +layout (std140) uniform FillExtrusionDrawableTilePropsUBO { + highp vec4 u_pattern_from; + highp vec4 u_pattern_to; +}; +layout (std140) uniform FillExtrusionInterpolateUBO { + highp float u_base_t; + highp float u_height_t; + highp float u_color_t; + highp float u_pattern_from_t; + highp float u_pattern_to_t; + highp float u_pad_interp1, u_pad_interp2, u_pad_interp3; +}; +layout (std140) uniform FillExtrusionDrawableUBO { + highp mat4 u_matrix; + highp vec4 u_scale; + highp vec2 u_texsize; + highp vec2 u_pixel_coord_upper; + highp vec2 u_pixel_coord_lower; + highp float u_height_factor; + highp float u_pad_drawable; +}; +layout (std140) uniform FillExtrusionDrawablePropsUBO { + highp vec4 u_color; + highp vec3 u_lightcolor; + highp float u_pad1; + highp vec3 u_lightpos; + highp float u_base; + highp float u_height; + highp float u_lightintensity; + highp float u_vertical_gradient; + highp float u_opacity; + highp float u_fade; + highp float u_pad_props2, u_pad_props3, u_pad_props4; +}; + +#pragma mapbox: define highp float base +#pragma mapbox: define highp float height +#pragma mapbox: define highp vec4 color + +void main() { + #pragma mapbox: initialize highp float base + #pragma mapbox: initialize highp float height + #pragma mapbox: initialize highp vec4 color + + vec3 normal = a_normal_ed.xyz; + + base = max(0.0, base); + height = max(0.0, height); + + float t = mod(normal.x, 2.0); + + gl_Position = u_matrix * vec4(a_pos, t > 0.0 ? height : base, 1); + + // Relative luminance (how dark/bright is the surface color?) + float colorvalue = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722; + + v_color = vec4(0.0, 0.0, 0.0, 1.0); + + // Add slight ambient lighting so no extrusions are totally black + vec4 ambientlight = vec4(0.03, 0.03, 0.03, 1.0); + color += ambientlight; + + // Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray + float directional = clamp(dot(normal / 16384.0, u_lightpos), 0.0, 1.0); + + // Adjust directional so that + // the range of values for highlight/shading is narrower + // with lower light intensity + // and with lighter/brighter surface colors + directional = mix((1.0 - u_lightintensity), max((1.0 - colorvalue + u_lightintensity), 1.0), directional); + + // Add gradient along z axis of side surfaces + if (normal.y != 0.0) { + // This avoids another branching statement, but multiplies by a constant of 0.84 if no vertical gradient, + // and otherwise calculates the gradient based on base + height + directional *= ( + (1.0 - u_vertical_gradient) + + (u_vertical_gradient * clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0))); + } + + // Assign final color based on surface + ambient light color, diffuse light directional, and light color + // with lower bounds adjusted to hue of light + // so that shading is tinted with the complementary (opposite) color to the light color + v_color.r += clamp(color.r * directional * u_lightcolor.r, mix(0.0, 0.3, 1.0 - u_lightcolor.r), 1.0); + v_color.g += clamp(color.g * directional * u_lightcolor.g, mix(0.0, 0.3, 1.0 - u_lightcolor.g), 1.0); + v_color.b += clamp(color.b * directional * u_lightcolor.b, mix(0.0, 0.3, 1.0 - u_lightcolor.b), 1.0); + v_color *= u_opacity; +} diff --git a/shaders/drawable.fill_extrusion_pattern.fragment.glsl b/shaders/drawable.fill_extrusion_pattern.fragment.glsl new file mode 100644 index 000000000..0ccad3d59 --- /dev/null +++ b/shaders/drawable.fill_extrusion_pattern.fragment.glsl @@ -0,0 +1,73 @@ +in vec2 v_pos_a; +in vec2 v_pos_b; +in vec4 v_lighting; + +layout (std140) uniform FillExtrusionDrawableTilePropsUBO { + highp vec4 u_pattern_from; + highp vec4 u_pattern_to; +}; +layout (std140) uniform FillExtrusionInterpolateUBO { + highp float u_base_t; + highp float u_height_t; + highp float u_color_t; + highp float u_pattern_from_t; + highp float u_pattern_to_t; + highp float u_pad_interp1, u_pad_interp2, u_pad_interp3; +}; +layout (std140) uniform FillExtrusionDrawableUBO { + highp mat4 u_matrix; + highp vec4 u_scale; + highp vec2 u_texsize; + highp vec2 u_pixel_coord_upper; + highp vec2 u_pixel_coord_lower; + highp float u_height_factor; + highp float u_pad_drawable; +}; +layout (std140) uniform FillExtrusionDrawablePropsUBO { + highp vec4 u_color; + highp vec3 u_lightcolor; + highp float u_pad1; + highp vec3 u_lightpos; + highp float u_base; + highp float u_height; + highp float u_lightintensity; + highp float u_vertical_gradient; + highp float u_opacity; + highp float u_fade; + highp float u_pad_props2, u_pad_props3, u_pad_props4; +}; + +uniform sampler2D u_image; + +#pragma mapbox: define lowp float base +#pragma mapbox: define lowp float height +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to + +void main() { + #pragma mapbox: initialize lowp float base + #pragma mapbox: initialize lowp float height + #pragma mapbox: initialize mediump vec4 pattern_from + #pragma mapbox: initialize mediump vec4 pattern_to + + vec2 pattern_tl_a = pattern_from.xy; + vec2 pattern_br_a = pattern_from.zw; + vec2 pattern_tl_b = pattern_to.xy; + vec2 pattern_br_b = pattern_to.zw; + + vec2 imagecoord = mod(v_pos_a, 1.0); + vec2 pos = mix(pattern_tl_a / u_texsize, pattern_br_a / u_texsize, imagecoord); + vec4 color1 = texture(u_image, pos); + + vec2 imagecoord_b = mod(v_pos_b, 1.0); + vec2 pos2 = mix(pattern_tl_b / u_texsize, pattern_br_b / u_texsize, imagecoord_b); + vec4 color2 = texture(u_image, pos2); + + vec4 mixedColor = mix(color1, color2, u_fade); + + fragColor = mixedColor * v_lighting; + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} diff --git a/shaders/drawable.fill_extrusion_pattern.vertex.glsl b/shaders/drawable.fill_extrusion_pattern.vertex.glsl new file mode 100644 index 000000000..5c852dcc1 --- /dev/null +++ b/shaders/drawable.fill_extrusion_pattern.vertex.glsl @@ -0,0 +1,99 @@ +layout (location = 0) in vec2 a_pos; +layout (location = 1) in vec4 a_normal_ed; + +out vec2 v_pos_a; +out vec2 v_pos_b; +out vec4 v_lighting; + +layout (std140) uniform FillExtrusionDrawableTilePropsUBO { + highp vec4 u_pattern_from; + highp vec4 u_pattern_to; +}; +layout (std140) uniform FillExtrusionInterpolateUBO { + highp float u_base_t; + highp float u_height_t; + highp float u_color_t; + highp float u_pattern_from_t; + highp float u_pattern_to_t; + highp float u_pad_interp1, u_pad_interp2, u_pad_interp3; +}; +layout (std140) uniform FillExtrusionDrawableUBO { + highp mat4 u_matrix; + highp vec4 u_scale; + highp vec2 u_texsize; + highp vec2 u_pixel_coord_upper; + highp vec2 u_pixel_coord_lower; + highp float u_height_factor; + highp float u_pad_drawable; +}; +layout (std140) uniform FillExtrusionDrawablePropsUBO { + highp vec4 u_color; + highp vec3 u_lightcolor; + highp float u_pad1; + highp vec3 u_lightpos; + highp float u_base; + highp float u_height; + highp float u_lightintensity; + highp float u_vertical_gradient; + highp float u_opacity; + highp float u_fade; + highp float u_pad_props2, u_pad_props3, u_pad_props4; +}; + +#pragma mapbox: define lowp float base +#pragma mapbox: define lowp float height +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to + +void main() { + #pragma mapbox: initialize lowp float base + #pragma mapbox: initialize lowp float height + #pragma mapbox: initialize mediump vec4 pattern_from + #pragma mapbox: initialize mediump vec4 pattern_to + + vec2 pattern_tl_a = pattern_from.xy; + vec2 pattern_br_a = pattern_from.zw; + vec2 pattern_tl_b = pattern_to.xy; + vec2 pattern_br_b = pattern_to.zw; + + float pixelRatio = u_scale.x; + float tileRatio = u_scale.y; + float fromScale = u_scale.z; + float toScale = u_scale.w; + + vec3 normal = a_normal_ed.xyz; + float edgedistance = a_normal_ed.w; + + vec2 display_size_a = vec2((pattern_br_a.x - pattern_tl_a.x) / pixelRatio, (pattern_br_a.y - pattern_tl_a.y) / pixelRatio); + vec2 display_size_b = vec2((pattern_br_b.x - pattern_tl_b.x) / pixelRatio, (pattern_br_b.y - pattern_tl_b.y) / pixelRatio); + + base = max(0.0, base); + height = max(0.0, height); + + float t = mod(normal.x, 2.0); + float z = t > 0.0 ? height : base; + + gl_Position = u_matrix * vec4(a_pos, z, 1); + + vec2 pos = normal.x == 1.0 && normal.y == 0.0 && normal.z == 16384.0 + ? a_pos // extrusion top + : vec2(edgedistance, z * u_height_factor); // extrusion side + + v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, fromScale * display_size_a, tileRatio, pos); + v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, toScale * display_size_b, tileRatio, pos); + + v_lighting = vec4(0.0, 0.0, 0.0, 1.0); + float directional = clamp(dot(normal / 16383.0, u_lightpos), 0.0, 1.0); + directional = mix((1.0 - u_lightintensity), max((0.5 + u_lightintensity), 1.0), directional); + + if (normal.y != 0.0) { + // This avoids another branching statement, but multiplies by a constant of 0.84 if no vertical gradient, + // and otherwise calculates the gradient based on base + height + directional *= ( + (1.0 - u_vertical_gradient) + + (u_vertical_gradient * clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0))); + } + + v_lighting.rgb += clamp(directional * u_lightcolor, mix(vec3(0.0), vec3(0.3), 1.0 - u_lightcolor), vec3(1.0)); + v_lighting *= u_opacity; +} diff --git a/shaders/fill_extrusion.vertex.glsl b/shaders/fill_extrusion.vertex.glsl index 236afdc0e..dda699133 100644 --- a/shaders/fill_extrusion.vertex.glsl +++ b/shaders/fill_extrusion.vertex.glsl @@ -11,7 +11,6 @@ out vec4 v_color; #pragma mapbox: define highp float base #pragma mapbox: define highp float height - #pragma mapbox: define highp vec4 color void main() { diff --git a/shaders/fill_extrusion_pattern.fragment.glsl b/shaders/fill_extrusion_pattern.fragment.glsl index e3ebeb79c..1e0638012 100644 --- a/shaders/fill_extrusion_pattern.fragment.glsl +++ b/shaders/fill_extrusion_pattern.fragment.glsl @@ -9,8 +9,8 @@ in vec4 v_lighting; #pragma mapbox: define lowp float base #pragma mapbox: define lowp float height -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to void main() { #pragma mapbox: initialize lowp float base diff --git a/shaders/fill_extrusion_pattern.vertex.glsl b/shaders/fill_extrusion_pattern.vertex.glsl index ee7f893a5..459cf8baa 100644 --- a/shaders/fill_extrusion_pattern.vertex.glsl +++ b/shaders/fill_extrusion_pattern.vertex.glsl @@ -19,8 +19,8 @@ out vec4 v_lighting; #pragma mapbox: define lowp float base #pragma mapbox: define lowp float height -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to void main() { #pragma mapbox: initialize lowp float base diff --git a/shaders/fill_outline_pattern.fragment.glsl b/shaders/fill_outline_pattern.fragment.glsl index 07984c717..031d8d648 100644 --- a/shaders/fill_outline_pattern.fragment.glsl +++ b/shaders/fill_outline_pattern.fragment.glsl @@ -8,8 +8,8 @@ in vec2 v_pos_b; in vec2 v_pos; #pragma mapbox: define lowp float opacity -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to void main() { #pragma mapbox: initialize lowp float opacity diff --git a/shaders/fill_outline_pattern.vertex.glsl b/shaders/fill_outline_pattern.vertex.glsl index c4c286b78..aa75f7865 100644 --- a/shaders/fill_outline_pattern.vertex.glsl +++ b/shaders/fill_outline_pattern.vertex.glsl @@ -11,8 +11,8 @@ out vec2 v_pos_b; out vec2 v_pos; #pragma mapbox: define lowp float opacity -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to void main() { #pragma mapbox: initialize lowp float opacity diff --git a/shaders/fill_pattern.fragment.glsl b/shaders/fill_pattern.fragment.glsl index 59643ecc4..9624f8de7 100644 --- a/shaders/fill_pattern.fragment.glsl +++ b/shaders/fill_pattern.fragment.glsl @@ -7,8 +7,8 @@ in vec2 v_pos_a; in vec2 v_pos_b; #pragma mapbox: define lowp float opacity -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to void main() { #pragma mapbox: initialize lowp float opacity diff --git a/shaders/fill_pattern.vertex.glsl b/shaders/fill_pattern.vertex.glsl index 8c2540c95..f3a5f891f 100644 --- a/shaders/fill_pattern.vertex.glsl +++ b/shaders/fill_pattern.vertex.glsl @@ -9,8 +9,8 @@ out vec2 v_pos_a; out vec2 v_pos_b; #pragma mapbox: define lowp float opacity -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to void main() { #pragma mapbox: initialize lowp float opacity diff --git a/shaders/line_pattern.fragment.glsl b/shaders/line_pattern.fragment.glsl index 977d9d2f2..10aff6031 100644 --- a/shaders/line_pattern.fragment.glsl +++ b/shaders/line_pattern.fragment.glsl @@ -10,15 +10,14 @@ in vec2 v_width2; in float v_linesofar; in float v_gamma_scale; -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to #pragma mapbox: define lowp float blur #pragma mapbox: define lowp float opacity void main() { #pragma mapbox: initialize mediump vec4 pattern_from #pragma mapbox: initialize mediump vec4 pattern_to - #pragma mapbox: initialize lowp float blur #pragma mapbox: initialize lowp float opacity diff --git a/shaders/line_pattern.vertex.glsl b/shaders/line_pattern.vertex.glsl index 93a2e525e..60ad0c5b4 100644 --- a/shaders/line_pattern.vertex.glsl +++ b/shaders/line_pattern.vertex.glsl @@ -28,8 +28,8 @@ out float v_gamma_scale; #pragma mapbox: define lowp float offset #pragma mapbox: define mediump float gapwidth #pragma mapbox: define mediump float width -#pragma mapbox: define lowp vec4 pattern_from -#pragma mapbox: define lowp vec4 pattern_to +#pragma mapbox: define mediump vec4 pattern_from +#pragma mapbox: define mediump vec4 pattern_to void main() { #pragma mapbox: initialize lowp float blur diff --git a/shaders/manifest.json b/shaders/manifest.json index e8236edf7..4043772e8 100644 --- a/shaders/manifest.json +++ b/shaders/manifest.json @@ -76,6 +76,20 @@ "glsl_frag": "drawable.fill_outline_pattern.fragment.glsl", "uses_ubos": true }, + { + "name": "FillExtrusionShader", + "header": "drawable_fill_extrusion", + "glsl_vert": "drawable.fill_extrusion.vertex.glsl", + "glsl_frag": "drawable.fill_extrusion.fragment.glsl", + "uses_ubos": true + }, + { + "name": "FillExtrusionPatternShader", + "header": "drawable_fill_extrusion_pattern", + "glsl_vert": "drawable.fill_extrusion_pattern.vertex.glsl", + "glsl_frag": "drawable.fill_extrusion_pattern.fragment.glsl", + "uses_ubos": true + }, { "name": "HeatmapShader", "header": "drawable_heatmap", diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index 44a7257c8..f2349fc1e 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -38,13 +38,11 @@ class ShaderRegistry; #if MLN_DRAWABLE_RENDERER class Drawable; class DrawableBuilder; -class DrawableTweaker; class ShaderProgramBase; class Texture2D; using DrawablePtr = std::shared_ptr; using UniqueDrawableBuilder = std::unique_ptr; -using DrawableTweakerPtr = std::shared_ptr; using UniformBufferPtr = std::shared_ptr; using ShaderProgramBasePtr = std::shared_ptr; using Texture2DPtr = std::shared_ptr; @@ -120,9 +118,6 @@ public: /// Create a new drawable builder virtual UniqueDrawableBuilder createDrawableBuilder(std::string name) = 0; - /// Create a new drawable tweaker - virtual DrawableTweakerPtr createDrawableTweaker() = 0; - /// Create a new uniform buffer virtual UniformBufferPtr createUniformBuffer(const void* data, std::size_t size) = 0; diff --git a/src/mbgl/gfx/drawable_atlases_tweaker.cpp b/src/mbgl/gfx/drawable_atlases_tweaker.cpp new file mode 100644 index 000000000..63f142c1f --- /dev/null +++ b/src/mbgl/gfx/drawable_atlases_tweaker.cpp @@ -0,0 +1,25 @@ +#include + +#include +#include +#include + +namespace mbgl { +namespace gfx { + +void DrawableAtlasesTweaker::execute(gfx::Drawable& drawable, const PaintParameters&) { + if (const auto& shader = drawable.getShader()) { + if (const auto samplerLocation = shader->getSamplerLocation(glyphName)) { + if (const auto iconSamplerLocation = shader->getSamplerLocation(iconName)) { + assert(*samplerLocation != *iconSamplerLocation); + drawable.setTexture(atlases ? atlases->glyph : nullptr, *samplerLocation); + drawable.setTexture(atlases ? atlases->icon : nullptr, *iconSamplerLocation); + } else { + drawable.setTexture(atlases ? (isText ? atlases->glyph : atlases->icon) : nullptr, *samplerLocation); + } + } + } +} + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 5020084db..80ee2bb44 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -41,17 +41,20 @@ void DrawableBuilder::flush() { const auto vertexCount = curVertexCount(); if (vertexCount) { const auto& draw = getCurrentDrawable(/*createIfNone=*/true); + draw->setEnabled(enabled); draw->setLineWidth(static_cast(lineWidth)); - draw->setNeedsStencil(needsStencil); + draw->setEnableColor(enableColor); + draw->setEnableStencil(enableStencil); draw->setRenderPass(renderPass); draw->setDrawPriority(drawPriority); draw->setSubLayerIndex(subLayerIndex); draw->setDepthType(depthType); + draw->setIs3D(is3D); draw->setColorMode(impl->colorMode); draw->setCullFaceMode(impl->cullFaceMode); draw->setShader(shader); draw->setTextures(textures); - draw->setTextureSource(textureSource); + draw->setTweakers(tweakers); if (auto drawAttrs = getVertexAttributes().clone()) { vertexAttrs.observeAttributes([&](const std::string& iName, const VertexAttribute& iAttr) { diff --git a/src/mbgl/gfx/drawable_tweaker.cpp b/src/mbgl/gfx/drawable_tweaker.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 6ba3ab758..a3ba6b963 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -19,7 +19,6 @@ #if MLN_DRAWABLE_RENDERER #include #include -#include #include #include #include @@ -464,10 +463,6 @@ gfx::UniqueDrawableBuilder Context::createDrawableBuilder(std::string name) { return std::make_unique(std::move(name)); } -gfx::DrawableTweakerPtr Context::createDrawableTweaker() { - return std::make_shared(); -} - gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t size) { return std::make_shared(data, size); } diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index ae1b0bdad..7a6a978b1 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -108,7 +108,6 @@ public: #if MLN_DRAWABLE_RENDERER gfx::UniqueDrawableBuilder createDrawableBuilder(std::string name) override; - gfx::DrawableTweakerPtr createDrawableTweaker() override; gfx::UniformBufferPtr createUniformBuffer(const void* data, std::size_t size) override; gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) override; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 9c88ab449..3beb37552 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -21,7 +21,7 @@ DrawableGL::~DrawableGL() { impl->attributeBuffer.reset(); } -void DrawableGL::draw(const PaintParameters& parameters) const { +void DrawableGL::draw(PaintParameters& parameters) const { auto& context = static_cast(parameters.context); if (shader) { @@ -36,16 +36,13 @@ void DrawableGL::draw(const PaintParameters& parameters) const { return; } - context.setDepthMode(parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType())); + context.setDepthMode(getIs3D() ? parameters.depthModeFor3D() + : parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType())); // force disable depth test for debugging // context.setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}}); - if (needsStencil && tileID) { - context.setStencilMode(parameters.stencilModeForClipping(tileID->toUnwrapped())); - } else { - context.setStencilMode(gfx::StencilMode::disabled()); - } + context.setStencilMode(makeStencilMode(parameters)); context.setColorMode(getColorMode()); context.setCullFaceMode(getCullFaceMode()); @@ -196,12 +193,6 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { }; } - if (const auto src = getTextureSource()) { - for (auto& pair : src()) { - setTexture(std::move(pair.second), pair.first); - } - } - const bool texturesNeedUpload = std::any_of( textures.begin(), textures.end(), [](const auto& pair) { return pair.second && pair.second->needsUpload(); }); @@ -210,6 +201,22 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { } } +gfx::ColorMode DrawableGL::makeColorMode(PaintParameters& parameters) const { + return enableColor ? parameters.colorModeForRenderPass() : gfx::ColorMode::disabled(); +} + +gfx::StencilMode DrawableGL::makeStencilMode(PaintParameters& parameters) const { + if (enableStencil) { + if (is3D) { + return parameters.stencilModeFor3D(); + } else if (tileID) { + return parameters.stencilModeForClipping(tileID->toUnwrapped()); + } + assert(false); + } + return gfx::StencilMode::disabled(); +} + void DrawableGL::uploadTextures() const { for (const auto& pair : textures) { if (const auto& tex = pair.second) { diff --git a/src/mbgl/gl/drawable_gl_tweaker.cpp b/src/mbgl/gl/drawable_gl_tweaker.cpp deleted file mode 100644 index 94de85c11..000000000 --- a/src/mbgl/gl/drawable_gl_tweaker.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -namespace mbgl { -namespace gl { - -void DrawableGLTweaker::execute(gfx::Drawable& drawable, const PaintParameters&) { - auto& drawGL = (gl::DrawableGL&)drawable; - // apply expressions based on current state, update attributes, uniforms, etc. - drawGL.getId(); -} - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index 020013fcd..fdc3e180f 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -54,7 +55,7 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) // Collect the tile IDs relevant to stenciling and update the stencil buffer, if necessary. std::set tileIDs; observeDrawables([&](const gfx::Drawable& drawable) { - if (drawable.getEnabled() && drawable.getNeedsStencil() && drawable.getTileID() && + if (drawable.getEnabled() && !drawable.getIs3D() && drawable.getEnableStencil() && drawable.getTileID() && drawable.hasRenderPass(parameters.pass)) { tileIDs.emplace(drawable.getTileID()->toUnwrapped()); } @@ -81,6 +82,10 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) const auto debugGroupTile = parameters.encoder->createDebugGroup(labelPtr); #endif + for (const auto& tweaker : drawable.getTweakers()) { + tweaker->execute(drawable, parameters); + } + drawable.draw(parameters); }); } @@ -127,6 +132,10 @@ void LayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) { const auto debugGroup = parameters.encoder->createDebugGroup(drawable.getName().c_str()); #endif + for (const auto& tweaker : drawable.getTweakers()) { + tweaker->execute(drawable, parameters); + } + drawable.draw(parameters); }); } diff --git a/src/mbgl/gl/renderer_backend.cpp b/src/mbgl/gl/renderer_backend.cpp index 202613ad0..169f26f1f 100644 --- a/src/mbgl/gl/renderer_backend.cpp +++ b/src/mbgl/gl/renderer_backend.cpp @@ -104,6 +104,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar shaders::BuiltIn::LineGradientShader, shaders::BuiltIn::FillOutlinePatternShader, shaders::BuiltIn::FillPatternShader, + shaders::BuiltIn::FillExtrusionShader, + shaders::BuiltIn::FillExtrusionPatternShader, shaders::BuiltIn::HeatmapShader, shaders::BuiltIn::HeatmapTextureShader, shaders::BuiltIn::RasterShader, diff --git a/src/mbgl/programs/fill_extrusion_program.cpp b/src/mbgl/programs/fill_extrusion_program.cpp index c50319855..e2b2ee849 100644 --- a/src/mbgl/programs/fill_extrusion_program.cpp +++ b/src/mbgl/programs/fill_extrusion_program.cpp @@ -11,12 +11,12 @@ using namespace style; static_assert(sizeof(FillExtrusionLayoutVertex) == 12, "expected FillExtrusionLayoutVertex size"); -std::array lightColor(const EvaluatedLight& light) { +std::array FillExtrusionProgram::lightColor(const EvaluatedLight& light) { const auto color = light.get(); return {{color.r, color.g, color.b}}; } -std::array lightPosition(const EvaluatedLight& light, const TransformState& state) { +std::array FillExtrusionProgram::lightPosition(const EvaluatedLight& light, const TransformState& state) { auto lightPos = light.get().getCartesian(); mat3 lightMat; matrix::identity(lightMat); @@ -27,26 +27,26 @@ std::array lightPosition(const EvaluatedLight& light, const TransformS return lightPos; } -float lightIntensity(const EvaluatedLight& light) { +float FillExtrusionProgram::lightIntensity(const EvaluatedLight& light) { return light.get(); } -FillExtrusionProgram::LayoutUniformValues FillExtrusionProgram::layoutUniformValues(mat4 matrix, +FillExtrusionProgram::LayoutUniformValues FillExtrusionProgram::layoutUniformValues(const mat4& matrix, const TransformState& state, const float opacity, const EvaluatedLight& light, const float verticalGradient) { return {uniforms::matrix::Value(matrix), uniforms::opacity::Value(opacity), - uniforms::lightcolor::Value(lightColor(light)), - uniforms::lightpos::Value(lightPosition(light, state)), - uniforms::lightintensity::Value(lightIntensity(light)), + uniforms::lightcolor::Value(FillExtrusionProgram::lightColor(light)), + uniforms::lightpos::Value(FillExtrusionProgram::lightPosition(light, state)), + uniforms::lightintensity::Value(FillExtrusionProgram::lightIntensity(light)), uniforms::vertical_gradient::Value(verticalGradient)}; } FillExtrusionPatternProgram::LayoutUniformValues FillExtrusionPatternProgram::layoutUniformValues( - mat4 matrix, - Size atlasSize, + const mat4& matrix, + const Size atlasSize, const CrossfadeParameters& crossfade, const UnwrappedTileID& tileID, const TransformState& state, @@ -56,11 +56,11 @@ FillExtrusionPatternProgram::LayoutUniformValues FillExtrusionPatternProgram::la const EvaluatedLight& light, const float verticalGradient) { const auto tileRatio = 1 / tileID.pixelsToTileUnits(1, state.getIntegerZoom()); - int32_t tileSizeAtNearestZoom = static_cast(util::tileSize_D * - state.zoomScale(state.getIntegerZoom() - tileID.canonical.z)); - int32_t pixelX = static_cast(tileSizeAtNearestZoom * - (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z))); - int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y; + const int32_t tileSizeAtNearestZoom = static_cast( + util::tileSize_D * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z)); + const int32_t pixelX = static_cast( + tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z))); + const int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y; return {uniforms::matrix::Value(matrix), uniforms::opacity::Value(opacity), @@ -72,9 +72,9 @@ FillExtrusionPatternProgram::LayoutUniformValues FillExtrusionPatternProgram::la uniforms::pixel_coord_lower::Value( std::array{{static_cast(pixelX & 0xFFFF), static_cast(pixelY & 0xFFFF)}}), uniforms::height_factor::Value(heightFactor), - uniforms::lightcolor::Value(lightColor(light)), - uniforms::lightpos::Value(lightPosition(light, state)), - uniforms::lightintensity::Value(lightIntensity(light)), + uniforms::lightcolor::Value(FillExtrusionProgram::lightColor(light)), + uniforms::lightpos::Value(FillExtrusionProgram::lightPosition(light, state)), + uniforms::lightintensity::Value(FillExtrusionProgram::lightIntensity(light)), uniforms::vertical_gradient::Value(verticalGradient)}; } diff --git a/src/mbgl/programs/fill_extrusion_program.hpp b/src/mbgl/programs/fill_extrusion_program.hpp index ee072631d..7e8f4374a 100644 --- a/src/mbgl/programs/fill_extrusion_program.hpp +++ b/src/mbgl/programs/fill_extrusion_program.hpp @@ -11,6 +11,7 @@ #include #include +#include #include namespace mbgl { @@ -78,8 +79,12 @@ public: static_cast(e)}}}; } + static std::array lightColor(const EvaluatedLight&); + static std::array lightPosition(const EvaluatedLight&, const TransformState&); + static float lightIntensity(const EvaluatedLight&); + static LayoutUniformValues layoutUniformValues( - mat4, const TransformState&, float opacity, const EvaluatedLight&, float verticalGradient); + const mat4&, const TransformState&, float opacity, const EvaluatedLight&, float verticalGradient); }; class FillExtrusionPatternProgram final : public Program& translation, style::TranslateAnchorType anchor, + bool nearClipped, bool inViewportPixelUnits) { // from RenderTile::prepare mat4 tileMatrix; - state.matrixFor(tileMatrix, tileID); + state.matrixFor(/*out*/ tileMatrix, tileID); - const auto& projMatrix = renderTree.getParameters().transformParams.projMatrix; + // nearClippedMatrix has near plane moved further, to enhance depth buffer precision + const auto& params = renderTree.getParameters().transformParams; + const auto& projMatrix = nearClipped ? params.nearClippedProjMatrix : params.projMatrix; matrix::multiply(tileMatrix, projMatrix, tileMatrix); return RenderTile::translateVtxMatrix(tileID, tileMatrix, translation, anchor, state, inViewportPixelUnits); diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index f4d4ad26c..4271b0f9c 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -58,7 +58,7 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif - CirclePaintParamsUBO paintParamsUBO = { + const CirclePaintParamsUBO paintParamsUBO = { /* .camera_to_center_distance = */ parameters.state.getCameraToCenterDistance(), /* .device_pixel_ratio = */ parameters.pixelRatio, /* .padding = */ {0}}; @@ -72,7 +72,7 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const bool pitchWithMap = evaluated.get() == AlignmentType::Map; if (!evaluatedPropsUniformBuffer) { - CircleEvaluatedPropsUBO evaluatedPropsUBO = { + const CircleEvaluatedPropsUBO evaluatedPropsUBO = { /* .color = */ evaluated.get().constantOr(CircleColor::defaultValue()), /* .stroke_color = */ evaluated.get().constantOr(CircleStrokeColor::defaultValue()), /* .radius = */ evaluated.get().constantOr(CircleRadius::defaultValue()), @@ -100,8 +100,9 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix + constexpr bool nearClipped = false; const auto matrix = getTileMatrix( - tileID, renderTree, parameters.state, translation, anchor, inViewportPixelUnits); + tileID, renderTree, parameters.state, translation, anchor, nearClipped, inViewportPixelUnits); const auto pixelsToTileUnits = tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())); diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp new file mode 100644 index 000000000..d6137622c --- /dev/null +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp @@ -0,0 +1,152 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +namespace { + +struct alignas(16) FillExtrusionDrawableUBO { + /* 0 */ std::array matrix; + /* 64 */ std::array scale; + /* 80 */ std::array texsize; + /* 88 */ std::array pixel_coord_upper; + /* 96 */ std::array pixel_coord_lower; + /* 104 */ float height_factor; + /* 108 */ float pad; + /* 112 */ +}; +static_assert(sizeof(FillExtrusionDrawableUBO) == 7 * 16); + +/// Evaluated properties that do not depend on the tile +struct alignas(16) FillExtrusionDrawablePropsUBO { + /* 0 */ std::array color; + /* 16 */ std::array light_color; + /* 28 */ float pad1; + /* 32 */ std::array light_position; + /* 44 */ float base; + /* 48 */ float height; + /* 52 */ float light_intensity; + /* 56 */ float vertical_gradient; + /* 60 */ float opacity; + /* 64 */ float fade; + /* 68 */ float pad2, pad3, pad4; + /* 80 */ +}; +static_assert(sizeof(FillExtrusionDrawablePropsUBO) == 5 * 16); + +constexpr auto FillExtrusionDrawableUBOName = "FillExtrusionDrawableUBO"; +constexpr auto FillExtrusionDrawablePropsUBOName = "FillExtrusionDrawablePropsUBO"; + +constexpr auto texUniformName = "u_image"; + +template +auto constOrDefault(const IndexedTuple, TypeList>& evaluated) { + return evaluated.template get().constantOr(T::defaultValue()); +} + +} // namespace + +void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, + const RenderTree& renderTree, + const PaintParameters& parameters) { + const auto& props = static_cast(*evaluatedProperties); + const auto& evaluated = props.evaluated; + const auto& crossfade = props.crossfade; + const auto& state = parameters.state; + + if (layerGroup.empty()) { + return; + } + +#if !defined(NDEBUG) + const auto label = layerGroup.getName() + "-update-uniforms"; + const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); +#endif + + // UBO depends on more than just evaluated properties, so we need to update every time. + const FillExtrusionDrawablePropsUBO paramsUBO = { + /* .color = */ gfx::Drawable::colorAttrRGBA(constOrDefault(evaluated)), + /* .light_color = */ FillExtrusionProgram::lightColor(parameters.evaluatedLight), + /* .pad = */ 0, + /* .light_position = */ FillExtrusionProgram::lightPosition(parameters.evaluatedLight, state), + /* .base = */ constOrDefault(evaluated), + /* .height = */ constOrDefault(evaluated), + /* .light_intensity = */ FillExtrusionProgram::lightIntensity(parameters.evaluatedLight), + /* .vertical_gradient = */ evaluated.get() ? 1.0f : 0.0f, + /* .opacity = */ evaluated.get(), + /* .fade = */ crossfade.t, + /* .pad = */ 0, + 0, + 0}; + if (!propsBuffer) { + propsBuffer = parameters.context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); + } else { + propsBuffer->update(¶msUBO, sizeof(paramsUBO)); + } + + layerGroup.observeDrawables([&](gfx::Drawable& drawable) { + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(FillExtrusionDrawablePropsUBOName, propsBuffer); + + if (!drawable.getTileID()) { + return; + } + + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + + const auto& translation = evaluated.get(); + const auto anchor = evaluated.get(); + constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix + constexpr bool nearClipped = true; + const auto matrix = getTileMatrix( + tileID, renderTree, parameters.state, translation, anchor, nearClipped, inViewportPixelUnits); + + const auto tileRatio = 1 / tileID.pixelsToTileUnits(1, state.getIntegerZoom()); + const auto zoomScale = state.zoomScale(tileID.canonical.z); + const auto nearestZoomScale = state.zoomScale(state.getIntegerZoom() - tileID.canonical.z); + const auto tileSizeAtNearestZoom = std::floor(util::tileSize_D * nearestZoomScale); + const auto pixelX = static_cast(tileSizeAtNearestZoom * + (tileID.canonical.x + tileID.wrap * zoomScale)); + const auto pixelY = static_cast(tileSizeAtNearestZoom * tileID.canonical.y); + const auto pixelRatio = parameters.pixelRatio; + const auto numTiles = std::pow(2, tileID.canonical.z); + const auto heightFactor = static_cast(-numTiles / util::tileSize_D / 8.0); + + Size textureSize = {0, 0}; + if (const auto shader = drawable.getShader()) { + if (const auto index = shader->getSamplerLocation(texUniformName)) { + if (const auto& tex = drawable.getTexture(*index)) { + textureSize = tex->getSize(); + } + } + } + + const FillExtrusionDrawableUBO drawableUBO = { + /* .matrix = */ util::cast(matrix), + /* .scale = */ {pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}, + /* .texsize = */ {static_cast(textureSize.width), static_cast(textureSize.height)}, + /* .pixel_coord_upper = */ {static_cast(pixelX >> 16), static_cast(pixelY >> 16)}, + /* .pixel_coord_lower = */ {static_cast(pixelX & 0xFFFF), static_cast(pixelY & 0xFFFF)}, + /* .height_factor = */ heightFactor, + /* .pad = */ 0}; + + uniforms.createOrUpdate(FillExtrusionDrawableUBOName, &drawableUBO, parameters.context); + }); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp new file mode 100644 index 000000000..ed45b1105 --- /dev/null +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include + +namespace mbgl { + +/** + Fill extrusion layer specific tweaker + */ +class FillExtrusionLayerTweaker : public LayerTweaker { +public: + FillExtrusionLayerTweaker(Immutable properties) + : LayerTweaker(properties){}; + +public: + ~FillExtrusionLayerTweaker() override = default; + + void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; + + static constexpr std::string_view FillExtrusionTilePropsUBOName = "FillExtrusionDrawableTilePropsUBO"; + static constexpr std::string_view FillExtrusionInterpolateUBOName = "FillExtrusionInterpolateUBO"; + +private: + gfx::UniformBufferPtr propsBuffer; +}; + +/// Evaluated properties that depend on the tile +struct alignas(16) FillExtrusionDrawableTilePropsUBO { + /* 0 */ std::array pattern_from; + /* 16 */ std::array pattern_to; + /* 32 */ +}; +static_assert(sizeof(FillExtrusionDrawableTilePropsUBO) == 2 * 16); + +/// Attribute interpolations +struct alignas(16) FillExtrusionInterpolateUBO { + /* 0 */ float base_t; + /* 4 */ float height_t; + /* 8 */ float color_t; + /* 12 */ float pattern_from_t; + /* 16 */ float pattern_to_t; + /* 20 */ float pad1, pad2, pad3; + /* 32 */ +}; +static_assert(sizeof(FillExtrusionInterpolateUBO) == 2 * 16); + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 5799b5d94..7c3ae62d4 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -33,7 +33,7 @@ struct alignas(16) FillDrawablePropsUBO { /* 0 */ Color color; /* 16 */ Color outline_color; /* 32 */ float opacity; - /* 36 */ std::array padding; + /* 36 */ float pad1, pad2, pad3; /* 48 */ }; static_assert(sizeof(FillDrawablePropsUBO) == 48); @@ -62,8 +62,9 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, /* .color = */ evaluated.get().constantOr(FillColor::defaultValue()), /* .outline_color = */ evaluated.get().constantOr(FillOutlineColor::defaultValue()), /* .opacity = */ evaluated.get().constantOr(FillOpacity::defaultValue()), - /* .padding = */ {0}, - }; + /* .padding = */ 0, + 0, + 0}; propsBuffer = parameters.context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); } @@ -79,8 +80,9 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix + constexpr bool nearClipped = false; const auto matrix = getTileMatrix( - tileID, renderTree, parameters.state, translation, anchor, inViewportPixelUnits); + tileID, renderTree, parameters.state, translation, anchor, nearClipped, inViewportPixelUnits); // from FillPatternProgram::layoutUniformValues const auto renderableSize = parameters.backend.getDefaultRenderable().getSize(); diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.hpp b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp index 6062f8f8a..e3015d488 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp @@ -42,7 +42,7 @@ struct alignas(16) FillInterpolateUBO { /* 12 */ float pattern_from_t; /* 16 */ float pattern_to_t; /* 20 */ float fade; - /* 24 */ std::array padding; + /* 24 */ float pad1, pad2; /* 32 */ }; static_assert(sizeof(FillInterpolateUBO) == 32); diff --git a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp index abafd4d43..51bd84763 100644 --- a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp @@ -62,8 +62,15 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); - const auto matrix = getTileMatrix( - tileID, renderTree, parameters.state, {0.f, 0.f}, TranslateAnchorType::Viewport, false); + constexpr bool nearClipped = false; + constexpr bool inViewportPixelUnits = false; + const auto matrix = getTileMatrix(tileID, + renderTree, + parameters.state, + {0.f, 0.f}, + TranslateAnchorType::Viewport, + nearClipped, + inViewportPixelUnits); HeatmapDrawableUBO drawableUBO = { /* .matrix = */ util::cast(matrix), /* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), diff --git a/src/mbgl/renderer/layers/line_layer_tweaker.cpp b/src/mbgl/renderer/layers/line_layer_tweaker.cpp index 8ec1f8e61..fecc8a8a5 100644 --- a/src/mbgl/renderer/layers/line_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/line_layer_tweaker.cpp @@ -123,7 +123,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& evaluated = static_cast(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; - LinePropertiesUBO linePropertiesUBO{ + const LinePropertiesUBO linePropertiesUBO{ /*color =*/evaluated.get().constantOr(LineColor::defaultValue()), /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), @@ -132,7 +132,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), 0, {0, 0}}; - LineGradientPropertiesUBO lineGradientPropertiesUBO{ + const LineGradientPropertiesUBO lineGradientPropertiesUBO{ /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), /*gapwidth =*/evaluated.get().constantOr(LineGapWidth::defaultValue()), @@ -140,7 +140,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), 0, {0, 0}}; - LineSDFPropertiesUBO lineSDFPropertiesUBO{ + const LineSDFPropertiesUBO lineSDFPropertiesUBO{ /*color =*/evaluated.get().constantOr(LineColor::defaultValue()), /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), @@ -151,58 +151,62 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, {0, 0}}; layerGroup.observeDrawables([&](gfx::Drawable& drawable) { - if (!drawable.getTileID()) return; + const auto shader = drawable.getShader(); + if (!drawable.getTileID() || !shader) { + return; + } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); + constexpr bool nearClipped = false; constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix + auto& uniforms = drawable.mutableUniformBuffers(); + const auto& shaderUniforms = shader->getUniformBlocks(); + const auto matrix = getTileMatrix( - tileID, renderTree, parameters.state, translation, anchor, inViewportPixelUnits); + tileID, renderTree, parameters.state, translation, anchor, nearClipped, inViewportPixelUnits); // simple line - if (drawable.getShader()->getUniformBlocks().get(std::string(LineUBOName))) { + if (shaderUniforms.get(std::string(LineUBOName))) { // main UBO - LineUBO lineUBO{ + const LineUBO lineUBO{ /*matrix = */ util::cast(matrix), /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), /*device_pixel_ratio = */ parameters.pixelRatio}; - drawable.mutableUniformBuffers().createOrUpdate(LineUBOName, &lineUBO, sizeof(lineUBO), parameters.context); + uniforms.createOrUpdate(LineUBOName, &lineUBO, sizeof(lineUBO), parameters.context); // properties UBO - drawable.mutableUniformBuffers().createOrUpdate( + uniforms.createOrUpdate( LinePropertiesUBOName, &linePropertiesUBO, sizeof(linePropertiesUBO), parameters.context); } // gradient line - else if (drawable.getShader()->getUniformBlocks().get(std::string(LineGradientUBOName))) { + else if (shaderUniforms.get(std::string(LineGradientUBOName))) { // main UBO - LineGradientUBO lineGradientUBO{ + const LineGradientUBO lineGradientUBO{ /*matrix = */ util::cast(matrix), /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), /*device_pixel_ratio = */ parameters.pixelRatio}; - drawable.mutableUniformBuffers().createOrUpdate( - LineGradientUBOName, &lineGradientUBO, sizeof(lineGradientUBO), parameters.context); + uniforms.createOrUpdate(LineGradientUBOName, &lineGradientUBO, sizeof(lineGradientUBO), parameters.context); // properties UBO - drawable.mutableUniformBuffers().createOrUpdate(LineGradientPropertiesUBOName, - &lineGradientPropertiesUBO, - sizeof(lineGradientPropertiesUBO), - parameters.context); + uniforms.createOrUpdate(LineGradientPropertiesUBOName, + &lineGradientPropertiesUBO, + sizeof(lineGradientPropertiesUBO), + parameters.context); } // pattern line - else if (drawable.getShader()->getUniformBlocks().get(std::string(LinePatternUBOName))) { + else if (shaderUniforms.get(std::string(LinePatternUBOName))) { // main UBO Size textureSize{0, 0}; - if (const auto shader = drawable.getShader()) { - if (const auto index = shader->getSamplerLocation("u_image")) { - if (const auto& texture = drawable.getTexture(index.value())) { - textureSize = texture->getSize(); - } + if (const auto index = shader->getSamplerLocation("u_image")) { + if (const auto& texture = drawable.getTexture(index.value())) { + textureSize = texture->getSize(); } } - LinePatternUBO linePatternUBO{ + const LinePatternUBO linePatternUBO{ /*matrix =*/util::cast(matrix), /*scale =*/ {parameters.pixelRatio, @@ -215,11 +219,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*device_pixel_ratio =*/parameters.pixelRatio, /*fade =*/crossfade.t, 0}; - drawable.mutableUniformBuffers().createOrUpdate( - LinePatternUBOName, &linePatternUBO, sizeof(linePatternUBO), parameters.context); + uniforms.createOrUpdate(LinePatternUBOName, &linePatternUBO, sizeof(linePatternUBO), parameters.context); // properties UBO - LinePatternPropertiesUBO linePatternPropertiesUBO{ + const LinePatternPropertiesUBO linePatternPropertiesUBO{ /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), /*offset =*/evaluated.get().constantOr(LineOffset::defaultValue()), @@ -227,27 +230,25 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), 0, {0, 0}}; - drawable.mutableUniformBuffers().createOrUpdate(LinePatternPropertiesUBOName, - &linePatternPropertiesUBO, - sizeof(linePatternPropertiesUBO), - parameters.context); + uniforms.createOrUpdate(LinePatternPropertiesUBOName, + &linePatternPropertiesUBO, + sizeof(linePatternPropertiesUBO), + parameters.context); } // SDF line - else if (drawable.getShader()->getUniformBlocks().get(std::string(LineSDFUBOName))) { + else if (shaderUniforms.get(std::string(LineSDFUBOName))) { if (const auto& data = drawable.getData()) { const gfx::LineDrawableData& lineData = static_cast(*data); const auto& dashPatternTexture = parameters.lineAtlas.getDashPatternTexture( evaluated.get().from, evaluated.get().to, lineData.linePatternCap); // texture - if (const auto shader = drawable.getShader()) { - if (const auto index = shader->getSamplerLocation("u_image")) { - if (!drawable.getTexture(index.value())) { - const auto& texture = dashPatternTexture.getTexture(); - drawable.setEnabled(!!texture); - if (texture) { - drawable.setTexture(texture, index.value()); - } + if (const auto index = shader->getSamplerLocation("u_image")) { + if (!drawable.getTexture(index.value())) { + const auto& texture = dashPatternTexture.getTexture(); + drawable.setEnabled(!!texture); + if (texture) { + drawable.setTexture(texture, index.value()); } } } @@ -257,7 +258,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const LinePatternPos& posB = dashPatternTexture.getTo(); const float widthA = posA.width * crossfade.fromScale; const float widthB = posB.width * crossfade.toScale; - LineSDFUBO lineSDFUBO{ + const LineSDFUBO lineSDFUBO{ /* matrix = */ util::cast(matrix), /* units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, @@ -272,11 +273,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /* sdfgamma = */ static_cast(dashPatternTexture.getSize().width) / (std::min(widthA, widthB) * 256.0f * parameters.pixelRatio) / 2.0f, /* mix = */ crossfade.t}; - drawable.mutableUniformBuffers().createOrUpdate( - LineSDFUBOName, &lineSDFUBO, sizeof(lineSDFUBO), parameters.context); + uniforms.createOrUpdate(LineSDFUBOName, &lineSDFUBO, sizeof(lineSDFUBO), parameters.context); // properties UBO - drawable.mutableUniformBuffers().createOrUpdate( + uniforms.createOrUpdate( LineSDFPropertiesUBOName, &lineSDFPropertiesUBO, sizeof(lineSDFPropertiesUBO), parameters.context); } } diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp index d8db43542..1df4f3aca 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -40,8 +40,8 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, layerGroup.observeDrawables([&](gfx::Drawable& drawable) { auto spinWeights = [](float spin) -> std::array { spin = util::deg2radf(spin); - float s = std::sin(spin); - float c = std::cos(spin); + const float s = std::sin(spin); + const 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, 0}}; return spin_weights; @@ -78,21 +78,22 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, matrix = parameters.matrixForTile(tileID, !parameters.state.isChanging()); } - RasterDrawableUBO drawableUBO{/*.matrix = */ util::cast(matrix), - /*.spin_weigths = */ spinWeights(evaluated.get()), - /*.tl_parent = */ {{0.0f, 0.0f}}, - /*.scale_parent = */ 1.0f, - /*.buffer_scale = */ 1.0f, - /*.fade_t = */ 1.0f, - /*.opacity = */ evaluated.get(), - /*.brightness_low = */ evaluated.get(), - /*.brightness_high = */ evaluated.get(), - /*.saturation_factor = */ saturationFactor(evaluated.get()), - /*.contrast_factor = */ contrastFactor(evaluated.get()), - 0, - 0}; - auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); - drawable.mutableUniformBuffers().addOrReplace("RasterDrawableUBO", drawableUniformBuffer); + const RasterDrawableUBO drawableUBO{ + /*.matrix = */ util::cast(matrix), + /*.spin_weigths = */ spinWeights(evaluated.get()), + /*.tl_parent = */ {{0.0f, 0.0f}}, + /*.scale_parent = */ 1.0f, + /*.buffer_scale = */ 1.0f, + /*.fade_t = */ 1.0f, + /*.opacity = */ evaluated.get(), + /*.brightness_low = */ evaluated.get(), + /*.brightness_high = */ evaluated.get(), + /*.saturation_factor = */ saturationFactor(evaluated.get()), + /*.contrast_factor = */ contrastFactor(evaluated.get()), + 0, + 0}; + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate("RasterDrawableUBO", &drawableUBO, sizeof(drawableUBO), parameters.context); }); } diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index 0bef4bd84..137be45c2 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -11,19 +11,40 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#if MLN_DRAWABLE_RENDERER +#include +#include +#include +#include +#include +#endif // MLN_DRAWABLE_RENDERER + namespace mbgl { using namespace style; namespace { +#if MLN_DRAWABLE_RENDERER + +constexpr std::string_view FillExtrusionShaderName = "FillExtrusionShader"; +constexpr std::string_view FillExtrusionPatternShaderName = "FillExtrusionPatternShader"; + +constexpr auto NormAttribName = "a_normal_ed"; + +constexpr auto IconTextureName = "u_image"; + +#endif // MLN_DRAWABLE_RENDERER + inline const FillExtrusionLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == FillExtrusionLayer::Impl::staticTypeInfo()); return static_cast(*impl); @@ -51,6 +72,12 @@ void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& para : RenderPass::None; properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); + +#if MLN_DRAWABLE_RENDERER + if (layerGroup) { + layerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + } +#endif // MLN_DRAWABLE_RENDERER } bool RenderFillExtrusionLayer::hasTransition() const { @@ -65,6 +92,14 @@ bool RenderFillExtrusionLayer::is3D() const { return true; } +void RenderFillExtrusionLayer::prepare(const LayerPrepareParameters& params) { + RenderLayer::prepare(params); + +#if MLN_DRAWABLE_RENDERER + updateRenderTileIDs(); +#endif // MLN_DRAWABLE_RENDERER +} + #if MLN_LEGACY_RENDERER void RenderFillExtrusionLayer::render(PaintParameters& parameters) { assert(renderTiles); @@ -128,7 +163,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { if (!renderData) { continue; } - auto& bucket = static_cast(*renderData->bucket); + const auto& bucket = static_cast(*renderData->bucket); draw(*fillExtrusionProgram, evaluated, crossfade, @@ -176,9 +211,11 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { if (!renderData) { continue; } - auto& bucket = static_cast(*renderData->bucket); - std::optional patternPosA = tile.getPattern(fillPatternValue.from.id()); - std::optional patternPosB = tile.getPattern(fillPatternValue.to.id()); + const auto& bucket = static_cast(*renderData->bucket); + const std::optional patternPosA = tile.getPattern(fillPatternValue.from.id()); + const std::optional patternPosB = tile.getPattern(fillPatternValue.to.id()); + const auto numTiles = std::pow(2, tile.id.canonical.z); + const auto heightFactor = static_cast(-numTiles / util::tileSize_D / 8.0); draw(*fillExtrusionPatternProgram, evaluated, @@ -195,7 +232,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { tile.id, parameters.state, evaluated.get(), - static_cast(-std::pow(2, tile.id.canonical.z) / util::tileSize_D / 8.0), + heightFactor, parameters.pixelRatio, parameters.evaluatedLight, evaluated.get()), @@ -241,4 +278,247 @@ bool RenderFillExtrusionLayer::queryIntersectsFeature(const GeometryCoordinates& feature.getGeometries()); } +#if MLN_DRAWABLE_RENDERER + +void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, + gfx::Context& context, + const TransformState& state, + const RenderTree& /*renderTree*/, + UniqueChangeRequestVec& changes) { + if (!renderTiles || renderTiles->empty() || passes == RenderPass::None) { + removeAllDrawables(); + return; + } + + // Set up a layer group + if (!layerGroup) { + if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { + layerGroup_->setLayerTweaker(std::make_shared(evaluatedProperties)); + setLayerGroup(std::move(layerGroup_), changes); + } + } + + if (!fillExtrusionGroup) { + fillExtrusionGroup = shaders.getShaderGroup(std::string(FillExtrusionShaderName)); + } + if (!fillExtrusionPatternGroup) { + fillExtrusionPatternGroup = shaders.getShaderGroup(std::string(FillExtrusionPatternShaderName)); + } + + auto* tileLayerGroup = static_cast(layerGroup.get()); + + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + const auto& crossfade = static_cast(*evaluatedProperties).crossfade; + + // `passes` is set to (RenderPass::Translucent | RenderPass::Pass3D), but `render()` + // only runs on the translucent pass, so although our output is 3D, it does not render + // in the "3D pass". + constexpr auto drawPass = RenderPass::Translucent; + + tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { + // If the render pass has changed or the tile has dropped out of the cover set, remove it. + const auto tileID = drawable->getTileID(); + if (drawable->getRenderPass() != drawPass || (tileID && renderTileIDs.find(*tileID) == renderTileIDs.end())) { + drawable.reset(); + ++stats.drawablesRemoved; + } + }); + + const auto zoom = static_cast(state.getZoom()); + const auto layerPrefix = getID() + "/"; + const auto hasPattern = !unevaluated.get().isUndefined(); + const auto opaque = evaluated.get() >= 1; + + std::unique_ptr depthBuilder; + std::unique_ptr colorBuilder; + gfx::VertexAttributeArray vertexAttrs; + std::vector rawVertices; + + const auto& shaderGroup = hasPattern ? fillExtrusionPatternGroup : fillExtrusionGroup; + if (!shaderGroup) { + removeAllDrawables(); + return; + } + + for (const RenderTile& tile : *renderTiles) { + const auto& tileID = tile.getOverscaledTileID(); + + const auto* optRenderData = getRenderDataForPass(tile, passes); + if (!optRenderData || !optRenderData->bucket) { + removeTile(drawPass, tileID); + continue; + } + + const auto& renderData = *optRenderData; + const auto& bucket = static_cast(*renderData.bucket); + + vertexAttrs.clear(); + + gfx::DrawableTweakerPtr tweaker; + if (depthBuilder) { + depthBuilder->clearTweakers(); + } + if (colorBuilder) { + colorBuilder->clearTweakers(); + } + + const auto vertexCount = bucket.vertices.elements(); + constexpr auto vertexSize = sizeof(FillExtrusionLayoutVertex::a1); + + const auto defPattern = mbgl::Faded{"", ""}; + const auto fillPatternValue = evaluated.get().constantOr(defPattern); + const auto patternPosA = tile.getPattern(fillPatternValue.from.id()); + const auto patternPosB = tile.getPattern(fillPatternValue.to.id()); + + const auto& binders = bucket.paintPropertyBinders.at(getID()); + if (hasPattern) { + binders.setPatternParameters(patternPosA, patternPosB, crossfade); + } + + const FillExtrusionInterpolateUBO interpUBO = { + /* .base_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), + /* .height_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), + /* .color_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), + /* .pattern_from_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), + /* .pattern_to_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), + /* .pad = */ 0, + 0, + 0}; + + const FillExtrusionDrawableTilePropsUBO tilePropsUBO = { + /* pattern_from = */ patternPosA ? util::cast(patternPosA->tlbr()) : std::array{0}, + /* pattern_to = */ patternPosB ? util::cast(patternPosB->tlbr()) : std::array{0}, + }; + + // If we already have drawables for this tile, update them. + if (tileLayerGroup->getDrawableCount(drawPass, tileID) > 0) { + // Just update the drawables we already created + tileLayerGroup->observeDrawables(drawPass, tileID, [&](gfx::Drawable& drawable) { + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate( + FillExtrusionLayerTweaker::FillExtrusionTilePropsUBOName, &tilePropsUBO, context); + uniforms.createOrUpdate( + FillExtrusionLayerTweaker::FillExtrusionInterpolateUBOName, &interpUBO, context); + }); + continue; + } + + const auto uniformProps = vertexAttrs.readDataDrivenPaintProperties(binders, evaluated); + + const auto shader = std::static_pointer_cast( + shaderGroup->getOrCreateShader(context, uniformProps)); + if (!shader) { + assert(false); + continue; + } + + // The non-pattern path in `render()` only uses two-pass rendering if there's translucency. + // The pattern path always uses two passes. + const auto doDepthPass = (!opaque || hasPattern); + + if (doDepthPass && !depthBuilder) { + if (auto builder = context.createDrawableBuilder(layerPrefix + "depth")) { + builder->setShader(shader); + builder->setIs3D(true); + builder->setEnableStencil(false); + builder->setEnableColor(false); + builder->setRenderPass(drawPass); + builder->setCullFaceMode(gfx::CullFaceMode::backCCW()); + if (tweaker) { + builder->addTweaker(tweaker); + } + depthBuilder = std::move(builder); + } + } + if (!colorBuilder) { + if (auto builder = context.createDrawableBuilder(layerPrefix + "color")) { + builder->setShader(shader); + builder->setIs3D(true); + builder->setEnableColor(true); + builder->setColorMode(gfx::ColorMode::alphaBlended()); + builder->setRenderPass(drawPass); + builder->setCullFaceMode(gfx::CullFaceMode::backCCW()); + if (tweaker) { + builder->addTweaker(tweaker); + } + colorBuilder = std::move(builder); + } + } + + if (hasPattern && !tweaker) { + if (const auto& atlases = tile.getAtlasTextures()) { + tweaker = std::make_shared(atlases, + std::string(), + std::string(IconTextureName), + /*isText=*/false); + if (depthBuilder) { + depthBuilder->addTweaker(tweaker); + } + if (colorBuilder) { + colorBuilder->addTweaker(tweaker); + } + } + } + + if (const auto& attr = vertexAttrs.getOrAdd(NormAttribName)) { + const auto count = bucket.vertices.elements(); + attr->reserve(count); + for (auto i = 0ULL; i < count; ++i) { + attr->set(i, util::cast(bucket.vertices.at(i).a2)); // int16_t x4 + } + } + + rawVertices.resize(vertexSize * vertexCount); + for (std::size_t i = 0; i < vertexCount; ++i) { + std::memcpy(&rawVertices[vertexSize * i], &bucket.vertices.at(i).a1, vertexSize); + } + + colorBuilder->setEnableStencil(doDepthPass); + if (doDepthPass) { + auto vertexCopy = rawVertices; + depthBuilder->setRawVertices(std::move(vertexCopy), vertexCount, gfx::AttributeDataType::Short2); + } + colorBuilder->setRawVertices(std::move(rawVertices), vertexCount, gfx::AttributeDataType::Short2); + + if (doDepthPass) { + gfx::VertexAttributeArray attribCopy; + attribCopy.copy(vertexAttrs); + depthBuilder->setVertexAttributes(std::move(attribCopy)); + } + colorBuilder->setVertexAttributes(std::move(vertexAttrs)); + + const auto finish = [&](gfx::DrawableBuilder& builder) { + builder.setSegments(gfx::Triangles(), + bucket.triangles.vector(), + bucket.triangleSegments.data(), + bucket.triangleSegments.size()); + + builder.flush(); + + for (auto& drawable : builder.clearDrawables()) { + drawable->setTileID(tileID); + + auto& uniforms = drawable->mutableUniformBuffers(); + uniforms.createOrUpdate( + FillExtrusionLayerTweaker::FillExtrusionTilePropsUBOName, &tilePropsUBO, context); + uniforms.createOrUpdate( + FillExtrusionLayerTweaker::FillExtrusionInterpolateUBOName, &interpUBO, context); + + tileLayerGroup->addDrawable(drawPass, tileID, std::move(drawable)); + ++stats.drawablesAdded; + } + }; + + if (doDepthPass) { + finish(*depthBuilder); + } + finish(*colorBuilder); + } +} + +#endif // MLN_DRAWABLE_RENDERER + } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp index 19678549d..213da6a7f 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -7,8 +7,10 @@ namespace mbgl { +#if MLN_LEGACY_RENDERER class FillExtrusionProgram; class FillExtrusionPatternProgram; +#endif // MLN_LEGACY_RENDERER class RenderFillExtrusionLayer final : public RenderLayer { public: @@ -21,11 +23,21 @@ private: bool hasTransition() const override; bool hasCrossfade() const override; bool is3D() const override; + void prepare(const LayerPrepareParameters&) override; #if MLN_LEGACY_RENDERER void render(PaintParameters&) override; #endif +#if MLN_DRAWABLE_RENDERER + /// Generate any changes needed by the layer + void update(gfx::ShaderRegistry&, + gfx::Context&, + const TransformState&, + const RenderTree&, + UniqueChangeRequestVec&) override; +#endif // MLN_DRAWABLE_RENDERER + bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, float, @@ -43,6 +55,11 @@ private: std::shared_ptr fillExtrusionPatternProgram; #endif +#if MLN_DRAWABLE_RENDERER + gfx::ShaderGroupPtr fillExtrusionGroup; + gfx::ShaderGroupPtr fillExtrusionPatternGroup; +#endif // MLN_DRAWABLE_RENDERER + std::unique_ptr renderTexture; }; diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 152ec185a..546295016 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -23,6 +23,7 @@ #include #if MLN_DRAWABLE_RENDERER +#include #include #include #include @@ -36,10 +37,12 @@ using namespace style; namespace { #if MLN_DRAWABLE_RENDERER -constexpr std::string_view FillShaderName = "FillShader"; -constexpr std::string_view FillOutlineShaderName = "FillOutlineShader"; -constexpr std::string_view FillPatternShaderName = "FillPatternShader"; -constexpr std::string_view FillOutlinePatternShaderName = "FillOutlinePatternShader"; +constexpr auto FillShaderName = "FillShader"; +constexpr auto FillOutlineShaderName = "FillOutlineShader"; +constexpr auto FillPatternShaderName = "FillPatternShader"; +constexpr auto FillOutlinePatternShaderName = "FillOutlinePatternShader"; + +constexpr auto IconTextureName = "u_image"; #endif // MLN_DRAWABLE_RENDERER inline const FillLayer::Impl& impl_cast(const Immutable& impl) { @@ -358,7 +361,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, const auto commonInit = [&](gfx::DrawableBuilder& builder) { builder.setCullFaceMode(gfx::CullFaceMode::disabled()); - builder.setNeedsStencil(true); + builder.setEnableStencil(true); }; tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { @@ -396,10 +399,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, /* .opacity_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), /* .outline_color_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), /* .pattern_from_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), - /* .pattern_to_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), + /* .pattern_to_t = */ std::get<0>(binders.get()->interpolationFactor(zoom)), /* .fade = */ crossfade.t, - /* .padding = */ {0}, - }; + /* .padding = */ 0, + 0}; // TODO: only update if properties re-evaluated? const FillDrawableTilePropsUBO tileProps = { @@ -432,6 +435,14 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, fillVertexAttrs.clear(); outlineVertexAttrs.clear(); + gfx::DrawableTweakerPtr tweaker; + if (fillBuilder) { + fillBuilder->clearTweakers(); + } + if (outlineBuilder) { + outlineBuilder->clearTweakers(); + } + // `Fill*Program` all use `style::FillPaintProperties` const auto fillUniformProps = fillVertexAttrs.readDataDrivenPaintProperties( @@ -518,6 +529,9 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setSubLayerIndex(1); builder->setRenderPass(RenderPass::Translucent); + if (tweaker) { + builder->addTweaker(tweaker); + } patternBuilder = std::move(builder); } } @@ -529,10 +543,28 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setSubLayerIndex(2); builder->setRenderPass(RenderPass::Translucent); + if (tweaker) { + builder->addTweaker(tweaker); + } outlinePatternBuilder = std::move(builder); } } + if ((patternBuilder || outlineBuilder) && !tweaker) { + if (const auto& atlases = tile.getAtlasTextures()) { + tweaker = std::make_shared(atlases, + /*glyphName=*/std::string(), + std::string(IconTextureName), + /*isText=*/false); + if (patternBuilder) { + patternBuilder->addTweaker(tweaker); + } + if (outlineBuilder) { + outlineBuilder->addTweaker(tweaker); + } + } + } + if (patternBuilder) { buildVertices(); patternBuilder->setShader(fillShader); @@ -544,14 +576,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, bucket.triangleSegments.data(), bucket.triangleSegments.size()); - if (const auto& atlases = tile.getAtlasTextures()) { - if (const auto samplerLocation = fillShader->getSamplerLocation("u_image")) { - patternBuilder->setTextureSource([=]() { - return gfx::Drawable::Textures{{*samplerLocation, atlases->icon}}; - }); - } - } - finish(*patternBuilder, tileID, interpolateUBO, tileProps); } if (outlinePatternBuilder) { @@ -563,14 +587,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, outlinePatternBuilder->setSegments( gfx::Lines(2), bucket.lines.vector(), bucket.lineSegments.data(), bucket.lineSegments.size()); - if (const auto& atlases = tile.getAtlasTextures()) { - if (const auto samplerLocation = outlineShader->getSamplerLocation("u_image")) { - outlinePatternBuilder->setTextureSource([=]() { - return gfx::Drawable::Textures{{*samplerLocation, atlases->icon}}; - }); - } - } - finish(*outlinePatternBuilder, tileID, interpolateUBO, tileProps); } } diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 18b2476c7..417aa6357 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -469,7 +469,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, builder->setColorMode(renderPass == RenderPass::Translucent ? gfx::ColorMode::alphaBlended() : gfx::ColorMode::unblended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); - builder->setNeedsStencil(true); + builder->setEnableStencil(true); builder->setVertexAttrName("a_pos_normal"); return builder; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 7546b3740..3752f6803 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -23,6 +23,7 @@ #include #if MLN_DRAWABLE_RENDERER +#include #include #include #include @@ -662,12 +663,7 @@ void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) { renderTiles = params.source->getRenderTilesSortedByYPosition(); #if MLN_DRAWABLE_RENDERER - renderTileIDs.clear(); - renderTileIDs.reserve(renderTiles->size()); - std::transform(renderTiles->begin(), - renderTiles->end(), - std::inserter(renderTileIDs, renderTileIDs.end()), - [](const auto& tile) { return tile.get().getOverscaledTileID(); }); + updateRenderTileIDs(); #endif // MLN_DRAWABLE_RENDERER addRenderPassesFromTiles(); @@ -899,11 +895,14 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, addRenderables(bucket.text, SymbolType::Text); } + // We'll be processing renderables across tiles, potentially out-of-order, so keep + // track of some things by tile ID so we don't have to re-build them multiple times. using RawVertexVec = std::vector; // - struct RawVertices { - RawVertexVec text, icon; + struct TileInfo { + RawVertexVec textVertices, iconVertices; + gfx::DrawableTweakerPtr textTweaker, iconTweaker; }; - std::unordered_map rawVertices; + std::unordered_map tileCache; for (auto& renderable : renderableSegments) { const auto isText = (renderable.type == SymbolType::Text); @@ -920,6 +919,14 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const auto& layout = *bucket.layout; const auto values = isText ? textPropertyValues(evaluated, layout) : iconPropertyValues(evaluated, layout); + const auto& atlases = tile.getAtlasTextures(); + if (!atlases) { + assert(false); + continue; + } + + auto& tileInfo = tileCache[tile.id]; + const auto buildVertices = [&](const SymbolBucket::Buffer& buffer_, RawVertexVec& dest) -> auto& { const std::vector& src = buffer_.vertices.vector(); const auto vertSize = sizeof(SymbolLayoutVertex::a1); @@ -985,6 +992,10 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const auto interpolateUBO = buildInterpUBO(bucketPaintProperties, isText, currentZoom); + if (builder) { + builder->clearTweakers(); + } + const auto draw = [&](const gfx::ShaderGroupPtr& shaderGroup, const Segment& segment, const gfx::IndexVector& indices, @@ -996,10 +1007,20 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, return; } + // We can use the same tweakers for all the segments in a tile + if (isText && !tileInfo.textTweaker) { + tileInfo.textTweaker = std::make_shared( + atlases, iconTexUniformName, texUniformName, isText); + } + if (!isText && !tileInfo.iconTweaker) { + tileInfo.iconTweaker = std::make_shared( + atlases, iconTexUniformName, texUniformName, isText); + } + if (!builder) { builder = context.createDrawableBuilder(layerPrefix); builder->setSubLayerIndex(0); - builder->setNeedsStencil(false); + builder->setEnableStencil(false); builder->setRenderPass(passes); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); builder->setDepthType(gfx::DepthMaskType::ReadOnly); @@ -1008,6 +1029,9 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, builder->setVertexAttrName(posOffsetAttribName); } + builder->clearTweakers(); + builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker); + builder->setDrawableName(layerPrefix + std::string(suffix)); builder->setVertexAttributes(std::move(attrs)); @@ -1023,21 +1047,6 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // !partiallyEvaluatedTextSize.isZoomConstant; const auto filterType = linear ? // gfx::TextureFilterType::Linear : gfx::TextureFilterType::Nearest; - if (const auto& atlases = tile.getAtlasTextures()) { - if (const auto texSamplerLocation = shader->getSamplerLocation(texUniformName)) { - if (const auto iconSamplerLocation = shader->getSamplerLocation(iconTexUniformName)) { - assert(*texSamplerLocation != *iconSamplerLocation); - builder->setTextureSource([=]() -> gfx::Drawable::Textures { - return {{*texSamplerLocation, atlases->glyph}, {*iconSamplerLocation, atlases->icon}}; - }); - } else { - builder->setTextureSource([=]() -> gfx::Drawable::Textures { - return {{*texSamplerLocation, isText ? atlases->glyph : atlases->icon}}; - }); - } - } - } - auto raw = vertices; builder->setRawVertices(std::move(raw), vertexCount, gfx::AttributeDataType::Short4); builder->setSegments(gfx::Triangles(), indices.vector(), &segment, 1); @@ -1069,7 +1078,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, }; if (isText) { - const auto& vertices = buildVertices(buffer, rawVertices[tile.id].text); + const auto& vertices = buildVertices(buffer, tileInfo.textVertices); const auto vertexCount = buffer.vertices.elements(); const auto& indices = buffer.triangles; if (bucket.iconsInText) { @@ -1114,7 +1123,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, } } } else { // icons - const auto& vertices = buildVertices(buffer, rawVertices[tile.id].icon); + const auto& vertices = buildVertices(buffer, tileInfo.iconVertices); const auto vertexCount = buffer.vertices.elements(); const auto& indices = buffer.triangles; if (sdfIcons) { diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp index 2d8921647..9e4d9e9f1 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.hpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp @@ -7,7 +7,7 @@ #include #if MLN_DRAWABLE_RENDERER -#include +#include #endif // MLN_DRAWABLE_RENDERER namespace mbgl { @@ -126,7 +126,6 @@ private: gfx::ShaderGroupPtr symbolSDFTextGroup; gfx::ShaderGroupPtr symbolTextAndIconGroup; - std::unordered_set renderTileIDs; std::unordered_map tileBucketInstances; #endif // MLN_DRAWABLE_RENDERER }; diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index b173b82e1..8c2dc8d08 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -78,6 +78,21 @@ auto constOrDefault(const IndexedTuple, TypeList>& evalua return evaluated.template get().constantOr(T::defaultValue()); } +SymbolDrawablePaintUBO buildPaintUBO(bool isText, const SymbolPaintProperties::PossiblyEvaluated& evaluated) { + return { + /*.fill_color=*/gfx::Drawable::colorAttrRGBA(isText ? constOrDefault(evaluated) + : constOrDefault(evaluated)), + /*.halo_color=*/ + gfx::Drawable::colorAttrRGBA(isText ? constOrDefault(evaluated) + : constOrDefault(evaluated)), + /*.opacity=*/isText ? constOrDefault(evaluated) : constOrDefault(evaluated), + /*.halo_width=*/ + isText ? constOrDefault(evaluated) : constOrDefault(evaluated), + /*.halo_blur=*/isText ? constOrDefault(evaluated) : constOrDefault(evaluated), + /*.padding=*/0, + }; +} + } // namespace void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, @@ -104,25 +119,24 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const auto tileID = drawable.getTileID()->toUnwrapped(); const auto& symbolData = static_cast(*drawable.getData()); const auto isText = (symbolData.symbolType == SymbolType::Text); - const SymbolDrawablePaintUBO paintUBO = { - /*.fill_color=*/gfx::Drawable::colorAttrRGBA(isText ? constOrDefault(evaluated) - : constOrDefault(evaluated)), - /*.halo_color=*/ - gfx::Drawable::colorAttrRGBA(isText ? constOrDefault(evaluated) - : constOrDefault(evaluated)), - /*.opacity=*/isText ? constOrDefault(evaluated) : constOrDefault(evaluated), - /*.halo_width=*/ - isText ? constOrDefault(evaluated) : constOrDefault(evaluated), - /*.halo_blur=*/isText ? constOrDefault(evaluated) : constOrDefault(evaluated), - /*.padding=*/0, - }; + + if (isText && !textPaintBuffer) { + auto props = buildPaintUBO(true, evaluated); + textPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); + } + if (!isText && !iconPaintBuffer) { + auto props = buildPaintUBO(false, evaluated); + iconPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); + } // from RenderTile::translatedMatrix const auto translate = isText ? evaluated.get() : evaluated.get(); const auto anchor = isText ? evaluated.get() : evaluated.get(); + constexpr bool nearClipped = false; constexpr bool inViewportPixelUnits = false; - const auto matrix = getTileMatrix(tileID, renderTree, state, translate, anchor, inViewportPixelUnits); + const auto matrix = getTileMatrix( + tileID, renderTree, state, translate, anchor, nearClipped, inViewportPixelUnits); // from symbol_program, makeValues const auto currentZoom = static_cast(state.getZoom()); @@ -169,8 +183,8 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, }; auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate(SymbolDrawablePaintUBOName, &paintUBO, context); uniforms.createOrUpdate(SymbolDrawableUBOName, &drawableUBO, context); + uniforms.addOrReplace(SymbolDrawablePaintUBOName, isText ? textPaintBuffer : iconPaintBuffer); }); } diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp index 440c5fa9d..8e4c5a8e8 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp @@ -25,6 +25,8 @@ public: static constexpr std::string_view SymbolDrawableInterpolateUBOName = "SymbolDrawableInterpolateUBO"; private: + gfx::UniformBufferPtr textPaintBuffer; + gfx::UniformBufferPtr iconPaintBuffer; }; /// Evaluated properties that depend on the tile diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index df49d109c..6df4c91ea 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -96,14 +96,17 @@ public: public: void renderTileClippingMasks(const RenderTiles&); void renderTileClippingMasks(const std::set&); + + /// Clear any tile masks and the stencil buffer, if necessary void clearTileClippingMasks(); + /// Clear the stencil buffer, even if there are no tile masks (for 3D) + void clearStencil(); + gfx::StencilMode stencilModeForClipping(const UnwrappedTileID&) const; gfx::StencilMode stencilModeFor3D(); private: - void clearStencil(); - template using GetTileIDFunc = std::function; template diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index dc244558c..cb18d33fd 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -144,6 +144,18 @@ void RenderLayer::removeAllDrawables() { } } +void RenderLayer::updateRenderTileIDs() { + renderTileIDs.clear(); + if (renderTiles) { + const auto inserter = std::inserter(renderTileIDs, renderTileIDs.end()); + const auto getID = [](const auto& tile) { + return tile.get().getOverscaledTileID(); + }; + renderTileIDs.reserve(renderTiles->size()); + std::transform(renderTiles->begin(), renderTiles->end(), inserter, getID); + } +} + void RenderLayer::layerIndexChanged(int32_t newLayerIndex, UniqueChangeRequestVec& changes) { layerIndex = newLayerIndex; diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index d8cac6b47..eecf333c4 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -1,8 +1,4 @@ #pragma once -#if MLN_DRAWABLE_RENDERER -#include -#include -#endif #include #include #include @@ -10,6 +6,13 @@ #include #include +#if MLN_DRAWABLE_RENDERER +#include +#include + +#include +#endif // MLN_DRAWABLE_RENDERER + #include #include #include @@ -201,7 +204,10 @@ protected: /// Remove all the drawables for tiles virtual void removeAllDrawables(); -#endif + + // Update `renderTileIDs` from `renderTiles` + void updateRenderTileIDs(); +#endif // MLN_DRAWABLE_RENDERER protected: // Stores current set of tiles to be rendered for this layer. @@ -216,6 +222,9 @@ protected: #if MLN_DRAWABLE_RENDERER // will need to be overriden to handle their activation. LayerGroupBasePtr layerGroup; + + // The set of Tile IDs in `renderTiles` + std::unordered_set renderTileIDs; #endif // Current layer index as specified by the layerIndexChanged event int32_t layerIndex{0}; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 34c07b11c..edda24a72 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -153,21 +153,40 @@ void Renderer::Impl::render(const RenderTree& renderTree) { // ------------------------------------------------------------------------------------- // Renders any 3D layers bottom-to-top to unique FBOs with texture // attachments, but share the same depth rbo between them. - if (parameters.staticData.has3D) { - parameters.staticData.backendSize = parameters.backend.getDefaultRenderable().getSize(); + const auto common3DPass = [&] { + if (parameters.staticData.has3D) { + parameters.staticData.backendSize = parameters.backend.getDefaultRenderable().getSize(); - const auto debugGroup(parameters.encoder->createDebugGroup("3d")); - parameters.pass = RenderPass::Pass3D; + const auto debugGroup(parameters.encoder->createDebugGroup("common-3d")); + parameters.pass = RenderPass::Pass3D; - if (!parameters.staticData.depthRenderbuffer || - parameters.staticData.depthRenderbuffer->getSize() != parameters.staticData.backendSize) { - parameters.staticData.depthRenderbuffer = - parameters.context.createRenderbuffer( - parameters.staticData.backendSize); + if (!parameters.staticData.depthRenderbuffer || + parameters.staticData.depthRenderbuffer->getSize() != parameters.staticData.backendSize) { + parameters.staticData.depthRenderbuffer = + parameters.context.createRenderbuffer( + parameters.staticData.backendSize); + } + parameters.staticData.depthRenderbuffer->setShouldClear(true); } - parameters.staticData.depthRenderbuffer->setShouldClear(true); + }; + +#if MLN_DRAWABLE_RENDERER + const auto drawable3DPass = [&] { + const auto debugGroup(parameters.encoder->createDebugGroup("drawables-3d")); + assert(parameters.pass == RenderPass::Pass3D); + parameters.currentLayer = 0; + + // draw layer groups, opaque pass + orchestrator.observeLayerGroups([&](LayerGroupBase& layerGroup) { + layerGroup.render(orchestrator, parameters); + parameters.currentLayer++; + }); + }; +#endif // MLN_DRAWABLE_RENDERER #if MLN_LEGACY_RENDERER + const auto renderLayer3DPass = [&] { + const auto debugGroup(parameters.encoder->createDebugGroup("3d")); int32_t i = static_cast(layerRenderItems.size()) - 1; for (auto it = layerRenderItems.begin(); it != layerRenderItems.end() && i >= 0; ++it, --i) { parameters.currentLayer = i; @@ -177,29 +196,33 @@ void Renderer::Impl::render(const RenderTree& renderTree) { renderItem.render(parameters); } } -#endif - } + }; +#endif // MLN_LEGACY_RENDERER #if MLN_DRAWABLE_RENDERER - // draw render targets - orchestrator.observeRenderTargets( - [&](RenderTarget& renderTarget) { renderTarget.render(orchestrator, renderTree, parameters); }); + const auto drawableTargetsPass = [&] { + // draw render targets + orchestrator.observeRenderTargets( + [&](RenderTarget& renderTarget) { renderTarget.render(orchestrator, renderTree, parameters); }); + }; #endif - // - CLEAR - // ------------------------------------------------------------------------------------- - // Renders the backdrop of the OpenGL view. This also paints in areas where - // we don't have any tiles whatsoever. - { - std::optional color; - if (parameters.debugOptions & MapDebugOptions::Overdraw) { - color = Color::black(); - } else if (!backend.contextIsShared()) { - color = renderTreeParameters.backgroundColor; + const auto commonClearPass = [&] { + // - CLEAR + // ------------------------------------------------------------------------------------- + // Renders the backdrop of the OpenGL view. This also paints in areas where + // we don't have any tiles whatsoever. + { + std::optional color; + if (parameters.debugOptions & MapDebugOptions::Overdraw) { + color = Color::black(); + } else if (!backend.contextIsShared()) { + color = renderTreeParameters.backgroundColor; + } + parameters.renderPass = parameters.encoder->createRenderPass( + "main buffer", {parameters.backend.getDefaultRenderable(), color, 1.0f, 0}); } - parameters.renderPass = parameters.encoder->createRenderPass( - "main buffer", {parameters.backend.getDefaultRenderable(), color, 1.0f, 0}); - } + }; // Actually render the layers #if MLN_DRAWABLE_RENDERER @@ -274,9 +297,20 @@ void Renderer::Impl::render(const RenderTree& renderTree) { #endif // MLN_LEGACY_RENDERER #if (MLN_DRAWABLE_RENDERER && !MLN_LEGACY_RENDERER) + if (parameters.staticData.has3D) { + common3DPass(); + drawable3DPass(); + } + drawableTargetsPass(); + commonClearPass(); drawableOpaquePass(); drawableTranslucentPass(); #elif (MLN_LEGACY_RENDERER && !MLN_DRAWABLE_RENDERER) + if (parameters.staticData.has3D) { + common3DPass(); + renderLayer3DPass(); + } + commonClearPass(); renderLayerOpaquePass(); renderLayerTranslucentPass(); #elif (MLN_DRAWABLE_RENDERER && MLN_LEGACY_RENDERER) @@ -289,44 +323,69 @@ void Renderer::Impl::render(const RenderTree& renderTree) { 0.5f); platform::glEnable(GL_SCISSOR_TEST); #if MLN_RENDERER_QUAD_SPLIT_VIEW + if (parameters.staticData.has3D) { + common3DPass(); + drawable3DPass(); + renderLayer3DPass(); + parameters.clearStencil(); + } + // Drawable LayerGroups on the left // Opaque only on top platform::glScissor(0, 0, halfW, H); + drawableTargetsPass(); + commonClearPass(); drawableOpaquePass(); // Composite (Opaque+Translucent) on bottom platform::glScissor(0, 0, halfW, halfH); - // Clipping masks were drawn only on the other side - parameters.clearTileClippingMasks(); drawableTranslucentPass(); // RenderLayers on the right // Opaque only on top platform::glScissor(halfW, 0, halfW, H); + commonClearPass(); + // Clipping masks were drawn only on the other side parameters.clearTileClippingMasks(); renderLayerOpaquePass(); // Composite (Opaque+Translucent) on bottom platform::glScissor(halfW, 0, halfW, halfH); - parameters.clearTileClippingMasks(); renderLayerTranslucentPass(); -#else +#else // MLN_RENDERER_QUAD_SPLIT_VIEW + if (parameters.staticData.has3D) { + common3DPass(); + drawable3DPass(); + renderLayer3DPass(); + parameters.clearStencil(); + } + // Drawable LayerGroups on the left platform::glScissor(0, 0, halfW, H); + drawableTargetsPass(); + commonClearPass(); parameters.clearTileClippingMasks(); drawableOpaquePass(); drawableTranslucentPass(); // RenderLayers on the right platform::glScissor(halfW, 0, W, H); + commonClearPass(); parameters.clearTileClippingMasks(); renderLayerOpaquePass(); renderLayerTranslucentPass(); -#endif +#endif // MLN_RENDERER_QUAD_SPLIT_VIEW // Reset viewport platform::glScissor(0, 0, W, H); platform::glDisable(GL_SCISSOR_TEST); -#else // ifdef MLN_RENDERER_SPLIT_VIEW +#else // if MLN_RENDERER_SPLIT_VIEW + if (parameters.staticData.has3D) { + common3DPass(); + renderLayer3DPass(); + drawable3DPass(); + parameters.clearStencil(); + } + commonClearPass(); // Do RenderLayers first, drawables last renderLayerOpaquePass(); renderLayerTranslucentPass();