Topic/fill pass (#1225)

This commit is contained in:
Tim Sylvester
2023-06-09 07:23:17 -07:00
committed by Bart Louwers
parent bffa77f98c
commit b060abeb92
15 changed files with 344 additions and 259 deletions

View File

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

View File

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

View File

@@ -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();

View File

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

View File

@@ -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}}}));

View File

@@ -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(); });

View File

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

View File

@@ -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); });
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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