Circle layer (#1153)

This commit is contained in:
Alex Cristici
2023-05-25 19:18:08 +03:00
committed by Bart Louwers
parent 5df482b12e
commit 2c53c138c8
32 changed files with 1041 additions and 85 deletions

View File

@@ -181,6 +181,7 @@ list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/platform/thread.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/query.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/layer_tweaker.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_frontend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_observer.hpp
@@ -520,6 +521,13 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager_observer.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_tweaker.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/background_layer_tweaker.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/background_layer_tweaker.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/circle_layer_tweaker.cpp
${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/render_background_layer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_circle_layer.cpp
@@ -929,6 +937,7 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/prelude.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline_pattern.hpp

View File

@@ -25,7 +25,6 @@ enum class DepthMaskType : bool;
class DrawableTweaker;
class ShaderProgramBase;
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
using DrawPriority = int64_t;
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
@@ -178,12 +177,5 @@ private:
bool desc;
};
struct alignas(16) DrawableUBO {
std::array<float, 4 * 4> matrix;
std::array<float, 2> world;
std::array<float, 2> padding;
};
static_assert(sizeof(DrawableUBO) % 16 == 0);
} // namespace gfx
} // namespace mbgl

View File

@@ -25,6 +25,9 @@ using DrawablePtr = std::shared_ptr<Drawable>;
using UniqueDrawable = std::unique_ptr<Drawable>;
} // namespace gfx
class LayerTweaker;
using LayerTweakerPtr = std::shared_ptr<LayerTweaker>;
/**
A layer-like group of drawables, not a group of layers.
*/
@@ -54,8 +57,15 @@ public:
/// Call the provided function for each drawable in undefined order, allowing ownership to be taken.
virtual void observeDrawables(std::function<void(gfx::UniqueDrawable&)>) = 0;
/// Attach a tweaker to be run on this layer group for each frame
void setLayerTweaker(LayerTweakerPtr tweaker) { layerTweaker = std::move(tweaker); }
/// Get the tweaker attached to this layer group
const LayerTweakerPtr& getLayerTweaker() const { return layerTweaker; }
protected:
int32_t layerIndex;
LayerTweakerPtr layerTweaker;
};
/**

View File

@@ -0,0 +1,33 @@
#pragma once
#include <mbgl/util/immutable.hpp>
#include <memory>
namespace mbgl {
namespace style {
class LayerProperties;
} // namespace style
class PaintParameters;
class LayerGroup;
/**
Base class for layer tweakers, which manipulate layer group per frame
*/
class LayerTweaker {
protected:
LayerTweaker() = delete;
LayerTweaker(Immutable<style::LayerProperties> properties);
public:
virtual ~LayerTweaker() = default;
virtual void execute(LayerGroup&, const PaintParameters&) = 0;
protected:
Immutable<style::LayerProperties> evaluatedProperties;
};
} // namespace mbgl

View File

