Drawable Renderer (#1570), Add fill-outline drawables
This commit is contained in:
committed by
Bart Louwers
parent
c505d3077e
commit
c81c665538
@@ -66,6 +66,10 @@ public:
|
||||
return (mbgl::underlying_type(renderPass) & underlying_value) == underlying_value;
|
||||
}
|
||||
|
||||
/// Width for lines
|
||||
int32_t getLineWidth() const { return lineWidth; }
|
||||
void setLineWidth(int32_t value) { lineWidth = value; }
|
||||
|
||||
/// not used for anything yet
|
||||
DrawPriority getDrawPriority() const { return drawPriority; }
|
||||
void setDrawPriority(DrawPriority value) { drawPriority = value; }
|
||||
@@ -74,6 +78,10 @@ public:
|
||||
int32_t getLayerIndex() const { return layerIndex; }
|
||||
void setLayerIndex(int32_t value) { layerIndex = value; }
|
||||
|
||||
/// Determines depth range within the layer
|
||||
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; }
|
||||
|
||||
@@ -129,7 +137,9 @@ protected:
|
||||
mat4 matrix; //= matrix::identity4();
|
||||
std::optional<OverscaledTileID> tileID;
|
||||
DrawPriority drawPriority = 0;
|
||||
int32_t lineWidth = 1;
|
||||
int32_t layerIndex = -1;
|
||||
int32_t subLayerIndex = 0;
|
||||
DepthMaskType depthType; // = DepthMaskType::ReadOnly;
|
||||
|
||||
std::vector<DrawableTweakerPtr> tweakers;
|
||||
|
||||
@@ -61,6 +61,10 @@ public:
|
||||
int32_t getLayerIndex() const { return layerIndex; }
|
||||
void setLayerIndex(int32_t value) { layerIndex = value; }
|
||||
|
||||
/// The layer index assigned to generated drawables
|
||||
int32_t getSubLayerIndex() const { return subLayerIndex; }
|
||||
void setSubLayerIndex(int32_t value) { subLayerIndex = value; }
|
||||
|
||||
/// Set the draw priority on all drawables including those already generated
|
||||
void resetDrawPriority(DrawPriority);
|
||||
|
||||
@@ -77,6 +81,10 @@ public:
|
||||
/// This should not be changed while a build is in progress
|
||||
void setColorMode(ColorMode mode) { colorMode = mode; }
|
||||
|
||||
/// Width for lines
|
||||
int32_t getLineWidth() const { return lineWidth; }
|
||||
void setLineWidth(int32_t value) { lineWidth = value; }
|
||||
|
||||
DepthMaskType getDepthType() const { return depthType; }
|
||||
void setDepthType(DepthMaskType value) { depthType = value; }
|
||||
|
||||
@@ -150,8 +158,10 @@ protected:
|
||||
std::string vertexAttrName;
|
||||
std::string colorAttrName;
|
||||
mbgl::RenderPass renderPass;
|
||||
int32_t lineWidth = 1;
|
||||
DrawPriority drawPriority = 0;
|
||||
int32_t layerIndex = -1;
|
||||
int32_t subLayerIndex = 0;
|
||||
DepthMaskType depthType = DepthMaskType::ReadOnly;
|
||||
gfx::ShaderProgramBasePtr shader;
|
||||
mat4 matrix;
|
||||
|
||||
@@ -69,8 +69,8 @@ public:
|
||||
std::size_t getDrawableCount() const;
|
||||
|
||||
const gfx::UniqueDrawable& getDrawable(mbgl::RenderPass, const OverscaledTileID&) const;
|
||||
gfx::UniqueDrawable removeDrawable(mbgl::RenderPass, const OverscaledTileID&);
|
||||
bool addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
|
||||
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass, const OverscaledTileID&);
|
||||
void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
|
||||
|
||||
void observeDrawables(std::function<void(gfx::Drawable&)>) override;
|
||||
void observeDrawables(std::function<void(const gfx::Drawable&)>) const override;
|
||||
|
||||
@@ -33,9 +33,11 @@ const UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) {
|
||||
void DrawableBuilder::flush() {
|
||||
if (!impl->vertices.empty()) {
|
||||
const auto& draw = getCurrentDrawable(/*createIfNone=*/true);
|
||||
draw->setLineWidth(lineWidth);
|
||||
draw->setRenderPass(renderPass);
|
||||
draw->setDrawPriority(drawPriority);
|
||||
draw->setLayerIndex(layerIndex);
|
||||
draw->setSubLayerIndex(subLayerIndex);
|
||||
draw->setDepthType(depthType);
|
||||
draw->setShader(shader);
|
||||
draw->setMatrix(matrix);
|
||||
|
||||
@@ -19,7 +19,7 @@ DrawableGL::~DrawableGL() {
|
||||
|
||||
void DrawableGL::draw(const PaintParameters& parameters) const {
|
||||
bindUniformBuffers();
|
||||
impl->draw(parameters);
|
||||
impl->draw(parameters, lineWidth);
|
||||
unbindUniformBuffers();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@ public:
|
||||
Impl() = default;
|
||||
~Impl() = default;
|
||||
|
||||
void draw(const PaintParameters& parameters) const {
|
||||
void draw(const PaintParameters& parameters, int32_t lineWidth) const {
|
||||
auto& glContext = static_cast<gl::Context&>(parameters.context);
|
||||
if (!triangleIndexes.empty()) {
|
||||
glContext.draw(gfx::Triangles(), lineIndexes.size(), triangleIndexes.size());
|
||||
}
|
||||
if (!lineIndexes.empty()) {
|
||||
glContext.draw(gfx::Lines(1), 0, lineIndexes.size());
|
||||
glContext.draw(gfx::Lines(lineWidth), 0, lineIndexes.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ struct TileLayerGroup::Impl {
|
||||
Impl(std::size_t capacity)
|
||||
: tileDrawables(capacity) {}
|
||||
|
||||
using TileMap = std::unordered_map<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
|
||||
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
|
||||
TileMap tileDrawables;
|
||||
};
|
||||
|
||||
@@ -49,27 +49,17 @@ const gfx::UniqueDrawable& TileLayerGroup::getDrawable(mbgl::RenderPass pass, co
|
||||
return (hit == impl->tileDrawables.end()) ? no_tile : hit->second;
|
||||
}
|
||||
|
||||
gfx::UniqueDrawable TileLayerGroup::removeDrawable(mbgl::RenderPass pass, const OverscaledTileID& id) {
|
||||
const auto hit = impl->tileDrawables.find({pass, id});
|
||||
if (hit == impl->tileDrawables.end()) {
|
||||
return {};
|
||||
}
|
||||
auto drawable = std::move(hit->second);
|
||||
impl->tileDrawables.erase(hit);
|
||||
return drawable;
|
||||
std::vector<gfx::UniqueDrawable> TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) {
|
||||
const auto range = impl->tileDrawables.equal_range({pass, id});
|
||||
std::vector<gfx::UniqueDrawable> result(std::distance(range.first, range.second));
|
||||
std::transform(std::make_move_iterator(range.first), std::make_move_iterator(range.second),
|
||||
result.begin(), [](auto&& pair) { return std::move(pair.second); });
|
||||
impl->tileDrawables.erase(range.first, range.second);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) {
|
||||
const auto result = impl->tileDrawables.insert(
|
||||
std::make_pair(TileLayerGroupTileKey{pass, id}, gfx::UniqueDrawable()));
|
||||
if (result.second) {
|
||||
// New item inserted, move the drawable into it
|
||||
result.first->second = std::move(drawable);
|
||||
return true;
|
||||
} else {
|
||||
// Not inserted
|
||||
return false;
|
||||
}
|
||||
void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) {
|
||||
impl->tileDrawables.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable)));
|
||||
}
|
||||
|
||||
void TileLayerGroup::observeDrawables(std::function<void(gfx::Drawable&)> f) {
|
||||
|
||||
@@ -298,7 +298,7 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
|
||||
if (!(renderPass & drawPasses)) {
|
||||
// Not in this pass
|
||||
if (tileDrawable) {
|
||||
tileLayerGroup->removeDrawable(renderPass, tileID);
|
||||
tileLayerGroup->removeDrawables(renderPass, tileID);
|
||||
++stats.tileDrawablesRemoved;
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -315,9 +315,11 @@ void RenderFillLayer::update(const int32_t layerIndex,
|
||||
std::inserter(newTileIDs, newTileIDs.begin()),
|
||||
[](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); });
|
||||
|
||||
std::unique_ptr<gfx::DrawableBuilder> builder;
|
||||
std::unique_ptr<gfx::DrawableBuilder> fillBuilder;
|
||||
std::unique_ptr<gfx::DrawableBuilder> outlineBuilder;
|
||||
std::vector<gfx::DrawablePtr> newTiles;
|
||||
gfx::VertexAttributeArray vertexAttrs;
|
||||
gfx::VertexAttributeArray fillVertexAttrs;
|
||||
gfx::VertexAttributeArray outlineVertexAttrs;
|
||||
|
||||
for (const auto renderPass : {RenderPass::Opaque, RenderPass::Translucent}) {
|
||||
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
|
||||
@@ -343,7 +345,8 @@ void RenderFillLayer::update(const int32_t layerIndex,
|
||||
|
||||
const auto removeTile = [&]() {
|
||||
if (tileDrawable) {
|
||||
tileLayerGroup->removeDrawable(renderPass, tileID);
|
||||
// Remove and discard all drawables for the tile
|
||||
tileLayerGroup->removeDrawables(renderPass, tileID);
|
||||
++stats.tileDrawablesRemoved;
|
||||
}
|
||||
};
|
||||
@@ -359,44 +362,63 @@ void RenderFillLayer::update(const int32_t layerIndex,
|
||||
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 fillAA = evaluated.get<FillAntialias>();
|
||||
|
||||
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 (fillRenderPass != renderPass) {
|
||||
if (!doFill && !doOutline) {
|
||||
removeTile();
|
||||
continue;
|
||||
}
|
||||
|
||||
vertexAttrs.clear();
|
||||
fillVertexAttrs.clear();
|
||||
outlineVertexAttrs.clear();
|
||||
|
||||
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
|
||||
|
||||
if (auto& p1 = paintPropertyBinders.get<FillColor>()) {
|
||||
const auto count = p1->getVertexCount();
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = vertexAttrs.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>>*>(
|
||||
p1->getVertexValue(i))
|
||||
->a1;
|
||||
attr->set<gfx::VertexAttribute::float4>(i, {packed[0], packed[1], packed[0], packed[1]});
|
||||
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 (auto& p1 = paintPropertyBinders.get<FillOpacity>()) {
|
||||
const auto count = p1->getVertexCount();
|
||||
if (auto& attr = vertexAttrs.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>>*>(
|
||||
p1->getVertexValue(i))
|
||||
->a1;
|
||||
attr->set<gfx::VertexAttribute::float2>(i, {opacity[0], opacity[0]});
|
||||
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]});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,56 +436,32 @@ void RenderFillLayer::update(const int32_t layerIndex,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!builder) {
|
||||
builder = context.createDrawableBuilder("fill");
|
||||
builder->setShader(fillShader);
|
||||
builder->addTweaker(context.createDrawableTweaker());
|
||||
builder->setColorMode(gfx::DrawableBuilder::ColorMode::None);
|
||||
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
builder->setLayerIndex(layerIndex);
|
||||
if (doFill && !fillBuilder) {
|
||||
fillBuilder = context.createDrawableBuilder("fill");
|
||||
fillBuilder->setShader(fillShader);
|
||||
//fillBuilder->addTweaker(context.createDrawableTweaker());
|
||||
fillBuilder->setColorMode(gfx::DrawableBuilder::ColorMode::None);
|
||||
fillBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite : gfx::DepthMaskType::ReadOnly);
|
||||
fillBuilder->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
fillBuilder->setLayerIndex(layerIndex);
|
||||
}
|
||||
if (doOutline && !outlineBuilder) {
|
||||
outlineBuilder = context.createDrawableBuilder("fill-outline");
|
||||
outlineBuilder->setShader(outlineShader);
|
||||
//outlineBuilder->addTweaker(context.createDrawableTweaker());
|
||||
outlineBuilder->setColorMode(gfx::DrawableBuilder::ColorMode::None);
|
||||
outlineBuilder->setLineWidth(2);
|
||||
outlineBuilder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
outlineBuilder->setLayerIndex(layerIndex);
|
||||
outlineBuilder->setSubLayerIndex(unevaluated.get<FillOutlineColor>().isUndefined() ? 2 : 0);
|
||||
}
|
||||
|
||||
// tile.translatedMatrix(evaluated.get<FillTranslate>(), evaluated.get<FillTranslateAnchor>(),
|
||||
// parameters.state)
|
||||
|
||||
builder->setRenderPass(renderPass);
|
||||
builder->setVertexAttributes(vertexAttrs);
|
||||
|
||||
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex>&
|
||||
verts = bucket.vertices.vector();
|
||||
std::vector<std::array<int16_t, 2>> rawVerts(verts.size());
|
||||
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
|
||||
|
||||
builder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.triangleSegments) {
|
||||
builder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
|
||||
if (fillAA) {
|
||||
// TODO: Different drawable? Multiple concurrent builders?
|
||||
for (const auto& seg : bucket.lineSegments) {
|
||||
builder->addLines(bucket.lines.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
}
|
||||
// evaluated.get<FillTranslate>(),
|
||||
// evaluated.get<FillTranslateAnchor>(),
|
||||
// parameters.stencilModeForClipping(tile.id),
|
||||
// parameters.colorModeForRenderPass(),
|
||||
// gfx::CullFaceMode::disabled(),
|
||||
//
|
||||
// const auto isOpaque = (evaluated.get<FillColor>().constantOr(Color()).a >= 1.0f &&
|
||||
// evaluated.get<FillOpacity>().constantOr(0) >= 1.0f
|
||||
// );// && layerIndex >= parameters.opaquePassCutoff);
|
||||
// const auto fillRenderPass = isOpaque ? RenderPass::Opaque : RenderPass::Translucent;
|
||||
//
|
||||
// if (renderPass == fillRenderPass) {
|
||||
// }
|
||||
|
||||
// const auto depthMask = (renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
// : gfx::DepthMaskType::ReadOnly;
|
||||
|
||||
// const auto depthMode = parameters.depthModeForSublayer(1, depthMask);
|
||||
|
||||
// if (evaluated.get<FillAntialias>() && parameters.pass == RenderPass::Translucent) {
|
||||
// draw(*fillOutlineProgram,
|
||||
@@ -476,22 +474,57 @@ void RenderFillLayer::update(const int32_t layerIndex,
|
||||
// FillOutlineProgram::TextureBindings{});
|
||||
// }
|
||||
|
||||
builder->flush();
|
||||
// tile.translatedMatrix(evaluated.get<FillTranslate>(), evaluated.get<FillTranslateAnchor>(),
|
||||
// parameters.state)
|
||||
|
||||
auto newDrawables = builder->clearDrawables();
|
||||
if (!newDrawables.empty()) {
|
||||
auto& drawable = newDrawables[0];
|
||||
drawable->setTileID(tileID);
|
||||
// drawable->mutableUniformBuffers().addOrReplace("FillLayerUBO", uniformBuffer);
|
||||
if (fillBuilder) {
|
||||
fillBuilder->setRenderPass(renderPass);
|
||||
fillBuilder->setVertexAttributes(fillVertexAttrs);
|
||||
}
|
||||
if (outlineBuilder) {
|
||||
outlineBuilder->setRenderPass(renderPass);
|
||||
outlineBuilder->setVertexAttributes(outlineVertexAttrs);
|
||||
}
|
||||
|
||||
// Track it.
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.tileDrawablesAdded;
|
||||
// Log::Warning(Event::General, "Adding drawable for " + util::toString(tileID) + " total " +
|
||||
// std::to_string(stats.tileDrawablesAdded+1));
|
||||
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex>&
|
||||
verts = bucket.vertices.vector();
|
||||
std::vector<std::array<int16_t, 2>> rawVerts(verts.size());
|
||||
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
|
||||
|
||||
if (fillBuilder) {
|
||||
fillBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.triangleSegments) {
|
||||
fillBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
|
||||
fillBuilder->flush();
|
||||
|
||||
for (auto& drawable : fillBuilder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.tileDrawablesAdded;
|
||||
}
|
||||
}
|
||||
if (outlineBuilder) {
|
||||
outlineBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.lineSegments) {
|
||||
outlineBuilder->addLines(bucket.lines.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
|
||||
outlineBuilder->flush();
|
||||
|
||||
for (auto& drawable : outlineBuilder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.tileDrawablesAdded;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else { // FillPattern is defined
|
||||
// if (parameters.pass != RenderPass::Translucent) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user