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
@@ -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