@@ -11,10 +11,8 @@ template <>
struct ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::OpenGL> {
static constexpr const char* name = "BackgroundShader";
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
layout (std140) uniform DrawableUBO {
layout (std140) uniform BackgroundDrawableUBO {
mat4 u_matrix;
vec2 u_world;
vec2 pad;
};
void main() {

View File

@@ -0,0 +1,234 @@
// Generated code, do not modify this file!
// Generated on 2023-05-17T18:24:20.170Z by alex using shaders/generate_shader_code.js
#pragma once
#include <mbgl/shaders/shader_source.hpp>
namespace mbgl {
namespace shaders {
template <>
struct ShaderSource<BuiltIn::CircleShader, gfx::Backend::Type::OpenGL> {
static constexpr const char* name = "CircleShader";
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
out vec3 v_data;
layout (std140) uniform CircleDrawableUBO {
mat4 u_matrix;
vec2 u_extrude_scale;
};
layout (std140) uniform CirclePaintParamsUBO {
highp float u_camera_to_center_distance;
lowp float u_device_pixel_ratio;
};
layout (std140) uniform CircleEvaluatedPropsUBO {
highp vec4 u_color;
highp vec4 u_stroke_color;
mediump float u_radius;
lowp float u_blur;
lowp float u_opacity;
mediump float u_stroke_width;
lowp float u_stroke_opacity;
bool u_scale_with_map;
bool u_pitch_with_map;
};
layout (std140) uniform CircleInterpolateUBO {
lowp float u_color_t;
lowp float u_radius_t;
lowp float u_blur_t;
lowp float u_opacity_t;
lowp float u_stroke_color_t;
lowp float u_stroke_width_t;
lowp float u_stroke_opacity_t;
};
#ifndef HAS_UNIFORM_u_color
layout (location = 1) in highp vec4 a_color;
out highp vec4 color;
#endif
#ifndef HAS_UNIFORM_u_radius
layout (location = 2) in mediump vec2 a_radius;
out mediump float radius;
#endif
#ifndef HAS_UNIFORM_u_blur
layout (location = 3) in lowp vec2 a_blur;
out lowp float blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
layout (location = 4) in lowp vec2 a_opacity;
out lowp float opacity;
#endif
#ifndef HAS_UNIFORM_u_stroke_color
layout (location = 5) in highp vec4 a_stroke_color;
out highp vec4 stroke_color;
#endif
#ifndef HAS_UNIFORM_u_stroke_width
layout (location = 6) in mediump vec2 a_stroke_width;
out mediump float stroke_width;
#endif
#ifndef HAS_UNIFORM_u_stroke_opacity
layout (location = 7) in lowp vec2 a_stroke_opacity;
out lowp float stroke_opacity;
#endif
void main(void) {
#ifndef HAS_UNIFORM_u_color
color = unpack_mix_color(a_color, u_color_t);
#else
highp vec4 color = u_color;
#endif
#ifndef HAS_UNIFORM_u_radius
radius = unpack_mix_vec2(a_radius, u_radius_t);
#else
mediump float radius = u_radius;
#endif
#ifndef HAS_UNIFORM_u_blur
blur = unpack_mix_vec2(a_blur, u_blur_t);
#else
lowp float blur = u_blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_stroke_color
stroke_color = unpack_mix_color(a_stroke_color, u_stroke_color_t);
#else
highp vec4 stroke_color = u_stroke_color;
#endif
#ifndef HAS_UNIFORM_u_stroke_width
stroke_width = unpack_mix_vec2(a_stroke_width, u_stroke_width_t);
#else
mediump float stroke_width = u_stroke_width;
#endif
#ifndef HAS_UNIFORM_u_stroke_opacity
stroke_opacity = unpack_mix_vec2(a_stroke_opacity, u_stroke_opacity_t);
#else
lowp float stroke_opacity = u_stroke_opacity;
#endif
// unencode the extrusion vector that we snuck into the a_pos vector
vec2 extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0);
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
// in extrusion data
vec2 circle_center = floor(a_pos * 0.5);
if (u_pitch_with_map) {
vec2 corner_position = circle_center;
if (u_scale_with_map) {
corner_position += extrude * (radius + stroke_width) * u_extrude_scale;
} else {
// Pitching the circle with the map effectively scales it with the map
// To counteract the effect for pitch-scale: viewport, we rescale the
// whole circle based on the pitch scaling effect at its central point
vec4 projected_center = u_matrix * vec4(circle_center, 0, 1);
corner_position += extrude * (radius + stroke_width) * u_extrude_scale * (projected_center.w / u_camera_to_center_distance);
}
gl_Position = u_matrix * vec4(corner_position, 0, 1);
} else {
gl_Position = u_matrix * vec4(circle_center, 0, 1);
if (u_scale_with_map) {
gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * u_camera_to_center_distance;
} else {
gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * gl_Position.w;
}
}
// This is a minimum blur distance that serves as a faux-antialiasing for
// the circle. since blur is a ratio of the circle's size and the intent is
// to keep the blur at roughly 1px, the two are inversely related.
lowp float antialiasblur = 1.0 / u_device_pixel_ratio / (radius + stroke_width);
v_data = vec3(extrude.x, extrude.y, antialiasblur);
}
)";
static constexpr const char* fragment = R"(in vec3 v_data;
layout (std140) uniform CircleEvaluatedPropsUBO {
highp vec4 u_color;
highp vec4 u_stroke_color;
mediump float u_radius;
lowp float u_blur;
lowp float u_opacity;
mediump float u_stroke_width;
lowp float u_stroke_opacity;
bool u_scale_with_map;
bool u_pitch_with_map;
};
#ifndef HAS_UNIFORM_u_color
in highp vec4 color;
#endif
#ifndef HAS_UNIFORM_u_radius
in mediump float radius;
#endif
#ifndef HAS_UNIFORM_u_blur
in lowp float blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
in lowp float opacity;
#endif
#ifndef HAS_UNIFORM_u_stroke_color
in highp vec4 stroke_color;
#endif
#ifndef HAS_UNIFORM_u_stroke_width
in mediump float stroke_width;
#endif
#ifndef HAS_UNIFORM_u_stroke_opacity
in lowp float stroke_opacity;
#endif
void main() {
#ifdef HAS_UNIFORM_u_color
highp vec4 color = u_color;
#endif
#ifdef HAS_UNIFORM_u_radius
mediump float radius = u_radius;
#endif
#ifdef HAS_UNIFORM_u_blur
lowp float blur = u_blur;
#endif
#ifdef HAS_UNIFORM_u_opacity
lowp float opacity = u_opacity;
#endif
#ifdef HAS_UNIFORM_u_stroke_color
highp vec4 stroke_color = u_stroke_color;
#endif
#ifdef HAS_UNIFORM_u_stroke_width
mediump float stroke_width = u_stroke_width;
#endif
#ifdef HAS_UNIFORM_u_stroke_opacity
lowp float stroke_opacity = u_stroke_opacity;
#endif
vec2 extrude = v_data.xy;
float extrude_length = length(extrude);
lowp float antialiasblur = v_data.z;
float antialiased_blur = -max(blur, antialiasblur);
float opacity_t = smoothstep(0.0, antialiased_blur, extrude_length - 1.0);
float color_t = stroke_width < 0.01 ? 0.0 : smoothstep(
antialiased_blur,
0.0,
extrude_length - radius / (radius + stroke_width)
);
fragColor = opacity_t * mix(color * opacity, stroke_color * stroke_opacity, color_t);
#ifdef OVERDRAW_INSPECTOR
fragColor = vec4(1.0);
#endif
}
)";
};
} // namespace shaders
} // namespace mbgl

View File

