summaryrefslogtreecommitdiff
path: root/src/mbgl/programs
diff options
context:
space:
mode:
authorAnand Thakker <anandthakker@users.noreply.github.com>2017-04-06 15:29:59 -0400
committerGitHub <noreply@github.com>2017-04-06 15:29:59 -0400
commit693c9f3641b3189b4cd439049904c95a516ae609 (patch)
tree8341a16f57ff184a2fe9e085c490e8762eb206ce /src/mbgl/programs
parentf9cc044357d60dd5cf15ba951384529f88802089 (diff)
downloadqtlocation-mapboxgl-693c9f3641b3189b4cd439049904c95a516ae609.tar.gz
[core] Add DDS support for {text,icon}-size (#8593)
* Update gl-js and generate style code * Factor out packUint8Pair() helper function * Draft implementation of DDS for {text,icon}-size Ports https://github.com/mapbox/mapbox-gl-js/pull/4455 * Fix text-size/composite-function-line-placement test * Refactor to PaintPropertyBinders-like strategy * Dedupe gl::Program construction * Use exponential function base for interpolation * Dedupe coveringZoomStops method * Fixup tests * Fix CI errors (hidden within #if block)
Diffstat (limited to 'src/mbgl/programs')
-rw-r--r--src/mbgl/programs/attributes.hpp19
-rw-r--r--src/mbgl/programs/collision_box_program.hpp2
-rw-r--r--src/mbgl/programs/line_program.hpp2
-rw-r--r--src/mbgl/programs/program.hpp55
-rw-r--r--src/mbgl/programs/symbol_program.cpp60
-rw-r--r--src/mbgl/programs/symbol_program.hpp356
6 files changed, 400 insertions, 94 deletions
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
index 7d39c04395..e9ca18927e 100644
--- a/src/mbgl/programs/attributes.hpp
+++ b/src/mbgl/programs/attributes.hpp
@@ -8,6 +8,16 @@
namespace mbgl {
namespace attributes {
+/*
+ * Pack a pair of values, interpreted as uint8's, into a single float.
+ * Used to conserve vertex attributes. Values are unpacked in the vertex
+ * shader using the `unpack_float()` function, defined in _prelude.vertex.glsl.
+ */
+template <typename T>
+inline uint16_t packUint8Pair(T a, T b) {
+ return static_cast<uint16_t>(a) * 256 + static_cast<uint16_t>(b);
+}
+
// Layout attributes
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos);
@@ -15,10 +25,15 @@ MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude);
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset);
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos);
-template <std::size_t N>
+template <typename T, std::size_t N>
struct a_data {
static auto name() { return "a_data"; }
- using Type = gl::Attribute<uint8_t, N>;
+ using Type = gl::Attribute<T, N>;
+};
+
+struct a_size {
+ static auto name() { return "a_size"; }
+ using Type = gl::Attribute<uint16_t, 3>;
};
template <std::size_t N>
diff --git a/src/mbgl/programs/collision_box_program.hpp b/src/mbgl/programs/collision_box_program.hpp
index 78ed6aa0c9..89b69484fd 100644
--- a/src/mbgl/programs/collision_box_program.hpp
+++ b/src/mbgl/programs/collision_box_program.hpp
@@ -18,7 +18,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom);
using CollisionBoxAttributes = gl::Attributes<
attributes::a_pos,
attributes::a_extrude,
- attributes::a_data<2>>;
+ attributes::a_data<uint8_t, 2>>;
class CollisionBoxProgram : public Program<
shaders::collision_box,
diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp
index 842b4cc602..b2e55a4f3b 100644
--- a/src/mbgl/programs/line_program.hpp
+++ b/src/mbgl/programs/line_program.hpp
@@ -32,7 +32,7 @@ MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_gl_units_to_pixels);
struct LineLayoutAttributes : gl::Attributes<
attributes::a_pos,
- attributes::a_data<4>>
+ attributes::a_data<uint8_t, 4>>
{};
class LineProgram : public Program<
diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp
index 8925bc75d6..7eec15e755 100644
--- a/src/mbgl/programs/program.hpp
+++ b/src/mbgl/programs/program.hpp
@@ -34,55 +34,12 @@ public:
ProgramType program;
Program(gl::Context& context, const ProgramParameters& programParameters)
- : program([&] {
-#if MBGL_HAS_BINARY_PROGRAMS
- if (!programParameters.cacheDir.empty() && context.supportsProgramBinaries()) {
- const std::string vertexSource =
- shaders::vertexSource(programParameters, Shaders::vertexSource);
- const std::string fragmentSource =
- shaders::fragmentSource(programParameters, Shaders::fragmentSource);
- const std::string cachePath =
- shaders::programCachePath(programParameters, Shaders::name);
- const std::string identifier =
- shaders::programIdentifier(vertexSource, fragmentSource);
-
- try {
- if (auto cachedBinaryProgram = util::readFile(cachePath)) {
- const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram));
- if (binaryProgram.identifier() == identifier) {
- return ProgramType{ context, binaryProgram };
- } else {
- Log::Warning(Event::OpenGL,
- "Cached program %s changed. Recompilation required.",
- Shaders::name);
- }
- }
- } catch (std::runtime_error& error) {
- Log::Warning(Event::OpenGL, "Could not load cached program: %s",
- error.what());
- }
-
- // Compile the shader
- ProgramType result{ context, vertexSource, fragmentSource };
-
- try {
- if (const auto binaryProgram =
- result.template get<BinaryProgram>(context, identifier)) {
- util::write_file(cachePath, binaryProgram->serialize());
- Log::Warning(Event::OpenGL, "Caching program in: %s", cachePath.c_str());
- }
- } catch (std::runtime_error& error) {
- Log::Warning(Event::OpenGL, "Failed to cache program: %s", error.what());
- }
-
- return std::move(result);
- }
-#endif
- return ProgramType{
- context, shaders::vertexSource(programParameters, Shaders::vertexSource),
- shaders::fragmentSource(programParameters, Shaders::fragmentSource)
- };
- }()) {
+ : program(ProgramType::createProgram(
+ context,
+ programParameters,
+ Shaders::name,
+ Shaders::vertexSource,
+ Shaders::fragmentSource)) {
}
template <class DrawMode>
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
index 19fe2bc2f6..86f61c4ad2 100644
--- a/src/mbgl/programs/symbol_program.cpp
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -3,6 +3,7 @@
#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/util/enum.hpp>
+#include <mbgl/math/clamp.hpp>
namespace mbgl {
@@ -10,51 +11,66 @@ using namespace style;
static_assert(sizeof(SymbolLayoutVertex) == 16, "expected SymbolLayoutVertex size");
+std::unique_ptr<SymbolSizeBinder> SymbolSizeBinder::create(const float tileZoom,
+ const style::DataDrivenPropertyValue<float>& sizeProperty,
+ const float defaultValue) {
+ return sizeProperty.match(
+ [&] (const style::CompositeFunction<float>& function) -> std::unique_ptr<SymbolSizeBinder> {
+ return std::make_unique<CompositeFunctionSymbolSizeBinder>(tileZoom, function, defaultValue);
+ },
+ [&] (const style::SourceFunction<float>& function) {
+ return std::make_unique<SourceFunctionSymbolSizeBinder>(tileZoom, function, defaultValue);
+ },
+ [&] (const auto& value) -> std::unique_ptr<SymbolSizeBinder> {
+ return std::make_unique<ConstantSymbolSizeBinder>(tileZoom, value, defaultValue);
+ }
+ );
+}
+
template <class Values, class...Args>
-Values makeValues(const style::SymbolPropertyValues& values,
+Values makeValues(const bool isText,
+ const style::SymbolPropertyValues& values,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
const RenderTile& tile,
const TransformState& state,
Args&&... args) {
std::array<float, 2> extrudeScale;
-
- const float scale = values.paintSize / values.sdfScale;
if (values.pitchAlignment == AlignmentType::Map) {
- extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * scale);
+ extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()));
} else {
extrudeScale = {{
- pixelsToGLUnits[0] * scale * state.getCameraToCenterDistance(),
- pixelsToGLUnits[1] * scale * state.getCameraToCenterDistance()
+ pixelsToGLUnits[0] * state.getCameraToCenterDistance(),
+ pixelsToGLUnits[1] * state.getCameraToCenterDistance()
}};
}
-
- // adjust min/max zooms for variable font sies
- float zoomAdjust = std::log(values.paintSize / values.layoutSize) / std::log(2);
-
+
return Values {
uniforms::u_matrix::Value{ tile.translatedMatrix(values.translate,
values.translateAnchor,
state) },
uniforms::u_extrude_scale::Value{ extrudeScale },
uniforms::u_texsize::Value{ std::array<float, 2> {{ float(texsize.width) / 4, float(texsize.height) / 4 }} },
- uniforms::u_zoom::Value{ float((state.getZoom() - zoomAdjust) * 10) },
+ uniforms::u_zoom::Value{ float(state.getZoom()) },
uniforms::u_rotate_with_map::Value{ values.rotationAlignment == AlignmentType::Map },
uniforms::u_texture::Value{ 0 },
uniforms::u_fadetexture::Value{ 1 },
+ uniforms::u_is_text::Value{ isText },
std::forward<Args>(args)...
};
}
SymbolIconProgram::UniformValues
-SymbolIconProgram::uniformValues(const style::SymbolPropertyValues& values,
+SymbolIconProgram::uniformValues(const bool isText,
+ const style::SymbolPropertyValues& values,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
const RenderTile& tile,
const TransformState& state)
{
return makeValues<SymbolIconProgram::UniformValues>(
+ isText,
values,
texsize,
pixelsToGLUnits,
@@ -64,26 +80,26 @@ SymbolIconProgram::uniformValues(const style::SymbolPropertyValues& values,
}
template <class PaintProperties>
-typename SymbolSDFProgram<PaintProperties>::UniformValues SymbolSDFProgram<PaintProperties>::uniformValues(const style::SymbolPropertyValues& values,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile& tile,
- const TransformState& state,
- const SymbolSDFPart part)
+typename SymbolSDFProgram<PaintProperties>::UniformValues SymbolSDFProgram<PaintProperties>::uniformValues(
+ const bool isText,
+ const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ const SymbolSDFPart part)
{
- const float scale = values.paintSize / values.sdfScale;
-
- const float gammaScale = scale * (values.pitchAlignment == AlignmentType::Map
+ const float gammaScale = (values.pitchAlignment == AlignmentType::Map
? std::cos(state.getPitch())
: 1.0) * state.getCameraToCenterDistance();
return makeValues<SymbolSDFProgram<PaintProperties>::UniformValues>(
+ isText,
values,
texsize,
pixelsToGLUnits,
tile,
state,
- uniforms::u_font_scale::Value{ scale },
uniforms::u_gamma_scale::Value{ gammaScale },
uniforms::u_pitch::Value{ state.getPitch() },
uniforms::u_bearing::Value{ -1.0f * state.getAngle() },
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index fdd1aa5c3b..ae50e790be 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -1,6 +1,10 @@
#pragma once
-#include <mbgl/programs/program.hpp>
+#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/program.hpp>
+#include <mbgl/math/clamp.hpp>
+#include <mbgl/util/interpolate.hpp>
+
#include <mbgl/programs/attributes.hpp>
#include <mbgl/programs/uniforms.hpp>
#include <mbgl/shaders/symbol_icon.hpp>
@@ -10,6 +14,7 @@
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
+
#include <cmath>
#include <array>
@@ -30,14 +35,19 @@ MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_texture);
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_fadetexture);
MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio);
MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_halo);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_font_scale);
MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma_scale);
+
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_text);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_size_zoom_constant);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_size_feature_constant);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_size_t);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_size);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_layout_size);
} // namespace uniforms
struct SymbolLayoutAttributes : gl::Attributes<
attributes::a_pos_offset,
- attributes::a_texture_pos,
- attributes::a_data<4>>
+ attributes::a_data<uint16_t, 4>>
{
static Vertex vertex(Point<float> a,
Point<float> o,
@@ -57,19 +67,324 @@ struct SymbolLayoutAttributes : gl::Attributes<
}},
{{
static_cast<uint16_t>(tx / 4),
- static_cast<uint16_t>(ty / 4)
- }},
+ static_cast<uint16_t>(ty / 4),
+ mbgl::attributes::packUint8Pair(
+ static_cast<uint8_t>(labelminzoom * 10), // 1/10 zoom levels: z16 == 160
+ static_cast<uint8_t>(labelangle)
+ ),
+ mbgl::attributes::packUint8Pair(
+ static_cast<uint8_t>(minzoom * 10),
+ static_cast<uint8_t>(::fmin(maxzoom, 25) * 10)
+ )
+ }}
+ };
+ }
+};
+
+class SymbolSizeAttributes : public gl::Attributes<attributes::a_size> {
+public:
+ using Attribute = attributes::a_size::Type;
+};
+
+// Mimic the PaintPropertyBinder technique specifically for the {text,icon}-size layout properties
+// in order to provide a 'custom' scheme for encoding the necessary attribute data. As with
+// PaintPropertyBinder, SymbolSizeBinder is an abstract class whose implementations handle the
+// particular attribute & uniform logic needed by each possible type of the {Text,Icon}Size properties.
+class SymbolSizeBinder {
+public:
+ using Uniforms = gl::Uniforms<
+ uniforms::u_is_size_zoom_constant,
+ uniforms::u_is_size_feature_constant,
+ uniforms::u_size_t,
+ uniforms::u_size,
+ uniforms::u_layout_size>;
+ using UniformValues = Uniforms::Values;
+
+ static std::unique_ptr<SymbolSizeBinder> create(const float tileZoom,
+ const style::DataDrivenPropertyValue<float>& sizeProperty,
+ const float defaultValue);
+
+ virtual SymbolSizeAttributes::Bindings attributeBindings(const style::PossiblyEvaluatedPropertyValue<float> currentValue) const = 0;
+ virtual void populateVertexVector(const GeometryTileFeature& feature) = 0;
+ virtual UniformValues uniformValues(float currentZoom) const = 0;
+ virtual void upload(gl::Context&) = 0;
+};
+
+// Return the smallest range of stops that covers the interval [lowerZoom, upperZoom]
+template <class Stops>
+Range<float> getCoveringStops(Stops s, float lowerZoom, float upperZoom) {
+ assert(!s.stops.empty());
+ auto minIt = s.stops.lower_bound(lowerZoom);
+ auto maxIt = s.stops.lower_bound(upperZoom);
+
+ // lower_bound yields first element >= lowerZoom, but we want the *last*
+ // element <= lowerZoom, so if we found a stop > lowerZoom, back up by one.
+ if (minIt != s.stops.begin() && minIt->first > lowerZoom) {
+ minIt--;
+ }
+ return Range<float> {
+ minIt == s.stops.end() ? s.stops.rbegin()->first : minIt->first,
+ maxIt == s.stops.end() ? s.stops.rbegin()->first : maxIt->first
+ };
+}
+
+class ConstantSymbolSizeBinder : public SymbolSizeBinder {
+public:
+ using PropertyValue = variant<float, style::CameraFunction<float>>;
+
+ ConstantSymbolSizeBinder(const float /*tileZoom*/, const float& size, const float /*defaultValue*/)
+ : layoutSize(size) {}
+
+ ConstantSymbolSizeBinder(const float /*tileZoom*/, const style::Undefined&, const float defaultValue)
+ : layoutSize(defaultValue) {}
+
+ ConstantSymbolSizeBinder(const float tileZoom, const style::CameraFunction<float>& function_, const float /*defaultValue*/)
+ : layoutSize(function_.evaluate(tileZoom + 1)) {
+ function_.stops.match(
+ [&] (const style::ExponentialStops<float>& stops) {
+ coveringRanges = std::make_tuple(
+ getCoveringStops(stops, tileZoom, tileZoom + 1),
+ Range<float> { function_.evaluate(tileZoom), function_.evaluate(tileZoom + 1) }
+ );
+ functionInterpolationBase = stops.base;
+ },
+ [&] (const style::IntervalStops<float>&) {
+ function = function_;
+ }
+ );
+ }
+
+ SymbolSizeAttributes::Bindings attributeBindings(const style::PossiblyEvaluatedPropertyValue<float>) const override {
+ return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::ConstantBinding {{{0, 0, 0}}} };
+ }
+ void upload(gl::Context&) override {}
+ void populateVertexVector(const GeometryTileFeature&) override {};
+
+ UniformValues uniformValues(float currentZoom) const override {
+ float size = layoutSize;
+ bool isZoomConstant = !(coveringRanges || function);
+ if (coveringRanges) {
+ // Even though we could get the exact value of the camera function
+ // at z = currentZoom, we intentionally do not: instead, we interpolate
+ // between the camera function values at a pair of zoom stops covering
+ // [tileZoom, tileZoom + 1] in order to be consistent with this
+ // restriction on composite functions.
+ const Range<float>& zoomLevels = std::get<0>(*coveringRanges);
+ const Range<float>& sizeLevels = std::get<1>(*coveringRanges);
+ float t = util::clamp(
+ util::interpolationFactor(*functionInterpolationBase, zoomLevels, currentZoom),
+ 0.0f, 1.0f
+ );
+ size = sizeLevels.min + t * (sizeLevels.max - sizeLevels.min);
+ } else if (function) {
+ size = function->evaluate(currentZoom);
+ }
+
+ return UniformValues {
+ uniforms::u_is_size_zoom_constant::Value{ isZoomConstant },
+ uniforms::u_is_size_feature_constant::Value{ true },
+ uniforms::u_size_t::Value{ 0.0f }, // unused
+ uniforms::u_size::Value{ size },
+ uniforms::u_layout_size::Value{ layoutSize }
+ };
+ }
+
+ float layoutSize;
+ // used for exponential functions
+ optional<std::tuple<Range<float>, Range<float>>> coveringRanges;
+ optional<float> functionInterpolationBase;
+ // used for interval functions
+ optional<style::CameraFunction<float>> function;
+};
+
+class SourceFunctionSymbolSizeBinder : public SymbolSizeBinder {
+public:
+ using Vertex = gl::detail::Vertex<gl::Attribute<uint16_t, 1>>;
+ using VertexVector = gl::VertexVector<Vertex>;
+ using VertexBuffer = gl::VertexBuffer<Vertex>;
+
+ SourceFunctionSymbolSizeBinder(const float /*tileZoom*/, const style::SourceFunction<float>& function_, const float defaultValue_)
+ : function(function_),
+ defaultValue(defaultValue_) {
+ }
+
+ SymbolSizeAttributes::Bindings attributeBindings(const style::PossiblyEvaluatedPropertyValue<float> currentValue) const override {
+ if (currentValue.isConstant()) {
+ return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::ConstantBinding {{{0, 0, 0}}} };
+ }
+
+ return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::variableBinding(*buffer, 0, 1) };
+ }
+
+ void populateVertexVector(const GeometryTileFeature& feature) override {
+ const auto sizeVertex = Vertex {
{{
- static_cast<uint8_t>(labelminzoom * 10), // 1/10 zoom levels: z16 == 160
- static_cast<uint8_t>(labelangle),
- static_cast<uint8_t>(minzoom * 10),
- static_cast<uint8_t>(::fmin(maxzoom, 25) * 10)
+ static_cast<uint16_t>(function.evaluate(feature, defaultValue) * 10)
}}
};
+
+ vertices.emplace_back(sizeVertex);
+ vertices.emplace_back(sizeVertex);
+ vertices.emplace_back(sizeVertex);
+ vertices.emplace_back(sizeVertex);
+ };
+
+ UniformValues uniformValues(float) const override {
+ return UniformValues {
+ uniforms::u_is_size_zoom_constant::Value{ true },
+ uniforms::u_is_size_feature_constant::Value{ false },
+ uniforms::u_size_t::Value{ 0.0f }, // unused
+ uniforms::u_size::Value{ 0.0f }, // unused
+ uniforms::u_layout_size::Value{ 0.0f } // unused
+ };
+ }
+
+ void upload(gl::Context& context) override {
+ buffer = VertexBuffer { context.createVertexBuffer(std::move(vertices)) };
+ }
+
+ const style::SourceFunction<float>& function;
+ const float defaultValue;
+
+ VertexVector vertices;
+ optional<VertexBuffer> buffer;
+};
+
+class CompositeFunctionSymbolSizeBinder: public SymbolSizeBinder {
+public:
+ using Vertex = SymbolSizeAttributes::Vertex;
+ using VertexVector = gl::VertexVector<Vertex>;
+ using VertexBuffer = gl::VertexBuffer<Vertex>;
+
+ CompositeFunctionSymbolSizeBinder(const float tileZoom, const style::CompositeFunction<float>& function_, const float defaultValue_)
+ : function(function_),
+ defaultValue(defaultValue_),
+ layoutZoom(tileZoom + 1),
+ coveringZoomStops(function.stops.match(
+ [&] (const auto& stops) {
+ return getCoveringStops(stops, tileZoom, tileZoom + 1); }))
+ {}
+
+ SymbolSizeAttributes::Bindings attributeBindings(const style::PossiblyEvaluatedPropertyValue<float> currentValue) const override {
+ if (currentValue.isConstant()) {
+ return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::ConstantBinding {{{0, 0, 0}}} };
+ }
+
+ return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::variableBinding(*buffer, 0) };
+ }
+
+ void populateVertexVector(const GeometryTileFeature& feature) override {
+ const auto sizeVertex = Vertex {
+ {{
+ static_cast<uint16_t>(function.evaluate(coveringZoomStops.min, feature, defaultValue) * 10),
+ static_cast<uint16_t>(function.evaluate(coveringZoomStops.max, feature, defaultValue) * 10),
+ static_cast<uint16_t>(function.evaluate(layoutZoom, feature, defaultValue) * 10)
+ }}
+ };
+
+ vertices.emplace_back(sizeVertex);
+ vertices.emplace_back(sizeVertex);
+ vertices.emplace_back(sizeVertex);
+ vertices.emplace_back(sizeVertex);
+ };
+
+ UniformValues uniformValues(float currentZoom) const override {
+ float sizeInterpolationT = util::clamp(
+ util::interpolationFactor(1.0f, coveringZoomStops, currentZoom),
+ 0.0f, 1.0f
+ );
+
+ return UniformValues {
+ uniforms::u_is_size_zoom_constant::Value{ false },
+ uniforms::u_is_size_feature_constant::Value{ false },
+ uniforms::u_size_t::Value{ sizeInterpolationT },
+ uniforms::u_size::Value{ 0.0f }, // unused
+ uniforms::u_layout_size::Value{ 0.0f } // unused
+ };
+ }
+
+ void upload(gl::Context& context) override {
+ buffer = VertexBuffer { context.createVertexBuffer(std::move(vertices)) };
}
+
+ const style::CompositeFunction<float>& function;
+ const float defaultValue;
+ float layoutZoom;
+ Range<float> coveringZoomStops;
+
+ VertexVector vertices;
+ optional<VertexBuffer> buffer;
};
-class SymbolIconProgram : public Program<
+
+template <class Shaders,
+ class Primitive,
+ class LayoutAttrs,
+ class Uniforms,
+ class PaintProperties>
+class SymbolProgram {
+public:
+ using LayoutAttributes = LayoutAttrs;
+ using LayoutVertex = typename LayoutAttributes::Vertex;
+
+ using LayoutAndSizeAttributes = gl::ConcatenateAttributes<LayoutAttributes, SymbolSizeAttributes>;
+
+ using PaintPropertyBinders = typename PaintProperties::Binders;
+ using PaintAttributes = typename PaintPropertyBinders::Attributes;
+ using Attributes = gl::ConcatenateAttributes<LayoutAndSizeAttributes, PaintAttributes>;
+
+ using UniformValues = typename Uniforms::Values;
+ using SizeUniforms = typename SymbolSizeBinder::Uniforms;
+ using PaintUniforms = typename PaintPropertyBinders::Uniforms;
+ using AllUniforms = gl::ConcatenateUniforms<Uniforms, gl::ConcatenateUniforms<SizeUniforms, PaintUniforms>>;
+
+ using ProgramType = gl::Program<Primitive, Attributes, AllUniforms>;
+
+ ProgramType program;
+
+ SymbolProgram(gl::Context& context, const ProgramParameters& programParameters)
+ : program(ProgramType::createProgram(
+ context,
+ programParameters,
+ Shaders::name,
+ Shaders::vertexSource,
+ Shaders::fragmentSource)) {
+ }
+
+ template <class DrawMode>
+ void draw(gl::Context& context,
+ DrawMode drawMode,
+ gl::DepthMode depthMode,
+ gl::StencilMode stencilMode,
+ gl::ColorMode colorMode,
+ UniformValues&& uniformValues,
+ const gl::VertexBuffer<LayoutVertex>& layoutVertexBuffer,
+ const SymbolSizeBinder& symbolSizeBinder,
+ const style::PossiblyEvaluatedPropertyValue<float>& currentSizeValue,
+ const gl::IndexBuffer<DrawMode>& indexBuffer,
+ const gl::SegmentVector<Attributes>& segments,
+ const PaintPropertyBinders& paintPropertyBinders,
+ const typename PaintProperties::Evaluated& currentProperties,
+ float currentZoom) {
+ program.draw(
+ context,
+ std::move(drawMode),
+ std::move(depthMode),
+ std::move(stencilMode),
+ std::move(colorMode),
+ uniformValues
+ .concat(symbolSizeBinder.uniformValues(currentZoom))
+ .concat(paintPropertyBinders.uniformValues(currentZoom)),
+ LayoutAttributes::allVariableBindings(layoutVertexBuffer)
+ .concat(symbolSizeBinder.attributeBindings(currentSizeValue))
+ .concat(paintPropertyBinders.attributeBindings(currentProperties)),
+ indexBuffer,
+ segments
+ );
+ }
+};
+
+class SymbolIconProgram : public SymbolProgram<
shaders::symbol_icon,
gl::Triangle,
SymbolLayoutAttributes,
@@ -80,13 +395,15 @@ class SymbolIconProgram : public Program<
uniforms::u_zoom,
uniforms::u_rotate_with_map,
uniforms::u_texture,
- uniforms::u_fadetexture>,
+ uniforms::u_fadetexture,
+ uniforms::u_is_text>,
style::IconPaintProperties>
{
public:
- using Program::Program;
+ using SymbolProgram::SymbolProgram;
- static UniformValues uniformValues(const style::SymbolPropertyValues&,
+ static UniformValues uniformValues(const bool isText,
+ const style::SymbolPropertyValues&,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
const RenderTile&,
@@ -99,7 +416,7 @@ enum class SymbolSDFPart {
};
template <class PaintProperties>
-class SymbolSDFProgram : public Program<
+class SymbolSDFProgram : public SymbolProgram<
shaders::symbol_sdf,
gl::Triangle,
SymbolLayoutAttributes,
@@ -111,7 +428,7 @@ class SymbolSDFProgram : public Program<
uniforms::u_rotate_with_map,
uniforms::u_texture,
uniforms::u_fadetexture,
- uniforms::u_font_scale,
+ uniforms::u_is_text,
uniforms::u_gamma_scale,
uniforms::u_pitch,
uniforms::u_bearing,
@@ -121,7 +438,7 @@ class SymbolSDFProgram : public Program<
PaintProperties>
{
public:
- using BaseProgram = Program<shaders::symbol_sdf,
+ using BaseProgram = SymbolProgram<shaders::symbol_sdf,
gl::Triangle,
SymbolLayoutAttributes,
gl::Uniforms<
@@ -132,7 +449,7 @@ public:
uniforms::u_rotate_with_map,
uniforms::u_texture,
uniforms::u_fadetexture,
- uniforms::u_font_scale,
+ uniforms::u_is_text,
uniforms::u_gamma_scale,
uniforms::u_pitch,
uniforms::u_bearing,
@@ -147,7 +464,8 @@ public:
using BaseProgram::BaseProgram;
- static UniformValues uniformValues(const style::SymbolPropertyValues&,
+ static UniformValues uniformValues(const bool isText,
+ const style::SymbolPropertyValues&,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
const RenderTile&,