Heatmap layer (#1230)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
committed by
Bart Louwers
parent
e631bc3c42
commit
813ddb024a
@@ -148,6 +148,7 @@ if(MLN_DRAWABLE_RENDERER)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/change_request.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/render_target.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_program_base.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program_mtl.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/identity.hpp
|
||||
@@ -159,6 +160,7 @@ if(MLN_DRAWABLE_RENDERER)
|
||||
${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
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_buffer_gl.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gl/vertex_attribute_gl.hpp
|
||||
@@ -590,6 +592,10 @@ list(APPEND SRC_FILES
|
||||
${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/heatmap_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_texture_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/render_background_layer.cpp
|
||||
@@ -631,6 +637,7 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_source_observer.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_static_data.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_static_data.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_target.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_tile.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_tile.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_tree.hpp
|
||||
@@ -1007,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_heatmap.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_heatmap_texture.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_raster.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_symbol_icon.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_symbol_sdf_text.hpp
|
||||
@@ -1069,6 +1078,7 @@ if(MLN_WITH_OPENGL)
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_custom_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_target_gl.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderbuffer_resource.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderer_backend.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gl/state.hpp
|
||||
|
||||
@@ -849,6 +849,8 @@ MLN_OPENGL_HEADERS = [
|
||||
"include/mbgl/shaders/gl/drawable_line_pattern.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_line_sdf.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_line.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_heatmap.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_heatmap_texture.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_raster.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_symbol_icon.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_symbol_sdf_text.hpp",
|
||||
@@ -892,12 +894,17 @@ MLN_DRAWABLES_SOURCE = [
|
||||
"src/mbgl/renderer/layer_group.cpp",
|
||||
"src/mbgl/renderer/tile_layer_group.cpp",
|
||||
"src/mbgl/renderer/layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/render_target.cpp",
|
||||
"src/mbgl/renderer/layers/background_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/background_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/circle_layer_tweaker.cpp",
|
||||
"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/heatmap_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/line_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/line_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/raster_layer_tweaker.cpp",
|
||||
@@ -913,6 +920,7 @@ MLN_DRAWABLES_SOURCE = [
|
||||
"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",
|
||||
"src/mbgl/gl/uniform_block_gl.cpp",
|
||||
"src/mbgl/gl/uniform_buffer_gl.cpp",
|
||||
@@ -932,6 +940,7 @@ MLN_DRAWABLES_HEADERS = [
|
||||
"include/mbgl/renderer/change_request.hpp",
|
||||
"include/mbgl/renderer/layer_group.hpp",
|
||||
"include/mbgl/renderer/layer_tweaker.hpp",
|
||||
"include/mbgl/renderer/render_target.hpp",
|
||||
"include/mbgl/shaders/shader_program_base.hpp",
|
||||
"include/mbgl/shaders/mtl/shader_program_mtl.hpp",
|
||||
"include/mbgl/util/identity.hpp",
|
||||
@@ -941,6 +950,7 @@ MLN_DRAWABLES_HEADERS = [
|
||||
"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",
|
||||
"include/mbgl/gl/uniform_buffer_gl.hpp",
|
||||
"include/mbgl/gl/vertex_attribute_gl.hpp",
|
||||
|
||||
@@ -22,6 +22,7 @@ enum class RenderPass : uint8_t;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class ColorMode;
|
||||
class CullFaceMode;
|
||||
enum class DepthMaskType : bool;
|
||||
class DrawableTweaker;
|
||||
@@ -134,6 +135,9 @@ public:
|
||||
const gfx::CullFaceMode& getCullFaceMode() const;
|
||||
void setCullFaceMode(const gfx::CullFaceMode&);
|
||||
|
||||
const gfx::ColorMode& getColorMode() const;
|
||||
void setColorMode(const gfx::ColorMode&);
|
||||
|
||||
/// Get the number of vertexes
|
||||
std::size_t getVertexCount() const { return getVertexAttributes().getMaxCount(); }
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ public:
|
||||
DepthMaskType getDepthType() const { return depthType; }
|
||||
void setDepthType(DepthMaskType value) { depthType = value; }
|
||||
|
||||
const gfx::ColorMode& getColorMode() const;
|
||||
void setColorMode(const gfx::ColorMode& value);
|
||||
|
||||
const gfx::CullFaceMode& getCullFaceMode() const;
|
||||
void setCullFaceMode(const gfx::CullFaceMode& value);
|
||||
|
||||
|
||||
29
include/mbgl/gl/render_target_gl.hpp
Normal file
29
include/mbgl/gl/render_target_gl.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/render_target.hpp>
|
||||
#include <mbgl/gfx/types.hpp>
|
||||
#include <mbgl/gl/object.hpp>
|
||||
#include <mbgl/gl/types.hpp>
|
||||
#include <mbgl/util/size.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gl {
|
||||
|
||||
class Context;
|
||||
using UniqueFramebufferPtr = std::shared_ptr<UniqueFramebuffer>;
|
||||
|
||||
class RenderTargetGL final : public RenderTarget {
|
||||
public:
|
||||
RenderTargetGL(Context& context, const Size size, const gfx::TextureChannelDataType type);
|
||||
~RenderTargetGL() override;
|
||||
|
||||
void upload(gfx::UploadPass& uploadPass) override;
|
||||
void render(RenderOrchestrator&, const RenderTree&, PaintParameters&) override;
|
||||
|
||||
private:
|
||||
Context& glContext;
|
||||
UniqueFramebufferPtr framebuffer;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
@@ -11,11 +11,13 @@ class ChangeRequest;
|
||||
class LayerGroupBase;
|
||||
class TileLayerGroup;
|
||||
class RenderOrchestrator;
|
||||
class RenderTarget;
|
||||
|
||||
using ChangeRequestPtr = std::shared_ptr<ChangeRequest>;
|
||||
using UniqueChangeRequest = std::unique_ptr<ChangeRequest>;
|
||||
using UniqueChangeRequestVec = std::vector<UniqueChangeRequest>;
|
||||
using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
|
||||
using RenderTargetPtr = std::shared_ptr<RenderTarget>;
|
||||
|
||||
namespace gfx {
|
||||
class Drawable;
|
||||
@@ -89,4 +91,30 @@ protected:
|
||||
int32_t newLayerIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
Add a new render target to the scene
|
||||
*/
|
||||
class AddRenderTargetRequest : public ChangeRequest {
|
||||
public:
|
||||
AddRenderTargetRequest(RenderTargetPtr renderTarget_);
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
RenderTargetPtr renderTarget;
|
||||
};
|
||||
|
||||
/**
|
||||
Remove a render target from the scene
|
||||
*/
|
||||
class RemoveRenderTargetRequest : public ChangeRequest {
|
||||
public:
|
||||
RemoveRenderTargetRequest(const RenderTargetPtr &renderTarget_);
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
const RenderTargetPtr &renderTarget;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
45
include/mbgl/renderer/render_target.hpp
Normal file
45
include/mbgl/renderer/render_target.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gfx {
|
||||
class Texture2D;
|
||||
class UploadPass;
|
||||
using Texture2DPtr = std::shared_ptr<Texture2D>;
|
||||
} // namespace gfx
|
||||
|
||||
class LayerGroupBase;
|
||||
class PaintParameters;
|
||||
class RenderOrchestrator;
|
||||
class RenderTree;
|
||||
|
||||
using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
|
||||
|
||||
class RenderTarget {
|
||||
public:
|
||||
virtual ~RenderTarget() = default;
|
||||
|
||||
void setTexture(const gfx::Texture2DPtr& texture_) { texture = std::move(texture_); };
|
||||
const gfx::Texture2DPtr& getTexture() const { return texture; };
|
||||
|
||||
bool addLayerGroup(LayerGroupBasePtr, bool replace);
|
||||
bool removeLayerGroup(const int32_t layerIndex);
|
||||
size_t numLayerGroups() const noexcept;
|
||||
const LayerGroupBasePtr& getLayerGroup(const int32_t layerIndex) const;
|
||||
void observeLayerGroups(std::function<void(LayerGroupBase&)>);
|
||||
void observeLayerGroups(std::function<void(const LayerGroupBase&)>) const;
|
||||
|
||||
virtual void upload(gfx::UploadPass& uploadPass) = 0;
|
||||
virtual void render(RenderOrchestrator&, const RenderTree&, PaintParameters&) = 0;
|
||||
|
||||
protected:
|
||||
gfx::Texture2DPtr texture;
|
||||
using LayerGroupMap = std::map<int32_t, LayerGroupBasePtr>;
|
||||
LayerGroupMap layerGroupsByLayerIndex;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
127
include/mbgl/shaders/gl/drawable_heatmap.hpp
Normal file
127
include/mbgl/shaders/gl/drawable_heatmap.hpp
Normal file
@@ -0,0 +1,127 @@
|
||||
// Generated code, do not modify this file!
|
||||
#pragma once
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::OpenGL> {
|
||||
static constexpr const char* name = "HeatmapShader";
|
||||
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
|
||||
out vec2 v_extrude;
|
||||
|
||||
layout (std140) uniform HeatmapDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp float u_extrude_scale;
|
||||
lowp float pad1_;
|
||||
lowp vec2 pad2_;
|
||||
};
|
||||
|
||||
layout (std140) uniform HeatmapEvaluatedPropsUBO {
|
||||
highp float u_weight;
|
||||
highp float u_radius;
|
||||
highp float u_intensity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
layout (std140) uniform HeatmapInterpolateUBO {
|
||||
lowp float u_weight_t;
|
||||
lowp float u_radius_t;
|
||||
lowp vec2 pad3_;
|
||||
};
|
||||
|
||||
#ifndef HAS_UNIFORM_u_weight
|
||||
layout (location = 1) in highp vec2 a_weight;
|
||||
out highp float weight;
|
||||
#endif
|
||||
#ifndef HAS_UNIFORM_u_radius
|
||||
layout (location = 2) in mediump vec2 a_radius;
|
||||
#endif
|
||||
|
||||
// Effective "0" in the kernel density texture to adjust the kernel size to;
|
||||
// this empirically chosen number minimizes artifacts on overlapping kernels
|
||||
// for typical heatmap cases (assuming clustered source)
|
||||
const highp float ZERO = 1.0 / 255.0 / 16.0;
|
||||
|
||||
// Gaussian kernel coefficient: 1 / sqrt(2 * PI)
|
||||
#define GAUSS_COEF 0.3989422804014327
|
||||
|
||||
void main(void) {
|
||||
#ifndef HAS_UNIFORM_u_weight
|
||||
weight = unpack_mix_vec2(a_weight, u_weight_t);
|
||||
#else
|
||||
highp float weight = u_weight;
|
||||
#endif
|
||||
#ifndef HAS_UNIFORM_u_radius
|
||||
mediump float radius = unpack_mix_vec2(a_radius, u_radius_t);
|
||||
#else
|
||||
mediump float radius = u_radius;
|
||||
#endif
|
||||
|
||||
// unencode the extrusion vector that we snuck into the a_pos vector
|
||||
vec2 unscaled_extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0);
|
||||
|
||||
// This 'extrude' comes in ranging from [-1, -1], to [1, 1]. We'll use
|
||||
// it to produce the vertices of a square mesh framing the point feature
|
||||
// we're adding to the kernel density texture. We'll also pass it as
|
||||
// a varying, so that the fragment shader can determine the distance of
|
||||
// each fragment from the point feature.
|
||||
// Before we do so, we need to scale it up sufficiently so that the
|
||||
// kernel falls effectively to zero at the edge of the mesh.
|
||||
// That is, we want to know S such that
|
||||
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
||||
// Which solves to:
|
||||
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
||||
float S = sqrt(-2.0 * log(ZERO / weight / u_intensity / GAUSS_COEF)) / 3.0;
|
||||
|
||||
// Pass the varying in units of radius
|
||||
v_extrude = S * unscaled_extrude;
|
||||
|
||||
// Scale by radius and the zoom-based scale factor to produce actual
|
||||
// mesh position
|
||||
vec2 extrude = v_extrude * radius * u_extrude_scale;
|
||||
|
||||
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
|
||||
// in extrusion data
|
||||
vec4 pos = vec4(floor(a_pos * 0.5) + extrude, 0, 1);
|
||||
|
||||
gl_Position = u_matrix * pos;
|
||||
}
|
||||
)";
|
||||
static constexpr const char* fragment = R"(in vec2 v_extrude;
|
||||
|
||||
layout (std140) uniform HeatmapEvaluatedPropsUBO {
|
||||
highp float u_weight;
|
||||
highp float u_radius;
|
||||
highp float u_intensity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
#ifndef HAS_UNIFORM_u_weight
|
||||
in highp float weight;
|
||||
#endif
|
||||
|
||||
// Gaussian kernel coefficient: 1 / sqrt(2 * PI)
|
||||
#define GAUSS_COEF 0.3989422804014327
|
||||
|
||||
void main() {
|
||||
#ifdef HAS_UNIFORM_u_weight
|
||||
highp float weight = u_weight;
|
||||
#endif
|
||||
|
||||
// Kernel density estimation with a Gaussian kernel of size 5x5
|
||||
float d = -0.5 * 3.0 * 3.0 * dot(v_extrude, v_extrude);
|
||||
float val = weight * u_intensity * GAUSS_COEF * exp(d);
|
||||
|
||||
fragColor = vec4(val, 1.0, 1.0, 1.0);
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
52
include/mbgl/shaders/gl/drawable_heatmap_texture.hpp
Normal file
52
include/mbgl/shaders/gl/drawable_heatmap_texture.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Generated code, do not modify this file!
|
||||
#pragma once
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::HeatmapTextureShader, gfx::Backend::Type::OpenGL> {
|
||||
static constexpr const char* name = "HeatmapTextureShader";
|
||||
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
|
||||
out vec2 v_pos;
|
||||
|
||||
layout (std140) uniform HeatmapTextureDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_world;
|
||||
highp float u_opacity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos * u_world, 0, 1);
|
||||
|
||||
v_pos.x = a_pos.x;
|
||||
v_pos.y = 1.0 - a_pos.y;
|
||||
}
|
||||
)";
|
||||
static constexpr const char* fragment = R"(in vec2 v_pos;
|
||||
uniform sampler2D u_image;
|
||||
uniform sampler2D u_color_ramp;
|
||||
|
||||
layout (std140) uniform HeatmapTextureDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_world;
|
||||
highp float u_opacity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
void main() {
|
||||
float t = texture(u_image, v_pos).r;
|
||||
vec4 color = texture(u_color_ramp, vec2(t, 0.5));
|
||||
fragColor = color * u_opacity;
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(0.0);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <mbgl/shaders/gl/drawable_line.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_fill_pattern.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_fill_outline_pattern.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_heatmap.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_heatmap_texture.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_raster.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_symbol_icon.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_symbol_sdf_icon.hpp>
|
||||
|
||||
@@ -20,11 +20,14 @@ enum class BuiltIn {
|
||||
LineShader,
|
||||
FillPatternShader,
|
||||
FillOutlinePatternShader,
|
||||
HeatmapShader,
|
||||
HeatmapTextureShader,
|
||||
RasterShader,
|
||||
SymbolIconShader,
|
||||
SymbolSDFTextShader,
|
||||
SymbolSDFIconShader,
|
||||
SymbolTextAndIconShader,
|
||||
|
||||
Prelude,
|
||||
BackgroundProgram,
|
||||
BackgroundPatternProgram,
|
||||
|
||||
27
shaders/drawable.heatmap.fragment.glsl
Normal file
27
shaders/drawable.heatmap.fragment.glsl
Normal file
@@ -0,0 +1,27 @@
|
||||
in vec2 v_extrude;
|
||||
|
||||
layout (std140) uniform HeatmapEvaluatedPropsUBO {
|
||||
highp float u_weight;
|
||||
highp float u_radius;
|
||||
highp float u_intensity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
#pragma mapbox: define highp float weight
|
||||
|
||||
// Gaussian kernel coefficient: 1 / sqrt(2 * PI)
|
||||
#define GAUSS_COEF 0.3989422804014327
|
||||
|
||||
void main() {
|
||||
#pragma mapbox: initialize highp float weight
|
||||
|
||||
// Kernel density estimation with a Gaussian kernel of size 5x5
|
||||
float d = -0.5 * 3.0 * 3.0 * dot(v_extrude, v_extrude);
|
||||
float val = weight * u_intensity * GAUSS_COEF * exp(d);
|
||||
|
||||
fragColor = vec4(val, 1.0, 1.0, 1.0);
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
67
shaders/drawable.heatmap.vertex.glsl
Normal file
67
shaders/drawable.heatmap.vertex.glsl
Normal file
@@ -0,0 +1,67 @@
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
out vec2 v_extrude;
|
||||
|
||||
layout (std140) uniform HeatmapDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp float u_extrude_scale;
|
||||
lowp float pad1_;
|
||||
lowp vec2 pad2_;
|
||||
};
|
||||
|
||||
layout (std140) uniform HeatmapEvaluatedPropsUBO {
|
||||
highp float u_weight;
|
||||
highp float u_radius;
|
||||
highp float u_intensity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
layout (std140) uniform HeatmapInterpolateUBO {
|
||||
lowp float u_weight_t;
|
||||
lowp float u_radius_t;
|
||||
lowp vec2 pad3_;
|
||||
};
|
||||
|
||||
#pragma mapbox: define highp float weight
|
||||
#pragma mapbox: define mediump float radius
|
||||
|
||||
// Effective "0" in the kernel density texture to adjust the kernel size to;
|
||||
// this empirically chosen number minimizes artifacts on overlapping kernels
|
||||
// for typical heatmap cases (assuming clustered source)
|
||||
const highp float ZERO = 1.0 / 255.0 / 16.0;
|
||||
|
||||
// Gaussian kernel coefficient: 1 / sqrt(2 * PI)
|
||||
#define GAUSS_COEF 0.3989422804014327
|
||||
|
||||
void main(void) {
|
||||
#pragma mapbox: initialize highp float weight
|
||||
#pragma mapbox: initialize mediump float radius
|
||||
|
||||
// unencode the extrusion vector that we snuck into the a_pos vector
|
||||
vec2 unscaled_extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0);
|
||||
|
||||
// This 'extrude' comes in ranging from [-1, -1], to [1, 1]. We'll use
|
||||
// it to produce the vertices of a square mesh framing the point feature
|
||||
// we're adding to the kernel density texture. We'll also pass it as
|
||||
// a varying, so that the fragment shader can determine the distance of
|
||||
// each fragment from the point feature.
|
||||
// Before we do so, we need to scale it up sufficiently so that the
|
||||
// kernel falls effectively to zero at the edge of the mesh.
|
||||
// That is, we want to know S such that
|
||||
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
||||
// Which solves to:
|
||||
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
||||
float S = sqrt(-2.0 * log(ZERO / weight / u_intensity / GAUSS_COEF)) / 3.0;
|
||||
|
||||
// Pass the varying in units of radius
|
||||
v_extrude = S * unscaled_extrude;
|
||||
|
||||
// Scale by radius and the zoom-based scale factor to produce actual
|
||||
// mesh position
|
||||
vec2 extrude = v_extrude * radius * u_extrude_scale;
|
||||
|
||||
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
|
||||
// in extrusion data
|
||||
vec4 pos = vec4(floor(a_pos * 0.5) + extrude, 0, 1);
|
||||
|
||||
gl_Position = u_matrix * pos;
|
||||
}
|
||||
20
shaders/drawable.heatmap_texture.fragment.glsl
Normal file
20
shaders/drawable.heatmap_texture.fragment.glsl
Normal file
@@ -0,0 +1,20 @@
|
||||
in vec2 v_pos;
|
||||
uniform sampler2D u_image;
|
||||
uniform sampler2D u_color_ramp;
|
||||
|
||||
layout (std140) uniform HeatmapTextureDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_world;
|
||||
highp float u_opacity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
void main() {
|
||||
float t = texture(u_image, v_pos).r;
|
||||
vec4 color = texture(u_color_ramp, vec2(t, 0.5));
|
||||
fragColor = color * u_opacity;
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(0.0);
|
||||
#endif
|
||||
}
|
||||
16
shaders/drawable.heatmap_texture.vertex.glsl
Normal file
16
shaders/drawable.heatmap_texture.vertex.glsl
Normal file
@@ -0,0 +1,16 @@
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
out vec2 v_pos;
|
||||
|
||||
layout (std140) uniform HeatmapTextureDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_world;
|
||||
highp float u_opacity;
|
||||
lowp float pad0_;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos * u_world, 0, 1);
|
||||
|
||||
v_pos.x = a_pos.x;
|
||||
v_pos.y = 1.0 - a_pos.y;
|
||||
}
|
||||
@@ -76,6 +76,20 @@
|
||||
"glsl_frag": "drawable.fill_outline_pattern.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "HeatmapShader",
|
||||
"header": "drawable_heatmap",
|
||||
"glsl_vert": "drawable.heatmap.vertex.glsl",
|
||||
"glsl_frag": "drawable.heatmap.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "HeatmapTextureShader",
|
||||
"header": "drawable_heatmap_texture",
|
||||
"glsl_vert": "drawable.heatmap_texture.vertex.glsl",
|
||||
"glsl_frag": "drawable.heatmap_texture.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "RasterShader",
|
||||
"header": "drawable_raster",
|
||||
|
||||
@@ -24,8 +24,10 @@ class ProgramParameters;
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
class TileLayerGroup;
|
||||
class LayerGroup;
|
||||
class RenderTarget;
|
||||
using TileLayerGroupPtr = std::shared_ptr<TileLayerGroup>;
|
||||
using LayerGroupPtr = std::shared_ptr<LayerGroup>;
|
||||
using RenderTargetPtr = std::shared_ptr<RenderTarget>;
|
||||
#endif
|
||||
|
||||
namespace gfx {
|
||||
@@ -137,6 +139,9 @@ public:
|
||||
|
||||
/// Create a texture
|
||||
virtual Texture2DPtr createTexture2D() = 0;
|
||||
|
||||
/// Create a render target
|
||||
virtual RenderTargetPtr createRenderTarget(const Size size, const TextureChannelDataType type) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
|
||||
#include <mbgl/gfx/color_mode.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/types.hpp>
|
||||
#include <mbgl/renderer/render_pass.hpp>
|
||||
@@ -8,6 +9,7 @@ namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
struct Drawable::Impl {
|
||||
gfx::ColorMode colorMode = gfx::ColorMode::disabled();
|
||||
gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled();
|
||||
};
|
||||
|
||||
@@ -19,6 +21,14 @@ Drawable::Drawable(std::string name_)
|
||||
|
||||
Drawable::~Drawable() = default;
|
||||
|
||||
const gfx::ColorMode& Drawable::getColorMode() const {
|
||||
return impl->colorMode;
|
||||
}
|
||||
|
||||
void Drawable::setColorMode(const gfx::ColorMode& value) {
|
||||
impl->colorMode = value;
|
||||
}
|
||||
|
||||
const gfx::CullFaceMode& Drawable::getCullFaceMode() const {
|
||||
return impl->cullFaceMode;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,13 @@ DrawableBuilder::DrawableBuilder(std::string name_)
|
||||
|
||||
DrawableBuilder::~DrawableBuilder() = default;
|
||||
|
||||
const gfx::ColorMode& DrawableBuilder::getColorMode() const {
|
||||
return impl->colorMode;
|
||||
}
|
||||
void DrawableBuilder::setColorMode(const gfx::ColorMode& value) {
|
||||
impl->colorMode = value;
|
||||
}
|
||||
|
||||
const gfx::CullFaceMode& DrawableBuilder::getCullFaceMode() const {
|
||||
return impl->cullFaceMode;
|
||||
}
|
||||
@@ -40,6 +47,7 @@ void DrawableBuilder::flush() {
|
||||
draw->setDrawPriority(drawPriority);
|
||||
draw->setSubLayerIndex(subLayerIndex);
|
||||
draw->setDepthType(depthType);
|
||||
draw->setColorMode(impl->colorMode);
|
||||
draw->setCullFaceMode(impl->cullFaceMode);
|
||||
draw->setShader(shader);
|
||||
draw->setTextures(textures);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <mbgl/gfx/attribute.hpp>
|
||||
#include <mbgl/gfx/color_mode.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/index_vector.hpp>
|
||||
#include <mbgl/gfx/vertex_vector.hpp>
|
||||
@@ -21,6 +22,7 @@ struct DrawableBuilder::Impl {
|
||||
std::vector<std::unique_ptr<Drawable::DrawSegment>> segments;
|
||||
|
||||
AttributeDataType rawVerticesType = static_cast<AttributeDataType>(-1);
|
||||
gfx::ColorMode colorMode = gfx::ColorMode::disabled();
|
||||
gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled();
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#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_buffer_gl.hpp>
|
||||
#include <mbgl/gl/texture2d.hpp>
|
||||
#include <mbgl/shaders/gl/shader_program_gl.hpp>
|
||||
@@ -472,9 +473,9 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t
|
||||
}
|
||||
|
||||
gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) {
|
||||
std::vector<std::string> emptyAttributes(0);
|
||||
std::vector<std::string> emptyProperties(0);
|
||||
return std::static_pointer_cast<gfx::ShaderProgramBase>(
|
||||
shaders.getShaderGroup(name)->getOrCreateShader(*this, emptyAttributes));
|
||||
shaders.getShaderGroup(name)->getOrCreateShader(*this, emptyProperties));
|
||||
}
|
||||
|
||||
TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) {
|
||||
@@ -488,6 +489,22 @@ LayerGroupPtr Context::createLayerGroup(int32_t layerIndex, std::size_t initialC
|
||||
gfx::Texture2DPtr Context::createTexture2D() {
|
||||
return std::make_shared<gl::Texture2D>(*this);
|
||||
}
|
||||
|
||||
RenderTargetPtr Context::createRenderTarget(const Size size, const gfx::TextureChannelDataType type) {
|
||||
return std::make_shared<gl::RenderTargetGL>(*this, size, type);
|
||||
}
|
||||
|
||||
UniqueFramebuffer Context::createFramebuffer(const gfx::Texture2D& color) {
|
||||
auto fbo = createFramebuffer();
|
||||
bindFramebuffer = fbo;
|
||||
MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D,
|
||||
static_cast<const gl::Texture2D&>(color).getTextureID(),
|
||||
0));
|
||||
checkFramebuffer();
|
||||
return fbo;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Context::clear(std::optional<mbgl::Color> color, std::optional<float> depth, std::optional<int32_t> stencil) {
|
||||
|
||||
@@ -118,6 +118,10 @@ public:
|
||||
LayerGroupPtr createLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) override;
|
||||
|
||||
gfx::Texture2DPtr createTexture2D() override;
|
||||
|
||||
RenderTargetPtr createRenderTarget(const Size size, const gfx::TextureChannelDataType type) override;
|
||||
|
||||
UniqueFramebuffer createFramebuffer(const gfx::Texture2D& color);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
@@ -47,7 +47,7 @@ void DrawableGL::draw(const PaintParameters& parameters) const {
|
||||
context.setStencilMode(gfx::StencilMode::disabled());
|
||||
}
|
||||
|
||||
context.setColorMode(parameters.colorModeForRenderPass());
|
||||
context.setColorMode(getColorMode());
|
||||
context.setCullFaceMode(getCullFaceMode());
|
||||
|
||||
bindUniformBuffers();
|
||||
|
||||
85
src/mbgl/gl/render_target_gl.cpp
Normal file
85
src/mbgl/gl/render_target_gl.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <mbgl/gl/render_target_gl.hpp>
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/gl/defines.hpp>
|
||||
#include <mbgl/gl/framebuffer.hpp>
|
||||
#include <mbgl/platform/gl_functions.hpp>
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_orchestrator.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gl {
|
||||
|
||||
using namespace platform;
|
||||
|
||||
RenderTargetGL::RenderTargetGL(Context& context, const Size size, const gfx::TextureChannelDataType type)
|
||||
: glContext(context) {
|
||||
texture = glContext.createTexture2D();
|
||||
texture->setSize(size);
|
||||
texture->setFormat(gfx::TexturePixelType::RGBA, type);
|
||||
texture->setSamplerConfiguration(
|
||||
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
|
||||
}
|
||||
|
||||
RenderTargetGL::~RenderTargetGL() {
|
||||
if (framebuffer) {
|
||||
MBGL_CHECK_ERROR(glDeleteFramebuffers(1, &framebuffer->get()));
|
||||
framebuffer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTargetGL::upload(gfx::UploadPass& uploadPass) {
|
||||
observeLayerGroups(([&](LayerGroupBase& layerGroup) { layerGroup.upload(uploadPass); }));
|
||||
}
|
||||
|
||||
void RenderTargetGL::render(RenderOrchestrator& orchestrator,
|
||||
const RenderTree& renderTree,
|
||||
PaintParameters& parameters) {
|
||||
texture->create();
|
||||
if (!framebuffer) {
|
||||
framebuffer = std::make_shared<UniqueFramebuffer>(glContext.createFramebuffer(*texture));
|
||||
}
|
||||
|
||||
glContext.bindFramebuffer = *framebuffer;
|
||||
glContext.activeTextureUnit = 0;
|
||||
glContext.scissorTest = false;
|
||||
glContext.viewport = {0, 0, texture->getSize()};
|
||||
glContext.clear(Color{0.0f, 0.0f, 0.0f, 1.0f}, {}, {});
|
||||
|
||||
// Run layer tweakers to update any dynamic elements
|
||||
observeLayerGroups([&](LayerGroupBase& layerGroup) {
|
||||
if (layerGroup.getLayerTweaker()) {
|
||||
layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters);
|
||||
}
|
||||
});
|
||||
|
||||
// draw layer groups, opaque pass
|
||||
parameters.pass = RenderPass::Opaque;
|
||||
parameters.currentLayer = 0;
|
||||
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
|
||||
|
||||
observeLayerGroups([&](LayerGroupBase& layerGroup) {
|
||||
layerGroup.render(orchestrator, parameters);
|
||||
parameters.currentLayer++;
|
||||
});
|
||||
|
||||
// draw layer groups, translucent pass
|
||||
parameters.pass = RenderPass::Translucent;
|
||||
parameters.currentLayer = static_cast<int32_t>(numLayerGroups()) - 1;
|
||||
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
|
||||
|
||||
observeLayerGroups([&](LayerGroupBase& layerGroup) {
|
||||
layerGroup.render(orchestrator, parameters);
|
||||
if (parameters.currentLayer != 0) {
|
||||
parameters.currentLayer--;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
@@ -104,6 +104,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
|
||||
shaders::BuiltIn::LineGradientShader,
|
||||
shaders::BuiltIn::FillOutlinePatternShader,
|
||||
shaders::BuiltIn::FillPatternShader,
|
||||
shaders::BuiltIn::HeatmapShader,
|
||||
shaders::BuiltIn::HeatmapTextureShader,
|
||||
shaders::BuiltIn::RasterShader,
|
||||
shaders::BuiltIn::SymbolIconShader,
|
||||
shaders::BuiltIn::SymbolSDFTextShader,
|
||||
|
||||
@@ -93,7 +93,7 @@ void Texture2D::createStorage(const void* data) noexcept {
|
||||
context.pixelStoreUnpack = {1};
|
||||
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
Enum<gfx::TexturePixelType>::to(pixelFormat),
|
||||
Enum<gfx::TexturePixelType>::sizedFor(pixelFormat, channelType),
|
||||
size.width,
|
||||
size.height,
|
||||
0,
|
||||
@@ -105,8 +105,12 @@ void Texture2D::createStorage(const void* data) noexcept {
|
||||
}
|
||||
|
||||
void Texture2D::create() noexcept {
|
||||
createObject();
|
||||
createStorage();
|
||||
if (!textureResource) {
|
||||
createObject();
|
||||
}
|
||||
if (storageDirty) {
|
||||
createStorage();
|
||||
}
|
||||
}
|
||||
|
||||
platform::GLuint Texture2D::getTextureID() const noexcept {
|
||||
|
||||
@@ -29,4 +29,18 @@ void UpdateLayerGroupIndexRequest::execute(RenderOrchestrator &orchestrator) {
|
||||
orchestrator.markLayerGroupOrderDirty();
|
||||
}
|
||||
|
||||
AddRenderTargetRequest::AddRenderTargetRequest(RenderTargetPtr renderTarget_)
|
||||
: renderTarget(std::move(renderTarget_)) {}
|
||||
|
||||
void AddRenderTargetRequest::execute(RenderOrchestrator &orchestrator) {
|
||||
orchestrator.addRenderTarget(std::move(renderTarget));
|
||||
}
|
||||
|
||||
RemoveRenderTargetRequest::RemoveRenderTargetRequest(const RenderTargetPtr &renderTarget_)
|
||||
: renderTarget(renderTarget_) {}
|
||||
|
||||
void RemoveRenderTargetRequest::execute(RenderOrchestrator &orchestrator) {
|
||||
orchestrator.removeRenderTarget(renderTarget);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
76
src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp
Normal file
76
src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <mbgl/renderer/layers/heatmap_layer_tweaker.hpp>
|
||||
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
struct alignas(16) HeatmapDrawableUBO {
|
||||
std::array<float, 4 * 4> matrix;
|
||||
float extrude_scale;
|
||||
std::array<float, 3> padding;
|
||||
};
|
||||
static_assert(sizeof(HeatmapDrawableUBO) % 16 == 0);
|
||||
|
||||
struct alignas(16) HeatmapEvaluatedPropsUBO {
|
||||
float weight;
|
||||
float radius;
|
||||
float intensity;
|
||||
float padding;
|
||||
};
|
||||
static_assert(sizeof(HeatmapEvaluatedPropsUBO) % 16 == 0);
|
||||
|
||||
static constexpr std::string_view HeatmapDrawableUBOName = "HeatmapDrawableUBO";
|
||||
static constexpr std::string_view HeatmapEvaluatedPropsUBOName = "HeatmapEvaluatedPropsUBO";
|
||||
|
||||
void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
const RenderTree& renderTree,
|
||||
const PaintParameters& parameters) {
|
||||
const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
|
||||
if (layerGroup.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
const auto label = layerGroup.getName() + "-update-uniforms";
|
||||
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
|
||||
#endif
|
||||
|
||||
if (!evaluatedPropsUniformBuffer) {
|
||||
HeatmapEvaluatedPropsUBO evaluatedPropsUBO = {
|
||||
/* .weight = */ evaluated.get<HeatmapWeight>().constantOr(HeatmapWeight::defaultValue()),
|
||||
/* .radius = */ evaluated.get<HeatmapRadius>().constantOr(HeatmapRadius::defaultValue()),
|
||||
/* .intensity = */ evaluated.get<HeatmapIntensity>(),
|
||||
/* .padding = */ 0};
|
||||
evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO,
|
||||
sizeof(evaluatedPropsUBO));
|
||||
}
|
||||
|
||||
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
|
||||
drawable.mutableUniformBuffers().addOrReplace(HeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer);
|
||||
|
||||
if (!drawable.getTileID()) {
|
||||
return;
|
||||
}
|
||||
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
|
||||
const auto matrix = getTileMatrix(
|
||||
tileID, renderTree, parameters.state, {0.f, 0.f}, TranslateAnchorType::Viewport, false);
|
||||
HeatmapDrawableUBO drawableUBO = {
|
||||
/* .matrix = */ util::cast<float>(matrix),
|
||||
/* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())),
|
||||
/* .padding = */ {0}};
|
||||
|
||||
drawable.mutableUniformBuffers().createOrUpdate(HeatmapDrawableUBOName, &drawableUBO, parameters.context);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
25
src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp
Normal file
25
src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
Heatmap layer specific tweaker
|
||||
*/
|
||||
class HeatmapLayerTweaker : public LayerTweaker {
|
||||
public:
|
||||
HeatmapLayerTweaker(Immutable<style::LayerProperties> properties)
|
||||
: LayerTweaker(properties){};
|
||||
|
||||
public:
|
||||
~HeatmapLayerTweaker() override = default;
|
||||
|
||||
void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
gfx::UniformBufferPtr paintParamsUniformBuffer;
|
||||
gfx::UniformBufferPtr evaluatedPropsUniformBuffer;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
55
src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp
Normal file
55
src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp>
|
||||
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
struct alignas(16) HeatmapTextureDrawableUBO {
|
||||
std::array<float, 4 * 4> matrix;
|
||||
std::array<float, 2> world;
|
||||
float opacity;
|
||||
float padding;
|
||||
};
|
||||
static_assert(sizeof(HeatmapTextureDrawableUBO) % 16 == 0);
|
||||
|
||||
static constexpr std::string_view HeatmapTextureDrawableUBOName = "HeatmapTextureDrawableUBO";
|
||||
|
||||
void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
const PaintParameters& parameters) {
|
||||
const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
|
||||
if (layerGroup.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
const auto label = layerGroup.getName() + "-update-uniforms";
|
||||
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
|
||||
#endif
|
||||
|
||||
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
|
||||
const auto& size = parameters.staticData.backendSize;
|
||||
mat4 viewportMat;
|
||||
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);
|
||||
HeatmapTextureDrawableUBO drawableUBO = {
|
||||
/* .matrix = */ util::cast<float>(viewportMat),
|
||||
/* .world = */ {static_cast<float>(size.width), static_cast<float>(size.height)},
|
||||
/* .opacity = */ evaluated.get<HeatmapOpacity>(),
|
||||
/* .padding = */ 0};
|
||||
|
||||
drawable.mutableUniformBuffers().createOrUpdate(
|
||||
HeatmapTextureDrawableUBOName, &drawableUBO, parameters.context);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
23
src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp
Normal file
23
src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
Heatmap texture layer specific tweaker
|
||||
*/
|
||||
class HeatmapTextureLayerTweaker : public LayerTweaker {
|
||||
public:
|
||||
HeatmapTextureLayerTweaker(Immutable<style::LayerProperties> properties)
|
||||
: LayerTweaker(properties){};
|
||||
|
||||
public:
|
||||
~HeatmapTextureLayerTweaker() override = default;
|
||||
|
||||
void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -306,6 +306,8 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
|
||||
builder->setRenderPass(drawPasses);
|
||||
builder->setShader(curShader);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
builder->setColorMode(drawPasses == RenderPass::Translucent ? gfx::ColorMode::alphaBlended()
|
||||
: gfx::ColorMode::unblended());
|
||||
}
|
||||
|
||||
auto verticesCopy = rawVertices;
|
||||
|
||||
@@ -390,6 +390,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
circleBuilder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(circleShader));
|
||||
circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
circleBuilder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
circleBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
|
||||
circleBuilder->setRenderPass(renderPass);
|
||||
|
||||
@@ -457,6 +457,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
commonInit(*builder);
|
||||
builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
builder->setColorMode(renderPass == RenderPass::Translucent ? gfx::ColorMode::alphaBlended()
|
||||
: gfx::ColorMode::unblended());
|
||||
builder->setSubLayerIndex(0);
|
||||
builder->setRenderPass(renderPass);
|
||||
fillBuilder = std::move(builder);
|
||||
@@ -467,6 +469,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
commonInit(*builder);
|
||||
builder->setLineWidth(2.0f);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
builder->setSubLayerIndex(unevaluated.get<FillOutlineColor>().isUndefined() ? 2 : 0);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
outlineBuilder = std::move(builder);
|
||||
@@ -512,6 +515,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) {
|
||||
commonInit(*builder);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
builder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
builder->setSubLayerIndex(1);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
patternBuilder = std::move(builder);
|
||||
@@ -522,6 +526,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
commonInit(*builder);
|
||||
builder->setLineWidth(2.0f);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
builder->setSubLayerIndex(2);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
outlinePatternBuilder = std::move(builder);
|
||||
|
||||
@@ -5,15 +5,25 @@
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/programs/programs.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
|
||||
#include <mbgl/geometry/feature_index.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/render_pass.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/intersection_tests.hpp>
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
#include <mbgl/renderer/layers/heatmap_layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/render_target.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/gfx/shader_group.hpp>
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
@@ -29,8 +39,9 @@ inline const HeatmapLayer::Impl& impl_cast(const Immutable<Layer::Impl>& impl) {
|
||||
|
||||
RenderHeatmapLayer::RenderHeatmapLayer(Immutable<HeatmapLayer::Impl> _impl)
|
||||
: RenderLayer(makeMutable<HeatmapLayerProperties>(std::move(_impl))),
|
||||
unevaluated(impl_cast(baseImpl).paint.untransitioned()),
|
||||
colorRamp({256, 1}) {}
|
||||
unevaluated(impl_cast(baseImpl).paint.untransitioned()) {
|
||||
colorRamp = std::make_shared<PremultipliedImage>(Size(256, 1));
|
||||
}
|
||||
|
||||
RenderHeatmapLayer::~RenderHeatmapLayer() = default;
|
||||
|
||||
@@ -47,6 +58,15 @@ void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters
|
||||
: RenderPass::None;
|
||||
properties->renderPasses = mbgl::underlying_type(passes);
|
||||
evaluatedProperties = std::move(properties);
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
if (renderTarget) {
|
||||
renderTarget->getLayerGroup(0)->setLayerTweaker(std::make_shared<HeatmapLayerTweaker>(evaluatedProperties));
|
||||
}
|
||||
if (layerGroup) {
|
||||
layerGroup->setLayerTweaker(std::make_shared<HeatmapTextureLayerTweaker>(evaluatedProperties));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RenderHeatmapLayer::hasTransition() const {
|
||||
@@ -59,7 +79,7 @@ bool RenderHeatmapLayer::hasCrossfade() const {
|
||||
|
||||
void RenderHeatmapLayer::upload(gfx::UploadPass& uploadPass) {
|
||||
if (!colorRampTexture) {
|
||||
colorRampTexture = uploadPass.createTexture(colorRamp, gfx::TextureChannelDataType::UnsignedByte);
|
||||
colorRampTexture = uploadPass.createTexture(*colorRamp, gfx::TextureChannelDataType::UnsignedByte);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,14 +200,14 @@ void RenderHeatmapLayer::updateColorRamp() {
|
||||
colorValue = HeatmapLayer::getDefaultHeatmapColor();
|
||||
}
|
||||
|
||||
const auto length = colorRamp.bytes();
|
||||
const auto length = (*colorRamp).bytes();
|
||||
|
||||
for (uint32_t i = 0; i < length; i += 4) {
|
||||
const auto color = colorValue.evaluate(static_cast<double>(i) / length);
|
||||
colorRamp.data[i + 0] = static_cast<uint8_t>(std::floor(color.r * 255.f));
|
||||
colorRamp.data[i + 1] = static_cast<uint8_t>(std::floor(color.g * 255.f));
|
||||
colorRamp.data[i + 2] = static_cast<uint8_t>(std::floor(color.b * 255.f));
|
||||
colorRamp.data[i + 3] = static_cast<uint8_t>(std::floor(color.a * 255.f));
|
||||
(*colorRamp).data[i + 0] = static_cast<uint8_t>(std::floor(color.r * 255.f));
|
||||
(*colorRamp).data[i + 1] = static_cast<uint8_t>(std::floor(color.g * 255.f));
|
||||
(*colorRamp).data[i + 2] = static_cast<uint8_t>(std::floor(color.b * 255.f));
|
||||
(*colorRamp).data[i + 3] = static_cast<uint8_t>(std::floor(color.a * 255.f));
|
||||
}
|
||||
|
||||
if (colorRampTexture) {
|
||||
@@ -209,4 +229,266 @@ bool RenderHeatmapLayer::queryIntersectsFeature(const GeometryCoordinates& query
|
||||
return false;
|
||||
}
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
void activateRenderTarget(const RenderTargetPtr& renderTarget_, bool activate, UniqueChangeRequestVec& changes) {
|
||||
if (renderTarget_) {
|
||||
if (activate) {
|
||||
// The RenderTree has determined this render target should be included in the renderable set for a frame
|
||||
changes.emplace_back(std::make_unique<AddRenderTargetRequest>(renderTarget_));
|
||||
} else {
|
||||
// The RenderTree is informing us we should not render anything
|
||||
changes.emplace_back(std::make_unique<RemoveRenderTargetRequest>(renderTarget_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderHeatmapLayer::markLayerRenderable(bool willRender, UniqueChangeRequestVec& changes) {
|
||||
RenderLayer::markLayerRenderable(willRender, changes);
|
||||
activateRenderTarget(renderTarget, willRender, changes);
|
||||
}
|
||||
|
||||
void RenderHeatmapLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) {
|
||||
auto* tileLayerGroup = static_cast<TileLayerGroup*>(renderTarget->getLayerGroup(0).get());
|
||||
stats.drawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size();
|
||||
}
|
||||
|
||||
void RenderHeatmapLayer::removeAllDrawables() {
|
||||
RenderLayer::removeAllDrawables();
|
||||
if (renderTarget) {
|
||||
stats.drawablesRemoved += renderTarget->getLayerGroup(0)->getDrawableCount();
|
||||
renderTarget->getLayerGroup(0)->clearDrawables();
|
||||
}
|
||||
}
|
||||
|
||||
struct alignas(16) HeatmapInterpolateUBO {
|
||||
float weight_t;
|
||||
float radius_t;
|
||||
std::array<float, 2> padding;
|
||||
};
|
||||
static_assert(sizeof(HeatmapInterpolateUBO) % 16 == 0);
|
||||
|
||||
static const std::string HeatmapShaderGroupName = "HeatmapShader";
|
||||
static const std::string HeatmapTextureShaderGroupName = "HeatmapTextureShader";
|
||||
static constexpr std::string_view HeatmapInterpolateUBOName = "HeatmapInterpolateUBO";
|
||||
|
||||
void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
const TransformState& state,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
[[maybe_unused]] UniqueChangeRequestVec& changes) {
|
||||
std::unique_lock<std::mutex> guard(mutex);
|
||||
|
||||
if (!renderTiles || renderTiles->empty()) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& viewportSize = state.getSize();
|
||||
const auto size = Size{viewportSize.width / 2, viewportSize.height / 2};
|
||||
|
||||
// Set up a render target
|
||||
if (!renderTarget) {
|
||||
renderTarget = context.createRenderTarget(size, gfx::TextureChannelDataType::HalfFloat);
|
||||
if (!renderTarget) {
|
||||
return;
|
||||
}
|
||||
activateRenderTarget(renderTarget, isRenderable, changes);
|
||||
|
||||
// Set up tile layer group
|
||||
auto tileLayerGroup = context.createTileLayerGroup(0, /*initialCapacity=*/64, getID());
|
||||
if (!tileLayerGroup) {
|
||||
return;
|
||||
}
|
||||
tileLayerGroup->setLayerTweaker(std::make_shared<HeatmapLayerTweaker>(evaluatedProperties));
|
||||
renderTarget->addLayerGroup(tileLayerGroup, /*canReplace=*/true);
|
||||
}
|
||||
|
||||
if (renderTarget->getTexture()->getSize() != size) {
|
||||
renderTarget->getTexture()->setSize(size);
|
||||
}
|
||||
|
||||
auto* tileLayerGroup = static_cast<TileLayerGroup*>(renderTarget->getLayerGroup(0).get());
|
||||
|
||||
if (!heatmapShaderGroup) {
|
||||
heatmapShaderGroup = shaders.getShaderGroup(HeatmapShaderGroupName);
|
||||
}
|
||||
if (!heatmapShaderGroup) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
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> heatmapBuilder;
|
||||
std::vector<gfx::DrawablePtr> newTiles;
|
||||
gfx::VertexAttributeArray heatmapVertexAttrs;
|
||||
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.drawablesRemoved;
|
||||
}
|
||||
});
|
||||
|
||||
const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
|
||||
for (const RenderTile& tile : *renderTiles) {
|
||||
const auto& tileID = tile.getOverscaledTileID();
|
||||
|
||||
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
|
||||
if (!renderData) {
|
||||
removeTile(renderPass, tileID);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& bucket = static_cast<HeatmapBucket&>(*renderData->bucket);
|
||||
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
|
||||
|
||||
float zoom = static_cast<float>(state.getZoom());
|
||||
const HeatmapInterpolateUBO interpolateUBO = {
|
||||
/* .weight_t = */ std::get<0>(paintPropertyBinders.get<HeatmapWeight>()->interpolationFactor(zoom)),
|
||||
/* .radius_t = */ std::get<0>(paintPropertyBinders.get<HeatmapRadius>()->interpolationFactor(zoom)),
|
||||
/* .padding = */ {0}};
|
||||
|
||||
tileLayerGroup->observeDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) {
|
||||
drawable.mutableUniformBuffers().createOrUpdate(HeatmapInterpolateUBOName, &interpolateUBO, context);
|
||||
});
|
||||
|
||||
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
heatmapVertexAttrs.clear();
|
||||
|
||||
auto propertiesAsUniforms = heatmapVertexAttrs.readDataDrivenPaintProperties<HeatmapWeight, HeatmapRadius>(
|
||||
paintPropertyBinders, evaluated);
|
||||
|
||||
auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
|
||||
if (!heatmapShader) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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; });
|
||||
}
|
||||
};
|
||||
|
||||
heatmapBuilder = context.createDrawableBuilder("heatmap");
|
||||
heatmapBuilder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(heatmapShader));
|
||||
heatmapBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
heatmapBuilder->setColorMode(gfx::ColorMode::additive());
|
||||
heatmapBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
|
||||
heatmapBuilder->setRenderPass(renderPass);
|
||||
heatmapBuilder->setVertexAttributes(heatmapVertexAttrs);
|
||||
|
||||
buildVertices();
|
||||
heatmapBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
heatmapBuilder->setSegments(
|
||||
gfx::Triangles(), bucket.triangles.vector(), bucket.segments.data(), bucket.segments.size());
|
||||
|
||||
heatmapBuilder->flush();
|
||||
|
||||
for (auto& drawable : heatmapBuilder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
drawable->mutableUniformBuffers().createOrUpdate(HeatmapInterpolateUBOName, &interpolateUBO, context);
|
||||
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.drawablesAdded;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up texture layer group
|
||||
if (!layerGroup) {
|
||||
auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID());
|
||||
if (!layerGroup_) {
|
||||
return;
|
||||
}
|
||||
layerGroup_->setLayerTweaker(std::make_shared<HeatmapTextureLayerTweaker>(evaluatedProperties));
|
||||
setLayerGroup(std::move(layerGroup_), changes);
|
||||
}
|
||||
|
||||
auto* textureLayerGroup = static_cast<LayerGroup*>(layerGroup.get());
|
||||
|
||||
if (!heatmapTextureShader) {
|
||||
heatmapTextureShader = context.getGenericShader(shaders, HeatmapTextureShaderGroupName);
|
||||
}
|
||||
if (!heatmapTextureShader) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
textureLayerGroup->clearDrawables();
|
||||
|
||||
std::unique_ptr<gfx::DrawableBuilder> heatmapTextureBuilder;
|
||||
|
||||
std::vector<std::array<int16_t, 2>> textureRawVerts;
|
||||
const auto buildTextureVertices = [&]() {
|
||||
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex> verts =
|
||||
RenderStaticData::heatmapTextureVertices().vector();
|
||||
if (textureRawVerts.size() < verts.size()) {
|
||||
textureRawVerts.resize(verts.size());
|
||||
std::transform(verts.begin(), verts.end(), textureRawVerts.begin(), [](const auto& x) { return x.a1; });
|
||||
}
|
||||
};
|
||||
|
||||
heatmapTextureBuilder = context.createDrawableBuilder("heatmapTexture");
|
||||
heatmapTextureBuilder->setShader(heatmapTextureShader);
|
||||
heatmapTextureBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
heatmapTextureBuilder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
heatmapTextureBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
|
||||
heatmapTextureBuilder->setRenderPass(renderPass);
|
||||
|
||||
buildTextureVertices();
|
||||
heatmapTextureBuilder->addVertices(textureRawVerts, 0, textureRawVerts.size());
|
||||
|
||||
if (segments.empty()) {
|
||||
segments = RenderStaticData::heatmapTextureSegments();
|
||||
}
|
||||
|
||||
heatmapTextureBuilder->setSegments(
|
||||
gfx::Triangles(), RenderStaticData::quadTriangleIndices().vector(), segments.data(), segments.size());
|
||||
|
||||
auto imageLocation = heatmapTextureShader->getSamplerLocation("u_image");
|
||||
if (imageLocation.has_value()) {
|
||||
heatmapTextureBuilder->setTexture(renderTarget->getTexture(), imageLocation.value());
|
||||
}
|
||||
auto colorRampLocation = heatmapTextureShader->getSamplerLocation("u_color_ramp");
|
||||
if (colorRampLocation.has_value()) {
|
||||
std::shared_ptr<gfx::Texture2D> texture = context.createTexture2D();
|
||||
texture->setImage(colorRamp);
|
||||
texture->setSamplerConfiguration(
|
||||
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
|
||||
heatmapTextureBuilder->setTexture(texture, colorRampLocation.value());
|
||||
}
|
||||
|
||||
heatmapTextureBuilder->flush();
|
||||
|
||||
for (auto& drawable : heatmapTextureBuilder->clearDrawables()) {
|
||||
textureLayerGroup->addDrawable(std::move(drawable));
|
||||
++stats.drawablesAdded;
|
||||
}
|
||||
}
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -16,6 +16,17 @@ public:
|
||||
explicit RenderHeatmapLayer(Immutable<style::HeatmapLayer::Impl>);
|
||||
~RenderHeatmapLayer() override;
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
void markLayerRenderable(bool willRender, UniqueChangeRequestVec& changes) override;
|
||||
|
||||
/// Generate any changes needed by the layer
|
||||
void update(gfx::ShaderRegistry&,
|
||||
gfx::Context&,
|
||||
const TransformState&,
|
||||
const RenderTree&,
|
||||
UniqueChangeRequestVec&) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void transition(const TransitionParameters&) override;
|
||||
void evaluate(const PropertyEvaluationParameters&) override;
|
||||
@@ -36,9 +47,17 @@ private:
|
||||
const FeatureState&) const override;
|
||||
void updateColorRamp();
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
/// Remove all drawables for the tile from the layer group
|
||||
void removeTile(RenderPass, const OverscaledTileID&) override;
|
||||
|
||||
/// Remove all the drawables for tiles
|
||||
void removeAllDrawables() override;
|
||||
#endif
|
||||
|
||||
// Paint properties
|
||||
style::HeatmapPaintProperties::Unevaluated unevaluated;
|
||||
PremultipliedImage colorRamp;
|
||||
std::shared_ptr<PremultipliedImage> colorRamp;
|
||||
std::unique_ptr<gfx::OffscreenTexture> renderTexture;
|
||||
std::optional<gfx::Texture> colorRampTexture;
|
||||
SegmentVector<HeatmapTextureAttributes> segments;
|
||||
@@ -48,6 +67,12 @@ private:
|
||||
std::shared_ptr<HeatmapProgram> heatmapProgram;
|
||||
std::shared_ptr<HeatmapTextureProgram> heatmapTextureProgram;
|
||||
#endif
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
gfx::ShaderGroupPtr heatmapShaderGroup;
|
||||
gfx::ShaderProgramBasePtr heatmapTextureShader;
|
||||
RenderTargetPtr renderTarget;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -466,6 +466,8 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
|
||||
builder->setRenderPass(renderPass);
|
||||
builder->setSubLayerIndex(0);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setColorMode(renderPass == RenderPass::Translucent ? gfx::ColorMode::alphaBlended()
|
||||
: gfx::ColorMode::unblended());
|
||||
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder->setNeedsStencil(true);
|
||||
builder->setVertexAttrName("a_pos_normal");
|
||||
|
||||
@@ -260,6 +260,7 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
|
||||
builder->setSubLayerIndex(0);
|
||||
builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
builder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder->setVertexAttrName("a_pos");
|
||||
|
||||
|
||||
@@ -1003,7 +1003,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
builder->setRenderPass(passes);
|
||||
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder->setColorMode(passes == RenderPass::Translucent ? gfx::ColorMode::alphaBlended()
|
||||
: gfx::ColorMode::unblended());
|
||||
builder->setVertexAttrName(posOffsetAttribName);
|
||||
}
|
||||
|
||||
|
||||
@@ -197,10 +197,10 @@ protected:
|
||||
void activateLayerGroup(const LayerGroupBasePtr&, bool activate, UniqueChangeRequestVec& changes);
|
||||
|
||||
/// Remove all drawables for the tile from the layer group
|
||||
void removeTile(RenderPass, const OverscaledTileID&);
|
||||
virtual void removeTile(RenderPass, const OverscaledTileID&);
|
||||
|
||||
/// Remove all the drawables for tiles
|
||||
void removeAllDrawables();
|
||||
virtual void removeAllDrawables();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@@ -897,6 +897,38 @@ void RenderOrchestrator::processChanges() {
|
||||
void RenderOrchestrator::markLayerGroupOrderDirty() {
|
||||
layerGroupOrderDirty = true;
|
||||
}
|
||||
|
||||
bool RenderOrchestrator::addRenderTarget(RenderTargetPtr renderTarget) {
|
||||
auto it = std::find(renderTargets.begin(), renderTargets.end(), renderTarget);
|
||||
if (it == renderTargets.end()) {
|
||||
renderTargets.emplace_back(renderTarget);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderOrchestrator::removeRenderTarget(const RenderTargetPtr& renderTarget) {
|
||||
auto it = std::find(renderTargets.begin(), renderTargets.end(), renderTarget);
|
||||
if (it != renderTargets.end()) {
|
||||
renderTargets.erase(it);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderOrchestrator::observeRenderTargets(std::function<void(RenderTarget&)> f) {
|
||||
for (auto& renderTarget : renderTargets) {
|
||||
f(*renderTarget);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderOrchestrator::observeRenderTargets(std::function<void(const RenderTarget&)> f) const {
|
||||
for (const auto& renderTarget : renderTargets) {
|
||||
f(*renderTarget);
|
||||
}
|
||||
}
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
|
||||
void RenderOrchestrator::onGlyphsError(const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
|
||||
|
||||
@@ -116,6 +116,11 @@ public:
|
||||
void processChanges();
|
||||
/// @brief Indicate that the orchestrator needs to re-sort layer groups when processing changes
|
||||
void markLayerGroupOrderDirty();
|
||||
|
||||
bool addRenderTarget(RenderTargetPtr);
|
||||
bool removeRenderTarget(const RenderTargetPtr&);
|
||||
void observeRenderTargets(std::function<void(RenderTarget&)> f);
|
||||
void observeRenderTargets(std::function<void(const RenderTarget&)> f) const;
|
||||
#endif
|
||||
|
||||
const ZoomHistory& getZoomHistory() const { return zoomHistory; }
|
||||
@@ -195,6 +200,8 @@ private:
|
||||
using LayerGroupMap = std::map<int32_t, LayerGroupBasePtr>;
|
||||
LayerGroupMap layerGroupsByLayerIndex;
|
||||
bool layerGroupOrderDirty = false;
|
||||
|
||||
std::vector<RenderTargetPtr> renderTargets;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ gfx::IndexVector<gfx::Triangles> RenderStaticData::quadTriangleIndices() {
|
||||
return result;
|
||||
}
|
||||
|
||||
static gfx::IndexVector<gfx::LineStrip> tileLineStripIndices() {
|
||||
gfx::IndexVector<gfx::LineStrip> RenderStaticData::tileLineStripIndices() {
|
||||
gfx::IndexVector<gfx::LineStrip> result;
|
||||
result.emplace_back(0);
|
||||
result.emplace_back(1);
|
||||
@@ -31,7 +31,7 @@ static gfx::IndexVector<gfx::LineStrip> tileLineStripIndices() {
|
||||
return result;
|
||||
}
|
||||
|
||||
static gfx::VertexVector<RasterLayoutVertex> rasterVertices() {
|
||||
gfx::VertexVector<RasterLayoutVertex> RenderStaticData::rasterVertices() {
|
||||
gfx::VertexVector<RasterLayoutVertex> result;
|
||||
result.emplace_back(RasterProgram::layoutVertex({0, 0}, {0, 0}));
|
||||
result.emplace_back(RasterProgram::layoutVertex({util::EXTENT, 0}, {util::EXTENT, 0}));
|
||||
@@ -40,7 +40,7 @@ static gfx::VertexVector<RasterLayoutVertex> rasterVertices() {
|
||||
return result;
|
||||
}
|
||||
|
||||
static gfx::VertexVector<HeatmapTextureLayoutVertex> heatmapTextureVertices() {
|
||||
gfx::VertexVector<HeatmapTextureLayoutVertex> RenderStaticData::heatmapTextureVertices() {
|
||||
gfx::VertexVector<HeatmapTextureLayoutVertex> result;
|
||||
result.emplace_back(HeatmapTextureProgram::layoutVertex({0, 0}));
|
||||
result.emplace_back(HeatmapTextureProgram::layoutVertex({1, 0}));
|
||||
|
||||
@@ -31,14 +31,17 @@ public:
|
||||
std::optional<gfx::IndexBuffer> quadTriangleIndexBuffer;
|
||||
std::optional<gfx::IndexBuffer> tileBorderIndexBuffer;
|
||||
|
||||
static gfx::VertexVector<gfx::Vertex<PositionOnlyLayoutAttributes>> tileVertices();
|
||||
static gfx::IndexVector<gfx::Triangles> quadTriangleIndices();
|
||||
static gfx::IndexVector<gfx::LineStrip> tileLineStripIndices();
|
||||
static gfx::VertexVector<RasterLayoutVertex> rasterVertices();
|
||||
static gfx::VertexVector<HeatmapTextureLayoutVertex> heatmapTextureVertices();
|
||||
|
||||
static SegmentVector<BackgroundAttributes> tileTriangleSegments();
|
||||
static SegmentVector<DebugAttributes> tileBorderSegments();
|
||||
static SegmentVector<RasterAttributes> rasterSegments();
|
||||
static SegmentVector<HeatmapTextureAttributes> heatmapTextureSegments();
|
||||
|
||||
static gfx::IndexVector<gfx::Triangles> quadTriangleIndices();
|
||||
static gfx::VertexVector<gfx::Vertex<PositionOnlyLayoutAttributes>> tileVertices();
|
||||
|
||||
std::optional<gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>> depthRenderbuffer;
|
||||
bool has3D = false;
|
||||
bool uploaded = false;
|
||||
|
||||
63
src/mbgl/renderer/render_target.cpp
Normal file
63
src/mbgl/renderer/render_target.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <mbgl/renderer/render_target.hpp>
|
||||
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
bool RenderTarget::addLayerGroup(LayerGroupBasePtr layerGroup, const bool replace) {
|
||||
const auto index = layerGroup->getLayerIndex();
|
||||
const auto result = layerGroupsByLayerIndex.insert(std::make_pair(index, LayerGroupBasePtr{}));
|
||||
if (result.second) {
|
||||
// added
|
||||
result.first->second = std::move(layerGroup);
|
||||
return true;
|
||||
} else {
|
||||
// not added
|
||||
if (replace) {
|
||||
result.first->second = std::move(layerGroup);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderTarget::removeLayerGroup(const int32_t layerIndex) {
|
||||
const auto hit = layerGroupsByLayerIndex.find(layerIndex);
|
||||
if (hit != layerGroupsByLayerIndex.end()) {
|
||||
layerGroupsByLayerIndex.erase(hit);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
size_t RenderTarget::numLayerGroups() const noexcept {
|
||||
return layerGroupsByLayerIndex.size();
|
||||
}
|
||||
|
||||
static const LayerGroupBasePtr no_group;
|
||||
|
||||
const LayerGroupBasePtr& RenderTarget::getLayerGroup(const int32_t layerIndex) const {
|
||||
const auto hit = layerGroupsByLayerIndex.find(layerIndex);
|
||||
return (hit == layerGroupsByLayerIndex.end()) ? no_group : hit->second;
|
||||
}
|
||||
|
||||
void RenderTarget::observeLayerGroups(std::function<void(LayerGroupBase&)> f) {
|
||||
for (auto& pair : layerGroupsByLayerIndex) {
|
||||
if (pair.second) {
|
||||
f(*pair.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTarget::observeLayerGroups(std::function<void(const LayerGroupBase&)> f) const {
|
||||
for (const auto& pair : layerGroupsByLayerIndex) {
|
||||
if (pair.second) {
|
||||
f(*pair.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <mbgl/gfx/drawable_tweaker.hpp>
|
||||
#include <mbgl/gl/drawable_gl.hpp>
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/render_target.hpp>
|
||||
#include <mbgl/shaders/gl/shader_program_gl.hpp>
|
||||
#endif
|
||||
|
||||
@@ -142,6 +143,9 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
// Give the layers a chance to upload
|
||||
orchestrator.observeLayerGroups([&](LayerGroupBase& layerGroup) { layerGroup.upload(*uploadPass); });
|
||||
|
||||
// Give the render targets a chance to upload
|
||||
orchestrator.observeRenderTargets([&](RenderTarget& renderTarget) { renderTarget.upload(*uploadPass); });
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -176,6 +180,12 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user