@@ -12,7 +12,7 @@ struct ShaderSource<BuiltIn::FillShader, gfx::Backend::Type::OpenGL> {
static constexpr const char* name = "FillShader";
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
layout (std140) uniform DrawableUBO {
layout (std140) uniform FillDrawableUBO {
mat4 u_matrix;
vec2 u_world;
vec2 pad;

View File

@@ -12,7 +12,7 @@ struct ShaderSource<BuiltIn::FillOutlineShader, gfx::Backend::Type::OpenGL> {
static constexpr const char* name = "FillOutlineShader";
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
layout (std140) uniform DrawableUBO {
layout (std140) uniform FillDrawableUBO {
mat4 u_matrix;
vec2 u_world;
vec2 pad;

View File

@@ -6,6 +6,7 @@
#ifdef MBGL_RENDER_BACKEND_OPENGL
#include <mbgl/shaders/gl/drawable_background.hpp>
#include <mbgl/shaders/gl/drawable_circle.hpp>
#include <mbgl/shaders/gl/drawable_fill.hpp>
#include <mbgl/shaders/gl/drawable_fill_outline.hpp>
#include <mbgl/shaders/gl/drawable_fill_pattern.hpp>

View File

@@ -12,6 +12,7 @@ namespace shaders {
enum class BuiltIn {
None,
BackgroundShader,
CircleShader,
FillShader,
FillOutlineShader,
FillPatternShader,

View File

@@ -1,5 +1,5 @@
layout (location = 0) in vec2 a_pos;
layout (std140) uniform DrawableUBO {
layout (std140) uniform BackgroundDrawableUBO {
mat4 u_matrix;
vec2 u_world;
vec2 pad;

View File

@@ -0,0 +1,51 @@
in vec3 v_data;
layout (std140) uniform CircleEvaluatedPropsUBO {
highp vec4 u_color;
mediump float u_radius;
lowp float u_blur;
lowp float u_opacity;
highp vec4 u_stroke_color;
mediump float u_stroke_width;
lowp float u_stroke_opacity;
bool u_scale_with_map;
bool u_pitch_with_map;
};
#pragma mapbox: define highp vec4 color
#pragma mapbox: define mediump float radius
#pragma mapbox: define lowp float blur
#pragma mapbox: define lowp float opacity
#pragma mapbox: define highp vec4 stroke_color
#pragma mapbox: define mediump float stroke_width
#pragma mapbox: define lowp float stroke_opacity
void main() {
#pragma mapbox: initialize highp vec4 color
#pragma mapbox: initialize mediump float radius
#pragma mapbox: initialize lowp float blur
#pragma mapbox: initialize lowp float opacity
#pragma mapbox: initialize highp vec4 stroke_color
#pragma mapbox: initialize mediump float stroke_width
#pragma mapbox: initialize lowp float stroke_opacity
vec2 extrude = v_data.xy;
float extrude_length = length(extrude);
lowp float antialiasblur = v_data.z;
float antialiased_blur = -max(blur, antialiasblur);
float opacity_t = smoothstep(0.0, antialiased_blur, extrude_length - 1.0);
float color_t = stroke_width < 0.01 ? 0.0 : smoothstep(
antialiased_blur,
0.0,
extrude_length - radius / (radius + stroke_width)
);
fragColor = opacity_t * mix(color * opacity, stroke_color * stroke_opacity, color_t);
#ifdef OVERDRAW_INSPECTOR
fragColor = vec4(1.0);
#endif
}

View File

@@ -0,0 +1,88 @@
layout (location = 0) in vec2 a_pos;
out vec3 v_data;
layout (std140) uniform CircleDrawableUBO {
mat4 u_matrix;
vec2 u_extrude_scale;
};
layout (std140) uniform CirclePaintParamsUBO {
highp float u_camera_to_center_distance;
lowp float u_device_pixel_ratio;
};
layout (std140) uniform CircleEvaluatedPropsUBO {
highp vec4 u_color;
highp vec4 u_stroke_color;
mediump float u_radius;
lowp float u_blur;
lowp float u_opacity;
mediump float u_stroke_width;
lowp float u_stroke_opacity;
bool u_scale_with_map;
bool u_pitch_with_map;
};
layout (std140) uniform CircleInterpolateUBO {
lowp float u_color_t;
lowp float u_radius_t;
lowp float u_blur_t;
lowp float u_opacity_t;
lowp float u_stroke_color_t;
lowp float u_stroke_width_t;
lowp float u_stroke_opacity_t;
};
#pragma mapbox: define highp vec4 color
#pragma mapbox: define mediump float radius
#pragma mapbox: define lowp float blur
#pragma mapbox: define lowp float opacity
#pragma mapbox: define highp vec4 stroke_color
#pragma mapbox: define mediump float stroke_width
#pragma mapbox: define lowp float stroke_opacity
void main(void) {
#pragma mapbox: initialize highp vec4 color
#pragma mapbox: initialize mediump float radius
#pragma mapbox: initialize lowp float blur
#pragma mapbox: initialize lowp float opacity
#pragma mapbox: initialize highp vec4 stroke_color
#pragma mapbox: initialize mediump float stroke_width
#pragma mapbox: initialize lowp float stroke_opacity
// unencode the extrusion vector that we snuck into the a_pos vector
vec2 extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0);
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
// in extrusion data
vec2 circle_center = floor(a_pos * 0.5);
if (u_pitch_with_map) {
vec2 corner_position = circle_center;
if (u_scale_with_map) {
corner_position += extrude * (radius + stroke_width) * u_extrude_scale;
} else {
// Pitching the circle with the map effectively scales it with the map
// To counteract the effect for pitch-scale: viewport, we rescale the
// whole circle based on the pitch scaling effect at its central point
vec4 projected_center = u_matrix * vec4(circle_center, 0, 1);
corner_position += extrude * (radius + stroke_width) * u_extrude_scale * (projected_center.w / u_camera_to_center_distance);
}
gl_Position = u_matrix * vec4(corner_position, 0, 1);
} else {
gl_Position = u_matrix * vec4(circle_center, 0, 1);
if (u_scale_with_map) {
gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * u_camera_to_center_distance;
} else {
gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * gl_Position.w;
}
}
// This is a minimum blur distance that serves as a faux-antialiasing for
// the circle. since blur is a ratio of the circle's size and the intent is
// to keep the blur at roughly 1px, the two are inversely related.
lowp float antialiasblur = 1.0 / u_device_pixel_ratio / (radius + stroke_width);
v_data = vec3(extrude.x, extrude.y, antialiasblur);
}

View File

@@ -1,6 +1,6 @@
layout (location = 0) in vec2 a_pos;
layout (std140) uniform DrawableUBO {
layout (std140) uniform FillDrawableUBO {
mat4 u_matrix;
vec2 u_world;
vec2 pad;

View File

@@ -1,6 +1,6 @@
layout (location = 0) in vec2 a_pos;
layout (std140) uniform DrawableUBO {
layout (std140) uniform FillDrawableUBO {
mat4 u_matrix;
vec2 u_world;
vec2 pad;

View File

@@ -6,6 +6,13 @@
"glsl_frag": "drawable.background.fragment.glsl",
"uses_ubos": true
},
{
"name": "CircleShader",
"header": "drawable_circle",
"glsl_vert": "drawable.circle.vertex.glsl",
"glsl_frag": "drawable.circle.fragment.glsl",
"uses_ubos": true
},
{
"name": "FillShader",
"header": "drawable_fill",

View File

@@ -81,22 +81,6 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters)
const auto labelPtr = (label.empty() ? drawable.getName() : label).c_str();
const auto debugGroup = parameters.encoder->createDebugGroup(labelPtr);
mat4 matrix = drawable.getMatrix();
if (drawable.getTileID()) {
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
const auto tileMat = parameters.matrixForTile(tileID);
matrix::multiply(matrix, drawable.getMatrix(), tileMat);
matrix = tileMat;
}
const auto renderableSize = parameters.backend.getDefaultRenderable().getSize();
gfx::DrawableUBO drawableUBO;
drawableUBO.matrix = util::cast<float>(matrix);
drawableUBO.world = {(float)renderableSize.width, (float)renderableSize.height};
auto uniformBuffer = context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
drawable.mutableUniformBuffers().addOrReplace("DrawableUBO", uniformBuffer);
drawable.draw(parameters);
});
}

View File

@@ -94,6 +94,7 @@ void registerTypes(gfx::ShaderRegistry& registry, gl::Context& glContext, const
void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramParameters& programParameters) {
registerTypes<shaders::BuiltIn::BackgroundShader,
shaders::BuiltIn::CircleShader,
shaders::BuiltIn::FillShader,
shaders::BuiltIn::FillOutlineShader,
shaders::BuiltIn::FillOutlinePatternShader,

View File

@@ -0,0 +1,9 @@
#include <mbgl/renderer/layer_tweaker.hpp>
#include <mbgl/style/layer_properties.hpp>
namespace mbgl {
LayerTweaker::LayerTweaker(Immutable<style::LayerProperties> properties)
: evaluatedProperties(std::move(properties)){};
}

View File

@@ -0,0 +1,72 @@
#include <mbgl/renderer/layers/background_layer_tweaker.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/style/layers/background_layer_properties.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/util/convert.hpp>
namespace mbgl {
using namespace style;
struct alignas(16) BackgroundDrawableUBO {
std::array<float, 4 * 4> matrix;
};
static_assert(sizeof(BackgroundDrawableUBO) % 16 == 0);
struct alignas(16) BackgroundLayerUBO {
Color color;
float opacity;
float padding[3];
};
static_assert(sizeof(BackgroundLayerUBO) % 16 == 0);
struct alignas(16) BackgroundPatternLayerUBO {
std::array<float, 2> pattern_tl_a;
std::array<float, 2> pattern_br_a;
std::array<float, 2> pattern_tl_b;
std::array<float, 2> pattern_br_b;
std::array<float, 2> texsize;
std::array<float, 2> pattern_size_a;
std::array<float, 2> pattern_size_b;
std::array<float, 2> pixel_coord_upper;
std::array<float, 2> pixel_coord_lower;
float tile_units_to_pixels;
float scale_a;
float scale_b;
float mix;
float opacity;
};
static_assert(sizeof(BackgroundPatternLayerUBO) % 16 == 0);
void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const PaintParameters& parameters) {
const auto& evaluated = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).evaluated;
if (!layerUniformBuffer) {
BackgroundLayerUBO layerUBO;
layerUBO.color = evaluated.get<BackgroundColor>();
layerUBO.opacity = evaluated.get<BackgroundOpacity>();
layerUniformBuffer = parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO));
}
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
drawable.mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", layerUniformBuffer);
if (!drawable.getTileID()) {
return;
}
mat4 matrix = drawable.getMatrix();
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
const auto tileMat = parameters.matrixForTile(tileID);
matrix::multiply(matrix, drawable.getMatrix(), tileMat);
matrix = tileMat;
BackgroundDrawableUBO drawableUBO;
drawableUBO.matrix = util::cast<float>(matrix);
auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
drawable.mutableUniformBuffers().addOrReplace("BackgroundDrawableUBO", drawableUniformBuffer);
});
}
} // namespace mbgl

View File

@@ -0,0 +1,29 @@
#pragma once
#include <mbgl/renderer/layer_tweaker.hpp>
namespace mbgl {
namespace gfx {
class UniformBuffer;
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
} // namespace gfx
/**
Background layer specific tweaker
*/
class BackgroundLayerTweaker : public LayerTweaker {
public:
BackgroundLayerTweaker(Immutable<style::LayerProperties> properties)
: LayerTweaker(properties){};
public:
~BackgroundLayerTweaker() override = default;
void execute(LayerGroup&, const PaintParameters&) override;
protected:
gfx::UniformBufferPtr layerUniformBuffer = nullptr;
};
} // namespace mbgl

View File

@@ -0,0 +1,110 @@
#include <mbgl/renderer/layers/circle_layer_tweaker.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/style/layers/circle_layer_properties.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/util/convert.hpp>
namespace mbgl {
using namespace style;
struct alignas(16) CircleDrawableUBO {
std::array<float, 4 * 4> matrix;
std::array<float, 2> extrude_scale;
};
static_assert(sizeof(CircleDrawableUBO) % 16 == 0);
struct alignas(16) CirclePaintParamsUBO {
float camera_to_center_distance;
float device_pixel_ratio;
};
static_assert(sizeof(CirclePaintParamsUBO) % 16 == 0);
struct alignas(16) CircleEvaluatedPropsUBO {
Color color;
Color stroke_color;
float radius;
float blur;
float opacity;
float stroke_width;
float stroke_opacity;
int scale_with_map;
int pitch_with_map;
};
static_assert(sizeof(CircleEvaluatedPropsUBO) % 16 == 0);
struct alignas(16) CircleInterpolateUBO {
float color_t;
float radius_t;
float blur_t;
float opacity_t;
float stroke_color_t;
float stroke_width_t;
float stroke_opacity_t;
};
static_assert(sizeof(CircleInterpolateUBO) % 16 == 0);
void CircleLayerTweaker::execute(LayerGroup& layerGroup, const PaintParameters& parameters) {
const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated;
CirclePaintParamsUBO paintParamsUBO;
paintParamsUBO.camera_to_center_distance = parameters.state.getCameraToCenterDistance();
paintParamsUBO.device_pixel_ratio = parameters.pixelRatio;
auto paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO));
const bool pitchWithMap = evaluated.get<CirclePitchAlignment>() == AlignmentType::Map;
if (!evaluatedPropsUniformBuffer) {
CircleEvaluatedPropsUBO evaluatedPropsUBO;
evaluatedPropsUBO.color = evaluated.get<CircleColor>().constantOr(Color());
evaluatedPropsUBO.radius = evaluated.get<CircleRadius>().constantOr(0);
evaluatedPropsUBO.blur = evaluated.get<CircleBlur>().constantOr(0);
evaluatedPropsUBO.opacity = evaluated.get<CircleOpacity>().constantOr(0);
evaluatedPropsUBO.stroke_color = evaluated.get<CircleStrokeColor>().constantOr(Color());
evaluatedPropsUBO.stroke_width = evaluated.get<CircleStrokeWidth>().constantOr(0);
evaluatedPropsUBO.stroke_opacity = evaluated.get<CircleStrokeOpacity>().constantOr(0);
evaluatedPropsUBO.scale_with_map = evaluated.get<CirclePitchScale>() == CirclePitchScaleType::Map;
evaluatedPropsUBO.pitch_with_map = pitchWithMap;
evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO,
sizeof(evaluatedPropsUBO));
}
CircleInterpolateUBO interpolateUBO;
interpolateUBO.color_t = 0;
interpolateUBO.radius_t = 0;
interpolateUBO.blur_t = 0;
interpolateUBO.opacity_t = 0;
interpolateUBO.stroke_color_t = 0;
interpolateUBO.stroke_width_t = 0;
interpolateUBO.stroke_opacity_t = 0;
auto interpolateUniformBuffer = parameters.context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO));
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
drawable.mutableUniformBuffers().addOrReplace("CirclePaintParamsUBO", paintParamsUniformBuffer);
drawable.mutableUniformBuffers().addOrReplace("CircleEvaluatedPropsUBO", evaluatedPropsUniformBuffer);
drawable.mutableUniformBuffers().addOrReplace("CircleInterpolateUBO", interpolateUniformBuffer);
if (!drawable.getTileID()) {
return;
}
mat4 matrix = drawable.getMatrix();
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
const auto tileMat = parameters.matrixForTile(tileID);
matrix::multiply(matrix, drawable.getMatrix(), tileMat);
matrix = tileMat;
CircleDrawableUBO drawableUBO;
drawableUBO.matrix = util::cast<float>(matrix);
drawableUBO.extrude_scale =
pitchWithMap
? std::array<float, 2>{{tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())),
tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom()))}}
: parameters.pixelsToGLUnits;
auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
drawable.mutableUniformBuffers().addOrReplace("CircleDrawableUBO", drawableUniformBuffer);
});
}
} // namespace mbgl

