summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r--src/mbgl/renderer/bucket.hpp5
-rw-r--r--src/mbgl/renderer/circle_bucket.cpp46
-rw-r--r--src/mbgl/renderer/circle_bucket.hpp12
-rw-r--r--src/mbgl/renderer/debug_bucket.cpp14
-rw-r--r--src/mbgl/renderer/debug_bucket.hpp7
-rw-r--r--src/mbgl/renderer/element_group.hpp28
-rw-r--r--src/mbgl/renderer/fill_bucket.cpp98
-rw-r--r--src/mbgl/renderer/fill_bucket.hpp23
-rw-r--r--src/mbgl/renderer/line_bucket.cpp83
-rw-r--r--src/mbgl/renderer/line_bucket.hpp31
-rw-r--r--src/mbgl/renderer/painter.cpp103
-rw-r--r--src/mbgl/renderer/painter.hpp53
-rw-r--r--src/mbgl/renderer/painter_background.cpp102
-rw-r--r--src/mbgl/renderer/painter_circle.cpp70
-rw-r--r--src/mbgl/renderer/painter_clipping.cpp63
-rw-r--r--src/mbgl/renderer/painter_debug.cpp125
-rw-r--r--src/mbgl/renderer/painter_fill.cpp243
-rw-r--r--src/mbgl/renderer/painter_line.cpp173
-rw-r--r--src/mbgl/renderer/painter_raster.cpp61
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp311
-rw-r--r--src/mbgl/renderer/raster_bucket.cpp16
-rw-r--r--src/mbgl/renderer/raster_bucket.hpp13
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp71
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp24
24 files changed, 534 insertions, 1241 deletions
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index 2c3c7a6e47..49619c14f7 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -5,9 +5,6 @@
#include <atomic>
-#define BUFFER_OFFSET_0 ((int8_t*)nullptr)
-#define BUFFER_OFFSET(i) ((BUFFER_OFFSET_0) + (i))
-
namespace mbgl {
class Painter;
@@ -38,8 +35,6 @@ public:
virtual bool hasData() const = 0;
- virtual bool needsClipping() const = 0;
-
bool needsUpload() const {
return !uploaded;
}
diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp
index f12139d004..cb6ba7d458 100644
--- a/src/mbgl/renderer/circle_bucket.cpp
+++ b/src/mbgl/renderer/circle_bucket.cpp
@@ -1,6 +1,6 @@
#include <mbgl/renderer/circle_bucket.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/gl/gl.hpp>
+#include <mbgl/gl/context.hpp>
#include <mbgl/shader/circle_shader.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
@@ -13,10 +13,6 @@ using namespace style;
CircleBucket::CircleBucket(MapMode mode_) : mode(mode_) {
}
-CircleBucket::~CircleBucket() {
- // Do not remove. header file only contains forward definitions to unique pointers.
-}
-
void CircleBucket::upload(gl::Context& context) {
vertexBuffer = context.createVertexBuffer(std::move(vertices));
indexBuffer = context.createIndexBuffer(std::move(triangles));
@@ -31,11 +27,7 @@ void CircleBucket::render(Painter& painter,
}
bool CircleBucket::hasData() const {
- return !groups.empty();
-}
-
-bool CircleBucket::needsClipping() const {
- return true;
+ return !segments.empty();
}
void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
@@ -50,6 +42,11 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
if ((mode != MapMode::Still) &&
(x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT)) continue;
+ if (!segments.size() || segments.back().vertexLength + 4 > 65535) {
+ // Move to a new segments because the old one can't hold the geometry.
+ segments.emplace_back(vertices.size(), triangles.size());
+ }
+
// this geometry will be of the Point type, and we'll derive
// two triangles from it.
//
@@ -64,13 +61,8 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
vertices.emplace_back(x, y, 1, 1); // 3
vertices.emplace_back(x, y, -1, 1); // 4
- if (!groups.size() || groups.back().vertexLength + 4 > 65535) {
- // Move to a new group because the old one can't hold the geometry.
- groups.emplace_back();
- }
-
- auto& group = groups.back();
- uint16_t index = group.vertexLength;
+ auto& segment = segments.back();
+ uint16_t index = segment.vertexLength;
// 1, 2, 3
// 1, 4, 3
@@ -81,26 +73,10 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
static_cast<uint16_t>(index + 3),
static_cast<uint16_t>(index + 2));
- group.vertexLength += 4;
- group.indexLength += 2;
+ segment.vertexLength += 4;
+ segment.primitiveLength += 2;
}
}
}
-void CircleBucket::drawCircles(CircleShader& shader, gl::Context& context, PaintMode paintMode) {
- GLbyte* vertexIndex = BUFFER_OFFSET(0);
- GLbyte* elementsIndex = BUFFER_OFFSET(0);
-
- for (auto& group : groups) {
- if (!group.indexLength) continue;
-
- group.getVAO(shader, paintMode).bind(shader, *vertexBuffer, *indexBuffer, vertexIndex, context);
-
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT, elementsIndex));
-
- vertexIndex += group.vertexLength * vertexBuffer->vertexSize;
- elementsIndex += group.indexLength * indexBuffer->primitiveSize;
- }
-}
-
} // namespace mbgl
diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp
index 2f3faccdec..a682d423d6 100644
--- a/src/mbgl/renderer/circle_bucket.hpp
+++ b/src/mbgl/renderer/circle_bucket.hpp
@@ -1,36 +1,28 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/segment.hpp>
#include <mbgl/shader/circle_vertex.hpp>
namespace mbgl {
-class CircleShader;
-
class CircleBucket : public Bucket {
public:
CircleBucket(const MapMode);
- ~CircleBucket() override;
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
void addGeometry(const GeometryCollection&);
- void drawCircles(CircleShader&, gl::Context&, PaintMode);
-
-private:
std::vector<CircleVertex> vertices;
std::vector<gl::Triangle> triangles;
-
- std::vector<ElementGroup<CircleShader>> groups;
+ std::vector<gl::Segment> segments;
optional<gl::VertexBuffer<CircleVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp
index c47ae434be..a9ef551fba 100644
--- a/src/mbgl/renderer/debug_bucket.cpp
+++ b/src/mbgl/renderer/debug_bucket.cpp
@@ -85,18 +85,4 @@ DebugBucket::DebugBucket(const OverscaledTileID& id,
vertexBuffer(context.createVertexBuffer(buildTextVertices(id, renderable_, complete_, modified_, expires_, debugMode_))) {
}
-void DebugBucket::drawLines(FillShader& shader, gl::Context& context) {
- if (vertexBuffer.vertexCount != 0) {
- array.bind(shader, vertexBuffer, BUFFER_OFFSET_0, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(vertexBuffer.vertexCount)));
- }
-}
-
-void DebugBucket::drawPoints(FillShader& shader, gl::Context& context) {
- if (vertexBuffer.vertexCount != 0) {
- array.bind(shader, vertexBuffer, BUFFER_OFFSET_0, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(vertexBuffer.vertexCount)));
- }
-}
-
} // namespace mbgl
diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp
index 89087f0010..cdffdd8d7a 100644
--- a/src/mbgl/renderer/debug_bucket.hpp
+++ b/src/mbgl/renderer/debug_bucket.hpp
@@ -6,13 +6,11 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
-#include <mbgl/gl/vao.hpp>
#include <mbgl/shader/fill_vertex.hpp>
namespace mbgl {
class OverscaledTileID;
-class FillShader;
namespace gl {
class Context;
@@ -28,18 +26,13 @@ public:
MapDebugOptions,
gl::Context&);
- void drawLines(FillShader&, gl::Context&);
- void drawPoints(FillShader&, gl::Context&);
-
const bool renderable;
const bool complete;
const optional<Timestamp> modified;
const optional<Timestamp> expires;
const MapDebugOptions debugMode;
-private:
gl::VertexBuffer<FillVertex> vertexBuffer;
- gl::VertexArrayObject array;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/element_group.hpp b/src/mbgl/renderer/element_group.hpp
deleted file mode 100644
index 59b5c3068d..0000000000
--- a/src/mbgl/renderer/element_group.hpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/vao.hpp>
-#include <mbgl/renderer/render_pass.hpp>
-
-namespace mbgl {
-
-template <class... Shaders>
-struct ElementGroup {
- template <class Shader>
- struct VAOs {
- gl::VertexArrayObject normalVAO;
- gl::VertexArrayObject overdrawVAO;
- };
-
- std::tuple<VAOs<Shaders>...> vaos;
-
- template <class Shader>
- gl::VertexArrayObject& getVAO(const Shader&, PaintMode paintMode) {
- auto& vao = std::get<VAOs<Shader>>(vaos);
- return paintMode == PaintMode::Overdraw ? vao.overdrawVAO : vao.normalVAO;
- }
-
- std::size_t vertexLength = 0;
- std::size_t indexLength = 0;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp
index cd4277cabc..2c69524c0d 100644
--- a/src/mbgl/renderer/fill_bucket.cpp
+++ b/src/mbgl/renderer/fill_bucket.cpp
@@ -30,11 +30,6 @@ using namespace style;
struct GeometryTooLongException : std::exception {};
-FillBucket::FillBucket() {
-}
-
-FillBucket::~FillBucket() = default;
-
void FillBucket::addGeometry(const GeometryCollection& geometry) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
@@ -48,17 +43,20 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
throw GeometryTooLongException();
}
+ std::size_t startVertices = vertices.size();
+
for (const auto& ring : polygon) {
std::size_t nVertices = ring.size();
if (nVertices == 0)
continue;
- if (lineGroups.empty() || lineGroups.back().vertexLength + nVertices > 65535)
- lineGroups.emplace_back();
+ if (lineSegments.empty() || lineSegments.back().vertexLength + nVertices > 65535) {
+ lineSegments.emplace_back(vertices.size(), lines.size());
+ }
- auto& lineGroup = lineGroups.back();
- uint16_t lineIndex = lineGroup.vertexLength;
+ auto& lineSegment = lineSegments.back();
+ uint16_t lineIndex = lineSegment.vertexLength;
vertices.emplace_back(ring[0].x, ring[0].y);
lines.emplace_back(static_cast<uint16_t>(lineIndex + nVertices - 1),
@@ -70,8 +68,8 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
static_cast<uint16_t>(lineIndex + i));
}
- lineGroup.vertexLength += nVertices;
- lineGroup.indexLength += nVertices;
+ lineSegment.vertexLength += nVertices;
+ lineSegment.primitiveLength += nVertices;
}
std::vector<uint32_t> indices = mapbox::earcut(polygon);
@@ -79,12 +77,12 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
std::size_t nIndicies = indices.size();
assert(nIndicies % 3 == 0);
- if (triangleGroups.empty() || triangleGroups.back().vertexLength + totalVertices > 65535) {
- triangleGroups.emplace_back();
+ if (triangleSegments.empty() || triangleSegments.back().vertexLength + totalVertices > 65535) {
+ triangleSegments.emplace_back(startVertices, triangles.size());
}
- auto& triangleGroup = triangleGroups.back();
- uint16_t triangleIndex = triangleGroup.vertexLength;
+ auto& triangleSegment = triangleSegments.back();
+ uint16_t triangleIndex = triangleSegment.vertexLength;
for (uint32_t i = 0; i < nIndicies; i += 3) {
triangles.emplace_back(static_cast<uint16_t>(triangleIndex + indices[i]),
@@ -92,8 +90,8 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
static_cast<uint16_t>(triangleIndex + indices[i + 2]));
}
- triangleGroup.vertexLength += totalVertices;
- triangleGroup.indexLength += nIndicies / 3;
+ triangleSegment.vertexLength += totalVertices;
+ triangleSegment.primitiveLength += nIndicies / 3;
}
}
@@ -114,71 +112,7 @@ void FillBucket::render(Painter& painter,
}
bool FillBucket::hasData() const {
- return !triangleGroups.empty() || !lineGroups.empty();
-}
-
-bool FillBucket::needsClipping() const {
- return true;
-}
-
-void FillBucket::drawElements(FillShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : triangleGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *triangleIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * triangleIndexBuffer->primitiveSize;
- }
-}
-
-void FillBucket::drawElements(FillPatternShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : triangleGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *triangleIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * triangleIndexBuffer->primitiveSize;
- }
-}
-
-void FillBucket::drawVertices(FillOutlineShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : lineGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *lineIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_LINES, static_cast<GLsizei>(group.indexLength * 2), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * lineIndexBuffer->primitiveSize;
- }
-}
-
-void FillBucket::drawVertices(FillOutlinePatternShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : lineGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *lineIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_LINES, static_cast<GLsizei>(group.indexLength * 2), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * lineIndexBuffer->primitiveSize;
- }
+ return !triangleSegments.empty() || !lineSegments.empty();
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp
index 34cd886687..715b8e2745 100644
--- a/src/mbgl/renderer/fill_bucket.hpp
+++ b/src/mbgl/renderer/fill_bucket.hpp
@@ -1,46 +1,29 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/segment.hpp>
#include <mbgl/shader/fill_vertex.hpp>
#include <vector>
-#include <memory>
namespace mbgl {
-class FillShader;
-class FillPatternShader;
-class FillOutlineShader;
-class FillOutlinePatternShader;
-
class FillBucket : public Bucket {
public:
- FillBucket();
- ~FillBucket() override;
-
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
void addGeometry(const GeometryCollection&);
- void drawElements(FillShader&, gl::Context&, PaintMode);
- void drawElements(FillPatternShader&, gl::Context&, PaintMode);
- void drawVertices(FillOutlineShader&, gl::Context&, PaintMode);
- void drawVertices(FillOutlinePatternShader&, gl::Context&, PaintMode);
-
-private:
std::vector<FillVertex> vertices;
std::vector<gl::Line> lines;
std::vector<gl::Triangle> triangles;
-
- std::vector<ElementGroup<FillOutlineShader, FillOutlinePatternShader>> lineGroups;
- std::vector<ElementGroup<FillShader, FillPatternShader>> triangleGroups;
+ std::vector<gl::Segment> lineSegments;
+ std::vector<gl::Segment> triangleSegments;
optional<gl::VertexBuffer<FillVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Line>> lineIndexBuffer;
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index 7a5309bafc..229b14d489 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -1,12 +1,8 @@
#include <mbgl/renderer/line_bucket.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/shader/line_shader.hpp>
-#include <mbgl/shader/line_sdf_shader.hpp>
-#include <mbgl/shader/line_pattern_shader.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/constants.hpp>
-#include <mbgl/gl/gl.hpp>
#include <cassert>
@@ -54,8 +50,8 @@ const float LINE_DISTANCE_SCALE = 1.0 / 2.0;
const float MAX_LINE_DISTANCE = std::pow(2, LINE_DISTANCE_BUFFER_BITS) / LINE_DISTANCE_SCALE;
void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
- const GLsizei len = [&coordinates] {
- GLsizei l = static_cast<GLsizei>(coordinates.size());
+ const std::size_t len = [&coordinates] {
+ std::size_t l = coordinates.size();
// If the line has duplicate vertices at the end, adjust length to remove them.
while (l > 2 && coordinates[l - 1] == coordinates[l - 2]) {
l--;
@@ -103,7 +99,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
const std::size_t startVertex = vertices.size();
std::vector<TriangleElement> triangleStore;
- for (GLsizei i = 0; i < len; ++i) {
+ for (std::size_t i = 0; i < len; ++i) {
if (closed && i == len - 1) {
// if the line is closed, we treat the last vertex like the first
nextCoordinate = coordinates[1];
@@ -352,13 +348,12 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
const std::size_t endVertex = vertices.size();
const std::size_t vertexCount = endVertex - startVertex;
- if (groups.empty() || groups.back().vertexLength + vertexCount > 65535) {
- // Move to a new group because the old one can't hold the geometry.
- groups.emplace_back();
+ if (segments.empty() || segments.back().vertexLength + vertexCount > 65535) {
+ segments.emplace_back(startVertex, triangles.size());
}
- auto& group = groups.back();
- uint16_t index = group.vertexLength;
+ auto& segment = segments.back();
+ uint16_t index = segment.vertexLength;
for (const auto& triangle : triangleStore) {
triangles.emplace_back(static_cast<uint16_t>(index + triangle.a),
@@ -366,8 +361,8 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
static_cast<uint16_t>(index + triangle.c));
}
- group.vertexLength += vertexCount;
- group.indexLength += triangleStore.size();
+ segment.vertexLength += vertexCount;
+ segment.primitiveLength += triangleStore.size();
}
void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
@@ -450,65 +445,7 @@ void LineBucket::render(Painter& painter,
}
bool LineBucket::hasData() const {
- return !groups.empty();
-}
-
-bool LineBucket::needsClipping() const {
- return true;
-}
-
-void LineBucket::drawLines(LineShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : groups) {
- if (!group.indexLength) {
- continue;
- }
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * indexBuffer->primitiveSize;
- }
-}
-
-void LineBucket::drawLineSDF(LineSDFShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : groups) {
- if (!group.indexLength) {
- continue;
- }
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * indexBuffer->primitiveSize;
- }
-}
-
-void LineBucket::drawLinePatterns(LinePatternShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : groups) {
- if (!group.indexLength) {
- continue;
- }
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * indexBuffer->primitiveSize;
- }
+ return !segments.empty();
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp
index 14af710877..7b4c5f1b57 100644
--- a/src/mbgl/renderer/line_bucket.hpp
+++ b/src/mbgl/renderer/line_bucket.hpp
@@ -1,10 +1,10 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/segment.hpp>
#include <mbgl/shader/line_vertex.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
@@ -12,12 +12,7 @@
namespace mbgl {
-class LineShader;
-class LineSDFShader;
-class LinePatternShader;
-
class LineBucket : public Bucket {
-
public:
LineBucket(uint32_t overscaling);
~LineBucket() override;
@@ -25,14 +20,18 @@ public:
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
void addGeometry(const GeometryCollection&);
void addGeometry(const GeometryCoordinates& line);
- void drawLines(LineShader&, gl::Context&, PaintMode);
- void drawLineSDF(LineSDFShader&, gl::Context&, PaintMode);
- void drawLinePatterns(LinePatternShader&, gl::Context&, PaintMode);
+ style::LineLayoutProperties layout;
+
+ std::vector<LineVertex> vertices;
+ std::vector<gl::Triangle> triangles;
+ std::vector<gl::Segment> segments;
+
+ optional<gl::VertexBuffer<LineVertex>> vertexBuffer;
+ optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
private:
struct TriangleElement {
@@ -46,18 +45,6 @@ private:
const Point<double>& extrude, bool lineTurnsLeft, std::size_t startVertex,
std::vector<TriangleElement>& triangleStore);
-public:
- style::LineLayoutProperties layout;
-
-private:
- std::vector<LineVertex> vertices;
- std::vector<gl::Triangle> triangles;
-
- std::vector<ElementGroup<LineShader, LineSDFShader, LinePatternShader>> groups;
-
- optional<gl::VertexBuffer<LineVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
-
std::ptrdiff_t e1;
std::ptrdiff_t e2;
std::ptrdiff_t e3;
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index effeb086af..303de91025 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -82,12 +82,6 @@ bool Painter::needsAnimation() const {
return frameHistory.needsAnimation(util::DEFAULT_FADE_DURATION);
}
-void Painter::setClipping(const ClipID& clip) {
- const GLint ref = (GLint)clip.reference.to_ulong();
- const GLuint mask = (GLuint)clip.mask.to_ulong();
- context.stencilFunc = { gl::StencilTestFunction::Equal, ref, mask };
-}
-
void Painter::cleanup() {
context.performCleanup();
}
@@ -114,7 +108,6 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
RenderData renderData = style.getRenderData(frame.debugOptions);
const std::vector<RenderItem>& order = renderData.order;
const std::unordered_set<Source*>& sources = renderData.sources;
- const Color& background = renderData.backgroundColor;
// Update the default matrices to the current viewport dimensions.
state.getProjMatrix(projMatrix);
@@ -153,26 +146,11 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
{
MBGL_DEBUG_GROUP("clear");
view.bind();
- context.stencilFunc = { gl::StencilTestFunction::Always, 0, ~0u };
- context.stencilTest = true;
- context.stencilMask = 0xFF;
- context.depthTest = false;
- context.depthMask = true;
- context.colorMask = { true, true, true, true };
-
- if (paintMode() == PaintMode::Overdraw) {
- context.blend = true;
- context.blendFunc = { gl::BlendSourceFactor::ConstantColor,
- gl::BlendDestinationFactor::One };
- const float overdraw = 1.0f / 8.0f;
- context.blendColor = { overdraw, overdraw, overdraw, 0.0f };
- context.clearColor = Color::black();
- } else {
- context.clearColor = background;
- }
- context.clearStencil = 0;
- context.clearDepth = 1;
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
+ context.clear(paintMode() == PaintMode::Overdraw
+ ? Color::black()
+ : renderData.backgroundColor,
+ 1.0f,
+ 0);
}
// - CLIPPING MASKS ----------------------------------------------------------------------------
@@ -186,7 +164,12 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
source->baseImpl->startRender(generator, projMatrix, state);
}
- drawClippingMasks(parameters, generator.getStencils());
+ MBGL_DEBUG_GROUP("clipping masks");
+
+ for (const auto& stencil : generator.getStencils()) {
+ MBGL_DEBUG_GROUP(std::string{ "mask: " } + util::toString(stencil.first));
+ renderClippingMask(stencil.first, stencil.second);
+ }
}
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
@@ -275,19 +258,6 @@ void Painter::renderPass(PaintParameters& parameters,
if (!layer.baseImpl->hasRenderPass(pass))
continue;
- if (paintMode() == PaintMode::Overdraw) {
- context.blend = true;
- } else if (pass == RenderPass::Translucent) {
- context.blend = true;
- context.blendFunc = { gl::BlendSourceFactor::One,
- gl::BlendDestinationFactor::OneMinusSrcAlpha };
- } else {
- context.blend = false;
- }
-
- context.colorMask = { true, true, true, true };
- context.stencilMask = 0x0;
-
if (layer.is<BackgroundLayer>()) {
MBGL_DEBUG_GROUP("background");
renderBackground(parameters, *layer.as<BackgroundLayer>());
@@ -296,11 +266,9 @@ void Painter::renderPass(PaintParameters& parameters,
// Reset GL state to a known state so the CustomLayer always has a clean slate.
context.vertexArrayObject = 0;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- context.stencilTest = false;
- setDepthSublayer(0);
+ context.setDepthMode(depthModeForSublayer(0, gl::DepthMode::ReadOnly));
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setColorMode(colorModeForRenderPass());
layer.as<CustomLayer>()->impl->render(state);
@@ -310,9 +278,6 @@ void Painter::renderPass(PaintParameters& parameters,
context.setDirtyState();
} else {
MBGL_DEBUG_GROUP(layer.baseImpl->id + " - " + util::toString(item.tile->id));
- if (item.bucket->needsClipping()) {
- setClipping(item.tile->clip);
- }
item.bucket->render(*this, parameters, layer, *item.tile);
}
}
@@ -322,10 +287,46 @@ void Painter::renderPass(PaintParameters& parameters,
}
}
-void Painter::setDepthSublayer(int n) {
+mat4 Painter::matrixForTile(const UnwrappedTileID& tileID) {
+ mat4 matrix;
+ state.matrixFor(matrix, tileID);
+ matrix::multiply(matrix, projMatrix, matrix);
+ return matrix;
+}
+
+gl::DepthMode Painter::depthModeForSublayer(uint8_t n, gl::DepthMode::Mask mask) const {
float nearDepth = ((1 + currentLayer) * numSublayers + n) * depthEpsilon;
float farDepth = nearDepth + depthRangeSize;
- context.depthRange = { nearDepth, farDepth };
+ return gl::DepthMode { gl::DepthMode::LessEqual, mask, { nearDepth, farDepth } };
+}
+
+gl::StencilMode Painter::stencilModeForClipping(const ClipID& id) const {
+ return gl::StencilMode {
+ gl::StencilMode::Equal { static_cast<uint32_t>(id.mask.to_ulong()) },
+ static_cast<int32_t>(id.reference.to_ulong()),
+ 0,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Replace
+ };
+}
+
+gl::ColorMode Painter::colorModeForRenderPass() const {
+ if (paintMode() == PaintMode::Overdraw) {
+ const float overdraw = 1.0f / 8.0f;
+ return gl::ColorMode {
+ gl::ColorMode::Add {
+ gl::ColorMode::ConstantColor,
+ gl::ColorMode::One
+ },
+ Color { overdraw, overdraw, overdraw, 0.0f },
+ gl::ColorMode::Mask { true, true, true, true }
+ };
+ } else if (pass == RenderPass::Translucent) {
+ return gl::ColorMode::alphaBlended();
+ } else {
+ return gl::ColorMode::unblended();
+ }
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index b64eb308c4..ea60f79801 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -8,7 +8,6 @@
#include <mbgl/renderer/render_item.hpp>
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/gl/vao.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/shader/fill_vertex.hpp>
#include <mbgl/shader/raster_vertex.hpp>
@@ -78,20 +77,8 @@ public:
void cleanup();
- // Renders debug information for a tile.
+ void renderClippingMask(const UnwrappedTileID&, const ClipID&);
void renderTileDebug(const RenderTile&);
-
- // Renders the red debug frame around a tile, visualizing its perimeter.
- void renderDebugFrame(const mat4 &matrix);
-
-#ifndef NDEBUG
- // Renders tile clip boundaries, using stencil buffer to calculate fill color.
- void renderClipMasks(PaintParameters&);
- // Renders the depth buffer.
- void renderDepthBuffer(PaintParameters&);
-#endif
-
- void renderDebugText(Tile&, const mat4&);
void renderFill(PaintParameters&, FillBucket&, const style::FillLayer&, const RenderTile&);
void renderLine(PaintParameters&, LineBucket&, const style::LineLayer&, const RenderTile&);
void renderCircle(PaintParameters&, CircleBucket&, const style::CircleLayer&, const RenderTile&);
@@ -99,7 +86,12 @@ public:
void renderRaster(PaintParameters&, RasterBucket&, const style::RasterLayer&, const RenderTile&);
void renderBackground(PaintParameters&, const style::BackgroundLayer&);
- void drawClippingMasks(PaintParameters&, const std::map<UnwrappedTileID, ClipID>&);
+#ifndef NDEBUG
+ // Renders tile clip boundaries, using stencil buffer to calculate fill color.
+ void renderClipMasks(PaintParameters&);
+ // Renders the depth buffer.
+ void renderDepthBuffer(PaintParameters&);
+#endif
bool needsAnimation() const;
@@ -112,31 +104,10 @@ private:
Iterator it, Iterator end,
uint32_t i, int8_t increment);
- void setClipping(const ClipID&);
-
- void renderSDF(SymbolBucket&,
- const RenderTile&,
- float scaleDivisor,
- std::array<float, 2> texsize,
- SymbolSDFShader& sdfShader,
- void (SymbolBucket::*drawSDF)(SymbolSDFShader&, gl::Context&, PaintMode),
-
- // Layout
- style::AlignmentType rotationAlignment,
- style::AlignmentType pitchAlignment,
- float layoutSize,
-
- // Paint
- float opacity,
- Color color,
- Color haloColor,
- float haloWidth,
- float haloBlur,
- std::array<float, 2> translate,
- style::TranslateAnchorType translateAnchor,
- float paintSize);
-
- void setDepthSublayer(int n);
+ mat4 matrixForTile(const UnwrappedTileID&);
+ gl::DepthMode depthModeForSublayer(uint8_t n, gl::DepthMode::Mask) const;
+ gl::StencilMode stencilModeForClipping(const ClipID&) const;
+ gl::ColorMode colorModeForRenderPass() const;
#ifndef NDEBUG
PaintMode paintMode() const {
@@ -189,8 +160,6 @@ private:
gl::VertexBuffer<FillVertex> tileTriangleVertexBuffer;
gl::VertexBuffer<FillVertex> tileLineStripVertexBuffer;
gl::VertexBuffer<RasterVertex> rasterVertexBuffer;
-
- gl::VertexArrayObject tileBorderArray;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp
index 61ec76d1d8..93c0fe982a 100644
--- a/src/mbgl/renderer/painter_background.cpp
+++ b/src/mbgl/renderer/painter_background.cpp
@@ -1,12 +1,10 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/gl/gl.hpp>
-
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/fill_uniforms.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
-#include <mbgl/util/mat4.hpp>
#include <mbgl/util/tile_cover.hpp>
namespace mbgl {
@@ -18,73 +16,53 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye
// glClear rather than this method.
const BackgroundPaintProperties& properties = layer.impl->paint;
- bool isPatterned = !properties.backgroundPattern.value.to.empty();// && false;
- optional<SpriteAtlasPosition> imagePosA;
- optional<SpriteAtlasPosition> imagePosB;
-
- auto& patternShader = parameters.shaders.fillPattern;
- auto& plainShader = parameters.shaders.fill;
- auto& arrayBackgroundPattern = parameters.shaders.backgroundPatternArray;
- auto& arrayBackground = parameters.shaders.backgroundArray;
-
- if (isPatterned) {
- imagePosA = spriteAtlas->getPosition(properties.backgroundPattern.value.from,
- SpritePatternMode::Repeating);
- imagePosB = spriteAtlas->getPosition(properties.backgroundPattern.value.to,
- SpritePatternMode::Repeating);
+ if (!properties.backgroundPattern.value.to.empty()) {
+ optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
+ properties.backgroundPattern.value.from, SpritePatternMode::Repeating);
+ optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(
+ properties.backgroundPattern.value.to, SpritePatternMode::Repeating);
if (!imagePosA || !imagePosB)
return;
- context.program = patternShader.getID();
- patternShader.u_matrix = identityMatrix;
- patternShader.u_pattern_tl_a = imagePosA->tl;
- patternShader.u_pattern_br_a = imagePosA->br;
- patternShader.u_pattern_tl_b = imagePosB->tl;
- patternShader.u_pattern_br_b = imagePosB->br;
- patternShader.u_mix = properties.backgroundPattern.value.t;
- patternShader.u_opacity = properties.backgroundOpacity;
-
spriteAtlas->bind(true, context, 0);
- arrayBackgroundPattern.bind(patternShader, tileTriangleVertexBuffer, BUFFER_OFFSET(0), context);
+ for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
+ context.draw({
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ parameters.shaders.fillPattern,
+ FillPatternUniforms::values(
+ matrixForTile(tileID),
+ properties.backgroundOpacity.value,
+ context.viewport.getCurrentValue().size,
+ *imagePosA,
+ *imagePosB,
+ properties.backgroundPattern.value,
+ tileID,
+ state
+ ),
+ gl::Unindexed<gl::TriangleStrip>(tileTriangleVertexBuffer)
+ });
+ }
} else {
- context.program = plainShader.getID();
- plainShader.u_color = properties.backgroundColor;
- plainShader.u_opacity = properties.backgroundOpacity;
-
- arrayBackground.bind(plainShader, tileTriangleVertexBuffer, BUFFER_OFFSET(0), context);
- }
-
- context.stencilTest = false;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- setDepthSublayer(0);
-
- for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
- mat4 vertexMatrix;
- state.matrixFor(vertexMatrix, tileID);
- matrix::multiply(vertexMatrix, projMatrix, vertexMatrix);
-
- if (isPatterned) {
- patternShader.u_matrix = vertexMatrix;
- patternShader.u_pattern_size_a = imagePosA->size;
- patternShader.u_pattern_size_b = imagePosB->size;
- patternShader.u_scale_a = properties.backgroundPattern.value.fromScale;
- patternShader.u_scale_b = properties.backgroundPattern.value.toScale;
- patternShader.u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
-
- GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
- GLint pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
- GLint pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
- patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
- patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
- } else {
- plainShader.u_matrix = vertexMatrix;
+ for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
+ context.draw({
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ parameters.shaders.fill,
+ FillColorUniforms::values(
+ matrixForTile(tileID),
+ properties.backgroundOpacity.value,
+ properties.backgroundColor.value,
+ properties.backgroundColor.value,
+ context.viewport.getCurrentValue().size
+ ),
+ gl::Unindexed<gl::TriangleStrip>(tileTriangleVertexBuffer)
+ });
}
-
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, static_cast<GLsizei>(tileTriangleVertexBuffer.vertexCount)));
}
}
diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp
index 462ed59ebf..9db7272dab 100644
--- a/src/mbgl/renderer/painter_circle.cpp
+++ b/src/mbgl/renderer/painter_circle.cpp
@@ -2,11 +2,11 @@
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/circle_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
-
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
-
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/circle_uniforms.hpp>
+#include <mbgl/gl/context.hpp>
namespace mbgl {
@@ -16,42 +16,42 @@ void Painter::renderCircle(PaintParameters& parameters,
CircleBucket& bucket,
const CircleLayer& layer,
const RenderTile& tile) {
- // Abort early.
- if (pass == RenderPass::Opaque) return;
-
- context.stencilTest = frame.mapMode == MapMode::Still;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- setDepthSublayer(0);
-
- const CirclePaintProperties& properties = layer.impl->paint;
- auto& circleShader = parameters.shaders.circle;
-
- context.program = circleShader.getID();
-
- circleShader.u_matrix = tile.translatedMatrix(properties.circleTranslate,
- properties.circleTranslateAnchor,
- state);
-
- if (properties.circlePitchScale == CirclePitchScaleType::Map) {
- circleShader.u_extrude_scale = {{
- pixelsToGLUnits[0] * state.getAltitude(),
- pixelsToGLUnits[1] * state.getAltitude()
- }};
- circleShader.u_scale_with_map = true;
- } else {
- circleShader.u_extrude_scale = pixelsToGLUnits;
- circleShader.u_scale_with_map = false;
+ if (pass == RenderPass::Opaque) {
+ return;
}
- circleShader.u_devicepixelratio = frame.pixelRatio;
- circleShader.u_color = properties.circleColor;
- circleShader.u_radius = properties.circleRadius;
- circleShader.u_blur = properties.circleBlur;
- circleShader.u_opacity = properties.circleOpacity;
+ const CirclePaintProperties& properties = layer.impl->paint;
- bucket.drawCircles(circleShader, context, paintMode());
+ context.draw({
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ frame.mapMode == MapMode::Still
+ ? stencilModeForClipping(tile.clip)
+ : gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ parameters.shaders.circle,
+ CircleUniforms::values(
+ tile.translatedMatrix(properties.circleTranslate.value,
+ properties.circleTranslateAnchor.value,
+ state),
+ properties.circleOpacity.value,
+ properties.circleColor.value,
+ properties.circleRadius.value,
+ properties.circleBlur.value,
+ properties.circlePitchScale.value == CirclePitchScaleType::Map,
+ properties.circlePitchScale.value == CirclePitchScaleType::Map
+ ? std::array<float, 2> {{
+ pixelsToGLUnits[0] * state.getAltitude(),
+ pixelsToGLUnits[1] * state.getAltitude()
+ }}
+ : pixelsToGLUnits,
+ frame.pixelRatio
+ ),
+ gl::Segmented<gl::Triangles>(
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments
+ )
+ });
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp
index 68f580c280..d3f95e6e65 100644
--- a/src/mbgl/renderer/painter_clipping.cpp
+++ b/src/mbgl/renderer/painter_clipping.cpp
@@ -1,49 +1,32 @@
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/gl/gl.hpp>
-
-#include <mbgl/style/source.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/fill_uniforms.hpp>
#include <mbgl/util/clip_id.hpp>
-#include <mbgl/util/string.hpp>
-#include <mbgl/gl/debugging.hpp>
namespace mbgl {
-
-void Painter::drawClippingMasks(PaintParameters& parameters, const std::map<UnwrappedTileID, ClipID>& stencils) {
- MBGL_DEBUG_GROUP("clipping masks");
-
- auto& plainShader = parameters.shaders.fill;
- auto& arrayCoveringPlain = parameters.shaders.coveringPlainArray;
-
- mat4 matrix;
- const GLuint mask = 0b11111111;
-
- context.program = plainShader.getID();
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- context.depthTest = false;
- context.depthMask = false;
- context.colorMask = { false, false, false, false };
- context.stencilMask = mask;
-
- arrayCoveringPlain.bind(plainShader, tileTriangleVertexBuffer, BUFFER_OFFSET_0, context);
-
- for (const auto& stencil : stencils) {
- const auto& id = stencil.first;
- const auto& clip = stencil.second;
-
- MBGL_DEBUG_GROUP(std::string{ "mask: " } + util::toString(id));
- state.matrixFor(matrix, id);
- matrix::multiply(matrix, projMatrix, matrix);
- plainShader.u_matrix = matrix;
-
- const GLint ref = (GLint)(clip.reference.to_ulong());
- context.stencilFunc = { gl::StencilTestFunction::Always, ref, mask };
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(tileTriangleVertexBuffer.vertexCount)));
- }
+void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& clip) {
+ context.draw({
+ gl::DepthMode::disabled(),
+ gl::StencilMode {
+ gl::StencilMode::Always(),
+ static_cast<int32_t>(clip.reference.to_ulong()),
+ 0b11111111,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Replace
+ },
+ gl::ColorMode::disabled(),
+ shaders->fill,
+ FillColorUniforms::values(
+ matrixForTile(tileID),
+ 0.0f,
+ Color {},
+ Color {},
+ context.viewport.getCurrentValue().size
+ ),
+ gl::Unindexed<gl::Triangles>(tileTriangleVertexBuffer)
+ });
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index 5a737369bf..5428631698 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -5,6 +5,7 @@
#include <mbgl/map/view.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/fill_uniforms.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/gl/debugging.hpp>
#include <mbgl/gl/gl.hpp>
@@ -12,89 +13,59 @@
namespace mbgl {
-void Painter::renderTileDebug(const RenderTile& tile) {
- MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(tile.id));
- if (frame.debugOptions != MapDebugOptions::NoDebug) {
- setClipping(tile.clip);
- if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
- renderDebugText(tile.tile, tile.matrix);
+void Painter::renderTileDebug(const RenderTile& renderTile) {
+ if (frame.debugOptions == MapDebugOptions::NoDebug)
+ return;
+
+ MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(renderTile.id));
+
+ auto draw = [&] (Color color, auto subject) {
+ context.draw({
+ gl::DepthMode::disabled(),
+ stencilModeForClipping(renderTile.clip),
+ gl::ColorMode::unblended(),
+ shaders->fill,
+ FillColorUniforms::values(
+ renderTile.matrix,
+ 1.0f,
+ color,
+ color,
+ context.viewport.getCurrentValue().size
+ ),
+ subject
+ });
+ };
+
+ if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
+ Tile& tile = renderTile.tile;
+ if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() ||
+ tile.debugBucket->complete != tile.isComplete() ||
+ !(tile.debugBucket->modified == tile.modified) ||
+ !(tile.debugBucket->expires == tile.expires) ||
+ tile.debugBucket->debugMode != frame.debugOptions) {
+ tile.debugBucket = std::make_unique<DebugBucket>(
+ tile.id, tile.isRenderable(), tile.isComplete(), tile.modified,
+ tile.expires, frame.debugOptions, context);
}
- if (frame.debugOptions & MapDebugOptions::TileBorders) {
- renderDebugFrame(tile.matrix);
- }
- }
-}
-
-void Painter::renderDebugText(Tile& tile, const mat4 &matrix) {
- MBGL_DEBUG_GROUP("debug text");
- context.depthTest = false;
+ const auto& vertexBuffer = tile.debugBucket->vertexBuffer;
- if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() ||
- tile.debugBucket->complete != tile.isComplete() ||
- !(tile.debugBucket->modified == tile.modified) ||
- !(tile.debugBucket->expires == tile.expires) ||
- tile.debugBucket->debugMode != frame.debugOptions) {
- tile.debugBucket = std::make_unique<DebugBucket>(
- tile.id, tile.isRenderable(), tile.isComplete(), tile.modified,
- tile.expires, frame.debugOptions, context);
+ draw(Color::white(), gl::Unindexed<gl::Lines>(vertexBuffer, 4.0f * frame.pixelRatio));
+ draw(Color::black(), gl::Unindexed<gl::Points>(vertexBuffer, 2.0f));
+ draw(Color::black(), gl::Unindexed<gl::Lines>(vertexBuffer, 2.0f * frame.pixelRatio));
}
- auto& plainShader = shaders->fill;
- context.program = plainShader.getID();
- plainShader.u_matrix = matrix;
- plainShader.u_opacity = 1.0f;
-
- // Draw white outline
- plainShader.u_color = Color::white();
- context.lineWidth = 4.0f * frame.pixelRatio;
- tile.debugBucket->drawLines(plainShader, context);
-
-#if not MBGL_USE_GLES2
- // Draw line "end caps"
- MBGL_CHECK_ERROR(glPointSize(2));
- tile.debugBucket->drawPoints(plainShader, context);
-#endif // MBGL_USE_GLES2
-
- // Draw black text.
- plainShader.u_color = Color::black();
- context.lineWidth = 2.0f * frame.pixelRatio;
- tile.debugBucket->drawLines(plainShader, context);
-
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
-}
-
-void Painter::renderDebugFrame(const mat4 &matrix) {
- MBGL_DEBUG_GROUP("debug frame");
-
- // Disable depth test and don't count this towards the depth buffer,
- // but *don't* disable stencil test, as we want to clip the red tile border
- // to the tile viewport.
- context.depthTest = false;
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
-
- auto& plainShader = shaders->fill;
- context.program = plainShader.getID();
- plainShader.u_matrix = matrix;
- plainShader.u_opacity = 1.0f;
-
- // draw tile outline
- tileBorderArray.bind(plainShader, tileLineStripVertexBuffer, BUFFER_OFFSET_0, context);
- plainShader.u_color = { 1.0f, 0.0f, 0.0f, 1.0f };
- context.lineWidth = 4.0f * frame.pixelRatio;
- MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0,
- static_cast<GLsizei>(tileLineStripVertexBuffer.vertexCount)));
+ if (frame.debugOptions & MapDebugOptions::TileBorders) {
+ draw(Color::red(), gl::Unindexed<gl::LineStrip>(tileLineStripVertexBuffer, 4.0f * frame.pixelRatio));
+ }
}
#ifndef NDEBUG
void Painter::renderClipMasks(PaintParameters&) {
- context.stencilTest = false;
- context.depthTest = false;
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setDepthMode(gl::DepthMode::disabled());
+ context.setColorMode(gl::ColorMode::unblended());
context.program = 0;
- context.colorMask = { true, true, true, true };
#if not MBGL_USE_GLES2
context.pixelZoom = { 1, 1 };
@@ -126,14 +97,12 @@ void Painter::renderClipMasks(PaintParameters&) {
GL_UNSIGNED_BYTE, pixels.get()));
#endif // MBGL_USE_GLES2
}
-#endif // NDEBUG
-#ifndef NDEBUG
void Painter::renderDepthBuffer(PaintParameters&) {
- context.stencilTest = false;
- context.depthTest = false;
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setDepthMode(gl::DepthMode::disabled());
+ context.setColorMode(gl::ColorMode::unblended());
context.program = 0;
- context.colorMask = { true, true, true, true };
#if not MBGL_USE_GLES2
context.pixelZoom = { 1, 1 };
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index 95e514298a..b386e227d5 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -1,14 +1,12 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/map/view.hpp>
-
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/fill_uniforms.hpp>
#include <mbgl/util/convert.hpp>
namespace mbgl {
@@ -20,159 +18,116 @@ void Painter::renderFill(PaintParameters& parameters,
const FillLayer& layer,
const RenderTile& tile) {
const FillPaintProperties& properties = layer.impl->paint;
- mat4 vertexMatrix = tile.translatedMatrix(properties.fillTranslate,
- properties.fillTranslateAnchor,
- state);
-
- Color fillColor = properties.fillColor;
- float opacity = properties.fillOpacity;
-
- const bool isOutlineColorDefined = !properties.fillOutlineColor.isUndefined();
- Color strokeColor = isOutlineColorDefined? properties.fillOutlineColor : fillColor;
-
- const auto viewport = context.viewport.getCurrentValue();
- const std::array<GLfloat, 2> worldSize{{ static_cast<GLfloat>(viewport.size.width),
- static_cast<GLfloat>(viewport.size.height) }};
-
- bool pattern = !properties.fillPattern.value.from.empty();
- bool outline = properties.fillAntialias && !pattern && isOutlineColorDefined;
- bool fringeline = properties.fillAntialias && !pattern && !isOutlineColorDefined;
-
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = true;
- context.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio!
-
- auto& outlineShader = parameters.shaders.fillOutline;
- auto& patternShader = parameters.shaders.fillPattern;
- auto& outlinePatternShader = parameters.shaders.fillOutlinePattern;
- auto& plainShader = parameters.shaders.fill;
- // Because we're drawing top-to-bottom, and we update the stencil mask
- // befrom, we have to draw the outline first (!)
- if (outline && pass == RenderPass::Translucent) {
- context.program = outlineShader.getID();
- outlineShader.u_matrix = vertexMatrix;
-
- outlineShader.u_outline_color = strokeColor;
- outlineShader.u_opacity = opacity;
-
- // Draw the entire line
- outlineShader.u_world = worldSize;
- if (isOutlineColorDefined) {
- // If we defined a different color for the fill outline, we are
- // going to ignore the bits in 0x07 and just care about the global
- // clipping mask.
- setDepthSublayer(2); // OK
- } else {
- // Otherwise, we only want to drawFill the antialiased parts that are
- // *outside* the current shape. This is important in case the fill
- // or stroke color is translucent. If we wouldn't clip to outside
- // the current shape, some pixels from the outline stroke overlapped
- // the (non-antialiased) fill.
- setDepthSublayer(0); // OK
+ if (!properties.fillPattern.value.from.empty()) {
+ if (pass != RenderPass::Translucent) {
+ return;
}
- bucket.drawVertices(outlineShader, context, paintMode());
- }
- if (pattern) {
optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
properties.fillPattern.value.from, SpritePatternMode::Repeating);
- optional<SpriteAtlasPosition> imagePosB =
- spriteAtlas->getPosition(properties.fillPattern.value.to, SpritePatternMode::Repeating);
-
- // Image fill.
- if (pass == RenderPass::Translucent && imagePosA && imagePosB) {
- context.program = patternShader.getID();
- patternShader.u_matrix = vertexMatrix;
- patternShader.u_pattern_tl_a = imagePosA->tl;
- patternShader.u_pattern_br_a = imagePosA->br;
- patternShader.u_pattern_tl_b = imagePosB->tl;
- patternShader.u_pattern_br_b = imagePosB->br;
- patternShader.u_opacity = properties.fillOpacity;
- patternShader.u_image = 0;
- patternShader.u_mix = properties.fillPattern.value.t;
- patternShader.u_pattern_size_a = imagePosA->size;
- patternShader.u_pattern_size_b = imagePosB->size;
- patternShader.u_scale_a = properties.fillPattern.value.fromScale;
- patternShader.u_scale_b = properties.fillPattern.value.toScale;
- patternShader.u_tile_units_to_pixels = 1.0f / tile.id.pixelsToTileUnits(1.0f, state.getIntegerZoom());
-
- GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tile.id.canonical.z);
- GLint pixelX = tileSizeAtNearestZoom * (tile.id.canonical.x + tile.id.wrap * state.zoomScale(tile.id.canonical.z));
- GLint pixelY = tileSizeAtNearestZoom * tile.id.canonical.y;
- patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
- patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
-
- spriteAtlas->bind(true, context, 0);
+ optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(
+ properties.fillPattern.value.to, SpritePatternMode::Repeating);
- // Draw the actual triangles into the color & stencil buffer.
- setDepthSublayer(0);
- bucket.drawElements(patternShader, context, paintMode());
-
- if (properties.fillAntialias && !isOutlineColorDefined) {
- context.program = outlinePatternShader.getID();
- outlinePatternShader.u_matrix = vertexMatrix;
-
- outlinePatternShader.u_pattern_tl_a = imagePosA->tl;
- outlinePatternShader.u_pattern_br_a = imagePosA->br;
- outlinePatternShader.u_pattern_tl_b = imagePosB->tl;
- outlinePatternShader.u_pattern_br_b = imagePosB->br;
- outlinePatternShader.u_opacity = properties.fillOpacity;
- outlinePatternShader.u_image = 0;
- outlinePatternShader.u_mix = properties.fillPattern.value.t;
- outlinePatternShader.u_pattern_size_a = imagePosA->size;
- outlinePatternShader.u_pattern_size_b = imagePosB->size;
- outlinePatternShader.u_scale_a = properties.fillPattern.value.fromScale;
- outlinePatternShader.u_scale_b = properties.fillPattern.value.toScale;
- outlinePatternShader.u_tile_units_to_pixels = 1.0f / tile.id.pixelsToTileUnits(1.0f, state.getIntegerZoom());
- outlinePatternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
- outlinePatternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
-
- // Draw the entire line
- outlinePatternShader.u_world = worldSize;
-
- spriteAtlas->bind(true, context, 0);
-
- setDepthSublayer(2);
- bucket.drawVertices(outlinePatternShader, context, paintMode());
- }
+ if (!imagePosA || !imagePosB) {
+ return;
}
- } else {
- // No image fill.
- if ((fillColor.a >= 1.0f && opacity >= 1.0f) == (pass == RenderPass::Opaque)) {
- // Only draw the fill when it's either opaque and we're drawing opaque
- // fragments or when it's translucent and we're drawing translucent
- // fragments
- // Draw filling rectangle.
- context.program = plainShader.getID();
- plainShader.u_matrix = vertexMatrix;
- plainShader.u_color = fillColor;
- plainShader.u_opacity = opacity;
- // Draw the actual triangles into the color & stencil buffer.
- setDepthSublayer(1);
- bucket.drawElements(plainShader, context, paintMode());
+ spriteAtlas->bind(true, context, 0);
+
+ auto draw = [&] (uint8_t sublayer, auto& shader, const auto& subject) {
+ context.draw({
+ depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
+ stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ shader,
+ FillPatternUniforms::values(
+ tile.translatedMatrix(properties.fillTranslate.value,
+ properties.fillTranslateAnchor.value,
+ state),
+ properties.fillOpacity.value,
+ context.viewport.getCurrentValue().size,
+ *imagePosA,
+ *imagePosB,
+ properties.fillPattern.value,
+ tile.id,
+ state
+ ),
+ subject
+ });
+ };
+
+ draw(0,
+ parameters.shaders.fillPattern,
+ gl::Segmented<gl::Triangles>(
+ *bucket.vertexBuffer,
+ *bucket.triangleIndexBuffer,
+ bucket.triangleSegments));
+
+ if (!properties.fillAntialias.value || !properties.fillOutlineColor.isUndefined()) {
+ return;
}
- }
-
- // Because we're drawing top-to-bottom, and we update the stencil mask
- // below, we have to draw the outline first (!)
- if (fringeline && pass == RenderPass::Translucent) {
- context.program = outlineShader.getID();
- outlineShader.u_matrix = vertexMatrix;
- outlineShader.u_outline_color = fillColor;
- outlineShader.u_opacity = opacity;
+ draw(2,
+ parameters.shaders.fillOutlinePattern,
+ gl::Segmented<gl::Lines>(
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments,
+ 2.0f));
+ } else {
+ auto draw = [&] (uint8_t sublayer, auto& shader, Color outlineColor, const auto& subject) {
+ context.draw({
+ depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
+ stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ shader,
+ FillColorUniforms::values(
+ tile.translatedMatrix(properties.fillTranslate.value,
+ properties.fillTranslateAnchor.value,
+ state),
+ properties.fillOpacity.value,
+ properties.fillColor.value,
+ outlineColor,
+ context.viewport.getCurrentValue().size
+ ),
+ subject
+ });
+ };
+
+ if (properties.fillAntialias.value && !properties.fillOutlineColor.isUndefined() && pass == RenderPass::Translucent) {
+ draw(2,
+ parameters.shaders.fillOutline,
+ properties.fillOutlineColor.value,
+ gl::Segmented<gl::Lines>(
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments,
+ 2.0f));
+ }
- // Draw the entire line
- outlineShader.u_world = worldSize;
+ // Only draw the fill when it's opaque and we're drawing opaque fragments,
+ // or when it's translucent and we're drawing translucent fragments.
+ if ((properties.fillColor.value.a >= 1.0f && properties.fillOpacity.value >= 1.0f) == (pass == RenderPass::Opaque)) {
+ draw(1,
+ parameters.shaders.fill,
+ properties.fillOutlineColor.value,
+ gl::Segmented<gl::Triangles>(
+ *bucket.vertexBuffer,
+ *bucket.triangleIndexBuffer,
+ bucket.triangleSegments));
+ }
- setDepthSublayer(2);
- bucket.drawVertices(outlineShader, context, paintMode());
+ if (properties.fillAntialias.value && properties.fillOutlineColor.isUndefined() && pass == RenderPass::Translucent) {
+ draw(2,
+ parameters.shaders.fillOutline,
+ properties.fillColor.value,
+ gl::Segmented<gl::Lines>(
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments,
+ 2.0f));
+ }
}
}
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 9880564ddc..9fa6b15559 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -5,9 +5,9 @@
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/line_uniforms.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
-#include <mbgl/util/mat2.hpp>
namespace mbgl {
@@ -17,150 +17,73 @@ void Painter::renderLine(PaintParameters& parameters,
LineBucket& bucket,
const LineLayer& layer,
const RenderTile& tile) {
- // Abort early.
- if (pass == RenderPass::Opaque) return;
-
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
+ if (pass == RenderPass::Opaque) {
+ return;
+ }
const auto& properties = layer.impl->paint;
- const auto& layout = bucket.layout;
-
- // the distance over which the line edge fades out.
- // Retina devices need a smaller distance to avoid aliasing.
- float antialiasing = 1.0 / frame.pixelRatio;
-
- float blur = properties.lineBlur + antialiasing;
-
- const Color color = properties.lineColor;
- const float opacity = properties.lineOpacity;
- const float ratio = 1.0 / tile.id.pixelsToTileUnits(1.0, state.getZoom());
-
- mat2 antialiasingMatrix;
- matrix::identity(antialiasingMatrix);
- matrix::scale(antialiasingMatrix, antialiasingMatrix, 1.0, std::cos(state.getPitch()));
- matrix::rotate(antialiasingMatrix, antialiasingMatrix, state.getAngle());
- // calculate how much longer the real world distance is at the top of the screen
- // than at the middle of the screen.
- float topedgelength = std::sqrt(std::pow(state.getSize().height, 2.0f) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2.0f)));
- float x = state.getSize().height / 2.0f * std::tan(state.getPitch());
- float extra = (topedgelength + x) / topedgelength - 1.0f;
-
- mat4 vtxMatrix = tile.translatedMatrix(properties.lineTranslate,
- properties.lineTranslateAnchor,
- state);
-
- setDepthSublayer(0);
-
- auto& linesdfShader = parameters.shaders.lineSDF;
- auto& linepatternShader = parameters.shaders.linePattern;
- auto& lineShader = parameters.shaders.line;
+ auto draw = [&] (auto& shader, auto&& uniformValues) {
+ context.draw({
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ shader,
+ std::move(uniformValues),
+ gl::Segmented<gl::Triangles>(
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments
+ )
+ });
+ };
if (!properties.lineDasharray.value.from.empty()) {
- context.program = linesdfShader.getID();
-
- linesdfShader.u_matrix = vtxMatrix;
- linesdfShader.u_linewidth = properties.lineWidth / 2;
- linesdfShader.u_gapwidth = properties.lineGapWidth / 2;
- linesdfShader.u_antialiasing = antialiasing / 2;
- linesdfShader.u_ratio = ratio;
- linesdfShader.u_blur = blur;
- linesdfShader.u_color = color;
- linesdfShader.u_opacity = opacity;
-
- const LinePatternCap cap =
- layout.lineCap == LineCapType::Round ? LinePatternCap::Round : LinePatternCap::Square;
+ const LinePatternCap cap = bucket.layout.lineCap == LineCapType::Round
+ ? LinePatternCap::Round : LinePatternCap::Square;
LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, cap);
LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, cap);
- const float widthA = posA.width * properties.lineDasharray.value.fromScale * layer.impl->dashLineWidth;
- const float widthB = posB.width * properties.lineDasharray.value.toScale * layer.impl->dashLineWidth;
-
- float scaleXA = 1.0 / tile.id.pixelsToTileUnits(widthA, state.getIntegerZoom());
- float scaleYA = -posA.height / 2.0;
- float scaleXB = 1.0 / tile.id.pixelsToTileUnits(widthB, state.getIntegerZoom());
- float scaleYB = -posB.height / 2.0;
-
- linesdfShader.u_patternscale_a = {{ scaleXA, scaleYA }};
- linesdfShader.u_tex_y_a = posA.y;
- linesdfShader.u_patternscale_b = {{ scaleXB, scaleYB }};
- linesdfShader.u_tex_y_b = posB.y;
- linesdfShader.u_sdfgamma = lineAtlas->width / (std::min(widthA, widthB) * 256.0 * frame.pixelRatio) / 2;
- linesdfShader.u_mix = properties.lineDasharray.value.t;
- linesdfShader.u_extra = extra;
- linesdfShader.u_offset = -properties.lineOffset;
- linesdfShader.u_antialiasingmatrix = antialiasingMatrix;
-
- linesdfShader.u_image = 0;
lineAtlas->bind(context, 0);
- bucket.drawLineSDF(linesdfShader, context, paintMode());
+ draw(parameters.shaders.lineSDF,
+ LineSDFUniforms::values(
+ properties,
+ frame.pixelRatio,
+ tile,
+ state,
+ posA,
+ posB,
+ layer.impl->dashLineWidth,
+ lineAtlas->width));
} else if (!properties.linePattern.value.from.empty()) {
- optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
+ optional<SpriteAtlasPosition> posA = spriteAtlas->getPosition(
properties.linePattern.value.from, SpritePatternMode::Repeating);
- optional<SpriteAtlasPosition> imagePosB =
- spriteAtlas->getPosition(properties.linePattern.value.to, SpritePatternMode::Repeating);
+ optional<SpriteAtlasPosition> posB = spriteAtlas->getPosition(
+ properties.linePattern.value.to, SpritePatternMode::Repeating);
- if (!imagePosA || !imagePosB)
+ if (!posA || !posB)
return;
- context.program = linepatternShader.getID();
-
- linepatternShader.u_matrix = vtxMatrix;
- linepatternShader.u_linewidth = properties.lineWidth / 2;
- linepatternShader.u_gapwidth = properties.lineGapWidth / 2;
- linepatternShader.u_antialiasing = antialiasing / 2;
- linepatternShader.u_ratio = ratio;
- linepatternShader.u_blur = blur;
-
- linepatternShader.u_pattern_size_a = {{
- tile.id.pixelsToTileUnits((*imagePosA).size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
- (*imagePosA).size[1]
- }};
- linepatternShader.u_pattern_tl_a = (*imagePosA).tl;
- linepatternShader.u_pattern_br_a = (*imagePosA).br;
-
- linepatternShader.u_pattern_size_b = {{
- tile.id.pixelsToTileUnits((*imagePosB).size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
- (*imagePosB).size[1]
- }};
- linepatternShader.u_pattern_tl_b = (*imagePosB).tl;
- linepatternShader.u_pattern_br_b = (*imagePosB).br;
-
- linepatternShader.u_fade = properties.linePattern.value.t;
- linepatternShader.u_opacity = properties.lineOpacity;
- linepatternShader.u_extra = extra;
- linepatternShader.u_offset = -properties.lineOffset;
- linepatternShader.u_antialiasingmatrix = antialiasingMatrix;
-
- linepatternShader.u_image = 0;
spriteAtlas->bind(true, context, 0);
- bucket.drawLinePatterns(linepatternShader, context, paintMode());
+ draw(parameters.shaders.linePattern,
+ LinePatternUniforms::values(
+ properties,
+ frame.pixelRatio,
+ tile,
+ state,
+ *posA,
+ *posB));
} else {
- context.program = lineShader.getID();
-
- lineShader.u_matrix = vtxMatrix;
- lineShader.u_linewidth = properties.lineWidth / 2;
- lineShader.u_gapwidth = properties.lineGapWidth / 2;
- lineShader.u_antialiasing = antialiasing / 2;
- lineShader.u_ratio = ratio;
- lineShader.u_blur = blur;
- lineShader.u_extra = extra;
- lineShader.u_offset = -properties.lineOffset;
- lineShader.u_antialiasingmatrix = antialiasingMatrix;
-
- lineShader.u_color = color;
- lineShader.u_opacity = opacity;
-
- bucket.drawLines(lineShader, context, paintMode());
+ draw(parameters.shaders.line,
+ LineColorUniforms::values(
+ properties,
+ frame.pixelRatio,
+ tile,
+ state));
}
}
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index 98299ed342..e77b4cf535 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -1,11 +1,11 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_tile.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/renderer/raster_bucket.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/raster_uniforms.hpp>
namespace mbgl {
@@ -43,40 +43,39 @@ void Painter::renderRaster(PaintParameters& parameters,
RasterBucket& bucket,
const RasterLayer& layer,
const RenderTile& tile) {
- if (pass != RenderPass::Translucent) return;
+ if (pass != RenderPass::Translucent)
+ return;
+ if (!bucket.hasData())
+ return;
const RasterPaintProperties& properties = layer.impl->paint;
- if (bucket.hasData()) {
- auto& rasterShader = parameters.shaders.raster;
- auto& rasterVAO = parameters.shaders.coveringRasterArray;
+ assert(bucket.texture);
+ context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear);
+ context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear);
- context.program = rasterShader.getID();
- rasterShader.u_matrix = tile.matrix;
- rasterShader.u_buffer_scale = 1.0f;
- rasterShader.u_opacity0 = properties.rasterOpacity;
- rasterShader.u_opacity1 = 0;
-
- rasterShader.u_brightness_low = properties.rasterBrightnessMin;
- rasterShader.u_brightness_high = properties.rasterBrightnessMax;
- rasterShader.u_saturation_factor = saturationFactor(properties.rasterSaturation);
- rasterShader.u_contrast_factor = contrastFactor(properties.rasterContrast);
- rasterShader.u_spin_weights = spinWeights(properties.rasterHueRotate);
-
- context.stencilTest = false;
-
- rasterShader.u_image0 = 0; // GL_TEXTURE0
- rasterShader.u_image1 = 1; // GL_TEXTURE1
- rasterShader.u_tl_parent = {{ 0.0f, 0.0f }};
- rasterShader.u_scale_parent = 1.0f;
-
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- setDepthSublayer(0);
-
- bucket.drawRaster(rasterShader, rasterVertexBuffer, rasterVAO, context);
- }
+ context.draw({
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ parameters.shaders.raster,
+ RasterUniforms::values(
+ tile.matrix,
+ 0,
+ 1,
+ properties.rasterOpacity.value,
+ 0,
+ properties.rasterBrightnessMin.value,
+ properties.rasterBrightnessMax.value,
+ saturationFactor(properties.rasterSaturation.value),
+ contrastFactor(properties.rasterContrast.value),
+ spinWeights(properties.rasterHueRotate.value),
+ 1.0f,
+ 1.0f,
+ std::array<float, 2> {{ 0.0f, 0.0f }}
+ ),
+ gl::Unindexed<gl::TriangleStrip>(rasterVertexBuffer)
+ });
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index a460e6a9db..78de30ca17 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -7,6 +7,8 @@
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/shader/shaders.hpp>
+#include <mbgl/shader/symbol_uniforms.hpp>
+#include <mbgl/shader/collision_box_uniforms.hpp>
#include <mbgl/util/math.hpp>
#include <cmath>
@@ -15,254 +17,123 @@ namespace mbgl {
using namespace style;
-void Painter::renderSDF(SymbolBucket& bucket,
- const RenderTile& tile,
- float sdfFontSize,
- std::array<float, 2> texsize,
- SymbolSDFShader& sdfShader,
- void (SymbolBucket::*drawSDF)(SymbolSDFShader&, gl::Context&, PaintMode),
-
- // Layout
- AlignmentType rotationAlignment,
- AlignmentType pitchAlignment,
- float layoutSize,
-
- // Paint
- float opacity,
- Color color,
- Color haloColor,
- float haloWidth,
- float haloBlur,
- std::array<float, 2> translate,
- TranslateAnchorType translateAnchor,
- float paintSize)
-{
- mat4 vtxMatrix = tile.translatedMatrix(translate, translateAnchor, state);
-
- // If layerStyle.size > bucket.info.fontSize then labels may collide
- float fontSize = paintSize;
- float fontScale = fontSize / sdfFontSize;
-
- bool rotateWithMap = rotationAlignment == AlignmentType::Map;
- bool pitchWithMap = pitchAlignment == AlignmentType::Map;
-
- std::array<float, 2> extrudeScale;
- float gammaScale;
-
- if (pitchWithMap) {
- gammaScale = 1.0 / std::cos(state.getPitch());
- extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * fontScale);
- } else {
- gammaScale = 1.0;
- extrudeScale = {{
- pixelsToGLUnits[0] * fontScale * state.getAltitude(),
- pixelsToGLUnits[1] * fontScale * state.getAltitude()
- }};
- }
-
- context.program = sdfShader.getID();
- sdfShader.u_matrix = vtxMatrix;
- sdfShader.u_extrude_scale = extrudeScale;
- sdfShader.u_texsize = texsize;
- sdfShader.u_rotate_with_map = rotateWithMap;
- sdfShader.u_pitch_with_map = pitchWithMap;
- sdfShader.u_texture = 0;
- sdfShader.u_pitch = state.getPitch();
- sdfShader.u_bearing = -1.0f * state.getAngle();
- sdfShader.u_aspect_ratio = double(state.getSize().width) / state.getSize().height;
-
- // adjust min/max zooms for variable font sies
- float zoomAdjust = std::log(fontSize / layoutSize) / std::log(2);
-
- sdfShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
-
- frameHistory.bind(context, 1);
- sdfShader.u_fadetexture = 1;
-
- // The default gamma value has to be adjust for the current pixelratio so that we're not
- // drawing blurry font on retina screens.
- const float gamma = 0.105 * sdfFontSize / fontSize / frame.pixelRatio;
-
- const float sdfPx = 8.0f;
- const float blurOffset = 1.19f;
- const float haloOffset = 6.0f;
-
- // We're drawing in the translucent pass which is bottom-to-top, so we need
- // to draw the halo first.
- if (haloColor.a > 0.0f && haloWidth > 0.0f) {
- sdfShader.u_gamma = (haloBlur * blurOffset / fontScale / sdfPx + gamma) * gammaScale;
- sdfShader.u_color = haloColor;
- sdfShader.u_opacity = opacity;
- sdfShader.u_buffer = (haloOffset - haloWidth / fontScale) / sdfPx;
- (bucket.*drawSDF)(sdfShader, context, paintMode());
- }
-
- // Then, we draw the text/icon over the halo
- if (color.a > 0.0f) {
- sdfShader.u_gamma = gamma * gammaScale;
- sdfShader.u_color = color;
- sdfShader.u_opacity = opacity;
- sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f;
- (bucket.*drawSDF)(sdfShader, context, paintMode());
- }
-}
-
void Painter::renderSymbol(PaintParameters& parameters,
SymbolBucket& bucket,
const SymbolLayer& layer,
const RenderTile& tile) {
- // Abort early.
if (pass == RenderPass::Opaque) {
return;
}
- const auto& paint = layer.impl->paint;
const auto& layout = bucket.layout;
- context.depthMask = false;
-
- // TODO remove the `true ||` when #1673 is implemented
- const bool drawAcrossEdges = (frame.mapMode == MapMode::Continuous) && (true || !(layout.textAllowOverlap || layout.iconAllowOverlap ||
- layout.textIgnorePlacement || layout.iconIgnorePlacement));
-
- // Disable the stencil test so that labels aren't clipped to tile boundaries.
- //
- // Layers with features that may be drawn overlapping aren't clipped. These
- // layers are sorted in the y direction, and to draw the correct ordering near
- // tile edges the icons are included in both tiles and clipped when drawing.
- if (drawAcrossEdges) {
- context.stencilTest = false;
- } else {
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- }
+ frameHistory.bind(context, 1);
- setDepthSublayer(0);
+ auto draw = [&] (auto& shader,
+ auto&& uniformValues,
+ const auto& buffers,
+ const SymbolPropertyValues& values_)
+ {
+ // In some cases, we disable the stencil test so that labels aren't clipped
+ // to tile boundaries.
+ //
+ // Layers with features that may be drawn overlapping aren't clipped. These
+ // layers are sorted in the y direction, and to draw the correct ordering near
+ // tile edges the icons are included in both tiles and clipped when drawing.
+ //
+ // TODO remove the `true ||` when #1673 is implemented
+ const bool drawAcrossEdges = (frame.mapMode == MapMode::Continuous) && (true || !(layout.textAllowOverlap || layout.iconAllowOverlap ||
+ layout.textIgnorePlacement || layout.iconIgnorePlacement));
+
+ context.draw({
+ values_.pitchAlignment == AlignmentType::Map
+ ? depthModeForSublayer(0, gl::DepthMode::ReadOnly)
+ : gl::DepthMode::disabled(),
+ drawAcrossEdges
+ ? gl::StencilMode::disabled()
+ : stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ shader,
+ std::move(uniformValues),
+ gl::Segmented<gl::Triangles>(
+ *buffers.vertexBuffer,
+ *buffers.indexBuffer,
+ buffers.segments
+ )
+ });
+ };
if (bucket.hasIconData()) {
- if (layout.iconRotationAlignment == AlignmentType::Map) {
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- } else {
- context.depthTest = false;
- }
+ auto values = layer.impl->iconPropertyValues(layout);
- bool sdf = bucket.sdfIcons;
+ SpriteAtlas& atlas = *layer.impl->spriteAtlas;
+ const bool iconScaled = values.paintSize != 1.0f || frame.pixelRatio != atlas.getPixelRatio() || bucket.iconsNeedLinear;
+ const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || state.getPitch() != 0;
+ atlas.bind(bucket.sdfIcons || state.isChanging() || iconScaled || iconTransformed, context, 0);
- const float angleOffset =
- layout.iconRotationAlignment == AlignmentType::Map
- ? state.getAngle()
- : 0;
+ std::array<uint16_t, 2> texsize {{ atlas.getWidth(), atlas.getHeight() }};
- const float fontSize = layer.impl->iconSize;
- const float fontScale = fontSize / 1.0f;
-
- SpriteAtlas* activeSpriteAtlas = layer.impl->spriteAtlas;
- const bool iconScaled = fontScale != 1 || frame.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear;
- const bool iconTransformed = layout.iconRotationAlignment == AlignmentType::Map || angleOffset != 0 || state.getPitch() != 0;
- activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed, context, 0);
-
- if (sdf) {
- renderSDF(bucket,
- tile,
- 1.0f,
- {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }},
- parameters.shaders.symbolIconSDF,
- &SymbolBucket::drawIcons,
- layout.iconRotationAlignment,
- // icon-pitch-alignment is not yet implemented
- // and we simply inherit the rotation alignment
- layout.iconRotationAlignment,
- layout.iconSize,
- paint.iconOpacity,
- paint.iconColor,
- paint.iconHaloColor,
- paint.iconHaloWidth,
- paint.iconHaloBlur,
- paint.iconTranslate,
- paint.iconTranslateAnchor,
- layer.impl->iconSize);
- } else {
- mat4 vtxMatrix = tile.translatedMatrix(paint.iconTranslate,
- paint.iconTranslateAnchor,
- state);
-
- std::array<float, 2> extrudeScale;
-
- const bool alignedWithMap = layout.iconRotationAlignment == AlignmentType::Map;
- if (alignedWithMap) {
- extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * fontScale);
- } else {
- extrudeScale = {{
- pixelsToGLUnits[0] * fontScale * state.getAltitude(),
- pixelsToGLUnits[1] * fontScale * state.getAltitude()
- }};
+ if (bucket.sdfIcons) {
+ if (values.hasHalo()) {
+ draw(parameters.shaders.symbolIconSDF,
+ SymbolSDFUniforms::haloValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.icon,
+ values);
}
- auto& iconShader = parameters.shaders.symbolIcon;
+ if (values.hasForeground()) {
+ draw(parameters.shaders.symbolIconSDF,
+ SymbolSDFUniforms::foregroundValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.icon,
+ values);
+ }
+ } else {
+ draw(parameters.shaders.symbolIcon,
+ SymbolIconUniforms::values(values, texsize, pixelsToGLUnits, tile, state),
+ bucket.icon,
+ values);
+ }
+ }
- context.program = iconShader.getID();
- iconShader.u_matrix = vtxMatrix;
- iconShader.u_extrude_scale = extrudeScale;
- iconShader.u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }};
- iconShader.u_rotate_with_map = alignedWithMap;
- iconShader.u_texture = 0;
+ if (bucket.hasTextData()) {
+ glyphAtlas->bind(context, 0);
- // adjust min/max zooms for variable font sies
- float zoomAdjust = std::log(fontSize / layout.iconSize) / std::log(2);
- iconShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
- iconShader.u_opacity = paint.iconOpacity;
+ auto values = layer.impl->textPropertyValues(layout);
- frameHistory.bind(context, 1);
- iconShader.u_fadetexture = 1;
+ std::array<uint16_t, 2> texsize {{ glyphAtlas->width, glyphAtlas->height }};
- bucket.drawIcons(iconShader, context, paintMode());
+ if (values.hasHalo()) {
+ draw(parameters.shaders.symbolGlyph,
+ SymbolSDFUniforms::haloValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.text,
+ values);
}
- }
- if (bucket.hasTextData()) {
- if (layout.textPitchAlignment == AlignmentType::Map) {
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- } else {
- context.depthTest = false;
+ if (values.hasForeground()) {
+ draw(parameters.shaders.symbolGlyph,
+ SymbolSDFUniforms::foregroundValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.text,
+ values);
}
-
- glyphAtlas->bind(context, 0);
-
- renderSDF(bucket,
- tile,
- 24.0f,
- {{ float(glyphAtlas->width) / 4, float(glyphAtlas->height) / 4 }},
- parameters.shaders.symbolGlyph,
- &SymbolBucket::drawGlyphs,
- layout.textRotationAlignment,
- layout.textPitchAlignment,
- layout.textSize,
- paint.textOpacity,
- paint.textColor,
- paint.textHaloColor,
- paint.textHaloWidth,
- paint.textHaloBlur,
- paint.textTranslate,
- paint.textTranslateAnchor,
- layer.impl->textSize);
}
if (bucket.hasCollisionBoxData()) {
- context.stencilTest = false;
-
- auto& collisionBoxShader = shaders->collisionBox;
- context.program = collisionBoxShader.getID();
- collisionBoxShader.u_matrix = tile.matrix;
- // TODO: This was the overscaled z instead of the canonical z.
- collisionBoxShader.u_scale = std::pow(2, state.getZoom() - tile.id.canonical.z);
- collisionBoxShader.u_zoom = state.getZoom() * 10;
- collisionBoxShader.u_maxzoom = (tile.id.canonical.z + 1) * 10;
- context.lineWidth = 1.0f;
-
- bucket.drawCollisionBoxes(collisionBoxShader, context);
+ context.draw({
+ gl::DepthMode::disabled(),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ shaders->collisionBox,
+ CollisionBoxUniforms::values(
+ tile.matrix,
+ std::pow(2, state.getZoom() - tile.id.canonical.z),
+ state.getZoom() * 10,
+ (tile.id.canonical.z + 1) * 10
+ ),
+ gl::Unindexed<gl::Lines>(
+ *bucket.collisionBox.vertexBuffer,
+ 1.0f
+ )
+ });
}
}
diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp
index 80d6dfe8dd..bfe728c0b0 100644
--- a/src/mbgl/renderer/raster_bucket.cpp
+++ b/src/mbgl/renderer/raster_bucket.cpp
@@ -2,7 +2,6 @@
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/shader/raster_shader.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
namespace mbgl {
@@ -25,23 +24,8 @@ void RasterBucket::render(Painter& painter,
painter.renderRaster(parameters, *this, *layer.as<RasterLayer>(), tile);
}
-void RasterBucket::drawRaster(RasterShader& shader,
- gl::VertexBuffer<RasterVertex>& vertices,
- gl::VertexArrayObject& array,
- gl::Context& context) {
- assert(texture);
- context.bindTexture(*texture, 0, gl::TextureFilter::Linear);
- context.bindTexture(*texture, 1, gl::TextureFilter::Linear);
- array.bind(shader, vertices, BUFFER_OFFSET_0, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, static_cast<GLsizei>(vertices.vertexCount)));
-}
-
bool RasterBucket::hasData() const {
return true;
}
-bool RasterBucket::needsClipping() const {
- return false;
-}
-
} // namespace mbgl
diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp
index b0d3ca49c7..9648e954bd 100644
--- a/src/mbgl/renderer/raster_bucket.hpp
+++ b/src/mbgl/renderer/raster_bucket.hpp
@@ -7,15 +7,6 @@
namespace mbgl {
-class RasterShader;
-class RasterVertex;
-
-namespace gl {
-class Context;
-template <class> class VertexBuffer;
-class VertexArrayObject;
-} // namespace gl
-
class RasterBucket : public Bucket {
public:
RasterBucket(PremultipliedImage&&);
@@ -23,11 +14,7 @@ public:
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
-
- void drawRaster(RasterShader&, gl::VertexBuffer<RasterVertex>&, gl::VertexArrayObject&, gl::Context&);
-private:
PremultipliedImage image;
optional<gl::Texture> texture;
};
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index 565c58c7ed..5edf742917 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -1,10 +1,6 @@
#include <mbgl/renderer/symbol_bucket.hpp>
#include <mbgl/renderer/painter.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/shader/symbol_sdf_shader.hpp>
-#include <mbgl/shader/symbol_icon_shader.hpp>
-#include <mbgl/shader/collision_box_shader.hpp>
-#include <mbgl/gl/gl.hpp>
namespace mbgl {
@@ -31,7 +27,7 @@ void SymbolBucket::upload(gl::Context& context) {
icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles));
}
- if (hasCollisionBoxData()) {
+ if (!collisionBox.vertices.empty()) {
collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices));
}
@@ -51,74 +47,15 @@ bool SymbolBucket::hasData() const {
}
bool SymbolBucket::hasTextData() const {
- return !text.groups.empty();
+ return !text.segments.empty();
}
bool SymbolBucket::hasIconData() const {
- return !icon.groups.empty();
+ return !icon.segments.empty();
}
bool SymbolBucket::hasCollisionBoxData() const {
- return !collisionBox.groups.empty();
-}
-
-bool SymbolBucket::needsClipping() const {
- return mode == MapMode::Still;
-}
-
-void SymbolBucket::drawGlyphs(SymbolSDFShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- GLbyte* elements_index = BUFFER_OFFSET_0;
- for (auto& group : text.groups) {
- group.getVAO(shader, paintMode).bind(
- shader, *text.vertexBuffer, *text.indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * text.vertexBuffer->vertexSize;
- elements_index += group.indexLength * text.indexBuffer->primitiveSize;
- }
-}
-
-void SymbolBucket::drawIcons(SymbolSDFShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- GLbyte* elements_index = BUFFER_OFFSET_0;
- for (auto& group : icon.groups) {
- group.getVAO(shader, paintMode).bind(
- shader, *icon.vertexBuffer, *icon.indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * icon.vertexBuffer->vertexSize;
- elements_index += group.indexLength * icon.indexBuffer->primitiveSize;
- }
-}
-
-void SymbolBucket::drawIcons(SymbolIconShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- GLbyte* elements_index = BUFFER_OFFSET_0;
- for (auto& group : icon.groups) {
- group.getVAO(shader, paintMode).bind(
- shader, *icon.vertexBuffer, *icon.indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * icon.vertexBuffer->vertexSize;
- elements_index += group.indexLength * icon.indexBuffer->primitiveSize;
- }
-}
-
-void SymbolBucket::drawCollisionBoxes(CollisionBoxShader& shader,
- gl::Context& context) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- for (auto& group : collisionBox.groups) {
- group.getVAO(shader, PaintMode::Regular).bind(
- shader, *collisionBox.vertexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(group.vertexLength)));
- }
+ return bool(collisionBox.vertexBuffer);
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index e5180c31e2..a905e25363 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -1,24 +1,19 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/segment.hpp>
#include <mbgl/shader/symbol_vertex.hpp>
#include <mbgl/shader/collision_box_vertex.hpp>
#include <mbgl/text/glyph_range.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
-#include <memory>
#include <vector>
namespace mbgl {
-class SymbolSDFShader;
-class SymbolIconShader;
-class CollisionBoxShader;
-
class SymbolBucket : public Bucket {
public:
SymbolBucket(const MapMode,
@@ -32,25 +27,16 @@ public:
bool hasTextData() const;
bool hasIconData() const;
bool hasCollisionBoxData() const;
- bool needsClipping() const override;
-
- void drawGlyphs(SymbolSDFShader&, gl::Context&, PaintMode);
- void drawIcons(SymbolSDFShader&, gl::Context&, PaintMode);
- void drawIcons(SymbolIconShader&, gl::Context&, PaintMode);
- void drawCollisionBoxes(CollisionBoxShader&, gl::Context&);
const MapMode mode;
const style::SymbolLayoutProperties layout;
const bool sdfIcons;
const bool iconsNeedLinear;
-private:
- friend class SymbolLayout;
-
struct TextBuffer {
std::vector<SymbolVertex> vertices;
std::vector<gl::Triangle> triangles;
- std::vector<ElementGroup<SymbolSDFShader>> groups;
+ std::vector<gl::Segment> segments;
optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
@@ -59,7 +45,7 @@ private:
struct IconBuffer {
std::vector<SymbolVertex> vertices;
std::vector<gl::Triangle> triangles;
- std::vector<ElementGroup<SymbolSDFShader, SymbolIconShader>> groups;
+ std::vector<gl::Segment> segments;
optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
@@ -67,11 +53,7 @@ private:
struct CollisionBoxBuffer {
std::vector<CollisionBoxVertex> vertices;
- std::vector<gl::Line> lines;
- std::vector<ElementGroup<CollisionBoxShader>> groups;
-
optional<gl::VertexBuffer<CollisionBoxVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Line>> indexBuffer;
} collisionBox;
};