diff options
97 files changed, 2227 insertions, 1851 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9169dea812..1c30081a24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ endif(WITH_COVERAGE) set(CMAKE_CONFIGURATION_TYPES Debug Release) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra -Wshadow -Werror -Wno-variadic-macros -Wno-unknown-pragmas") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -ftemplate-depth=1024 -Wall -Wextra -Wshadow -Werror -Wno-variadic-macros -Wno-unknown-pragmas") if(APPLE) # -Wno-error=unused-command-line-argument is required due to https://llvm.org/bugs/show_bug.cgi?id=7798 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-command-line-argument") diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index b161aec160..9bab51aec8 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -56,10 +56,16 @@ set(MBGL_CORE_FILES include/mbgl/gl/gl.hpp include/mbgl/gl/implementation.hpp src/mbgl/gl/attribute.hpp + src/mbgl/gl/color_mode.cpp + src/mbgl/gl/color_mode.hpp src/mbgl/gl/context.cpp src/mbgl/gl/context.hpp src/mbgl/gl/debugging.cpp src/mbgl/gl/debugging.hpp + src/mbgl/gl/depth_mode.cpp + src/mbgl/gl/depth_mode.hpp + src/mbgl/gl/draw_mode.hpp + src/mbgl/gl/drawable.hpp src/mbgl/gl/extension.cpp src/mbgl/gl/extension.hpp src/mbgl/gl/framebuffer.hpp @@ -68,17 +74,18 @@ set(MBGL_CORE_FILES src/mbgl/gl/object.cpp src/mbgl/gl/object.hpp src/mbgl/gl/renderbuffer.hpp + src/mbgl/gl/segment.hpp src/mbgl/gl/shader.cpp src/mbgl/gl/shader.hpp src/mbgl/gl/state.hpp + src/mbgl/gl/stencil_mode.cpp + src/mbgl/gl/stencil_mode.hpp src/mbgl/gl/texture.hpp src/mbgl/gl/types.hpp src/mbgl/gl/uniform.cpp src/mbgl/gl/uniform.hpp src/mbgl/gl/value.cpp src/mbgl/gl/value.hpp - src/mbgl/gl/vao.cpp - src/mbgl/gl/vao.hpp src/mbgl/gl/vertex_array.cpp src/mbgl/gl/vertex_array.hpp src/mbgl/gl/vertex_buffer.hpp @@ -146,7 +153,6 @@ set(MBGL_CORE_FILES src/mbgl/renderer/circle_bucket.hpp src/mbgl/renderer/debug_bucket.cpp src/mbgl/renderer/debug_bucket.hpp - src/mbgl/renderer/element_group.hpp src/mbgl/renderer/fill_bucket.cpp src/mbgl/renderer/fill_bucket.hpp src/mbgl/renderer/frame_history.cpp @@ -176,10 +182,12 @@ set(MBGL_CORE_FILES # shader src/mbgl/shader/circle_shader.cpp src/mbgl/shader/circle_shader.hpp + src/mbgl/shader/circle_uniforms.hpp src/mbgl/shader/circle_vertex.cpp src/mbgl/shader/circle_vertex.hpp src/mbgl/shader/collision_box_shader.cpp src/mbgl/shader/collision_box_shader.hpp + src/mbgl/shader/collision_box_uniforms.hpp src/mbgl/shader/collision_box_vertex.cpp src/mbgl/shader/collision_box_vertex.hpp src/mbgl/shader/fill_outline_pattern_shader.cpp @@ -190,6 +198,8 @@ set(MBGL_CORE_FILES src/mbgl/shader/fill_pattern_shader.hpp src/mbgl/shader/fill_shader.cpp src/mbgl/shader/fill_shader.hpp + src/mbgl/shader/fill_uniforms.cpp + src/mbgl/shader/fill_uniforms.hpp src/mbgl/shader/fill_vertex.cpp src/mbgl/shader/fill_vertex.hpp src/mbgl/shader/line_pattern_shader.cpp @@ -198,10 +208,13 @@ set(MBGL_CORE_FILES src/mbgl/shader/line_sdf_shader.hpp src/mbgl/shader/line_shader.cpp src/mbgl/shader/line_shader.hpp + src/mbgl/shader/line_uniforms.cpp + src/mbgl/shader/line_uniforms.hpp src/mbgl/shader/line_vertex.cpp src/mbgl/shader/line_vertex.hpp src/mbgl/shader/raster_shader.cpp src/mbgl/shader/raster_shader.hpp + src/mbgl/shader/raster_uniforms.hpp src/mbgl/shader/raster_vertex.cpp src/mbgl/shader/raster_vertex.hpp src/mbgl/shader/shaders.hpp @@ -209,8 +222,11 @@ set(MBGL_CORE_FILES src/mbgl/shader/symbol_icon_shader.hpp src/mbgl/shader/symbol_sdf_shader.cpp src/mbgl/shader/symbol_sdf_shader.hpp + src/mbgl/shader/symbol_uniforms.cpp + src/mbgl/shader/symbol_uniforms.hpp src/mbgl/shader/symbol_vertex.cpp src/mbgl/shader/symbol_vertex.hpp + src/mbgl/shader/uniforms.hpp # sprite include/mbgl/sprite/sprite_image.hpp diff --git a/include/mbgl/util/color.hpp b/include/mbgl/util/color.hpp index 4be380fde3..7693ce636d 100644 --- a/include/mbgl/util/color.hpp +++ b/include/mbgl/util/color.hpp @@ -17,6 +17,10 @@ public: static constexpr Color black() { return { 0.0f, 0.0f, 0.0f, 1.0f }; }; static constexpr Color white() { return { 1.0f, 1.0f, 1.0f, 1.0f }; }; + static constexpr Color red() { return { 1.0f, 0.0f, 0.0f, 1.0f }; }; + static constexpr Color green() { return { 0.0f, 1.0f, 0.0f, 1.0f }; }; + static constexpr Color blue() { return { 0.0f, 0.0f, 1.0f, 1.0f }; }; + static optional<Color> parse(const std::string&); }; diff --git a/include/mbgl/util/range.hpp b/include/mbgl/util/range.hpp index 8da2dd45bb..f7fa92eb8b 100644 --- a/include/mbgl/util/range.hpp +++ b/include/mbgl/util/range.hpp @@ -5,7 +5,7 @@ namespace mbgl { template <class T> class Range { public: - Range(const T& min_, const T& max_) + constexpr Range(const T& min_, const T& max_) : min(min_), max(max_) {} T min; diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp index e974b4ff02..66a2343a42 100644 --- a/src/mbgl/geometry/line_atlas.hpp +++ b/src/mbgl/geometry/line_atlas.hpp @@ -13,11 +13,12 @@ namespace gl { class Context; } // namespace gl -typedef struct { +class LinePatternPos { +public: float width; float height; float y; -} LinePatternPos; +}; enum class LinePatternCap : bool { Square = false, diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 8bc474e967..f270a250bb 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -4,8 +4,6 @@ #include <mbgl/gl/shader.hpp> #include <cstddef> -#include <limits> -#include <vector> namespace mbgl { namespace gl { @@ -27,10 +25,8 @@ public: type(DataTypeOf<T>::value), count(N), offset(O) { - static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout"); static_assert(O % 4 == 0, "vertex attribute must be optimally aligned"); static_assert(1 <= N && N <= 4, "count must be 1, 2, 3, or 4"); - static_assert(sizeof(Vertex) <= std::numeric_limits<int32_t>::max(), "vertex type is too big"); } AttributeLocation location; diff --git a/src/mbgl/gl/color_mode.cpp b/src/mbgl/gl/color_mode.cpp new file mode 100644 index 0000000000..e838c8e2ff --- /dev/null +++ b/src/mbgl/gl/color_mode.cpp @@ -0,0 +1,44 @@ +#include <mbgl/gl/color_mode.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/util/traits.hpp> + +namespace mbgl { +namespace gl { + +static_assert(underlying_type(ColorMode::BlendEquation::Add) == GL_FUNC_ADD, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::BlendEquation::Subtract) == GL_FUNC_SUBTRACT, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::BlendEquation::ReverseSubtract) == GL_FUNC_REVERSE_SUBTRACT, "OpenGL enum mismatch"); + +static_assert(underlying_type(ColorMode::Zero) == GL_ZERO, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::One) == GL_ONE, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcAlphaSaturate) == GL_SRC_ALPHA_SATURATE, "OpenGL enum mismatch"); + +static_assert(underlying_type(ColorMode::Zero) == GL_ZERO, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::One) == GL_ONE, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/color_mode.hpp b/src/mbgl/gl/color_mode.hpp new file mode 100644 index 0000000000..e73c8737eb --- /dev/null +++ b/src/mbgl/gl/color_mode.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include <mbgl/util/variant.hpp> +#include <mbgl/util/color.hpp> + +namespace mbgl { +namespace gl { + +class ColorMode { +public: + enum class BlendEquation { + Add = 0x8006, + Subtract = 0x800A, + ReverseSubtract = 0x800B + }; + + enum BlendFactor { + Zero = 0x0000, + One = 0x0001, + SrcColor = 0x0300, + OneMinusSrcColor = 0x0301, + SrcAlpha = 0x0302, + OneMinusSrcAlpha = 0x0303, + DstAlpha = 0x0304, + OneMinusDstAlpha = 0x0305, + DstColor = 0x0306, + OneMinusDstColor = 0x0307, + SrcAlphaSaturate = 0x0308, + ConstantColor = 0x8001, + OneMinusConstantColor = 0x8002, + ConstantAlpha = 0x8003, + OneMinusConstantAlpha = 0x8004 + }; + + template <BlendEquation E> + struct ConstantBlend { + static constexpr BlendEquation equation = E; + static constexpr BlendFactor srcFactor = One; + static constexpr BlendFactor dstFactor = One; + }; + + template <BlendEquation E> + struct LinearBlend { + static constexpr BlendEquation equation = E; + BlendFactor srcFactor; + BlendFactor dstFactor; + }; + + struct Replace { + static constexpr BlendEquation equation = BlendEquation::Add; + static constexpr BlendFactor srcFactor = One; + static constexpr BlendFactor dstFactor = One; + }; + + using Add = LinearBlend<BlendEquation::Add>; + using Subtract = LinearBlend<BlendEquation::Subtract>; + using ReverseSubtract = LinearBlend<BlendEquation::ReverseSubtract>; + + using BlendFunction = variant< + Replace, + Add, + Subtract, + ReverseSubtract>; + + BlendFunction blendFunction; + Color blendColor; + + struct Mask { + bool r; + bool g; + bool b; + bool a; + }; + + Mask mask; + + static ColorMode disabled() { + return ColorMode { Replace(), {}, { false, false, false, false } }; + } + + static ColorMode unblended() { + return ColorMode { Replace(), {}, { true, true, true, true } }; + } + + static ColorMode alphaBlended() { + return ColorMode { Add { One, OneMinusSrcAlpha }, {}, { true, true, true, true } }; + } +}; + +constexpr bool operator!=(const ColorMode::Mask& a, const ColorMode::Mask& b) { + return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a; +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index bf9bae4fe7..26a8e299ec 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -7,6 +7,14 @@ namespace mbgl { namespace gl { +static_assert(underlying_type(PrimitiveType::Points) == GL_POINTS, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::Lines) == GL_LINES, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::LineLoop) == GL_LINE_LOOP, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::LineStrip) == GL_LINE_STRIP, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::Triangles) == GL_TRIANGLES, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::TriangleStrip) == GL_TRIANGLE_STRIP, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::TriangleFan) == GL_TRIANGLE_FAN, "OpenGL type mismatch"); + static_assert(std::is_same<ProgramID, GLuint>::value, "OpenGL type mismatch"); static_assert(std::is_same<ShaderID, GLuint>::value, "OpenGL type mismatch"); static_assert(std::is_same<BufferID, GLuint>::value, "OpenGL type mismatch"); @@ -15,67 +23,6 @@ static_assert(std::is_same<VertexArrayID, GLuint>::value, "OpenGL type mismatch" static_assert(std::is_same<FramebufferID, GLuint>::value, "OpenGL type mismatch"); static_assert(std::is_same<RenderbufferID, GLuint>::value, "OpenGL type mismatch"); -static_assert(std::is_same<StencilValue, GLint>::value, "OpenGL type mismatch"); -static_assert(std::is_same<StencilMaskValue, GLuint>::value, "OpenGL type mismatch"); - -static_assert(underlying_type(StencilTestFunction::Never) == GL_NEVER, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Less) == GL_LESS, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Equal) == GL_EQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Greater) == GL_GREATER, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Always) == GL_ALWAYS, "OpenGL enum mismatch"); - -static_assert(underlying_type(StencilTestOperation::Keep) == GL_KEEP, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Zero) == GL_ZERO, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Replace) == GL_REPLACE, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Increment) == GL_INCR, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::IncrementWrap) == GL_INCR_WRAP, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Decrement) == GL_DECR, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::DecrementWrap) == GL_DECR_WRAP, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Invert) == GL_INVERT, "OpenGL enum mismatch"); - -static_assert(underlying_type(DepthTestFunction::Never) == GL_NEVER, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Less) == GL_LESS, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Equal) == GL_EQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Greater) == GL_GREATER, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Always) == GL_ALWAYS, "OpenGL enum mismatch"); - -static_assert(underlying_type(BlendSourceFactor::Zero) == GL_ZERO, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::One) == GL_ONE, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::SrcAlphaSaturate) == GL_SRC_ALPHA_SATURATE, "OpenGL enum mismatch"); - -static_assert(underlying_type(BlendDestinationFactor::Zero) == GL_ZERO, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::One) == GL_ONE, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); - Context::~Context() { reset(); } @@ -110,16 +57,6 @@ UniqueBuffer Context::createIndexBuffer(const void* data, std::size_t size) { return result; } -void Context::bindAttribute(const AttributeBinding& binding, std::size_t stride, const int8_t* offset) { - MBGL_CHECK_ERROR(glEnableVertexAttribArray(binding.location)); - MBGL_CHECK_ERROR(glVertexAttribPointer(binding.location, - binding.count, - static_cast<GLenum>(binding.type), - false, - static_cast<GLsizei>(stride), - offset + binding.offset)); -} - UniqueTexture Context::createTexture() { if (pooledTextures.empty()) { pooledTextures.resize(TextureMax); @@ -304,6 +241,7 @@ void Context::setDirtyState() { depthTest.setDirty(); depthFunc.setDirty(); blend.setDirty(); + blendEquation.setDirty(); blendFunc.setDirty(); blendColor.setDirty(); colorMask.setDirty(); @@ -314,6 +252,7 @@ void Context::setDirtyState() { lineWidth.setDirty(); activeTexture.setDirty(); #if not MBGL_USE_GLES2 + pointSize.setDirty(); pixelZoom.setDirty(); rasterPos.setDirty(); #endif // MBGL_USE_GLES2 @@ -325,6 +264,145 @@ void Context::setDirtyState() { vertexArrayObject.setDirty(); } +void Context::clear(optional<mbgl::Color> color, + optional<float> depth, + optional<int32_t> stencil) { + GLbitfield mask = 0; + + if (color) { + mask |= GL_COLOR_BUFFER_BIT; + clearColor = *color; + colorMask = { true, true, true, true }; + } + + if (depth) { + mask |= GL_DEPTH_BUFFER_BIT; + clearDepth = *depth; + depthMask = true; + } + + if (stencil) { + mask |= GL_STENCIL_BUFFER_BIT; + clearStencil = *stencil; + stencilMask = 0xFF; + } + + MBGL_CHECK_ERROR(glClear(mask)); +} + +#if not MBGL_USE_GLES2 +PrimitiveType Context::operator()(const Points& points) { + pointSize = points.pointSize; + return PrimitiveType::Points; +} +#else +PrimitiveType Context::operator()(const Points&) { + return PrimitiveType::Points; +} +#endif // MBGL_USE_GLES2 + +PrimitiveType Context::operator()(const Lines& lines) { + lineWidth = lines.lineWidth; + return PrimitiveType::Lines; +} + +PrimitiveType Context::operator()(const LineStrip& lineStrip) { + lineWidth = lineStrip.lineWidth; + return PrimitiveType::LineStrip; +} + +PrimitiveType Context::operator()(const Triangles&) { + return PrimitiveType::Triangles; +} + +PrimitiveType Context::operator()(const TriangleStrip&) { + return PrimitiveType::TriangleStrip; +} + +void Context::setDepthMode(const DepthMode& depth) { + if (depth.func == DepthMode::Always && !depth.mask) { + depthTest = false; + } else { + depthTest = true; + depthFunc = depth.func; + depthMask = depth.mask; + depthRange = depth.range; + } +} + +void Context::setStencilMode(const StencilMode& stencil) { + if (stencil.test.is<StencilMode::Always>() && !stencil.mask) { + stencilTest = false; + } else { + stencilTest = true; + stencilMask = stencil.mask; + stencilOp = { stencil.fail, stencil.depthFail, stencil.pass }; + apply_visitor([&] (const auto& test) { + stencilFunc = { test.func, stencil.ref, test.mask }; + }, stencil.test); + } +} + +void Context::setColorMode(const ColorMode& color) { + if (color.blendFunction.is<ColorMode::Replace>()) { + blend = false; + } else { + blend = true; + blendColor = color.blendColor; + apply_visitor([&] (const auto& blendFunction) { + blendEquation = ColorMode::BlendEquation(blendFunction.equation); + blendFunc = { blendFunction.srcFactor, blendFunction.dstFactor }; + }, color.blendFunction); + } + + colorMask = color.mask; +} + +void Context::draw(const Drawable& drawable) { + if (drawable.segments.empty()) { + return; + } + + PrimitiveType primitiveType = apply_visitor([&] (auto m) { return (*this)(m); }, drawable.drawMode); + + setDepthMode(drawable.depthMode); + setStencilMode(drawable.stencilMode); + setColorMode(drawable.colorMode); + + program = drawable.program; + + drawable.bindUniforms(); + + for (const auto& segment : drawable.segments) { + vertexBuffer = drawable.vertexBuffer; + elementBuffer = drawable.indexBuffer; + + for (const auto& binding : drawable.attributeBindings) { + MBGL_CHECK_ERROR(glEnableVertexAttribArray(binding.location)); + MBGL_CHECK_ERROR(glVertexAttribPointer( + binding.location, + binding.count, + static_cast<GLenum>(binding.type), + GL_FALSE, + static_cast<GLsizei>(drawable.vertexSize), + reinterpret_cast<GLvoid*>(binding.offset + (drawable.vertexSize * segment.vertexOffset)))); + } + + if (drawable.indexBuffer) { + MBGL_CHECK_ERROR(glDrawElements( + static_cast<GLenum>(primitiveType), + static_cast<GLsizei>(drawable.primitiveSize / sizeof(uint16_t) * segment.primitiveLength), + GL_UNSIGNED_SHORT, + reinterpret_cast<GLvoid*>(drawable.primitiveSize * segment.primitiveOffset))); + } else { + MBGL_CHECK_ERROR(glDrawArrays( + static_cast<GLenum>(primitiveType), + static_cast<GLint>(segment.vertexOffset), + static_cast<GLsizei>(segment.vertexLength))); + } + } +} + void Context::performCleanup() { for (auto id : abandonedPrograms) { if (program == id) { diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 6daf3f9bfb..74c1bcba56 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -8,7 +8,7 @@ #include <mbgl/gl/framebuffer.hpp> #include <mbgl/gl/vertex_buffer.hpp> #include <mbgl/gl/index_buffer.hpp> -#include <mbgl/gl/attribute.hpp> +#include <mbgl/gl/drawable.hpp> #include <mbgl/util/noncopyable.hpp> #include <memory> @@ -78,13 +78,15 @@ public: TextureFilter = TextureFilter::Nearest, TextureMipMap = TextureMipMap::No); - template <class Shader, class Vertex> - void bindAttributes(const Shader& shader, const VertexBuffer<Vertex>&, const int8_t* offset) { - static_assert(std::is_same<typename Shader::VertexType, Vertex>::value, "vertex type mismatch"); - for (const auto& binding : AttributeBindings<Shader, Vertex>()(shader)) { - bindAttribute(binding, sizeof(Vertex), offset); - } - } + void clear(optional<mbgl::Color> color, + optional<float> depth, + optional<int32_t> stencil); + + void draw(const Drawable&); + + void setDepthMode(const DepthMode&); + void setStencilMode(const StencilMode&); + void setColorMode(const ColorMode&); // Actually remove the objects we marked as abandoned with the above methods. // Only call this while the OpenGL context is exclusive to this thread. @@ -106,6 +108,19 @@ public: void setDirtyState(); + State<value::ActiveTexture> activeTexture; + State<value::BindFramebuffer> bindFramebuffer; + State<value::Viewport> viewport; + std::array<State<value::BindTexture>, 2> texture; + State<value::BindVertexArray> vertexArrayObject; + State<value::Program> program; + +#if not MBGL_USE_GLES2 + State<value::PixelZoom> pixelZoom; + State<value::RasterPos> rasterPos; +#endif // MBGL_USE_GLES2 + +private: State<value::StencilFunc> stencilFunc; State<value::StencilMask> stencilMask; State<value::StencilTest> stencilTest; @@ -115,34 +130,32 @@ public: State<value::DepthTest> depthTest; State<value::DepthFunc> depthFunc; State<value::Blend> blend; + State<value::BlendEquation> blendEquation; State<value::BlendFunc> blendFunc; State<value::BlendColor> blendColor; State<value::ColorMask> colorMask; State<value::ClearDepth> clearDepth; State<value::ClearColor> clearColor; State<value::ClearStencil> clearStencil; - State<value::Program> program; State<value::LineWidth> lineWidth; - State<value::ActiveTexture> activeTexture; - State<value::BindFramebuffer> bindFramebuffer; - State<value::Viewport> viewport; State<value::BindRenderbuffer> bindRenderbuffer; #if not MBGL_USE_GLES2 - State<value::PixelZoom> pixelZoom; - State<value::RasterPos> rasterPos; + State<value::PointSize> pointSize; #endif // MBGL_USE_GLES2 - std::array<State<value::BindTexture>, 2> texture; State<value::BindVertexBuffer> vertexBuffer; State<value::BindElementBuffer> elementBuffer; - State<value::BindVertexArray> vertexArrayObject; -private: UniqueBuffer createVertexBuffer(const void* data, std::size_t size); UniqueBuffer createIndexBuffer(const void* data, std::size_t size); UniqueTexture createTexture(Size size, const void* data, TextureUnit); UniqueFramebuffer createFramebuffer(); UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size); - void bindAttribute(const AttributeBinding&, std::size_t stride, const int8_t* offset); + + PrimitiveType operator()(const Points&); + PrimitiveType operator()(const Lines&); + PrimitiveType operator()(const LineStrip&); + PrimitiveType operator()(const Triangles&); + PrimitiveType operator()(const TriangleStrip&); friend detail::ProgramDeleter; friend detail::ShaderDeleter; diff --git a/src/mbgl/gl/depth_mode.cpp b/src/mbgl/gl/depth_mode.cpp new file mode 100644 index 0000000000..21af75a391 --- /dev/null +++ b/src/mbgl/gl/depth_mode.cpp @@ -0,0 +1,18 @@ +#include <mbgl/gl/depth_mode.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/util/traits.hpp> + +namespace mbgl { +namespace gl { + +static_assert(underlying_type(DepthMode::Never) == GL_NEVER, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Less) == GL_LESS, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Equal) == GL_EQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Greater) == GL_GREATER, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Always) == GL_ALWAYS, "OpenGL enum mismatch"); + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/depth_mode.hpp b/src/mbgl/gl/depth_mode.hpp new file mode 100644 index 0000000000..37617e3c34 --- /dev/null +++ b/src/mbgl/gl/depth_mode.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include <mbgl/util/range.hpp> + +namespace mbgl { +namespace gl { + +class DepthMode { +public: + enum Function { + Never = 0x0200, + Less = 0x0201, + Equal = 0x0202, + LessEqual = 0x0203, + Greater = 0x0204, + NotEqual = 0x0205, + GreaterEqual = 0x0206, + Always = 0x0207 + }; + + enum Mask : bool { + ReadOnly = false, + ReadWrite = true + }; + + Function func; + Mask mask; + Range<float> range; + + static DepthMode disabled() { + return DepthMode { Always, ReadOnly, { 0.0, 1.0 } }; + } +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/draw_mode.hpp b/src/mbgl/gl/draw_mode.hpp new file mode 100644 index 0000000000..a379162210 --- /dev/null +++ b/src/mbgl/gl/draw_mode.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include <mbgl/util/variant.hpp> + +namespace mbgl { +namespace gl { + +class Points { +public: + float pointSize; +}; + +class Lines { +public: + float lineWidth; +}; + +class LineStrip { +public: + float lineWidth; +}; + +class Triangles {}; +class TriangleStrip {}; + +using DrawMode = variant< + Points, + Lines, + LineStrip, + Triangles, + TriangleStrip>; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/drawable.hpp b/src/mbgl/gl/drawable.hpp new file mode 100644 index 0000000000..4f2f11e2f1 --- /dev/null +++ b/src/mbgl/gl/drawable.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include <mbgl/gl/types.hpp> +#include <mbgl/gl/draw_mode.hpp> +#include <mbgl/gl/depth_mode.hpp> +#include <mbgl/gl/stencil_mode.hpp> +#include <mbgl/gl/color_mode.hpp> +#include <mbgl/gl/vertex_buffer.hpp> +#include <mbgl/gl/index_buffer.hpp> +#include <mbgl/gl/attribute.hpp> +#include <mbgl/gl/uniform.hpp> +#include <mbgl/gl/segment.hpp> + +#include <cstddef> +#include <functional> +#include <limits> +#include <vector> + +namespace mbgl { +namespace gl { + +template <class Vertex> +class UnindexedVertices { +public: + using VertexType = Vertex; + + UnindexedVertices(DrawMode drawMode_, const VertexBuffer<Vertex>& vertexBuffer_) + : drawMode(std::move(drawMode_)), + vertexBuffer(vertexBuffer_.buffer), + segments({{ 0, 0, vertexBuffer_.vertexCount, 0 }}) {} + + DrawMode drawMode; + gl::BufferID vertexBuffer; + static constexpr std::size_t vertexSize = sizeof(Vertex); + static constexpr gl::BufferID indexBuffer = 0; + static constexpr std::size_t primitiveSize = 0; + std::vector<Segment> segments; +}; + +template <class DrawMode, class Vertex, class...Args> +auto Unindexed(const VertexBuffer<Vertex>& vertexBuffer, + Args&&... drawModeArguments) { + return UnindexedVertices<Vertex>( + DrawMode { std::forward<Args>(drawModeArguments)... }, + vertexBuffer); +} + +template <class Vertex, class Primitive> +class SegmentedVertices { +public: + using VertexType = Vertex; + + SegmentedVertices(DrawMode drawMode_, + const VertexBuffer<Vertex>& vertexBuffer_, + const IndexBuffer<Primitive>& indexBuffer_, + const std::vector<Segment>& segments_) + : drawMode(std::move(drawMode_)), + vertexBuffer(vertexBuffer_.buffer), + indexBuffer(indexBuffer_.buffer), + segments(segments_) {} + + DrawMode drawMode; + gl::BufferID vertexBuffer; + static constexpr std::size_t vertexSize = sizeof(Vertex); + gl::BufferID indexBuffer; + static constexpr std::size_t primitiveSize = sizeof(Primitive); + const std::vector<Segment>& segments; +}; + +template <class DrawMode, class Vertex, class Primitive, class...Args> +auto Segmented(const VertexBuffer<Vertex>& vertexBuffer, + const IndexBuffer<Primitive>& indexBuffer, + const std::vector<Segment>& segments, + Args&&... drawModeArguments) { + static_assert(std::is_same<typename Primitive::DrawMode, DrawMode>::value, "primitive mode mismatch"); + return SegmentedVertices<Vertex, Primitive>( + DrawMode { std::forward<Args>(drawModeArguments)... }, + vertexBuffer, + indexBuffer, + segments); +} + +class Drawable { +public: + template <class Shader, class Subject> + Drawable(DepthMode depthMode_, + StencilMode stencilMode_, + ColorMode colorMode_, + Shader& shader, + typename Shader::UniformsType::Values&& uniformValues, + const Subject& subject) + : drawMode(subject.drawMode), + depthMode(std::move(depthMode_)), + stencilMode(std::move(stencilMode_)), + colorMode(std::move(colorMode_)), + program(shader.getID()), + vertexBuffer(subject.vertexBuffer), + vertexSize(subject.vertexSize), + indexBuffer(subject.indexBuffer), + primitiveSize(subject.primitiveSize), + segments(subject.segments), + bindUniforms(Shader::UniformsType::binder(shader.uniformsState, std::move(uniformValues))), + attributeBindings(AttributeBindings<Shader, typename Subject::VertexType>()(shader)) + { + static_assert(std::is_standard_layout<typename Subject::VertexType>::value, "vertex type must use standard layout"); + static_assert(std::is_same<typename Shader::VertexType, typename Subject::VertexType>::value, "vertex type mismatch"); + } + + DrawMode drawMode; + DepthMode depthMode; + StencilMode stencilMode; + ColorMode colorMode; + gl::ProgramID program; + gl::BufferID vertexBuffer; + std::size_t vertexSize; + gl::BufferID indexBuffer; + std::size_t primitiveSize; + const std::vector<Segment>& segments; + std::function<void ()> bindUniforms; + std::vector<AttributeBinding> attributeBindings; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/index_buffer.hpp b/src/mbgl/gl/index_buffer.hpp index f38d7fd4f5..5d8630b902 100644 --- a/src/mbgl/gl/index_buffer.hpp +++ b/src/mbgl/gl/index_buffer.hpp @@ -1,31 +1,32 @@ #pragma once #include <mbgl/gl/object.hpp> +#include <mbgl/gl/draw_mode.hpp> namespace mbgl { namespace gl { class Line { public: + using DrawMode = Lines; + Line(uint16_t a_, uint16_t b_) : a(a_), b(b_) {} uint16_t a; uint16_t b; - - static constexpr std::size_t IndexCount = 2; }; class Triangle { public: + using DrawMode = Triangles; + Triangle(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {} uint16_t a; uint16_t b; uint16_t c; - - static constexpr std::size_t IndexCount = 3; }; template <class Primitive> diff --git a/src/mbgl/gl/segment.hpp b/src/mbgl/gl/segment.hpp new file mode 100644 index 0000000000..648d02e902 --- /dev/null +++ b/src/mbgl/gl/segment.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include <cstddef> + +namespace mbgl { +namespace gl { + +class Segment { +public: + Segment(std::size_t vertexOffset_, + std::size_t primitiveOffset_, + std::size_t vertexLength_ = 0, + std::size_t primitiveLength_ = 0) + : vertexOffset(vertexOffset_), + primitiveOffset(primitiveOffset_), + vertexLength(vertexLength_), + primitiveLength(primitiveLength_) {} + + const std::size_t vertexOffset; + const std::size_t primitiveOffset; + + std::size_t vertexLength; + std::size_t primitiveLength; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/stencil_mode.cpp b/src/mbgl/gl/stencil_mode.cpp new file mode 100644 index 0000000000..6858d6d106 --- /dev/null +++ b/src/mbgl/gl/stencil_mode.cpp @@ -0,0 +1,27 @@ +#include <mbgl/gl/stencil_mode.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/util/traits.hpp> + +namespace mbgl { +namespace gl { + +static_assert(StencilMode::Never::func == GL_NEVER, "OpenGL enum mismatch"); +static_assert(StencilMode::Less::func == GL_LESS, "OpenGL enum mismatch"); +static_assert(StencilMode::Equal::func == GL_EQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::LessEqual::func == GL_LEQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::Greater::func == GL_GREATER, "OpenGL enum mismatch"); +static_assert(StencilMode::NotEqual::func == GL_NOTEQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::GreaterEqual::func == GL_GEQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::Always::func == GL_ALWAYS, "OpenGL enum mismatch"); + +static_assert(underlying_type(StencilMode::Keep) == GL_KEEP, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Zero) == GL_ZERO, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Replace) == GL_REPLACE, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Increment) == GL_INCR, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::IncrementWrap) == GL_INCR_WRAP, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Decrement) == GL_DECR, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::DecrementWrap) == GL_DECR_WRAP, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Invert) == GL_INVERT, "OpenGL enum mismatch"); + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/stencil_mode.hpp b/src/mbgl/gl/stencil_mode.hpp new file mode 100644 index 0000000000..bc959c9a73 --- /dev/null +++ b/src/mbgl/gl/stencil_mode.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include <mbgl/util/variant.hpp> + +namespace mbgl { +namespace gl { + +class StencilMode { +public: + template <uint32_t F> + struct SimpleTest { + static constexpr uint32_t func = F; + static constexpr uint32_t mask = 0; + }; + + template <uint32_t F> + struct MaskedTest { + static constexpr uint32_t func = F; + uint32_t mask; + }; + + using Never = SimpleTest<0x0200>; + using Less = MaskedTest<0x0201>; + using Equal = MaskedTest<0x0202>; + using LessEqual = MaskedTest<0x0203>; + using Greater = MaskedTest<0x0204>; + using NotEqual = MaskedTest<0x0205>; + using GreaterEqual = MaskedTest<0x0206>; + using Always = SimpleTest<0x0207>; + + using Test = variant< + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always>; + + enum Op { + Zero = 0x0000, + Keep = 0x1E00, + Replace = 0x1E01, + Increment = 0x1E02, + Decrement = 0x1E03, + Invert = 0x150A, + IncrementWrap = 0x8507, + DecrementWrap = 0x8508 + }; + + Test test; + int32_t ref; + uint32_t mask; + + Op fail; + Op depthFail; + Op pass; + + static StencilMode disabled() { + return StencilMode { Always(), 0, 0, Keep, Keep, Keep }; + } +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp index dccc61b03a..9a1eb365d1 100644 --- a/src/mbgl/gl/types.hpp +++ b/src/mbgl/gl/types.hpp @@ -19,10 +19,6 @@ using AttributeLocation = int32_t; using UniformLocation = int32_t; using TextureUnit = uint8_t; -using DepthValue = double; -using StencilValue = int32_t; -using StencilMaskValue = uint32_t; - enum class DataType : uint32_t { Byte = 0x1400, UnsignedByte = 0x1401, @@ -43,11 +39,6 @@ template <> struct DataTypeOf<int32_t> : std::integral_constant<DataType, DataT template <> struct DataTypeOf<uint32_t> : std::integral_constant<DataType, DataType::UnsignedInteger> {}; template <> struct DataTypeOf<float> : std::integral_constant<DataType, DataType::Float> {}; -enum class BufferType : uint32_t { - Vertex = 0x8892, - Element = 0x8893 -}; - enum class RenderbufferType : uint32_t { RGBA = 0x8058, DepthStencil = 0x88F0, @@ -56,72 +47,14 @@ enum class RenderbufferType : uint32_t { enum class TextureMipMap : bool { No = false, Yes = true }; enum class TextureFilter : bool { Nearest = false, Linear = true }; -enum class StencilTestFunction : uint32_t { - Never = 0x0200, - Less = 0x0201, - Equal = 0x0202, - LessEqual = 0x0203, - Greater = 0x0204, - NotEqual = 0x0205, - GreaterEqual = 0x0206, - Always = 0x0207, -}; - -enum class StencilTestOperation : uint32_t { - Keep = 0x1E00, - Zero = 0x0000, - Replace = 0x1E01, - Increment = 0x1E02, - IncrementWrap = 0x8507, - Decrement = 0x1E03, - DecrementWrap = 0x8508, - Invert = 0x150A, -}; - -enum class DepthTestFunction : uint32_t { - Never = 0x0200, - Less = 0x0201, - Equal = 0x0202, - LessEqual = 0x0203, - Greater = 0x0204, - NotEqual = 0x0205, - GreaterEqual = 0x0206, - Always = 0x0207, -}; - -enum class BlendSourceFactor : uint32_t { - Zero = 0x0000, - One = 0x0001, - SrcColor = 0x0300, - OneMinusSrcColor = 0x0301, - DstColor = 0x0306, - OneMinusDstColor = 0x0307, - SrcAlpha = 0x0302, - OneMinusSrcAlpha = 0x0303, - DstAlpha = 0x0304, - OneMinusDstAlpha = 0x0305, - ConstantColor = 0x8001, - OneMinusConstantColor = 0x8002, - ConstantAlpha = 0x8003, - OneMinusConstantAlpha = 0x8004, - SrcAlphaSaturate = 0x0308, -}; - -enum class BlendDestinationFactor : uint32_t { - Zero = 0x0000, - One = 0x0001, - SrcColor = 0x0300, - OneMinusSrcColor = 0x0301, - DstColor = 0x0306, - OneMinusDstColor = 0x0307, - SrcAlpha = 0x0302, - OneMinusSrcAlpha = 0x0303, - DstAlpha = 0x0304, - OneMinusDstAlpha = 0x0305, - ConstantColor = 0x8001, - OneMinusConstantColor = 0x8002, - ConstantAlpha = 0x8003, - OneMinusConstantAlpha = 0x8004, +enum class PrimitiveType { + Points = 0x0000, + Lines = 0x0001, + LineLoop = 0x0002, + LineStrip = 0x0003, + Triangles = 0x0004, + TriangleStrip = 0x0005, + TriangleFan = 0x0006 }; } // namespace gl diff --git a/src/mbgl/gl/uniform.cpp b/src/mbgl/gl/uniform.cpp index 07a27963d9..8018953fb5 100644 --- a/src/mbgl/gl/uniform.cpp +++ b/src/mbgl/gl/uniform.cpp @@ -1,54 +1,76 @@ #include <mbgl/gl/uniform.hpp> #include <mbgl/gl/gl.hpp> #include <mbgl/util/color.hpp> +#include <mbgl/util/size.hpp> +#include <mbgl/util/convert.hpp> namespace mbgl { namespace gl { template <> -void Uniform<float>::bind(const float& t) { +void bindUniform<float>(UniformLocation location, const float& t) { MBGL_CHECK_ERROR(glUniform1f(location, t)); } template <> -void Uniform<int32_t>::bind(const int32_t& t) { +void bindUniform<int32_t>(UniformLocation location, const int32_t& t) { MBGL_CHECK_ERROR(glUniform1i(location, t)); } template <> -void Uniform<std::array<float, 2>>::bind(const std::array<float, 2>& t) { +void bindUniform<std::array<float, 2>>(UniformLocation location, const std::array<float, 2>& t) { MBGL_CHECK_ERROR(glUniform2fv(location, 1, t.data())); } template <> -void Uniform<std::array<float, 3>>::bind(const std::array<float, 3>& t) { +void bindUniform<std::array<float, 3>>(UniformLocation location, const std::array<float, 3>& t) { MBGL_CHECK_ERROR(glUniform3fv(location, 1, t.data())); } template <> -void Uniform<std::array<float, 4>>::bind(const std::array<float, 4>& t) { +void bindUniform<std::array<float, 4>>(UniformLocation location, const std::array<float, 4>& t) { MBGL_CHECK_ERROR(glUniform4fv(location, 1, t.data())); } template <> -void Uniform<Color>::bind(const Color& t) { - std::array<float, 4> a = {{ t.r, t.g, t.b, t.a }}; - MBGL_CHECK_ERROR(glUniform4fv(location, 1, a.data())); +void bindUniform<std::array<double, 4>>(UniformLocation location, const std::array<double, 4>& t) { + MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, util::convert<float>(t).data())); } template <> -void UniformMatrix<2>::bind(const std::array<float, 4>& t) { - MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, t.data())); +void bindUniform<std::array<double, 9>>(UniformLocation location, const std::array<double, 9>& t) { + MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, util::convert<float>(t).data())); } template <> -void UniformMatrix<3>::bind(const std::array<float, 9>& t) { - MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, t.data())); +void bindUniform<std::array<double, 16>>(UniformLocation location, const std::array<double, 16>& t) { + MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, util::convert<float>(t).data())); +} + + +template <> +void bindUniform<bool>(UniformLocation location, const bool& t) { + return bindUniform(location, int32_t(t)); +} + +template <> +void bindUniform<uint8_t>(UniformLocation location, const uint8_t& t) { + bindUniform(location, int32_t(t)); +} + +template <> +void bindUniform<Color>(UniformLocation location, const Color& t) { + bindUniform(location, std::array<float, 4> {{ t.r, t.g, t.b, t.a }}); +} + +template <> +void bindUniform<Size>(UniformLocation location, const Size& t) { + bindUniform(location, util::convert<float>(std::array<uint32_t, 2> {{ t.width, t.height }})); } template <> -void UniformMatrix<4>::bind(const std::array<float, 16>& t) { - MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, t.data())); +void bindUniform<std::array<uint16_t, 2>>(UniformLocation location, const std::array<uint16_t, 2>& t) { + bindUniform(location, util::convert<float>(t)); } // Add more as needed. diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp index 5af781043d..d233614aa6 100644 --- a/src/mbgl/gl/uniform.hpp +++ b/src/mbgl/gl/uniform.hpp @@ -1,60 +1,87 @@ #pragma once #include <mbgl/gl/shader.hpp> +#include <mbgl/util/optional.hpp> #include <array> +#include <functional> +#include <tuple> namespace mbgl { namespace gl { -template <typename T> +template <class T> +void bindUniform(UniformLocation, const T&); + +template <class Tag, class T> class Uniform { public: - Uniform(const char* name, const Shader& shader) - : current(), location(shader.getUniformLocation(name)) { - } + class Value { + public: + Value(T t_) : t(std::move(t_)) {} + T t; + }; - void operator=(const T& t) { - if (current != t) { - current = t; - bind(t); - } - } + class State { + public: + State(const char* name, const Shader& shader) + : location(shader.getUniformLocation(name)) {} -private: - void bind(const T&); + void operator=(const Value& value) { + if (!current || *current != value.t) { + current = value.t; + bindUniform(location, value.t); + } + } - T current; - UniformLocation location; + private: + optional<T> current; + UniformLocation location; + }; }; -template <size_t C, size_t R = C> -class UniformMatrix { +template <class Tag, class T> +using UniformScalar = Uniform<Tag, T>; + +template <class Tag, class T, size_t N> +using UniformVector = Uniform<Tag, std::array<T, N>>; + +template <class Tag, class T, size_t N> +using UniformMatrix = Uniform<Tag, std::array<T, N*N>>; + +#define MBGL_DEFINE_UNIFORM_SCALAR(type_, name_) \ + struct name_ : ::mbgl::gl::UniformScalar<name_, type_> { static constexpr auto name = #name_; } + +#define MBGL_DEFINE_UNIFORM_VECTOR(type_, n_, name_) \ + struct name_ : ::mbgl::gl::UniformVector<name_, type_, n_> { static constexpr auto name = #name_; } + +#define MBGL_DEFINE_UNIFORM_MATRIX(type_, n_, name_) \ + struct name_ : ::mbgl::gl::UniformMatrix<name_, type_, n_> { static constexpr auto name = #name_; } + +template <class... Us> +class Uniforms { public: - typedef std::array<float, C*R> T; + using State = std::tuple<typename Us::State...>; + using Values = std::tuple<typename Us::Value...>; - UniformMatrix(const char* name, const Shader& shader) - : current(), location(shader.getUniformLocation(name)) { + static State state(const Shader& shader) { + return State { { Us::name, shader }... }; } - void operator=(const std::array<double, C*R>& t) { - bool dirty = false; - for (unsigned int i = 0; i < C*R; i++) { - if (current[i] != t[i]) { - current[i] = t[i]; - dirty = true; - } - } - if (dirty) { - bind(current); - } + template <class... Args> + static Values values(Args&&... args) { + return Values { std::forward<Args>(args)... }; } -private: - void bind(const T&); + static std::function<void ()> binder(State& state, Values&& values_) { + return [&state, values = std::move(values_)] () mutable { + noop((std::get<typename Us::State>(state) = std::get<typename Us::Value>(values), 0)...); + }; + } - T current; - UniformLocation location; +private: + // This exists only to provide a varags context for unpacking the assignments in `binder`. + template <int...> static void noop(int...) {} }; } // namespace gl diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp index b308dc9de5..f25008854d 100644 --- a/src/mbgl/gl/value.cpp +++ b/src/mbgl/gl/value.cpp @@ -94,7 +94,7 @@ StencilFunc::Type StencilFunc::Get() { MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FUNC, &func)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_REF, &ref)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask)); - return { static_cast<StencilTestFunction>(func), ref, static_cast<StencilMaskValue>(mask) }; + return { static_cast<uint32_t>(func), ref, static_cast<uint32_t>(mask) }; } const constexpr StencilTest::Type StencilTest::Default; @@ -122,17 +122,17 @@ StencilOp::Type StencilOp::Get() { MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FAIL, &sfail)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &dppass)); - return { static_cast<StencilTestOperation>(sfail), static_cast<StencilTestOperation>(dpfail), - static_cast<StencilTestOperation>(dppass) }; + return { static_cast<StencilMode::Op>(sfail), static_cast<StencilMode::Op>(dpfail), + static_cast<StencilMode::Op>(dppass) }; } const constexpr DepthRange::Type DepthRange::Default; void DepthRange::Set(const Type& value) { #if MBGL_USE_GLES2 - MBGL_CHECK_ERROR(glDepthRangef(value.near, value.far)); + MBGL_CHECK_ERROR(glDepthRangef(value.min, value.max)); #else - MBGL_CHECK_ERROR(glDepthRange(value.near, value.far)); + MBGL_CHECK_ERROR(glDepthRange(value.min, value.max)); #endif } @@ -178,6 +178,18 @@ Blend::Type Blend::Get() { return blend; } +const constexpr BlendEquation::Type BlendEquation::Default; + +void BlendEquation::Set(const Type& value) { + MBGL_CHECK_ERROR(glBlendEquation(static_cast<GLenum>(value))); +} + +BlendEquation::Type BlendEquation::Get() { + GLint blend; + MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend)); + return static_cast<Type>(blend); +} + const constexpr BlendFunc::Type BlendFunc::Default; void BlendFunc::Set(const Type& value) { @@ -189,8 +201,8 @@ BlendFunc::Type BlendFunc::Get() { GLint sfactor, dfactor; MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_SRC_ALPHA, &sfactor)); MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_DST_ALPHA, &dfactor)); - return { static_cast<BlendSourceFactor>(sfactor), - static_cast<BlendDestinationFactor>(dfactor) }; + return { static_cast<ColorMode::BlendFactor>(sfactor), + static_cast<ColorMode::BlendFactor>(dfactor) }; } const constexpr BlendColor::Type BlendColor::Default; @@ -340,6 +352,18 @@ BindVertexArray::Type BindVertexArray::Get() { #if not MBGL_USE_GLES2 +const constexpr PointSize::Type PointSize::Default; + +void PointSize::Set(const Type& value) { + MBGL_CHECK_ERROR(glPointSize(value)); +} + +PointSize::Type PointSize::Get() { + GLfloat pointSize; + MBGL_CHECK_ERROR(glGetFloatv(GL_POINT_SIZE, &pointSize)); + return pointSize; +} + const constexpr PixelZoom::Type PixelZoom::Default; void PixelZoom::Set(const Type& value) { diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp index becf2e63f4..6296d64416 100644 --- a/src/mbgl/gl/value.hpp +++ b/src/mbgl/gl/value.hpp @@ -1,8 +1,12 @@ #pragma once #include <mbgl/gl/types.hpp> +#include <mbgl/gl/depth_mode.hpp> +#include <mbgl/gl/stencil_mode.hpp> +#include <mbgl/gl/color_mode.hpp> #include <mbgl/util/color.hpp> #include <mbgl/util/size.hpp> +#include <mbgl/util/range.hpp> namespace mbgl { namespace gl { @@ -23,14 +27,14 @@ struct ClearColor { }; struct ClearStencil { - using Type = StencilValue; + using Type = int32_t; static const constexpr Type Default = 0; static void Set(const Type&); static Type Get(); }; struct StencilMask { - using Type = StencilMaskValue; + using Type = uint32_t; static const constexpr Type Default = ~0u; static void Set(const Type&); static Type Get(); @@ -44,28 +48,19 @@ struct DepthMask { }; struct ColorMask { - struct Type { - bool r; - bool g; - bool b; - bool a; - }; + using Type = ColorMode::Mask; static const constexpr Type Default = { true, true, true, true }; static void Set(const Type&); static Type Get(); }; -constexpr bool operator!=(const ColorMask::Type& a, const ColorMask::Type& b) { - return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a; -} - struct StencilFunc { struct Type { - StencilTestFunction func; - StencilValue ref; - StencilMaskValue mask; + uint32_t func; + int32_t ref; + uint32_t mask; }; - static const constexpr Type Default = { StencilTestFunction::Always, 0, ~0u }; + static const constexpr Type Default = { StencilMode::Always::func, 0, ~0u }; static void Set(const Type&); static Type Get(); }; @@ -83,12 +78,11 @@ struct StencilTest { struct StencilOp { struct Type { - StencilTestOperation sfail; - StencilTestOperation dpfail; - StencilTestOperation dppass; + StencilMode::Op sfail; + StencilMode::Op dpfail; + StencilMode::Op dppass; }; - static const constexpr Type Default = { StencilTestOperation::Keep, StencilTestOperation::Keep, - StencilTestOperation::Keep }; + static const constexpr Type Default = { StencilMode::Keep, StencilMode::Keep, StencilMode::Keep }; static void Set(const Type&); static Type Get(); }; @@ -98,19 +92,12 @@ constexpr bool operator!=(const StencilOp::Type& a, const StencilOp::Type& b) { } struct DepthRange { - struct Type { - float near; - float far; - }; + using Type = Range<float>; static const constexpr Type Default = { 0, 1 }; static void Set(const Type&); static Type Get(); }; -constexpr bool operator!=(const DepthRange::Type& a, const DepthRange::Type& b) { - return a.near != b.near || a.far != b.far; -} - struct DepthTest { using Type = bool; static const constexpr Type Default = false; @@ -119,8 +106,8 @@ struct DepthTest { }; struct DepthFunc { - using Type = DepthTestFunction; - static const constexpr Type Default = DepthTestFunction::Less; + using Type = DepthMode::Function; + static const constexpr Type Default = DepthMode::Less; static void Set(const Type&); static Type Get(); }; @@ -132,12 +119,19 @@ struct Blend { static Type Get(); }; +struct BlendEquation { + using Type = ColorMode::BlendEquation; + static const constexpr Type Default = ColorMode::BlendEquation::Add; + static void Set(const Type&); + static Type Get(); +}; + struct BlendFunc { struct Type { - BlendSourceFactor sfactor; - BlendDestinationFactor dfactor; + ColorMode::BlendFactor sfactor; + ColorMode::BlendFactor dfactor; }; - static const constexpr Type Default = { BlendSourceFactor::One, BlendDestinationFactor::Zero }; + static const constexpr Type Default = { ColorMode::One, ColorMode::Zero }; static void Set(const Type&); static Type Get(); }; @@ -233,6 +227,13 @@ struct BindVertexArray { #if not MBGL_USE_GLES2 +struct PointSize { + using Type = float; + static const constexpr Type Default = 1; + static void Set(const Type&); + static Type Get(); +}; + struct PixelZoom { struct Type { float xfactor; diff --git a/src/mbgl/gl/vao.cpp b/src/mbgl/gl/vao.cpp deleted file mode 100644 index b235b0e63b..0000000000 --- a/src/mbgl/gl/vao.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include <mbgl/gl/vao.hpp> -#include <mbgl/gl/vertex_array.hpp> -#include <mbgl/platform/log.hpp> -#include <mbgl/util/string.hpp> -#include <mbgl/gl/gl.hpp> - -namespace mbgl { -namespace gl { - -void VertexArrayObject::bindVertexArrayObject(Context& context) { - if (!GenVertexArrays || !BindVertexArray) { - static bool reported = false; - if (!reported) { - Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); - reported = true; - } - return; - } - - if (!vertexArray) { - vertexArray = context.createVertexArray(); - context.vertexBuffer.setDirty(); - context.elementBuffer.setDirty(); - } - - context.vertexArrayObject = *vertexArray; -} - -void VertexArrayObject::verifyBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset) { - if (bound_shader != shader.getID()) { - throw std::runtime_error(std::string("trying to rebind VAO to another shader from " + - util::toString(bound_shader) + "(" + bound_shader_name + ") to " + - util::toString(shader.getID()) + "(" + shader.name + ")" )); - } else if (bound_offset != offset) { - throw std::runtime_error("trying to bind VAO to another offset"); - } else if (bound_vertex_buffer != vertexBuffer) { - throw std::runtime_error("trying to bind VAO to another vertex buffer"); - } else if (bound_elements_buffer != elementsBuffer) { - throw std::runtime_error("trying to bind VAO to another elements buffer"); - } -} - -void VertexArrayObject::storeBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset) { - bound_shader = shader.getID(); - bound_shader_name = shader.name; - bound_offset = offset; - bound_vertex_buffer = vertexBuffer; - bound_elements_buffer = elementsBuffer; -} - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/vao.hpp b/src/mbgl/gl/vao.hpp deleted file mode 100644 index 826c028d32..0000000000 --- a/src/mbgl/gl/vao.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include <mbgl/gl/shader.hpp> -#include <mbgl/gl/context.hpp> -#include <mbgl/gl/vertex_buffer.hpp> -#include <mbgl/util/optional.hpp> - -#include <stdexcept> - -namespace mbgl { -namespace gl { - -class VertexArrayObject { -public: - template <typename Shader, typename T> - void bind(Shader& shader, - const VertexBuffer<T>& vertexBuffer, - int8_t* offset, - Context& context) { - bindVertexArrayObject(context); - if (bound_shader == 0) { - context.vertexBuffer = vertexBuffer.buffer; - context.bindAttributes(shader, vertexBuffer, offset); - if (vertexArray) { - storeBinding(shader, vertexBuffer.buffer, 0, offset); - } - } else { - verifyBinding(shader, vertexBuffer.buffer, 0, offset); - } - } - - template <typename Shader, typename T, typename P> - void bind(Shader& shader, - const VertexBuffer<T>& vertexBuffer, - const IndexBuffer<P>& indexBuffer, - int8_t* offset, - Context& context) { - bindVertexArrayObject(context); - if (bound_shader == 0) { - context.vertexBuffer = vertexBuffer.buffer; - context.elementBuffer = indexBuffer.buffer; - context.bindAttributes(shader, vertexBuffer, offset); - if (vertexArray) { - storeBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset); - } - } else { - verifyBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset); - } - } - - VertexArrayID getID() const { - return *vertexArray; - } - -private: - void bindVertexArrayObject(Context&); - void storeBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset); - void verifyBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset); - - optional<UniqueVertexArray> vertexArray; - - // For debug reasons, we're storing the bind information so that we can - // detect errors and report - ProgramID bound_shader = 0; - const char* bound_shader_name = ""; - BufferID bound_vertex_buffer = 0; - BufferID bound_elements_buffer = 0; - int8_t *bound_offset = nullptr; -}; - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 07ba2bf4a3..0bf152e973 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -451,15 +451,14 @@ void SymbolLayout::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float const int glyph_vertex_length = 4; - if (buffer.groups.empty() || buffer.groups.back().vertexLength + glyph_vertex_length > 65535) { - // Move to a new group because the old one can't hold the geometry. - buffer.groups.emplace_back(); + if (buffer.segments.empty() || buffer.segments.back().vertexLength + glyph_vertex_length > 65535) { + buffer.segments.emplace_back(buffer.vertices.size(), buffer.triangles.size()); } // We're generating triangle fans, so we always start with the first // coordinate in this polygon. - auto& group = buffer.groups.back(); - size_t index = group.vertexLength; + auto& segment = buffer.segments.back(); + size_t index = segment.vertexLength; // Encode angle of glyph uint8_t glyphAngle = std::round((symbol.glyphAngle / (M_PI * 2)) * 256); @@ -482,8 +481,8 @@ void SymbolLayout::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float static_cast<uint16_t>(index + 2), static_cast<uint16_t>(index + 3)); - group.vertexLength += glyph_vertex_length; - group.indexLength += 2; + segment.vertexLength += glyph_vertex_length; + segment.primitiveLength += 2; } } @@ -496,10 +495,6 @@ void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket& const float yStretch = collisionTile.yStretch; auto& collisionBox = bucket.collisionBox; - if (collisionBox.groups.empty()) { - // Move to a new group because the old one can't hold the geometry. - collisionBox.groups.emplace_back(); - } for (const SymbolInstance &symbolInstance : symbolInstances) { auto populateCollisionBox = [&](const auto& feature) { @@ -526,9 +521,6 @@ void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket& collisionBox.vertices.emplace_back(anchor.x, anchor.y, bl.x, bl.y, maxZoom, placementZoom); collisionBox.vertices.emplace_back(anchor.x, anchor.y, bl.x, bl.y, maxZoom, placementZoom); collisionBox.vertices.emplace_back(anchor.x, anchor.y, tl.x, tl.y, maxZoom, placementZoom); - - auto& group = collisionBox.groups.back(); - group.vertexLength += 8; } }; populateCollisionBox(symbolInstance.textCollisionFeature); 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; }; diff --git a/src/mbgl/shader/circle_shader.cpp b/src/mbgl/shader/circle_shader.cpp index 9e294f8d76..c43c435e1b 100644 --- a/src/mbgl/shader/circle_shader.cpp +++ b/src/mbgl/shader/circle_shader.cpp @@ -9,7 +9,8 @@ CircleShader::CircleShader(gl::Context& context, Defines defines) : Shader(shaders::circle::name, shaders::circle::vertex, shaders::circle::fragment, - context, defines) { + context, defines), + uniformsState(CircleUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/circle_shader.hpp b/src/mbgl/shader/circle_shader.hpp index c2c4053ba4..1c67fd02f3 100644 --- a/src/mbgl/shader/circle_shader.hpp +++ b/src/mbgl/shader/circle_shader.hpp @@ -2,8 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> -#include <mbgl/util/color.hpp> +#include <mbgl/shader/circle_uniforms.hpp> namespace mbgl { @@ -14,17 +13,11 @@ public: CircleShader(gl::Context&, Defines defines = None); using VertexType = CircleVertex; + using UniformsType = CircleUniforms; gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this}; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<std::array<float, 2>> u_extrude_scale = {"u_extrude_scale", *this}; - gl::Uniform<float> u_devicepixelratio = {"u_devicepixelratio", *this}; - gl::Uniform<Color> u_color = {"u_color", *this}; - gl::Uniform<float> u_radius = {"u_radius", *this}; - gl::Uniform<float> u_blur = {"u_blur", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<int32_t> u_scale_with_map = {"u_scale_with_map", *this}; + typename CircleUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/circle_uniforms.hpp b/src/mbgl/shader/circle_uniforms.hpp new file mode 100644 index 0000000000..c77c0daaba --- /dev/null +++ b/src/mbgl/shader/circle_uniforms.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include <mbgl/shader/uniforms.hpp> + +namespace mbgl { + +namespace uniforms { +MBGL_DEFINE_UNIFORM_SCALAR(float, u_radius); +MBGL_DEFINE_UNIFORM_SCALAR(bool, u_scale_with_map); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_devicepixelratio); +} // namespace uniforms + +struct CircleUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_color, + uniforms::u_radius, + uniforms::u_blur, + uniforms::u_scale_with_map, + uniforms::u_extrude_scale, + uniforms::u_devicepixelratio> {}; + +} // namespace mbgl diff --git a/src/mbgl/shader/circle_vertex.hpp b/src/mbgl/shader/circle_vertex.hpp index 4fce49f137..62e6e2da5b 100644 --- a/src/mbgl/shader/circle_vertex.hpp +++ b/src/mbgl/shader/circle_vertex.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/attribute.hpp> -#include <array> +#include <vector> #include <cstdint> namespace mbgl { @@ -28,7 +28,7 @@ namespace gl { template <class Shader> struct AttributeBindings<Shader, CircleVertex> { - std::array<AttributeBinding, 1> operator()(const Shader& shader) { + std::vector<AttributeBinding> operator()(const Shader& shader) { return {{ MBGL_MAKE_ATTRIBUTE_BINDING(CircleVertex, shader, a_pos) }}; diff --git a/src/mbgl/shader/collision_box_shader.cpp b/src/mbgl/shader/collision_box_shader.cpp index d61c849cd1..f12327102a 100644 --- a/src/mbgl/shader/collision_box_shader.cpp +++ b/src/mbgl/shader/collision_box_shader.cpp @@ -9,7 +9,9 @@ CollisionBoxShader::CollisionBoxShader(gl::Context& context) : Shader(shaders::collision_box::name, shaders::collision_box::vertex, shaders::collision_box::fragment, - context) { + context), + uniformsState(CollisionBoxUniforms::state(*this)) +{ } } // namespace mbgl diff --git a/src/mbgl/shader/collision_box_shader.hpp b/src/mbgl/shader/collision_box_shader.hpp index 2f5c506168..337de77150 100644 --- a/src/mbgl/shader/collision_box_shader.hpp +++ b/src/mbgl/shader/collision_box_shader.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> +#include <mbgl/shader/collision_box_uniforms.hpp> namespace mbgl { @@ -13,15 +13,13 @@ public: CollisionBoxShader(gl::Context&); using VertexType = CollisionBoxVertex; + using UniformsType = CollisionBoxUniforms; gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this}; gl::Attribute<int16_t, 2> a_extrude = {"a_extrude", *this}; gl::Attribute<uint8_t, 2> a_data = {"a_data", *this}; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<float> u_scale = {"u_scale", *this}; - gl::Uniform<float> u_zoom = {"u_zoom", *this}; - gl::Uniform<float> u_maxzoom = {"u_maxzoom", *this}; + typename CollisionBoxUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/collision_box_uniforms.hpp b/src/mbgl/shader/collision_box_uniforms.hpp new file mode 100644 index 0000000000..f195cc9a6a --- /dev/null +++ b/src/mbgl/shader/collision_box_uniforms.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include <mbgl/shader/uniforms.hpp> + +namespace mbgl { + +namespace uniforms { +MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom); +} // namespace uniforms + +struct CollisionBoxUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_scale, + uniforms::u_zoom, + uniforms::u_maxzoom> {}; + +} // namespace mbgl diff --git a/src/mbgl/shader/collision_box_vertex.hpp b/src/mbgl/shader/collision_box_vertex.hpp index ba72b1c0ee..563b6403bf 100644 --- a/src/mbgl/shader/collision_box_vertex.hpp +++ b/src/mbgl/shader/collision_box_vertex.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/attribute.hpp> -#include <array> +#include <vector> #include <cstdint> #include <cmath> @@ -30,7 +30,7 @@ namespace gl { template <class Shader> struct AttributeBindings<Shader, CollisionBoxVertex> { - std::array<AttributeBinding, 3> operator()(const Shader& shader) { + std::vector<AttributeBinding> operator()(const Shader& shader) { return {{ MBGL_MAKE_ATTRIBUTE_BINDING(CollisionBoxVertex, shader, a_pos), MBGL_MAKE_ATTRIBUTE_BINDING(CollisionBoxVertex, shader, a_extrude), diff --git a/src/mbgl/shader/fill_outline_pattern_shader.cpp b/src/mbgl/shader/fill_outline_pattern_shader.cpp index b03921d384..7b9cf81c6d 100644 --- a/src/mbgl/shader/fill_outline_pattern_shader.cpp +++ b/src/mbgl/shader/fill_outline_pattern_shader.cpp @@ -9,7 +9,8 @@ FillOutlinePatternShader::FillOutlinePatternShader(gl::Context& context, Defines : Shader(shaders::fill_outline_pattern::name, shaders::fill_outline_pattern::vertex, shaders::fill_outline_pattern::fragment, - context, defines) { + context, defines), + uniformsState(FillPatternUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/fill_outline_pattern_shader.hpp b/src/mbgl/shader/fill_outline_pattern_shader.hpp index 630e6a7ce8..c76b93c355 100644 --- a/src/mbgl/shader/fill_outline_pattern_shader.hpp +++ b/src/mbgl/shader/fill_outline_pattern_shader.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> +#include <mbgl/shader/fill_uniforms.hpp> namespace mbgl { @@ -13,25 +13,11 @@ public: FillOutlinePatternShader(gl::Context&, Defines defines = None); using VertexType = FillVertex; + using UniformsType = FillPatternUniforms; gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this}; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<float> u_mix = {"u_mix", *this}; - gl::Uniform<float> u_scale_a = {"u_scale_a", *this}; - gl::Uniform<float> u_scale_b = {"u_scale_b", *this}; - gl::Uniform<float> u_tile_units_to_pixels = {"u_tile_units_to_pixels", *this}; - gl::Uniform<int32_t> u_image = {"u_image", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this}; - gl::Uniform<std::array<float, 2>> u_pixel_coord_upper = {"u_pixel_coord_upper", *this}; - gl::Uniform<std::array<float, 2>> u_pixel_coord_lower = {"u_pixel_coord_lower", *this}; - gl::Uniform<std::array<float, 2>> u_world = {"u_world", *this}; + typename FillPatternUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/fill_outline_shader.cpp b/src/mbgl/shader/fill_outline_shader.cpp index 6e6d8c2239..f3d8ac5f5b 100644 --- a/src/mbgl/shader/fill_outline_shader.cpp +++ b/src/mbgl/shader/fill_outline_shader.cpp @@ -9,7 +9,8 @@ FillOutlineShader::FillOutlineShader(gl::Context& context, Defines defines) : Shader(shaders::fill_outline::name, shaders::fill_outline::vertex, shaders::fill_outline::fragment, - context, defines) { + context, defines), + uniformsState(FillColorUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/fill_outline_shader.hpp b/src/mbgl/shader/fill_outline_shader.hpp index c20bc187d3..4194f7c8c0 100644 --- a/src/mbgl/shader/fill_outline_shader.hpp +++ b/src/mbgl/shader/fill_outline_shader.hpp @@ -2,8 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> -#include <mbgl/util/color.hpp> +#include <mbgl/shader/fill_uniforms.hpp> namespace mbgl { @@ -14,13 +13,11 @@ public: FillOutlineShader(gl::Context&, Defines defines = None); using VertexType = FillVertex; + using UniformsType = FillColorUniforms; gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this}; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<Color> u_outline_color = {"u_outline_color", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<std::array<float, 2>> u_world = {"u_world", *this}; + typename FillColorUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/fill_pattern_shader.cpp b/src/mbgl/shader/fill_pattern_shader.cpp index 60be6d79ad..b3cd2c595c 100644 --- a/src/mbgl/shader/fill_pattern_shader.cpp +++ b/src/mbgl/shader/fill_pattern_shader.cpp @@ -9,7 +9,8 @@ FillPatternShader::FillPatternShader(gl::Context& context, Defines defines) : Shader(shaders::fill_pattern::name, shaders::fill_pattern::vertex, shaders::fill_pattern::fragment, - context, defines) { + context, defines), + uniformsState(FillPatternUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/fill_pattern_shader.hpp b/src/mbgl/shader/fill_pattern_shader.hpp index 36be538000..92a16ee45a 100644 --- a/src/mbgl/shader/fill_pattern_shader.hpp +++ b/src/mbgl/shader/fill_pattern_shader.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> +#include <mbgl/shader/fill_uniforms.hpp> namespace mbgl { @@ -13,24 +13,11 @@ public: FillPatternShader(gl::Context&, Defines defines = None); using VertexType = FillVertex; + using UniformsType = FillPatternUniforms; gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this}; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<float> u_mix = {"u_mix", *this}; - gl::Uniform<float> u_scale_a = {"u_scale_a", *this}; - gl::Uniform<float> u_scale_b = {"u_scale_b", *this}; - gl::Uniform<float> u_tile_units_to_pixels = {"u_tile_units_to_pixels", *this}; - gl::Uniform<int32_t> u_image = {"u_image", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this}; - gl::Uniform<std::array<float, 2>> u_pixel_coord_upper = {"u_pixel_coord_upper", *this}; - gl::Uniform<std::array<float, 2>> u_pixel_coord_lower = {"u_pixel_coord_lower", *this}; + typename FillPatternUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/fill_shader.cpp b/src/mbgl/shader/fill_shader.cpp index 7026bb2f1c..59028d7384 100644 --- a/src/mbgl/shader/fill_shader.cpp +++ b/src/mbgl/shader/fill_shader.cpp @@ -9,7 +9,8 @@ FillShader::FillShader(gl::Context& context, Defines defines) : Shader(shaders::fill::name, shaders::fill::vertex, shaders::fill::fragment, - context, defines) { + context, defines), + uniformsState(FillColorUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/fill_shader.hpp b/src/mbgl/shader/fill_shader.hpp index 1240b73aa2..a7f3b8e2f9 100644 --- a/src/mbgl/shader/fill_shader.hpp +++ b/src/mbgl/shader/fill_shader.hpp @@ -2,8 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> -#include <mbgl/util/color.hpp> +#include <mbgl/shader/fill_uniforms.hpp> namespace mbgl { @@ -14,12 +13,11 @@ public: FillShader(gl::Context&, Defines defines = None); using VertexType = FillVertex; + using UniformsType = FillColorUniforms; gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this}; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<Color> u_color = {"u_color", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; + typename FillColorUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/fill_uniforms.cpp b/src/mbgl/shader/fill_uniforms.cpp new file mode 100644 index 0000000000..368cb12fcf --- /dev/null +++ b/src/mbgl/shader/fill_uniforms.cpp @@ -0,0 +1,45 @@ +#include <mbgl/shader/fill_uniforms.hpp> +#include <mbgl/sprite/sprite_atlas.hpp> +#include <mbgl/style/property_evaluator.hpp> +#include <mbgl/tile/tile_id.hpp> +#include <mbgl/map/transform_state.hpp> + +namespace mbgl { + +using namespace style; + +FillPatternUniforms::Values +FillPatternUniforms::values(mat4 matrix, + float opacity, + Size framebufferSize, + const SpriteAtlasPosition& a, + const SpriteAtlasPosition& b, + const Faded<std::string>& fading, + const UnwrappedTileID& tileID, + const TransformState& state) +{ + int32_t tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z); + int32_t pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z)); + int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y; + + return FillPatternUniforms::Values { + matrix, + opacity, + framebufferSize, + a.tl, + a.br, + b.tl, + b.br, + a.size, + b.size, + fading.fromScale, + fading.toScale, + fading.t, + 0, + std::array<float, 2> {{ float(pixelX >> 16), float(pixelY >> 16) }}, + std::array<float, 2> {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }}, + 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom()) + }; +} + +} // namespace mbgl diff --git a/src/mbgl/shader/fill_uniforms.hpp b/src/mbgl/shader/fill_uniforms.hpp new file mode 100644 index 0000000000..a596da0ea9 --- /dev/null +++ b/src/mbgl/shader/fill_uniforms.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include <mbgl/shader/uniforms.hpp> +#include <mbgl/util/mat4.hpp> +#include <mbgl/util/size.hpp> + +#include <string> + +namespace mbgl { + +namespace uniforms { +MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world); +MBGL_DEFINE_UNIFORM_SCALAR(Color, u_outline_color); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_a); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_b); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_tile_units_to_pixels); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_upper); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_lower); +} // namespace uniforms + +struct FillColorUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_color, + uniforms::u_outline_color, + uniforms::u_world> {}; + +class SpriteAtlasPosition; +class UnwrappedTileID; +class TransformState; + +namespace style { +template <class> class Faded; +} // namespace style + +struct FillPatternUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_world, + uniforms::u_pattern_tl_a, + uniforms::u_pattern_br_a, + uniforms::u_pattern_tl_b, + uniforms::u_pattern_br_b, + uniforms::u_pattern_size_a, + uniforms::u_pattern_size_b, + uniforms::u_scale_a, + uniforms::u_scale_b, + uniforms::u_mix, + uniforms::u_image, + uniforms::u_pixel_coord_upper, + uniforms::u_pixel_coord_lower, + uniforms::u_tile_units_to_pixels> { + static Values values(mat4 matrix, + float opacity, + Size framebufferSize, + const SpriteAtlasPosition&, + const SpriteAtlasPosition&, + const style::Faded<std::string>&, + const UnwrappedTileID&, + const TransformState&); +}; + +} // namespace mbgl diff --git a/src/mbgl/shader/fill_vertex.hpp b/src/mbgl/shader/fill_vertex.hpp index 1b8130382a..86b83d28e5 100644 --- a/src/mbgl/shader/fill_vertex.hpp +++ b/src/mbgl/shader/fill_vertex.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/attribute.hpp> -#include <array> +#include <vector> #include <cstdint> namespace mbgl { @@ -19,7 +19,7 @@ namespace gl { template <class Shader> struct AttributeBindings<Shader, FillVertex> { - std::array<AttributeBinding, 1> operator()(const Shader& shader) { + std::vector<AttributeBinding> operator()(const Shader& shader) { return {{ MBGL_MAKE_ATTRIBUTE_BINDING(FillVertex, shader, a_pos) }}; diff --git a/src/mbgl/shader/line_pattern_shader.cpp b/src/mbgl/shader/line_pattern_shader.cpp index e6bc32a5c9..134e619b22 100644 --- a/src/mbgl/shader/line_pattern_shader.cpp +++ b/src/mbgl/shader/line_pattern_shader.cpp @@ -9,7 +9,8 @@ LinePatternShader::LinePatternShader(gl::Context& context, Defines defines) : Shader(shaders::line_pattern::name, shaders::line_pattern::vertex, shaders::line_pattern::fragment, - context, defines) { + context, defines), + uniformsState(LinePatternUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/line_pattern_shader.hpp b/src/mbgl/shader/line_pattern_shader.hpp index 1bd6085c8b..57fb7b6d61 100644 --- a/src/mbgl/shader/line_pattern_shader.hpp +++ b/src/mbgl/shader/line_pattern_shader.hpp @@ -1,8 +1,8 @@ #pragma once #include <mbgl/gl/shader.hpp> -#include <mbgl/gl/uniform.hpp> #include <mbgl/gl/attribute.hpp> +#include <mbgl/shader/line_uniforms.hpp> namespace mbgl { @@ -13,29 +13,12 @@ public: LinePatternShader(gl::Context&, Defines defines = None); using VertexType = LineVertex; + using UniformsType = LinePatternUniforms; gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; gl::Attribute<uint8_t, 4> a_data = { "a_data", *this }; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<float> u_linewidth = {"u_linewidth", *this}; - gl::Uniform<float> u_gapwidth = {"u_gapwidth", *this}; - gl::Uniform<float> u_antialiasing = {"u_antialiasing", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this}; - gl::Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this}; - gl::Uniform<float> u_ratio = {"u_ratio", *this}; - gl::Uniform<float> u_point = {"u_point", *this}; - gl::Uniform<float> u_blur = {"u_blur", *this}; - gl::Uniform<float> u_fade = {"u_fade", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<float> u_extra = {"u_extra", *this}; - gl::Uniform<float> u_offset = {"u_offset", *this}; - gl::Uniform<int32_t> u_image = {"u_image", *this}; - gl::UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this}; + typename LinePatternUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/line_sdf_shader.cpp b/src/mbgl/shader/line_sdf_shader.cpp index dd724365ea..d290c16676 100644 --- a/src/mbgl/shader/line_sdf_shader.cpp +++ b/src/mbgl/shader/line_sdf_shader.cpp @@ -9,7 +9,8 @@ LineSDFShader::LineSDFShader(gl::Context& context, Defines defines) : Shader(shaders::line_sdf::name, shaders::line_sdf::vertex, shaders::line_sdf::fragment, - context, defines) { + context, defines), + uniformsState(LineSDFUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/line_sdf_shader.hpp b/src/mbgl/shader/line_sdf_shader.hpp index d74e42e50f..b6cced7ae7 100644 --- a/src/mbgl/shader/line_sdf_shader.hpp +++ b/src/mbgl/shader/line_sdf_shader.hpp @@ -2,8 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> -#include <mbgl/util/color.hpp> +#include <mbgl/shader/line_uniforms.hpp> namespace mbgl { @@ -14,28 +13,12 @@ public: LineSDFShader(gl::Context&, Defines defines = None); using VertexType = LineVertex; + using UniformsType = LineSDFUniforms; gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; gl::Attribute<uint8_t, 4> a_data = { "a_data", *this }; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<Color> u_color = {"u_color", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<float> u_linewidth = {"u_linewidth", *this}; - gl::Uniform<float> u_gapwidth = {"u_gapwidth", *this}; - gl::Uniform<float> u_antialiasing = {"u_antialiasing", *this}; - gl::Uniform<float> u_ratio = {"u_ratio", *this}; - gl::Uniform<float> u_blur = {"u_blur", *this}; - gl::Uniform<std::array<float, 2>> u_patternscale_a = { "u_patternscale_a", *this}; - gl::Uniform<float> u_tex_y_a = {"u_tex_y_a", *this}; - gl::Uniform<std::array<float, 2>> u_patternscale_b = { "u_patternscale_b", *this}; - gl::Uniform<float> u_tex_y_b = {"u_tex_y_b", *this}; - gl::Uniform<int32_t> u_image = {"u_image", *this}; - gl::Uniform<float> u_sdfgamma = {"u_sdfgamma", *this}; - gl::Uniform<float> u_mix = {"u_mix", *this}; - gl::Uniform<float> u_extra = {"u_extra", *this}; - gl::Uniform<float> u_offset = {"u_offset", *this}; - gl::UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this}; + typename LineSDFUniforms::State uniformsState; }; diff --git a/src/mbgl/shader/line_shader.cpp b/src/mbgl/shader/line_shader.cpp index 4e934cd60c..07227070be 100644 --- a/src/mbgl/shader/line_shader.cpp +++ b/src/mbgl/shader/line_shader.cpp @@ -9,7 +9,8 @@ LineShader::LineShader(gl::Context& context, Defines defines) : Shader(shaders::line::name, shaders::line::vertex, shaders::line::fragment, - context, defines) { + context, defines), + uniformsState(LineColorUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp index 79991e1883..eafaf15bef 100644 --- a/src/mbgl/shader/line_shader.hpp +++ b/src/mbgl/shader/line_shader.hpp @@ -2,8 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> -#include <mbgl/util/color.hpp> +#include <mbgl/shader/line_uniforms.hpp> namespace mbgl { @@ -14,21 +13,12 @@ public: LineShader(gl::Context&, Defines defines = None); using VertexType = LineVertex; + using UniformsType = LineColorUniforms; gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; gl::Attribute<uint8_t, 4> a_data = { "a_data", *this }; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<Color> u_color = {"u_color", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<float> u_ratio = {"u_ratio", *this}; - gl::Uniform<float> u_linewidth = {"u_linewidth", *this}; - gl::Uniform<float> u_gapwidth = {"u_gapwidth", *this}; - gl::Uniform<float> u_antialiasing = {"u_antialiasing", *this}; - gl::Uniform<float> u_blur = {"u_blur", *this}; - gl::Uniform<float> u_extra = {"u_extra", *this}; - gl::Uniform<float> u_offset = {"u_offset", *this}; - gl::UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this}; + typename LineColorUniforms::State uniformsState; }; diff --git a/src/mbgl/shader/line_uniforms.cpp b/src/mbgl/shader/line_uniforms.cpp new file mode 100644 index 0000000000..f1d73e20eb --- /dev/null +++ b/src/mbgl/shader/line_uniforms.cpp @@ -0,0 +1,133 @@ +#include <mbgl/shader/line_uniforms.hpp> +#include <mbgl/style/layers/line_layer_properties.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/map/transform_state.hpp> +#include <mbgl/util/mat2.hpp> +#include <mbgl/sprite/sprite_atlas.hpp> +#include <mbgl/geometry/line_atlas.hpp> + +namespace mbgl { + +template <class Values, class...Args> +Values makeValues(const style::LinePaintProperties& properties, + float pixelRatio, + const RenderTile& tile, + const TransformState& state, + Args&&... args) { + // the distance over which the line edge fades out. + // Retina devices need a smaller distance to avoid aliasing. + float antialiasing = 1.0 / pixelRatio; + + 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()); + + return Values { + tile.translatedMatrix(properties.lineTranslate.value, + properties.lineTranslateAnchor.value, + state), + properties.lineOpacity.value, + properties.lineWidth.value / 2, + properties.lineGapWidth.value / 2, + properties.lineBlur.value + antialiasing, + -properties.lineOffset.value, + antialiasing / 2, + antialiasingMatrix, + 1.0f / tile.id.pixelsToTileUnits(1.0, state.getZoom()), + (topedgelength + x) / topedgelength - 1.0f, + std::forward<Args>(args)... + }; +} + +LineColorUniforms::Values +LineColorUniforms::values(const style::LinePaintProperties& properties, + float pixelRatio, + const RenderTile& tile, + const TransformState& state) { + return makeValues<LineColorUniforms::Values>( + properties, + pixelRatio, + tile, + state, + properties.lineColor.value + ); +} + +LineSDFUniforms::Values +LineSDFUniforms::values(const style::LinePaintProperties& properties, + float pixelRatio, + const RenderTile& tile, + const TransformState& state, + const LinePatternPos& posA, + const LinePatternPos& posB, + float dashLineWidth, + float atlasWidth) { + const float widthA = posA.width * properties.lineDasharray.value.fromScale * dashLineWidth; + const float widthB = posB.width * properties.lineDasharray.value.toScale * dashLineWidth; + + std::array<float, 2> scaleA {{ + 1.0f / tile.id.pixelsToTileUnits(widthA, state.getIntegerZoom()), + -posA.height / 2.0f + }}; + + std::array<float, 2> scaleB {{ + 1.0f / tile.id.pixelsToTileUnits(widthB, state.getIntegerZoom()), + -posB.height / 2.0f + }}; + + return makeValues<LineSDFUniforms::Values>( + properties, + pixelRatio, + tile, + state, + properties.lineColor.value, + scaleA, + scaleB, + posA.y, + posB.y, + properties.lineDasharray.value.t, + atlasWidth / (std::min(widthA, widthB) * 256.0f * pixelRatio) / 2.0f, + 0 + ); +} + +LinePatternUniforms::Values +LinePatternUniforms::values(const style::LinePaintProperties& properties, + float pixelRatio, + const RenderTile& tile, + const TransformState& state, + const SpriteAtlasPosition& posA, + const SpriteAtlasPosition& posB) { + std::array<float, 2> sizeA {{ + tile.id.pixelsToTileUnits(posA.size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()), + posA.size[1] + }}; + + std::array<float, 2> sizeB {{ + tile.id.pixelsToTileUnits(posB.size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()), + posB.size[1] + }}; + + return makeValues<LinePatternUniforms::Values>( + properties, + pixelRatio, + tile, + state, + posA.tl, + posA.br, + posB.tl, + posB.br, + sizeA, + sizeB, + properties.linePattern.value.t, + 0 + ); +} + +} // namespace mbgl diff --git a/src/mbgl/shader/line_uniforms.hpp b/src/mbgl/shader/line_uniforms.hpp new file mode 100644 index 0000000000..8a9c5310b5 --- /dev/null +++ b/src/mbgl/shader/line_uniforms.hpp @@ -0,0 +1,109 @@ +#pragma once + +#include <mbgl/shader/uniforms.hpp> + +namespace mbgl { + +namespace style { +class LinePaintProperties; +} // namespace style + +class RenderTile; +class TransformState; +class LinePatternPos; +class SpriteAtlasPosition; + +namespace uniforms { +MBGL_DEFINE_UNIFORM_SCALAR(float, u_ratio); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_linewidth); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_gapwidth); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_antialiasing); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_extra); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_offset); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_a); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_b); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_sdfgamma); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_a); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_b); +MBGL_DEFINE_UNIFORM_MATRIX(double, 2, u_antialiasingmatrix); +} // namespace uniforms + +struct LineColorUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_linewidth, + uniforms::u_gapwidth, + uniforms::u_blur, + uniforms::u_offset, + uniforms::u_antialiasing, + uniforms::u_antialiasingmatrix, + uniforms::u_ratio, + uniforms::u_extra, + uniforms::u_color> +{ + static Values values(const style::LinePaintProperties&, + float pixelRatio, + const RenderTile&, + const TransformState&); +}; + +struct LineSDFUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_linewidth, + uniforms::u_gapwidth, + uniforms::u_blur, + uniforms::u_offset, + uniforms::u_antialiasing, + uniforms::u_antialiasingmatrix, + uniforms::u_ratio, + uniforms::u_extra, + uniforms::u_color, + uniforms::u_patternscale_a, + uniforms::u_patternscale_b, + uniforms::u_tex_y_a, + uniforms::u_tex_y_b, + uniforms::u_mix, + uniforms::u_sdfgamma, + uniforms::u_image> +{ + static Values values(const style::LinePaintProperties&, + float pixelRatio, + const RenderTile&, + const TransformState&, + const LinePatternPos& posA, + const LinePatternPos& posB, + float dashLineWidth, + float atlasWidth); +}; + +struct LinePatternUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_linewidth, + uniforms::u_gapwidth, + uniforms::u_blur, + uniforms::u_offset, + uniforms::u_antialiasing, + uniforms::u_antialiasingmatrix, + uniforms::u_ratio, + uniforms::u_extra, + uniforms::u_pattern_tl_a, + uniforms::u_pattern_br_a, + uniforms::u_pattern_tl_b, + uniforms::u_pattern_br_b, + uniforms::u_pattern_size_a, + uniforms::u_pattern_size_b, + uniforms::u_fade, + uniforms::u_image> +{ + static Values values(const style::LinePaintProperties&, + float pixelRatio, + const RenderTile&, + const TransformState&, + const SpriteAtlasPosition& posA, + const SpriteAtlasPosition& posB); +}; + +} // namespace mbgl diff --git a/src/mbgl/shader/line_vertex.hpp b/src/mbgl/shader/line_vertex.hpp index 086100810e..6d299c5197 100644 --- a/src/mbgl/shader/line_vertex.hpp +++ b/src/mbgl/shader/line_vertex.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/attribute.hpp> -#include <array> +#include <vector> #include <cstdint> #include <cmath> @@ -60,7 +60,7 @@ namespace gl { template <class Shader> struct AttributeBindings<Shader, LineVertex> { - std::array<AttributeBinding, 2> operator()(const Shader& shader) { + std::vector<AttributeBinding> operator()(const Shader& shader) { return {{ MBGL_MAKE_ATTRIBUTE_BINDING(LineVertex, shader, a_pos), MBGL_MAKE_ATTRIBUTE_BINDING(LineVertex, shader, a_data) diff --git a/src/mbgl/shader/raster_shader.cpp b/src/mbgl/shader/raster_shader.cpp index 34b2bdf47b..17d6b246a1 100644 --- a/src/mbgl/shader/raster_shader.cpp +++ b/src/mbgl/shader/raster_shader.cpp @@ -9,7 +9,8 @@ RasterShader::RasterShader(gl::Context& context, Defines defines) : Shader(shaders::raster::name, shaders::raster::vertex, shaders::raster::fragment, - context, defines) { + context, defines), + uniformsState(RasterUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/raster_shader.hpp b/src/mbgl/shader/raster_shader.hpp index 9633fd5fa0..977556a097 100644 --- a/src/mbgl/shader/raster_shader.hpp +++ b/src/mbgl/shader/raster_shader.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> +#include <mbgl/shader/raster_uniforms.hpp> namespace mbgl { @@ -13,23 +13,12 @@ public: RasterShader(gl::Context&, Defines defines = None); using VertexType = RasterVertex; + using UniformsType = RasterUniforms; gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this }; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<int32_t> u_image0 = {"u_image0", *this}; - gl::Uniform<int32_t> u_image1 = {"u_image1", *this}; - gl::Uniform<float> u_opacity0 = {"u_opacity0", *this}; - gl::Uniform<float> u_opacity1 = {"u_opacity1", *this}; - gl::Uniform<float> u_buffer_scale = {"u_buffer_scale", *this}; - gl::Uniform<float> u_brightness_low = {"u_brightness_low", *this}; - gl::Uniform<float> u_brightness_high = {"u_brightness_high", *this}; - gl::Uniform<float> u_saturation_factor = {"u_saturation_factor", *this}; - gl::Uniform<float> u_contrast_factor = {"u_contrast_factor", *this}; - gl::Uniform<std::array<float, 3>> u_spin_weights = {"u_spin_weights", *this}; - gl::Uniform<std::array<float, 2>> u_tl_parent = {"u_tl_parent", *this}; - gl::Uniform<float> u_scale_parent = {"u_scale_parent", *this}; + typename RasterUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/raster_uniforms.hpp b/src/mbgl/shader/raster_uniforms.hpp new file mode 100644 index 0000000000..0a81b95c66 --- /dev/null +++ b/src/mbgl/shader/raster_uniforms.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include <mbgl/shader/uniforms.hpp> + +namespace mbgl { + +namespace uniforms { +MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image0); +MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image1); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity0); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity1); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer_scale); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_low); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_high); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_saturation_factor); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_contrast_factor); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_parent); +MBGL_DEFINE_UNIFORM_VECTOR(float, 3, u_spin_weights); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_tl_parent); +} // namespace uniforms + +struct RasterUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_image0, + uniforms::u_image1, + uniforms::u_opacity0, + uniforms::u_opacity1, + uniforms::u_brightness_low, + uniforms::u_brightness_high, + uniforms::u_saturation_factor, + uniforms::u_contrast_factor, + uniforms::u_spin_weights, + uniforms::u_buffer_scale, + uniforms::u_scale_parent, + uniforms::u_tl_parent> {}; + +} // namespace mbgl diff --git a/src/mbgl/shader/raster_vertex.hpp b/src/mbgl/shader/raster_vertex.hpp index 70e08c609d..889405d6cd 100644 --- a/src/mbgl/shader/raster_vertex.hpp +++ b/src/mbgl/shader/raster_vertex.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/attribute.hpp> -#include <array> +#include <vector> #include <cstdint> namespace mbgl { @@ -27,7 +27,7 @@ namespace gl { template <class Shader> struct AttributeBindings<Shader, RasterVertex> { - std::array<AttributeBinding, 2> operator()(const Shader& shader) { + std::vector<AttributeBinding> operator()(const Shader& shader) { return {{ MBGL_MAKE_ATTRIBUTE_BINDING(RasterVertex, shader, a_pos), MBGL_MAKE_ATTRIBUTE_BINDING(RasterVertex, shader, a_texture_pos) diff --git a/src/mbgl/shader/shaders.hpp b/src/mbgl/shader/shaders.hpp index 937ee85f44..56b063ce29 100644 --- a/src/mbgl/shader/shaders.hpp +++ b/src/mbgl/shader/shaders.hpp @@ -48,11 +48,6 @@ public: SymbolSDFShader symbolGlyph; CollisionBoxShader collisionBox; - - gl::VertexArrayObject coveringPlainArray; - gl::VertexArrayObject coveringRasterArray; - gl::VertexArrayObject backgroundPatternArray; - gl::VertexArrayObject backgroundArray; }; } // namespace mbgl diff --git a/src/mbgl/shader/symbol_icon_shader.cpp b/src/mbgl/shader/symbol_icon_shader.cpp index 2655a1c9b5..66fce84d83 100644 --- a/src/mbgl/shader/symbol_icon_shader.cpp +++ b/src/mbgl/shader/symbol_icon_shader.cpp @@ -9,7 +9,8 @@ SymbolIconShader::SymbolIconShader(gl::Context& context, Defines defines) : Shader(shaders::symbol_icon::name, shaders::symbol_icon::vertex, shaders::symbol_icon::fragment, - context, defines) { + context, defines), + uniformsState(SymbolIconUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/symbol_icon_shader.hpp b/src/mbgl/shader/symbol_icon_shader.hpp index 5281beb60c..95b669e8f7 100644 --- a/src/mbgl/shader/symbol_icon_shader.hpp +++ b/src/mbgl/shader/symbol_icon_shader.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> +#include <mbgl/shader/symbol_uniforms.hpp> namespace mbgl { @@ -13,20 +13,14 @@ public: SymbolIconShader(gl::Context&, Defines defines = None); using VertexType = SymbolVertex; + using UniformsType = SymbolIconUniforms; gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; gl::Attribute<int16_t, 2> a_offset = { "a_offset", *this }; gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this }; gl::Attribute<uint8_t, 4> a_data = { "a_data", *this }; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<std::array<float, 2>> u_extrude_scale = {"u_extrude_scale", *this}; - gl::Uniform<float> u_zoom = {"u_zoom", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this}; - gl::Uniform<int32_t> u_rotate_with_map = {"u_rotate_with_map", *this}; - gl::Uniform<int32_t> u_texture = {"u_texture", *this}; - gl::Uniform<int32_t> u_fadetexture = {"u_fadetexture", *this}; + typename SymbolIconUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/symbol_sdf_shader.cpp b/src/mbgl/shader/symbol_sdf_shader.cpp index 63c3bd5a4a..b8dffbab11 100644 --- a/src/mbgl/shader/symbol_sdf_shader.cpp +++ b/src/mbgl/shader/symbol_sdf_shader.cpp @@ -9,7 +9,8 @@ SymbolSDFShader::SymbolSDFShader(gl::Context& context, Defines defines) : Shader(shaders::symbol_sdf::name, shaders::symbol_sdf::vertex, shaders::symbol_sdf::fragment, - context, defines) { + context, defines), + uniformsState(SymbolSDFUniforms::state(*this)) { } } // namespace mbgl diff --git a/src/mbgl/shader/symbol_sdf_shader.hpp b/src/mbgl/shader/symbol_sdf_shader.hpp index 8d3b3df939..b7c12811c0 100644 --- a/src/mbgl/shader/symbol_sdf_shader.hpp +++ b/src/mbgl/shader/symbol_sdf_shader.hpp @@ -2,8 +2,7 @@ #include <mbgl/gl/shader.hpp> #include <mbgl/gl/attribute.hpp> -#include <mbgl/gl/uniform.hpp> -#include <mbgl/util/color.hpp> +#include <mbgl/shader/symbol_uniforms.hpp> namespace mbgl { @@ -14,27 +13,14 @@ public: SymbolSDFShader(gl::Context&, Defines defines = None); using VertexType = SymbolVertex; + using UniformsType = SymbolSDFUniforms; gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; gl::Attribute<int16_t, 2> a_offset = { "a_offset", *this }; gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this }; gl::Attribute<uint8_t, 4> a_data = { "a_data", *this }; - gl::UniformMatrix<4> u_matrix = {"u_matrix", *this}; - gl::Uniform<std::array<float, 2>> u_extrude_scale = {"u_extrude_scale", *this}; - gl::Uniform<Color> u_color = {"u_color", *this}; - gl::Uniform<float> u_opacity = {"u_opacity", *this}; - gl::Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this}; - gl::Uniform<float> u_buffer = {"u_buffer", *this}; - gl::Uniform<float> u_gamma = {"u_gamma", *this}; - gl::Uniform<float> u_zoom = {"u_zoom", *this}; - gl::Uniform<float> u_pitch = {"u_pitch", *this}; - gl::Uniform<float> u_bearing = {"u_bearing", *this}; - gl::Uniform<float> u_aspect_ratio = {"u_aspect_ratio", *this}; - gl::Uniform<int32_t> u_rotate_with_map = {"u_rotate_with_map", *this}; - gl::Uniform<int32_t> u_pitch_with_map = {"u_pitch_with_map", *this}; - gl::Uniform<int32_t> u_texture = {"u_texture", *this}; - gl::Uniform<int32_t> u_fadetexture = {"u_fadetexture", *this}; + typename SymbolSDFUniforms::State uniformsState; }; } // namespace mbgl diff --git a/src/mbgl/shader/symbol_uniforms.cpp b/src/mbgl/shader/symbol_uniforms.cpp new file mode 100644 index 0000000000..cd9f33de71 --- /dev/null +++ b/src/mbgl/shader/symbol_uniforms.cpp @@ -0,0 +1,143 @@ +#include <mbgl/shader/symbol_uniforms.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/map/transform_state.hpp> +#include <mbgl/style/layers/symbol_layer_impl.hpp> + +namespace mbgl { + +using namespace style; + +template <class Values, class...Args> +Values makeValues(const style::SymbolPropertyValues& values, + const std::array<uint16_t, 2>& 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); + } else { + extrudeScale = {{ + pixelsToGLUnits[0] * scale * state.getAltitude(), + pixelsToGLUnits[1] * scale * state.getAltitude() + }}; + } + + // adjust min/max zooms for variable font sies + float zoomAdjust = std::log(values.paintSize / values.layoutSize) / std::log(2); + + return Values { + tile.translatedMatrix(values.translate, + values.translateAnchor, + state), + values.opacity, + extrudeScale, + std::array<float, 2> {{ texsize[0] / 4.0f, texsize[1] / 4.0f }}, + (state.getZoom() - zoomAdjust) * 10.0f, + values.rotationAlignment == AlignmentType::Map, + 0, + 1, + std::forward<Args>(args)... + }; +} + +SymbolIconUniforms::Values +SymbolIconUniforms::values(const style::SymbolPropertyValues& values, + const std::array<uint16_t, 2>& texsize, + const std::array<float, 2>& pixelsToGLUnits, + const RenderTile& tile, + const TransformState& state) +{ + return makeValues<SymbolIconUniforms::Values>( + values, + texsize, + pixelsToGLUnits, + tile, + state + ); +} + +static SymbolSDFUniforms::Values makeSDFValues(const style::SymbolPropertyValues& values, + const std::array<uint16_t, 2>& texsize, + const std::array<float, 2>& pixelsToGLUnits, + const RenderTile& tile, + const TransformState& state, + float pixelRatio, + Color color, + float buffer, + float gammaAdjust) +{ + // 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 gammaBase = 0.105 * values.sdfScale / values.paintSize / pixelRatio; + const float gammaScale = values.pitchAlignment == AlignmentType::Map + ? 1.0 / std::cos(state.getPitch()) + : 1.0; + + return makeValues<SymbolSDFUniforms::Values>( + values, + texsize, + pixelsToGLUnits, + tile, + state, + color, + buffer, + (gammaBase + gammaAdjust) * gammaScale, + state.getPitch(), + -1.0f * state.getAngle(), + (state.getSize().width * 1.0f) / (state.getSize().height * 1.0f), + values.pitchAlignment == AlignmentType::Map + ); +} + +SymbolSDFUniforms::Values +SymbolSDFUniforms::haloValues(const style::SymbolPropertyValues& values, + const std::array<uint16_t, 2>& texsize, + const std::array<float, 2>& pixelsToGLUnits, + const RenderTile& tile, + const TransformState& state, + float pixelRatio) +{ + const float scale = values.paintSize / values.sdfScale; + const float sdfPx = 8.0f; + const float blurOffset = 1.19f; + const float haloOffset = 6.0f; + + return makeSDFValues( + values, + texsize, + pixelsToGLUnits, + tile, + state, + pixelRatio, + values.haloColor, + (haloOffset - values.haloWidth / scale) / sdfPx, + values.haloBlur * blurOffset / scale / sdfPx + ); +} + +SymbolSDFUniforms::Values +SymbolSDFUniforms::foregroundValues(const style::SymbolPropertyValues& values, + const std::array<uint16_t, 2>& texsize, + const std::array<float, 2>& pixelsToGLUnits, + const RenderTile& tile, + const TransformState& state, + float pixelRatio) +{ + return makeSDFValues( + values, + texsize, + pixelsToGLUnits, + tile, + state, + pixelRatio, + values.color, + (256.0f - 64.0f) / 256.0f, + 0 + ); +} + +} // namespace mbgl diff --git a/src/mbgl/shader/symbol_uniforms.hpp b/src/mbgl/shader/symbol_uniforms.hpp new file mode 100644 index 0000000000..dc1b25004f --- /dev/null +++ b/src/mbgl/shader/symbol_uniforms.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include <mbgl/shader/uniforms.hpp> + +#include <array> + +namespace mbgl { + +namespace style { +class SymbolPropertyValues; +} // namespace style + +class RenderTile; +class TransformState; + +namespace uniforms { +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_texsize); +MBGL_DEFINE_UNIFORM_SCALAR(bool, u_rotate_with_map); +MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map); +MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_texture); +MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_fadetexture); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio); +} // namespace uniforms + +struct SymbolIconUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_extrude_scale, + uniforms::u_texsize, + uniforms::u_zoom, + uniforms::u_rotate_with_map, + uniforms::u_texture, + uniforms::u_fadetexture> +{ + static Values values(const style::SymbolPropertyValues&, + const std::array<uint16_t, 2>& texsize, + const std::array<float, 2>& pixelsToGLUnits, + const RenderTile&, + const TransformState&); +}; + +struct SymbolSDFUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_opacity, + uniforms::u_extrude_scale, + uniforms::u_texsize, + uniforms::u_zoom, + uniforms::u_rotate_with_map, + uniforms::u_texture, + uniforms::u_fadetexture, + uniforms::u_color, + uniforms::u_buffer, + uniforms::u_gamma, + uniforms::u_pitch, + uniforms::u_bearing, + uniforms::u_aspect_ratio, + uniforms::u_pitch_with_map> +{ + static Values haloValues(const style::SymbolPropertyValues&, + const std::array<uint16_t, 2>& texsize, + const std::array<float, 2>& pixelsToGLUnits, + const RenderTile&, + const TransformState&, + float pixelRatio); + + static Values foregroundValues(const style::SymbolPropertyValues&, + const std::array<uint16_t, 2>& texsize, + const std::array<float, 2>& pixelsToGLUnits, + const RenderTile&, + const TransformState&, + float pixelRatio); +}; + +} // namespace mbgl diff --git a/src/mbgl/shader/symbol_vertex.hpp b/src/mbgl/shader/symbol_vertex.hpp index 4eba86f946..4bb6c82a60 100644 --- a/src/mbgl/shader/symbol_vertex.hpp +++ b/src/mbgl/shader/symbol_vertex.hpp @@ -2,7 +2,7 @@ #include <mbgl/gl/attribute.hpp> -#include <array> +#include <vector> #include <cstdint> #include <cmath> @@ -40,7 +40,7 @@ namespace gl { template <class Shader> struct AttributeBindings<Shader, SymbolVertex> { - std::array<AttributeBinding, 4> operator()(const Shader& shader) { + std::vector<AttributeBinding> operator()(const Shader& shader) { return {{ MBGL_MAKE_ATTRIBUTE_BINDING(SymbolVertex, shader, a_pos), MBGL_MAKE_ATTRIBUTE_BINDING(SymbolVertex, shader, a_offset), diff --git a/src/mbgl/shader/uniforms.hpp b/src/mbgl/shader/uniforms.hpp new file mode 100644 index 0000000000..e0c5a0d361 --- /dev/null +++ b/src/mbgl/shader/uniforms.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include <mbgl/gl/uniform.hpp> +#include <mbgl/util/color.hpp> + +namespace mbgl { +namespace uniforms { + +// Uniforms common to several shaders. + +MBGL_DEFINE_UNIFORM_MATRIX(double, 4, u_matrix); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity); +MBGL_DEFINE_UNIFORM_SCALAR(Color, u_color); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_blur); + +MBGL_DEFINE_UNIFORM_SCALAR(float, u_zoom); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_pitch); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_bearing); + +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale); + +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_tl_a); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_br_a); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_tl_b); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_br_b); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_a); +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_b); + +MBGL_DEFINE_UNIFORM_SCALAR(float, u_mix); +MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image); + +} // namespace uniforms +} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp index 3a0aea2dad..f4ed1b306e 100644 --- a/src/mbgl/sprite/sprite_atlas.hpp +++ b/src/mbgl/sprite/sprite_atlas.hpp @@ -26,13 +26,15 @@ class Context; class SpriteImage; class SpritePosition; -struct SpriteAtlasPosition { +class SpriteAtlasPosition { +public: std::array<float, 2> size = {{ 0, 0 }}; std::array<float, 2> tl = {{ 0, 0 }}; std::array<float, 2> br = {{ 0, 0 }}; }; -struct SpriteAtlasElement { +class SpriteAtlasElement { +public: Rect<uint16_t> pos; std::shared_ptr<const SpriteImage> spriteImage; float relativePixelRatio; diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp index e85f3a90f9..0ac9ff832d 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.cpp +++ b/src/mbgl/style/layers/symbol_layer_impl.cpp @@ -76,5 +76,39 @@ std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters& *spriteAtlas); } +SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties& layout_) const { + return SymbolPropertyValues { + layout_.iconRotationAlignment.value, // icon-pitch-alignment is not yet implemented; inherit the rotation alignment + layout_.iconRotationAlignment.value, + layout_.iconSize.value, + paint.iconOpacity.value, + paint.iconColor.value, + paint.iconHaloColor.value, + paint.iconHaloWidth.value, + paint.iconHaloBlur.value, + paint.iconTranslate.value, + paint.iconTranslateAnchor.value, + iconSize, + 1.0f + }; +} + +SymbolPropertyValues SymbolLayer::Impl::textPropertyValues(const SymbolLayoutProperties& layout_) const { + return SymbolPropertyValues { + layout_.textPitchAlignment.value, + layout_.textRotationAlignment.value, + layout_.textSize.value, + paint.textOpacity.value, + paint.textColor.value, + paint.textHaloColor.value, + paint.textHaloWidth.value, + paint.textHaloBlur.value, + paint.textTranslate.value, + paint.textTranslateAnchor.value, + textSize, + 24.0f + }; +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp index fe37ba86ea..b760538f86 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.hpp +++ b/src/mbgl/style/layers/symbol_layer_impl.hpp @@ -11,6 +11,36 @@ class SymbolLayout; namespace style { +// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties +// for genericity over icons vs. text. +class SymbolPropertyValues { +public: + // Layout + AlignmentType pitchAlignment; + AlignmentType rotationAlignment; + float layoutSize; + + // Paint + float opacity; + Color color; + Color haloColor; + float haloWidth; + float haloBlur; + std::array<float, 2> translate; + TranslateAnchorType translateAnchor; + float paintSize; + + float sdfScale; // Constant (1.0 or 24.0) + + bool hasHalo() const { + return haloColor.a > 0.0f && haloWidth > 0.0f; + } + + bool hasForeground() const { + return color.a > 0.0f; + } +}; + class SymbolLayer::Impl : public Layer::Impl { public: std::unique_ptr<Layer> clone() const override; @@ -22,6 +52,9 @@ public: std::unique_ptr<Bucket> createBucket(BucketParameters&) const override; std::unique_ptr<SymbolLayout> createLayout(BucketParameters&) const; + SymbolPropertyValues iconPropertyValues(const SymbolLayoutProperties&) const; + SymbolPropertyValues textPropertyValues(const SymbolLayoutProperties&) const; + SymbolLayoutProperties layout; SymbolPaintProperties paint; diff --git a/src/mbgl/style/property_evaluator.hpp b/src/mbgl/style/property_evaluator.hpp index a0bce2f499..3f657fe3f4 100644 --- a/src/mbgl/style/property_evaluator.hpp +++ b/src/mbgl/style/property_evaluator.hpp @@ -27,7 +27,8 @@ private: }; template <typename T> -struct Faded { +class Faded { +public: T from; T to; float fromScale; diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp index 7852f710f1..d7c64e88b4 100644 --- a/src/mbgl/text/shaping.hpp +++ b/src/mbgl/text/shaping.hpp @@ -7,7 +7,7 @@ namespace mbgl { -struct SpriteAtlasElement; +class SpriteAtlasElement; namespace style { class SymbolLayoutProperties; diff --git a/test/util/offscreen_texture.test.cpp b/test/util/offscreen_texture.test.cpp index a1e444ed65..56972b9810 100644 --- a/test/util/offscreen_texture.test.cpp +++ b/test/util/offscreen_texture.test.cpp @@ -107,21 +107,19 @@ void main() { // Make sure the texture gets destructed before we call context.reset(); { OffscreenView view(context, { 512, 256 }); + view.bind(); // First, draw red to the bound FBO. - context.clearColor = { 1, 0, 0, 1 }; - view.bind(); - MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT)); + context.clear(Color::red(), {}, {}); // Then, create a texture, bind it, and render yellow to that texture. This should not // affect the originally bound FBO. OffscreenTexture texture(context, { 128, 128 }); texture.bind(); - context.clearColor = { 0, 0, 0, 0 }; - MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT)); + context.clear(Color(), {}, {}); - context.program = paintShader.program; + MBGL_CHECK_ERROR(glUseProgram(paintShader.program)); MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, triangleBuffer.buffer)); MBGL_CHECK_ERROR(glEnableVertexAttribArray(paintShader.a_pos)); MBGL_CHECK_ERROR( @@ -138,8 +136,8 @@ void main() { test::checkImage("test/fixtures/offscreen_texture/render-to-fbo", image, 0, 0); // Now, composite the Framebuffer texture we've rendered to onto the main FBO. - context.program = compositeShader.program; context.bindTexture(texture.getTexture(), 0, gl::TextureFilter::Linear); + MBGL_CHECK_ERROR(glUseProgram(compositeShader.program)); MBGL_CHECK_ERROR(glUniform1i(u_texture, 0)); MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, viewportBuffer.buffer)); MBGL_CHECK_ERROR(glEnableVertexAttribArray(compositeShader.a_pos)); |