View File

@@ -0,0 +1,29 @@
#pragma once
#include <mbgl/renderer/layer_tweaker.hpp>
namespace mbgl {
namespace gfx {
class UniformBuffer;
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
} // namespace gfx
/**
Circle layer specific tweaker
*/
class CircleLayerTweaker : public LayerTweaker {
public:
CircleLayerTweaker(Immutable<style::LayerProperties> properties)
: LayerTweaker(properties){};
public:
~CircleLayerTweaker() override = default;
void execute(LayerGroup&, const PaintParameters&) override;
protected:
gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr;
};
} // namespace mbgl

View File

@@ -0,0 +1,61 @@
#include <mbgl/renderer/layers/fill_layer_tweaker.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/style/layers/fill_layer_properties.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/util/convert.hpp>
namespace mbgl {
using namespace style;
struct alignas(16) FillDrawableUBO {
std::array<float, 4 * 4> matrix;
std::array<float, 2> world;
std::array<float, 2> padding;
};
static_assert(sizeof(FillDrawableUBO) % 16 == 0);
void FillLayerTweaker::execute(LayerGroup& layerGroup, const PaintParameters& parameters) {
// const auto& evaluated = static_cast<const FillLayerProperties&>(*evaluatedProperties).evaluated;
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
if (!drawable.getTileID()) {
return;
}
/*mat4 matrix = drawable.getMatrix();
if (drawable.getTileID()) {
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
const auto tileMat = parameters.matrixForTile(tileID);
matrix::multiply(matrix, drawable.getMatrix(), tileMat);
matrix = tileMat;
}
const auto renderableSize = parameters.backend.getDefaultRenderable().getSize();
gfx::DrawableUBO drawableUBO;
drawableUBO.matrix = util::cast<float>(matrix);
drawableUBO.world = {(float)renderableSize.width, (float)renderableSize.height};
auto uniformBuffer = context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
drawable.mutableUniformBuffers().addOrReplace("DrawableUBO", uniformBuffer);*/
mat4 matrix = drawable.getMatrix();
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
const auto tileMat = parameters.matrixForTile(tileID);
matrix::multiply(matrix, drawable.getMatrix(), tileMat);
matrix = tileMat;
const auto renderableSize = parameters.backend.getDefaultRenderable().getSize();
FillDrawableUBO drawableUBO;
drawableUBO.matrix = util::cast<float>(matrix);
drawableUBO.world = {(float)renderableSize.width, (float)renderableSize.height};
auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
drawable.mutableUniformBuffers().addOrReplace("FillDrawableUBO", drawableUniformBuffer);
});
}
} // namespace mbgl

