Files
MapLibreParticleLab/src/mbgl/gl/layer_group_gl.cpp
2025-02-28 21:49:20 +00:00

198 lines
6.2 KiB
C++

#include <mbgl/gl/layer_group_gl.hpp>
#include <mbgl/gfx/drawable_tweaker.hpp>
#include <mbgl/gfx/render_pass.hpp>
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/upload_pass.hpp>
#include <mbgl/gl/drawable_gl.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/util/instrumentation.hpp>
namespace mbgl {
namespace gl {
using namespace platform;
TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity, std::string name_)
: TileLayerGroup(layerIndex_, initialCapacity, std::move(name_)) {}
void TileLayerGroupGL::upload(gfx::UploadPass& uploadPass) {
MLN_TRACE_FUNC();
MLN_ZONE_STR(name);
if (!enabled) {
return;
}
visitDrawables([&](gfx::Drawable& drawable) {
if (!drawable.getEnabled()) {
return;
}
auto& drawableGL = static_cast<gl::DrawableGL&>(drawable);
#if !defined(NDEBUG)
std::string label;
if (const auto& tileID = drawable.getTileID()) {
label = drawable.getName() + "/" + util::toString(*tileID);
}
const auto labelPtr = (label.empty() ? drawable.getName() : label).c_str();
const auto debugGroup = uploadPass.createDebugGroup(labelPtr);
#endif
drawableGL.upload(uploadPass);
});
}
void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) {
if (!enabled) {
return;
}
MLN_TRACE_FUNC();
auto& context = static_cast<gl::Context&>(parameters.context);
// `stencilModeFor3D` uses a different stencil mask value each time its called, so if the
// drawables in this layer use 3D stencil mode, we need to set it up here so that all the
// drawables end up using the same mode value.
// 2D and 3D features in the same layer group is not supported.
bool features3d = false;
bool stencil3d = false;
gfx::StencilMode stencilMode3d;
if (getDrawableCount()) {
MLN_TRACE_ZONE(clip masks);
#if !defined(NDEBUG)
const auto label_clip = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks";
const auto debugGroupClip = parameters.encoder->createDebugGroup(label_clip.c_str());
#endif
// If we're using stencil clipping, we need to handle 3D features separately
if (stencilTiles && !stencilTiles->empty()) {
visitDrawables([&](const gfx::Drawable& drawable) {
if (drawable.getEnabled() && drawable.getIs3D() && drawable.hasRenderPass(parameters.pass)) {
features3d = true;
if (drawable.getEnableStencil()) {
stencil3d = true;
}
}
});
}
// If we're doing 3D stenciling and have any features
// to draw, set up the single-value stencil mask.
// If we're doing 2D stenciling and have any drawables with tile IDs,
// render each tile into the stencil buffer with a different value.
if (features3d) {
stencilMode3d = stencil3d ? parameters.stencilModeFor3D() : gfx::StencilMode::disabled();
} else if (stencilTiles && !stencilTiles->empty()) {
parameters.renderTileClippingMasks(stencilTiles);
}
}
#if !defined(NDEBUG)
const auto label_render = getName() + (getName().empty() ? "" : "-") + "render";
const auto debugGroupRender = parameters.encoder->createDebugGroup(label_render.c_str());
#endif
bool bindUBOs = false;
visitDrawables([&](gfx::Drawable& drawable) {
if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) {
return;
}
#if !defined(NDEBUG)
std::string label_tile;
if (const auto& tileID = drawable.getTileID()) {
label_tile = util::toString(drawable.getID().id()) + "/" + drawable.getName() + "/" +
util::toString(*tileID);
}
const auto labelPtr = (label_tile.empty() ? drawable.getName() : label_tile).c_str();
const auto debugGroupTile = parameters.encoder->createDebugGroup(labelPtr);
#endif
if (!bindUBOs) {
uniformBuffers.bind();
bindUBOs = true;
}
for (const auto& tweaker : drawable.getTweakers()) {
tweaker->execute(drawable, parameters);
}
// For layer groups with 3D features, enable either the single-value
// stencil mode for features with stencil enabled or disable stenciling.
// 2D drawables will set their own stencil mode within `draw`.
if (features3d) {
context.setStencilMode(drawable.getEnableStencil() ? stencilMode3d : gfx::StencilMode::disabled());
}
drawable.draw(parameters);
});
if (bindUBOs) {
uniformBuffers.unbind();
}
}
LayerGroupGL::LayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity, std::string name_)
: LayerGroup(layerIndex_, initialCapacity, std::move(name_)) {}
void LayerGroupGL::upload(gfx::UploadPass& uploadPass) {
if (!enabled) {
return;
}
visitDrawables([&](gfx::Drawable& drawable) {
if (!drawable.getEnabled()) {
return;
}
auto& drawableGL = static_cast<gl::DrawableGL&>(drawable);
#if !defined(NDEBUG)
const auto debugGroup = uploadPass.createDebugGroup(drawable.getName().c_str());
#endif
drawableGL.upload(uploadPass);
});
}
void LayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) {
if (!enabled) {
return;
}
bool bindUBOs = false;
visitDrawables([&](gfx::Drawable& drawable) {
if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) {
return;
}
#if !defined(NDEBUG)
const auto debugGroup = parameters.encoder->createDebugGroup(drawable.getName().c_str());
#endif
if (!bindUBOs) {
uniformBuffers.bind();
bindUBOs = true;
}
for (const auto& tweaker : drawable.getTweakers()) {
tweaker->execute(drawable, parameters);
}
drawable.draw(parameters);
});
if (bindUBOs) {
uniformBuffers.unbind();
}
}
} // namespace gl
} // namespace mbgl