Topic/fill pass (#1225)
This commit is contained in:
committed by
Bart Louwers
parent
bffa77f98c
commit
b060abeb92
@@ -29,6 +29,7 @@ class ShaderProgramBase;
|
||||
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
|
||||
using DrawPriority = int64_t;
|
||||
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
|
||||
using Texture2DPtr = std::shared_ptr<Texture2D>;
|
||||
|
||||
class Drawable {
|
||||
public:
|
||||
@@ -104,6 +105,15 @@ public:
|
||||
/// @param location A sampler location in the shader being used with this drawable.
|
||||
void setTexture(std::shared_ptr<gfx::Texture2D> texture, int32_t location);
|
||||
|
||||
using TexSourceFunc = std::function<gfx::Texture2DPtr()>;
|
||||
|
||||
/// @brief Provide a function to get the current texture
|
||||
void setTextureSource(int32_t location, TexSourceFunc);
|
||||
const TexSourceFunc& getTextureSource(int32_t location) const;
|
||||
|
||||
/// @brief Provide all texture sources at once
|
||||
void setTextureSources(std::vector<TexSourceFunc>);
|
||||
|
||||
/// Whether the drawble should be drawn
|
||||
bool getEnabled() const { return enabled; }
|
||||
void setEnabled(bool value) { enabled = value; }
|
||||
@@ -120,8 +130,8 @@ public:
|
||||
int32_t getSubLayerIndex() const { return subLayerIndex; }
|
||||
void setSubLayerIndex(int32_t value) { subLayerIndex = value; }
|
||||
|
||||
std::optional<OverscaledTileID> getTileID() const { return tileID; }
|
||||
void setTileID(OverscaledTileID value) { tileID = value; }
|
||||
const std::optional<OverscaledTileID>& getTileID() const { return tileID; }
|
||||
void setTileID(const OverscaledTileID& value) { tileID = value; }
|
||||
|
||||
DepthMaskType getDepthType() const { return depthType; }
|
||||
void setDepthType(DepthMaskType value) { depthType = value; }
|
||||
@@ -174,6 +184,7 @@ protected:
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
Textures textures;
|
||||
std::vector<TexSourceFunc> textureSources;
|
||||
std::vector<DrawableTweakerPtr> tweakers;
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ class ShaderProgramBase;
|
||||
|
||||
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
|
||||
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
|
||||
using Texture2DPtr = std::shared_ptr<Texture2D>;
|
||||
|
||||
/**
|
||||
Base class for drawable builders, which construct Drawables from primitives
|
||||
@@ -111,7 +112,12 @@ public:
|
||||
/// @brief Attach the given texture at the given sampler location.
|
||||
/// @param texture Texture2D instance
|
||||
/// @param location A sampler location in the shader being used.
|
||||
void setTexture(const std::shared_ptr<gfx::Texture2D>& texture, int32_t location);
|
||||
void setTexture(const gfx::Texture2DPtr&, int32_t location);
|
||||
|
||||
using TexSourceFunc = std::function<gfx::Texture2DPtr()>;
|
||||
|
||||
/// @brief Provide a function to get the current texture
|
||||
void setTextureSource(int32_t location, TexSourceFunc);
|
||||
|
||||
/// Add a triangle
|
||||
void addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
|
||||
@@ -171,6 +177,7 @@ protected:
|
||||
ColorAttrMode colorAttrMode = ColorAttrMode::PerVertex;
|
||||
VertexAttributeArray vertexAttrs;
|
||||
gfx::Drawable::Textures textures;
|
||||
std::vector<TexSourceFunc> textureSources;
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
@@ -102,7 +102,8 @@ public:
|
||||
void observeDrawables(std::function<void(gfx::UniqueDrawable&)>) override;
|
||||
|
||||
/// Call the provided function for each drawable for the given tile
|
||||
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function<void(const gfx::Drawable&)>) const;
|
||||
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function<void(gfx::Drawable&)>&&);
|
||||
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function<void(const gfx::Drawable&)>&&) const;
|
||||
|
||||
std::size_t clearDrawables();
|
||||
|
||||
|
||||
@@ -46,5 +46,22 @@ void Drawable::removeTexture(int32_t location) {
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Provide a function to get the current texture
|
||||
void Drawable::setTextureSource(int32_t location, TexSourceFunc source) {
|
||||
textureSources.resize(std::max(textureSources.size(), static_cast<size_t>(location + 1)));
|
||||
textureSources[location] = std::move(source);
|
||||
}
|
||||
|
||||
static const Drawable::TexSourceFunc noSource;
|
||||
|
||||
const Drawable::TexSourceFunc& Drawable::getTextureSource(int32_t location) const {
|
||||
return (static_cast<std::size_t>(location) < textureSources.size()) ? textureSources[location] : noSource;
|
||||
}
|
||||
|
||||
/// @brief Provide all texture sources at once
|
||||
void Drawable::setTextureSources(std::vector<TexSourceFunc> sources) {
|
||||
textureSources = std::move(sources);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -50,6 +50,7 @@ void DrawableBuilder::flush() {
|
||||
draw->setCullFaceMode(impl->cullFaceMode);
|
||||
draw->setShader(shader);
|
||||
draw->setTextures(textures);
|
||||
draw->setTextureSources(textureSources);
|
||||
|
||||
if (auto drawAttrs = getVertexAttributes().clone()) {
|
||||
vertexAttrs.observeAttributes([&](const std::string& iName, const VertexAttribute& iAttr) {
|
||||
@@ -112,6 +113,11 @@ void DrawableBuilder::setTexture(const std::shared_ptr<gfx::Texture2D>& texture,
|
||||
textures.emplace_back(texture, location);
|
||||
}
|
||||
|
||||
void DrawableBuilder::setTextureSource(int32_t location, TexSourceFunc source) {
|
||||
textureSources.resize(std::max(textureSources.size(), static_cast<size_t>(location + 1)));
|
||||
textureSources[location] = std::move(source);
|
||||
}
|
||||
|
||||
void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
|
||||
const auto n = static_cast<uint16_t>(impl->vertices.elements());
|
||||
impl->vertices.emplace_back(Impl::VT({{{x0, y0}}}));
|
||||
|
||||
@@ -39,7 +39,7 @@ void DrawableGL::draw(const PaintParameters& parameters) const {
|
||||
context.setDepthMode(parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType()));
|
||||
|
||||
// force disable depth test for debugging
|
||||
// setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}});
|
||||
// context.setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}});
|
||||
|
||||
if (needsStencil && tileID) {
|
||||
context.setStencilMode(parameters.stencilModeForClipping(tileID->toUnwrapped()));
|
||||
@@ -176,6 +176,12 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) {
|
||||
};
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < textureSources.size(); ++i) {
|
||||
if (const auto& source = textureSources[i]) {
|
||||
setTexture(source(), static_cast<int32_t>(i));
|
||||
}
|
||||
}
|
||||
|
||||
const bool texturesNeedUpload = std::any_of(
|
||||
textures.begin(), textures.end(), [](const auto& tex) { return tex.texture->needsUpload(); });
|
||||
|
||||
|
||||
@@ -62,6 +62,11 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters)
|
||||
parameters.renderTileClippingMasks(tileIDs);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
const auto label = getName() + (getName().empty() ? "" : "-") + "render";
|
||||
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
|
||||
#endif
|
||||
|
||||
observeDrawables([&](gfx::Drawable& drawable) {
|
||||
if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) {
|
||||
return;
|
||||
|
||||
@@ -103,7 +103,14 @@ void TileLayerGroup::observeDrawables(std::function<void(gfx::UniqueDrawable&)>
|
||||
|
||||
void TileLayerGroup::observeDrawables(mbgl::RenderPass pass,
|
||||
const OverscaledTileID& tileID,
|
||||
std::function<void(const gfx::Drawable&)> f) const {
|
||||
std::function<void(gfx::Drawable&)>&& f) {
|
||||
const auto range = impl->tileDrawables.equal_range({pass, tileID});
|
||||
std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); });
|
||||
}
|
||||
|
||||
void TileLayerGroup::observeDrawables(mbgl::RenderPass pass,
|
||||
const OverscaledTileID& tileID,
|
||||
std::function<void(const gfx::Drawable&)>&& f) const {
|
||||
const auto range = impl->tileDrawables.equal_range({pass, tileID});
|
||||
std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); });
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mbgl/renderer/paint_property_binder.hpp>
|
||||
#include <mbgl/style/layers/fill_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -44,15 +45,6 @@ struct alignas(16) FillDrawableUBO {
|
||||
};
|
||||
static_assert(sizeof(FillDrawableUBO) == 208);
|
||||
|
||||
// move to utils, or does it already exist somewhere?
|
||||
template <typename T, std::size_t N, std::size_t M>
|
||||
auto concat(const std::array<T, N>& a1, const std::array<T, M>& a2) {
|
||||
std::array<T, N + M> result;
|
||||
std::copy(a1.cbegin(), a1.cend(), result.begin());
|
||||
std::copy(a2.cbegin(), a2.cend(), result.begin() + N);
|
||||
return result;
|
||||
}
|
||||
|
||||
void FillLayerTweaker::execute(LayerGroup& layerGroup,
|
||||
const RenderTree& renderTree,
|
||||
const PaintParameters& parameters) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_source.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/tile_render_data.hpp>
|
||||
#include <mbgl/style/expression/image.hpp>
|
||||
#include <mbgl/style/layers/fill_layer_impl.hpp>
|
||||
#include <mbgl/tile/geometry_tile.hpp>
|
||||
@@ -22,6 +23,7 @@
|
||||
#include <mbgl/util/intersection_tests.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -277,6 +279,101 @@ void RenderFillLayer::removeTile(RenderPass renderPass, const OverscaledTileID&
|
||||
stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size();
|
||||
}
|
||||
|
||||
using FloatAttr = gfx::AttributeType<float, 1>;
|
||||
using FloatPairAttr = gfx::AttributeType<float, 2>;
|
||||
using FloatPair = FloatPairAttr::Value;
|
||||
using UShortQuadAttr = gfx::AttributeType<uint16_t, 4>;
|
||||
using UShortQuad = UShortQuadAttr::Value;
|
||||
using FloatVertex = gfx::detail::VertexType<FloatAttr>;
|
||||
using FloatPairVertex = gfx::detail::VertexType<FloatPairAttr>;
|
||||
using UShortQuadVertex = gfx::detail::VertexType<UShortQuadAttr>;
|
||||
using FloatBinder = PaintPropertyBinder<float, float, mbgl::PossiblyEvaluatedPropertyValue<float>, FloatAttr>;
|
||||
using FloatPairBinder =
|
||||
PaintPropertyBinder<FloatPair, FloatPair, mbgl::PossiblyEvaluatedPropertyValue<FloatPair>, FloatPairAttr>;
|
||||
using ColorBinder = PaintPropertyBinder<Color, Color, mbgl::PossiblyEvaluatedPropertyValue<Color>, FloatPairAttr>;
|
||||
using ImageBinder = PaintPropertyBinder<style::expression::Image,
|
||||
UShortQuad,
|
||||
PossiblyEvaluatedPropertyValue<mbgl::Faded<mbgl::style::expression::Image>>,
|
||||
UShortQuadAttr,
|
||||
UShortQuadAttr>;
|
||||
|
||||
bool bindFloat(const FloatBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) {
|
||||
const auto count = binder.getVertexCount();
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const FloatVertex*>(binder.getVertexValue(i))->a1;
|
||||
const auto& from = value; // TODO: should be two different values, right?
|
||||
const auto& to = value;
|
||||
attr->set(i, util::concat(from, to));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool bindFloat(const std::unique_ptr<FloatBinder>& binder,
|
||||
gfx::VertexAttributeArray& attrs,
|
||||
std::string attributeName) {
|
||||
return binder && bindFloat(*binder, attrs, std::move(attributeName));
|
||||
}
|
||||
|
||||
bool bindFloatPair(const FloatPairBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) {
|
||||
const auto count = binder.getVertexCount();
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const FloatPairVertex*>(binder.getVertexValue(i))->a1;
|
||||
const auto& from = value; // TODO: should be two different values, right?
|
||||
const auto& to = value;
|
||||
attr->set(i, util::concat(from, to));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool bindFloatPair(const std::unique_ptr<FloatPairBinder>& binder,
|
||||
gfx::VertexAttributeArray& attrs,
|
||||
std::string attributeName) {
|
||||
return binder && bindFloatPair(*binder, attrs, std::move(attributeName));
|
||||
}
|
||||
|
||||
bool bindColor(const ColorBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) {
|
||||
const auto count = binder.getVertexCount();
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const FloatPairVertex*>(binder.getVertexValue(i))->a1;
|
||||
const auto& from = value; // TODO: should be two different values, right?
|
||||
const auto& to = value;
|
||||
attr->set(i, util::concat(from, to));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool bindColor(const std::unique_ptr<ColorBinder>& binder,
|
||||
gfx::VertexAttributeArray& attrs,
|
||||
std::string attributeName) {
|
||||
return binder && bindColor(*binder, attrs, std::move(attributeName));
|
||||
}
|
||||
|
||||
bool bindImage(const ImageBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) {
|
||||
const auto count = binder.getVertexCount();
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const UShortQuadVertex*>(binder.getVertexValue(i))->a1;
|
||||
attr->set(i, util::cast<int32_t>(value));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool bindImage(const std::unique_ptr<ImageBinder>& binder,
|
||||
gfx::VertexAttributeArray& attrs,
|
||||
std::string attributeName) {
|
||||
return binder && bindImage(*binder, attrs, std::move(attributeName));
|
||||
}
|
||||
|
||||
void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
const TransformState& /*state*/,
|
||||
@@ -329,276 +426,195 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::VertexAttributeArray patternVertexAttrs;
|
||||
gfx::VertexAttributeArray patternOutlineVertexAttrs;
|
||||
|
||||
const auto finish = [&](gfx::DrawableBuilder& builder, RenderPass pass, const OverscaledTileID& tileID) {
|
||||
constexpr auto samplerLocation = 0;
|
||||
const auto layerPrefix = getID() + "/";
|
||||
const auto renderPass = static_cast<RenderPass>(evaluatedProperties->renderPasses);
|
||||
|
||||
const auto finish = [&](gfx::DrawableBuilder& builder, const OverscaledTileID& tileID) {
|
||||
builder.flush();
|
||||
|
||||
for (auto& drawable : builder.clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
tileLayerGroup->addDrawable(pass, tileID, std::move(drawable));
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.tileDrawablesAdded;
|
||||
}
|
||||
};
|
||||
|
||||
const auto commonInit = [](gfx::DrawableBuilder& builder) {
|
||||
const auto commonInit = [&](gfx::DrawableBuilder& builder) {
|
||||
builder.setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None);
|
||||
builder.setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder.setNeedsStencil(true);
|
||||
};
|
||||
|
||||
for (const auto renderPass : {RenderPass::Opaque, RenderPass::Translucent}) {
|
||||
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
|
||||
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
|
||||
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
|
||||
const auto tileID = drawable->getTileID();
|
||||
if (drawable->getRenderPass() != renderPass || (tileID && newTileIDs.find(*tileID) == newTileIDs.end())) {
|
||||
drawable.reset();
|
||||
++stats.tileDrawablesRemoved;
|
||||
}
|
||||
});
|
||||
|
||||
for (const RenderTile& tile : *renderTiles) {
|
||||
const auto& tileID = tile.getOverscaledTileID();
|
||||
|
||||
// If we already have drawables for this tile, skip.
|
||||
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
|
||||
// Has this tile dropped out of the cover set?
|
||||
const auto tileID = drawable->getTileID();
|
||||
if (tileID && newTileIDs.find(*tileID) == newTileIDs.end()) {
|
||||
// remove it
|
||||
drawable.reset();
|
||||
++stats.tileDrawablesRemoved;
|
||||
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
|
||||
if (!renderData) {
|
||||
removeTile(renderPass, tileID);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& bucket = static_cast<FillBucket&>(*renderData->bucket);
|
||||
const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties);
|
||||
const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties);
|
||||
|
||||
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; });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
constexpr auto samplerLocation = 0;
|
||||
const auto layerPrefix = getID() + "/";
|
||||
fillVertexAttrs.clear();
|
||||
outlineVertexAttrs.clear();
|
||||
|
||||
for (const RenderTile& tile : *renderTiles) {
|
||||
const auto& tileID = tile.getOverscaledTileID();
|
||||
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
|
||||
|
||||
// If we already have drawables for this tile, skip.
|
||||
// If a drawable needs to be updated, that's handled in the layer tweaker.
|
||||
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
|
||||
if (unevaluated.get<FillPattern>().isUndefined()) {
|
||||
// Fill will occur in opaque or translucent pass based on `opaquePassCutoff`.
|
||||
// Outline always occurs in translucent pass, defaults to fill color
|
||||
const auto doOutline = evaluated.get<FillAntialias>();
|
||||
|
||||
bindColor(paintPropertyBinders.get<FillColor>(), fillVertexAttrs, "a_color");
|
||||
bindFloat(paintPropertyBinders.get<FillOpacity>(), fillVertexAttrs, "a_opacity");
|
||||
|
||||
if (doOutline) {
|
||||
bindColor(paintPropertyBinders.get<FillOutlineColor>(), outlineVertexAttrs, "a_outline_color");
|
||||
bindFloat(paintPropertyBinders.get<FillOpacity>(), outlineVertexAttrs, "a_opacity");
|
||||
}
|
||||
|
||||
if (!fillBuilder && fillShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(fillShader);
|
||||
builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
builder->setSubLayerIndex(0);
|
||||
builder->setRenderPass(renderPass);
|
||||
fillBuilder = std::move(builder);
|
||||
}
|
||||
}
|
||||
if (doOutline && !outlineBuilder && outlineShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(outlineShader);
|
||||
builder->setLineWidth(2.0f);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setSubLayerIndex(unevaluated.get<FillOutlineColor>().isUndefined() ? 2 : 0);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
outlineBuilder = std::move(builder);
|
||||
}
|
||||
}
|
||||
|
||||
if (fillBuilder) {
|
||||
buildVertices();
|
||||
fillBuilder->setVertexAttributes(fillVertexAttrs);
|
||||
fillBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
fillBuilder->setSegments(gfx::Triangles(),
|
||||
bucket.triangles.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.triangleSegments));
|
||||
finish(*fillBuilder, tileID);
|
||||
}
|
||||
if (outlineBuilder) {
|
||||
buildVertices();
|
||||
outlineBuilder->setVertexAttributes(outlineVertexAttrs);
|
||||
outlineBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
outlineBuilder->setSegments(gfx::Lines(2),
|
||||
bucket.lines.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.lineSegments));
|
||||
finish(*outlineBuilder, tileID);
|
||||
}
|
||||
} else { // FillPattern is defined
|
||||
if ((renderPass & RenderPass::Translucent) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
|
||||
if (!renderData) {
|
||||
removeTile(renderPass, tileID);
|
||||
continue;
|
||||
// Outline does not default to fill in the pattern case
|
||||
const auto doOutline = evaluated.get<FillAntialias>() && unevaluated.get<FillOutlineColor>().isUndefined();
|
||||
const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<expression::Image>{"", ""});
|
||||
const auto patternPosA = tile.getPattern(fillPatternValue.from.id());
|
||||
const auto patternPosB = tile.getPattern(fillPatternValue.to.id());
|
||||
paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade);
|
||||
|
||||
// if (samplerLocation < 0) curShader->getSamplerLocation("u_image");
|
||||
|
||||
bindFloat(paintPropertyBinders.get<FillOpacity>(), fillVertexAttrs, "a_opacity");
|
||||
bindImage(paintPropertyBinders.get<FillPattern>(), fillVertexAttrs, "a_pattern_from");
|
||||
bindImage(paintPropertyBinders.get<FillPattern>(), fillVertexAttrs, "a_pattern_to");
|
||||
|
||||
if (doOutline) {
|
||||
bindFloat(paintPropertyBinders.get<FillOpacity>(), outlineVertexAttrs, "a_opacity");
|
||||
bindImage(paintPropertyBinders.get<FillPattern>(), outlineVertexAttrs, "a_pattern_from");
|
||||
bindImage(paintPropertyBinders.get<FillPattern>(), outlineVertexAttrs, "a_pattern_to");
|
||||
}
|
||||
|
||||
auto& bucket = static_cast<FillBucket&>(*renderData->bucket);
|
||||
const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties);
|
||||
const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties);
|
||||
|
||||
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; });
|
||||
}
|
||||
};
|
||||
|
||||
fillVertexAttrs.clear();
|
||||
outlineVertexAttrs.clear();
|
||||
|
||||
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
|
||||
|
||||
if (unevaluated.get<FillPattern>().isUndefined()) {
|
||||
const auto evalColor = evaluated.get<FillColor>().constantOr(Color());
|
||||
const auto fillOpacity = evaluated.get<FillOpacity>().constantOr(0);
|
||||
const auto fillColor = evalColor * (fillOpacity > 0.0f ? fillOpacity : 1.0f);
|
||||
const auto fillRenderPass = (fillColor.a >= 1.0f
|
||||
/* && parameters.currentLayer >= parameters.opaquePassCutoff*/)
|
||||
? RenderPass::Opaque
|
||||
: RenderPass::Translucent;
|
||||
const auto doFill = fillRenderPass == renderPass;
|
||||
const auto doOutline = evaluated.get<FillAntialias>() && renderPass == RenderPass::Translucent;
|
||||
|
||||
if (!doFill && !doOutline) {
|
||||
removeTile(renderPass, tileID);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (doFill) {
|
||||
if (auto& binder = paintPropertyBinders.get<FillColor>()) {
|
||||
const auto count = binder->getVertexCount();
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = fillVertexAttrs.getOrAdd("a_color")) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& packed =
|
||||
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
|
||||
binder->getVertexValue(i))
|
||||
->a1;
|
||||
attr->set<gfx::VertexAttribute::float4>(i,
|
||||
{packed[0], packed[1], packed[0], packed[1]});
|
||||
}
|
||||
}
|
||||
if (!patternBuilder && patternShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(patternShader);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
builder->setSubLayerIndex(1);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
if (const auto& atlases = tile.getAtlasTextures()) {
|
||||
builder->setTextureSource(samplerLocation, [=]() { return atlases ? atlases->icon : nullptr; });
|
||||
}
|
||||
patternBuilder = std::move(builder);
|
||||
}
|
||||
if (doOutline) {
|
||||
if (auto& binder = paintPropertyBinders.get<FillOutlineColor>()) {
|
||||
const auto count = binder->getVertexCount();
|
||||
if (auto& attr = outlineVertexAttrs.getOrAdd("a_outline_color")) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& packed =
|
||||
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
|
||||
binder->getVertexValue(i))
|
||||
->a1;
|
||||
attr->set<gfx::VertexAttribute::float4>(i,
|
||||
{packed[0], packed[1], packed[0], packed[1]});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (auto& binder = paintPropertyBinders.get<FillOpacity>()) {
|
||||
const auto count = binder->getVertexCount();
|
||||
for (auto& attrs :
|
||||
{std::reference_wrapper(fillVertexAttrs), std::reference_wrapper(outlineVertexAttrs)}) {
|
||||
if (auto& attr = attrs.get().getOrAdd("a_opacity")) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& opacity =
|
||||
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
|
||||
binder->getVertexValue(i))
|
||||
->a1;
|
||||
attr->set<gfx::VertexAttribute::float2>(i, {opacity[0], opacity[0]});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doOutline && !outlinePatternBuilder && outlinePatternShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline-pattern")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(outlinePatternShader);
|
||||
builder->setLineWidth(2.0f);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setSubLayerIndex(2);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
if (const auto& atlases = tile.getAtlasTextures()) {
|
||||
builder->setTextureSource(samplerLocation, [=]() { return atlases ? atlases->icon : nullptr; });
|
||||
}
|
||||
outlinePatternBuilder = std::move(builder);
|
||||
}
|
||||
}
|
||||
|
||||
if (doFill && !fillBuilder && fillShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(fillShader);
|
||||
builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
builder->setSubLayerIndex(0);
|
||||
fillBuilder = std::move(builder);
|
||||
}
|
||||
}
|
||||
if (doOutline && !outlineBuilder && outlineShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(outlineShader);
|
||||
builder->setLineWidth(2.0f);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setSubLayerIndex(unevaluated.get<FillOutlineColor>().isUndefined() ? 2 : 0);
|
||||
outlineBuilder = std::move(builder);
|
||||
}
|
||||
}
|
||||
|
||||
if (fillBuilder) {
|
||||
buildVertices();
|
||||
fillBuilder->setRenderPass(renderPass);
|
||||
fillBuilder->setVertexAttributes(fillVertexAttrs);
|
||||
fillBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
fillBuilder->setSegments(
|
||||
gfx::Triangles(),
|
||||
bucket.triangles.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.triangleSegments));
|
||||
finish(*fillBuilder, renderPass, tileID);
|
||||
}
|
||||
if (outlineBuilder) {
|
||||
buildVertices();
|
||||
outlineBuilder->setRenderPass(renderPass);
|
||||
outlineBuilder->setVertexAttributes(outlineVertexAttrs);
|
||||
outlineBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
outlineBuilder->setSegments(
|
||||
gfx::Lines(2),
|
||||
bucket.lines.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.lineSegments));
|
||||
finish(*outlineBuilder, renderPass, tileID);
|
||||
}
|
||||
} else { // FillPattern is defined
|
||||
if (renderPass != RenderPass::Translucent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto doOutline = evaluated.get<FillAntialias>() &&
|
||||
unevaluated.get<FillOutlineColor>().isUndefined();
|
||||
const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(
|
||||
Faded<expression::Image>{"", ""});
|
||||
const auto patternPosA = tile.getPattern(fillPatternValue.from.id());
|
||||
const auto patternPosB = tile.getPattern(fillPatternValue.to.id());
|
||||
paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade);
|
||||
|
||||
// if (samplerLocation < 0) curShader->getSamplerLocation("u_image");
|
||||
|
||||
if (auto& binder = paintPropertyBinders.get<FillOpacity>()) {
|
||||
const auto count = binder->getVertexCount();
|
||||
for (auto& attrs : {std::reference_wrapper(patternVertexAttrs),
|
||||
std::reference_wrapper(patternOutlineVertexAttrs)}) {
|
||||
if (auto& attr = attrs.get().getOrAdd("a_opacity")) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& opacity =
|
||||
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
|
||||
binder->getVertexValue(i))
|
||||
->a1;
|
||||
attr->set<gfx::VertexAttribute::float2>(i, {opacity[0], opacity[0]});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (auto& binder = paintPropertyBinders.get<FillOpacity>()) {
|
||||
// const auto count = binder->getVertexCount();
|
||||
// for (auto& attrs :
|
||||
// {std::reference_wrapper(patternVertexAttrs),
|
||||
// std::reference_wrapper(patternOutlineVertexAttrs)}) {
|
||||
// if (auto& attr = attrs.get().getOrAdd("a_pattern_from")) {
|
||||
// for (std::size_t i = 0; i < count; ++i) {
|
||||
// const auto& opacity =
|
||||
// static_cast<const
|
||||
// gfx::detail::VertexType<gfx::AttributeType<float, 4>>*>(
|
||||
// binder->getVertexValue(i))
|
||||
// ->a1;
|
||||
// attr->set<gfx::VertexAttribute::float2>(i, {});
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!patternBuilder && patternShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(fillShader);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
builder->setSubLayerIndex(1);
|
||||
if (auto& tex = tile.getIconAtlasTexture()) {
|
||||
builder->setTexture(tex, samplerLocation);
|
||||
}
|
||||
patternBuilder = std::move(builder);
|
||||
}
|
||||
}
|
||||
if (doOutline && !outlinePatternBuilder && outlinePatternShader) {
|
||||
if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline-pattern")) {
|
||||
commonInit(*builder);
|
||||
builder->setShader(outlineShader);
|
||||
builder->setLineWidth(2.0f);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
builder->setSubLayerIndex(2);
|
||||
if (auto& tex = tile.getIconAtlasTexture()) {
|
||||
builder->setTexture(tex, samplerLocation);
|
||||
}
|
||||
outlinePatternBuilder = std::move(builder);
|
||||
}
|
||||
}
|
||||
|
||||
if (patternBuilder) {
|
||||
buildVertices();
|
||||
patternBuilder->setRenderPass(renderPass);
|
||||
patternBuilder->setVertexAttributes(fillVertexAttrs);
|
||||
patternBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
patternBuilder->setSegments(
|
||||
gfx::Triangles(),
|
||||
bucket.triangles.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.triangleSegments));
|
||||
finish(*patternBuilder, renderPass, tileID);
|
||||
}
|
||||
if (outlinePatternBuilder) {
|
||||
buildVertices();
|
||||
outlinePatternBuilder->setRenderPass(renderPass);
|
||||
outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs);
|
||||
outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
outlinePatternBuilder->setSegments(
|
||||
gfx::Lines(2),
|
||||
bucket.lines.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.lineSegments));
|
||||
finish(*outlinePatternBuilder, renderPass, tileID);
|
||||
}
|
||||
if (patternBuilder) {
|
||||
buildVertices();
|
||||
patternBuilder->setRenderPass(renderPass);
|
||||
patternBuilder->setVertexAttributes(fillVertexAttrs);
|
||||
patternBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
patternBuilder->setSegments(
|
||||
gfx::Triangles(),
|
||||
bucket.triangles.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.triangleSegments));
|
||||
finish(*patternBuilder, tileID);
|
||||
}
|
||||
if (outlinePatternBuilder) {
|
||||
buildVertices();
|
||||
outlinePatternBuilder->setRenderPass(renderPass);
|
||||
outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs);
|
||||
outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
outlinePatternBuilder->setSegments(
|
||||
gfx::Lines(2),
|
||||
bucket.lines.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.lineSegments));
|
||||
finish(*outlinePatternBuilder, tileID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,9 +222,9 @@ public:
|
||||
return constantPatternPositions;
|
||||
}
|
||||
|
||||
std::size_t getVertexCount() const override { return 0; }
|
||||
std::size_t getVertexCount() const override { return 1; }
|
||||
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t) const override {
|
||||
return nullptr; // ?
|
||||
return &constantPatternPositions;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -124,6 +124,11 @@ gfx::TextureBinding RenderTile::getIconAtlasTextureBinding(gfx::TextureFilterTyp
|
||||
return {getIconAtlasTexture()->getResource(), filter};
|
||||
}
|
||||
|
||||
static const std::shared_ptr<TileAtlasTextures> noAtlas;
|
||||
const std::shared_ptr<TileAtlasTextures>& RenderTile::getAtlasTextures() const {
|
||||
return renderData ? renderData->getAtlasTextures() : noAtlas;
|
||||
}
|
||||
|
||||
void RenderTile::upload(gfx::UploadPass& uploadPass) const {
|
||||
assert(renderData);
|
||||
renderData->upload(uploadPass);
|
||||
|
||||
@@ -27,6 +27,7 @@ class PaintParameters;
|
||||
class DebugBucket;
|
||||
class SourcePrepareParameters;
|
||||
class FeatureIndex;
|
||||
class TileAtlasTextures;
|
||||
class TileRenderData;
|
||||
|
||||
class RenderTile final {
|
||||
@@ -66,6 +67,8 @@ public:
|
||||
const gfx::Texture2DPtr& getIconAtlasTexture() const;
|
||||
gfx::TextureBinding getIconAtlasTextureBinding(gfx::TextureFilterType) const;
|
||||
|
||||
const std::shared_ptr<TileAtlasTextures>& getAtlasTextures() const;
|
||||
|
||||
void upload(gfx::UploadPass&) const;
|
||||
void prepare(const SourcePrepareParameters&);
|
||||
void finishRender(PaintParameters&) const;
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
virtual ~TileRenderData();
|
||||
const gfx::Texture2DPtr& getGlyphAtlasTexture() const;
|
||||
const gfx::Texture2DPtr& getIconAtlasTexture() const;
|
||||
const std::shared_ptr<TileAtlasTextures>& getAtlasTextures() const { return atlasTextures; }
|
||||
// To be implemented for concrete tile types.
|
||||
virtual std::optional<ImagePosition> getPattern(const std::string&) const;
|
||||
virtual const LayerRenderData* getLayerRenderData(const style::Layer::Impl&) const;
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace mbgl {
|
||||
namespace util {
|
||||
|
||||
template <typename Container, typename ForwardIterator, typename Predicate>
|
||||
void erase_if(Container &container, ForwardIterator it, Predicate pred) {
|
||||
void erase_if(Container& container, ForwardIterator it, Predicate pred) {
|
||||
while (it != container.end()) {
|
||||
if (pred(*it)) {
|
||||
it = container.erase(it);
|
||||
@@ -19,9 +19,17 @@ void erase_if(Container &container, ForwardIterator it, Predicate pred) {
|
||||
}
|
||||
|
||||
template <typename Container, typename Predicate>
|
||||
void erase_if(Container &container, Predicate pred) {
|
||||
void erase_if(Container& container, Predicate pred) {
|
||||
erase_if(container, container.begin(), pred);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N, std::size_t M>
|
||||
auto concat(const std::array<T, N>& a1, const std::array<T, M>& a2) {
|
||||
std::array<T, N + M> result;
|
||||
std::copy(a1.cbegin(), a1.cend(), result.begin());
|
||||
std::copy(a2.cbegin(), a2.cend(), result.begin() + N);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace mbgl
|
||||
|
||||
Reference in New Issue
Block a user