View File

@@ -0,0 +1,21 @@
#pragma once
#include <mbgl/renderer/layer_tweaker.hpp>
namespace mbgl {
/**
Fill layer specific tweaker
*/
class FillLayerTweaker : public LayerTweaker {
public:
FillLayerTweaker(Immutable<style::LayerProperties> properties)
: LayerTweaker(properties){};
public:
~FillLayerTweaker() override = default;
void execute(LayerGroup&, const PaintParameters&) override;
};
} // namespace mbgl

View File

@@ -1,5 +1,5 @@
#include <mbgl/renderer/layers/render_background_layer.hpp>
#include <mbgl/renderer/layers/background_layer_tweaker.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/shader_registry.hpp>
@@ -62,7 +62,9 @@ void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters& paramet
properties->renderPasses = mbgl::underlying_type(passes);
evaluatedProperties = std::move(properties);
evaluatedPropertiesChange = true;
if (tileLayerGroup) {
tileLayerGroup->setLayerTweaker(std::make_shared<BackgroundLayerTweaker>(evaluatedProperties));
}
}
bool RenderBackgroundLayer::hasTransition() const {
@@ -73,10 +75,16 @@ bool RenderBackgroundLayer::hasCrossfade() const {
return getCrossfade<BackgroundLayerProperties>(evaluatedProperties).t != 1;
}
static bool enableDefaultRender = false;
void RenderBackgroundLayer::render(PaintParameters& parameters) {
// Note that for bottommost layers without a pattern, the background color
// is drawn with glClear rather than this method.
if (!enableDefaultRender) {
return;
}
// Ensure programs are available
if (!parameters.shaders.populate(backgroundProgram)) return;
if (!parameters.shaders.populate(backgroundPatternProgram)) return;
@@ -210,6 +218,10 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
gfx::Context& context,
const TransformState& state,
UniqueChangeRequestVec& changes) {
if (enableDefaultRender) {
return;
}
std::unique_lock<std::mutex> guard(mutex);
if (!shader) {
@@ -253,19 +265,12 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
return;
}
if (evaluatedPropertiesChange) {
BackgroundLayerUBO backgroundLayerUBO;
backgroundLayerUBO.color = evaluated.get<BackgroundColor>();
backgroundLayerUBO.opacity = evaluated.get<BackgroundOpacity>();
uniformBuffer = context.createUniformBuffer(&backgroundLayerUBO, sizeof(backgroundLayerUBO));
evaluatedPropertiesChange = false;
}
if (!tileLayerGroup) {
tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64);
if (!tileLayerGroup) {
return;
}
tileLayerGroup->setLayerTweaker(std::make_shared<BackgroundLayerTweaker>(evaluatedProperties));
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true));
}
@@ -306,7 +311,6 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
if (tileDrawable) {
// Already created, update it.
tileDrawable->mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", uniformBuffer);
continue;
}
@@ -332,7 +336,6 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
if (!newDrawables.empty()) {
auto& drawable = newDrawables[0];
drawable->setTileID(tileID);
drawable->mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", uniformBuffer);
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
++stats.tileDrawablesAdded;
}

View File

@@ -52,29 +52,4 @@ private:
gfx::ShaderProgramBasePtr shader;
};
struct alignas(16) BackgroundLayerUBO {
Color color;
float opacity;
float padding[3];
};
static_assert(sizeof(BackgroundLayerUBO) % 16 == 0);
struct alignas(16) BackgroundPatternLayerUBO {
std::array<float, 2> pattern_tl_a;
std::array<float, 2> pattern_br_a;
std::array<float, 2> pattern_tl_b;
std::array<float, 2> pattern_br_b;
std::array<float, 2> texsize;
std::array<float, 2> pattern_size_a;
std::array<float, 2> pattern_size_b;
std::array<float, 2> pixel_coord_upper;
std::array<float, 2> pixel_coord_lower;
float tile_units_to_pixels;
float scale_a;
float scale_b;
float mix;
float opacity;
};
static_assert(sizeof(BackgroundPatternLayerUBO) % 16 == 0);
} // namespace mbgl

View File

@@ -1,5 +1,7 @@
#include <mbgl/renderer/layers/render_circle_layer.hpp>
#include <mbgl/renderer/layers/circle_layer_tweaker.hpp>
#include <mbgl/renderer/buckets/circle_bucket.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/programs/programs.hpp>
@@ -7,6 +9,7 @@
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/gfx/drawable_builder.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/shader_registry.hpp>
#include <mbgl/util/math.hpp>
@@ -69,6 +72,9 @@ void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters)
: RenderPass::None;
properties->renderPasses = mbgl::underlying_type(passes);
evaluatedProperties = std::move(properties);
if (tileLayerGroup) {
tileLayerGroup->setLayerTweaker(std::make_shared<CircleLayerTweaker>(evaluatedProperties));
}
}
bool RenderCircleLayer::hasTransition() const {
@@ -79,8 +85,15 @@ bool RenderCircleLayer::hasCrossfade() const {
return false;
}
static bool enableDefaultRender = false;
void RenderCircleLayer::render(PaintParameters& parameters) {
assert(renderTiles);
if (!enableDefaultRender) {
return;
}
if (parameters.pass == RenderPass::Opaque) {
return;
}
@@ -236,4 +249,214 @@ bool RenderCircleLayer::queryIntersectsFeature(const GeometryCoordinates& queryG
return false;
}
void RenderCircleLayer::layerRemoved(UniqueChangeRequestVec& changes) {
// Remove everything
if (tileLayerGroup) {
changes.emplace_back(std::make_unique<RemoveLayerGroupRequest>(tileLayerGroup->getLayerIndex()));
tileLayerGroup.reset();
}
}
void RenderCircleLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) {
stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size();
}
void RenderCircleLayer::update(const int32_t layerIndex,
gfx::ShaderRegistry& shaders,
gfx::Context& context,
const TransformState& /*state*/,
UniqueChangeRequestVec& changes) {
if (enableDefaultRender) {
return;
}
std::unique_lock<std::mutex> guard(mutex);
if (!renderTiles || renderTiles->empty()) {
if (tileLayerGroup) {
stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount();
tileLayerGroup->clearDrawables();
}
return;
}
// Set up a layer group
if (!tileLayerGroup) {
tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64);
if (!tileLayerGroup) {
return;
}
tileLayerGroup->setLayerTweaker(std::make_shared<CircleLayerTweaker>(evaluatedProperties));
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true));
}
if (!circleShader) {
circleShader = context.getGenericShader(shaders, "CircleShader");
}
std::unordered_set<OverscaledTileID> newTileIDs(renderTiles->size());
std::transform(renderTiles->begin(),
renderTiles->end(),
std::inserter(newTileIDs, newTileIDs.begin()),
[](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); });
std::unique_ptr<gfx::DrawableBuilder> circleBuilder;
std::vector<gfx::DrawablePtr> newTiles;
gfx::VertexAttributeArray circleVertexAttrs;
auto renderPass = RenderPass::Translucent;
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
return;
}
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
const auto tileID = drawable->getTileID();
if (tileID && newTileIDs.find(*tileID) == newTileIDs.end()) {
// remove it
drawable.reset();
++stats.tileDrawablesRemoved;
}
});
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
auto& tileDrawable = tileLayerGroup->getDrawable(renderPass, tileID);
if (tileDrawable) {
continue;
}
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
if (!renderData) {
removeTile(renderPass, tileID);
continue;
}
auto& bucket = static_cast<CircleBucket&>(*renderData->bucket);
std::vector<std::array<int16_t, 2>> rawVerts;
const auto buildVertices = [&]() {
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex>&
verts = bucket.vertices.vector();
if (rawVerts.size() < verts.size()) {
rawVerts.resize(verts.size());
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
}
};
circleVertexAttrs.clear();
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
if (auto& binder = paintPropertyBinders.get<CircleColor>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_color")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& packedColor = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float4>(
i, {packedColor[0], packedColor[1], packedColor[0], packedColor[1]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleRadius>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_radius")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& radius = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {radius[0], radius[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleBlur>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_blur")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& blur = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {blur[0], blur[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleOpacity>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_opacity")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& opacity = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {opacity[0], opacity[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleStrokeColor>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_color")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& packedStrokeColor =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float4>(
i, {packedStrokeColor[0], packedStrokeColor[1], packedStrokeColor[0], packedStrokeColor[1]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleStrokeWidth>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_width")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& strokeWidth = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {strokeWidth[0], strokeWidth[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleStrokeOpacity>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_opacity")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& strokeOpacity =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {strokeOpacity[0], strokeOpacity[0]});
}
}
}
circleBuilder = context.createDrawableBuilder("circle");
circleBuilder->setShader(circleShader);
circleBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None);
circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
: gfx::DepthMaskType::ReadOnly);
circleBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
circleBuilder->setLayerIndex(layerIndex);
circleBuilder->setRenderPass(renderPass);
circleBuilder->setVertexAttributes(circleVertexAttrs);
buildVertices();
circleBuilder->addVertices(rawVerts, 0, rawVerts.size());
for (const auto& seg : bucket.segments) {
circleBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
}
circleBuilder->flush();
for (auto& drawable : circleBuilder->clearDrawables()) {
drawable->setTileID(tileID);
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
++stats.tileDrawablesAdded;
}
}
}
} // namespace mbgl

View File

@@ -13,6 +13,15 @@ public:
explicit RenderCircleLayer(Immutable<style::CircleLayer::Impl>);
~RenderCircleLayer() final = default;
void layerRemoved(UniqueChangeRequestVec&) override;
/// Generate any changes needed by the layer
void update(int32_t layerIndex,
gfx::ShaderRegistry&,
gfx::Context&,
const TransformState&,
UniqueChangeRequestVec&) override;
private:
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
@@ -28,11 +37,16 @@ private:
const mat4&,
const FeatureState&) const override;
/// Remove all drawables for the tile from the layer group
void removeTile(RenderPass, const OverscaledTileID&);
// Paint properties
style::CirclePaintProperties::Unevaluated unevaluated;
// Programs
std::shared_ptr<CircleProgram> circleProgram;
gfx::ShaderProgramBasePtr circleShader;
};
} // namespace mbgl

View File

@@ -9,6 +9,7 @@
#include <mbgl/renderer/buckets/fill_bucket.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/layers/fill_layer_tweaker.hpp>
#include <mbgl/renderer/layers/render_fill_layer.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_source.hpp>
@@ -64,8 +65,9 @@ void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) {
}
properties->renderPasses = mbgl::underlying_type(passes);
evaluatedProperties = std::move(properties);
evaluatedPropertiesChange = true;
if (tileLayerGroup) {
tileLayerGroup->setLayerTweaker(std::make_shared<FillLayerTweaker>(evaluatedProperties));
}
}
bool RenderFillLayer::hasTransition() const {
@@ -287,6 +289,10 @@ void RenderFillLayer::update(const int32_t layerIndex,
gfx::Context& context,
const TransformState& /*state*/,
UniqueChangeRequestVec& changes) {
if (enableDefaultRender) {
return;
}
std::unique_lock<std::mutex> guard(mutex);
if (!renderTiles || renderTiles->empty()) {
@@ -303,6 +309,7 @@ void RenderFillLayer::update(const int32_t layerIndex,
if (!tileLayerGroup) {
return;
}
tileLayerGroup->setLayerTweaker(std::make_shared<FillLayerTweaker>(evaluatedProperties));
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true));
}
@@ -442,16 +449,7 @@ void RenderFillLayer::update(const int32_t layerIndex,
}
}
if (evaluatedPropertiesChange) {
// FillLayerUBO fillLayerUBO;
// fillLayerUBO.color = evaluated.get<FillColor>();
// fillLayerUBO.opacity = evaluated.get<FillOpacity>();
// uniformBuffer = context.createUniformBuffer(&fillLayerUBO, sizeof(fillLayerUBO));
evaluatedPropertiesChange = false;
}
if (tileDrawable) {
// tileDrawable->mutableUniformBuffers().addOrReplace("FillLayerUBO", uniformBuffer);
continue;
}

View File

@@ -169,8 +169,6 @@ protected:
TileLayerGroupPtr tileLayerGroup;
std::mutex mutex;
bool evaluatedPropertiesChange = false;
gfx::UniformBufferPtr uniformBuffer = nullptr;
struct Stats {
size_t propertyEvaluations = 0;

View File

@@ -11,6 +11,7 @@
#include <mbgl/gfx/upload_pass.hpp>
#include <mbgl/gl/drawable_gl.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/renderer/layer_tweaker.hpp>
#include <mbgl/renderer/pattern_atlas.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/renderer/render_static_data.hpp>
@@ -106,6 +107,13 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
}
}
// Run layer tweakers to update any dynamic elements
orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) {
if (layerGroup.getLayerTweaker()) {
layerGroup.getLayerTweaker()->execute(layerGroup, parameters);
}
});
// Give the layers a chance to do setup
orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.preRender(orchestrator, parameters); });
@@ -200,9 +208,6 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
for (auto it = layerRenderItems.rbegin(); it != layerRenderItems.rend(); ++it, ++i) {
parameters.currentLayer = i;
const RenderItem& renderItem = it->get();
if (renderItem.getName() == "background") {
continue;
}
if (renderItem.hasRenderPass(parameters.pass)) {
const auto layerDebugGroup(parameters.renderPass->createDebugGroup(renderItem.getName().c_str()));
renderItem.render(parameters);