[core] Modern C++ bindings for OpenGL
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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&);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
44
src/mbgl/gl/color_mode.cpp
Normal file
44
src/mbgl/gl/color_mode.cpp
Normal file
@@ -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
|
||||
95
src/mbgl/gl/color_mode.hpp
Normal file
95
src/mbgl/gl/color_mode.hpp
Normal file
@@ -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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
18
src/mbgl/gl/depth_mode.cpp
Normal file
18
src/mbgl/gl/depth_mode.cpp
Normal file
@@ -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
|
||||
36
src/mbgl/gl/depth_mode.hpp
Normal file
36
src/mbgl/gl/depth_mode.hpp
Normal file
@@ -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
|
||||
34
src/mbgl/gl/draw_mode.hpp
Normal file
34
src/mbgl/gl/draw_mode.hpp
Normal file
@@ -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
|
||||
124
src/mbgl/gl/drawable.hpp
Normal file
124
src/mbgl/gl/drawable.hpp
Normal file
@@ -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
|
||||
@@ -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>
|
||||
|
||||
27
src/mbgl/gl/segment.hpp
Normal file
27
src/mbgl/gl/segment.hpp
Normal file
@@ -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
|
||||
27
src/mbgl/gl/stencil_mode.cpp
Normal file
27
src/mbgl/gl/stencil_mode.cpp
Normal file
@@ -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
|
||||
66
src/mbgl/gl/stencil_mode.hpp
Normal file
66
src/mbgl/gl/stencil_mode.hpp
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 UniformMatrix<4>::bind(const std::array<float, 16>& t) {
|
||||
MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, t.data()));
|
||||
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 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.
|
||||
|
||||
@@ -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&);
|
||||
|
||||
T current;
|
||||
UniformLocation location;
|
||||
};
|
||||
|
||||
template <size_t C, size_t R = C>
|
||||
class UniformMatrix {
|
||||
public:
|
||||
typedef std::array<float, C*R> T;
|
||||
|
||||
UniformMatrix(const char* name, const Shader& shader)
|
||||
: current(), location(shader.getUniformLocation(name)) {
|
||||
}
|
||||
|
||||
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;
|
||||
void operator=(const Value& value) {
|
||||
if (!current || *current != value.t) {
|
||||
current = value.t;
|
||||
bindUniform(location, value.t);
|
||||
}
|
||||
}
|
||||
if (dirty) {
|
||||
bind(current);
|
||||
}
|
||||
|
||||
private:
|
||||
optional<T> current;
|
||||
UniformLocation location;
|
||||
};
|
||||
};
|
||||
|
||||
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:
|
||||
using State = std::tuple<typename Us::State...>;
|
||||
using Values = std::tuple<typename Us::Value...>;
|
||||
|
||||
static State state(const Shader& shader) {
|
||||
return State { { Us::name, shader }... };
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
static Values values(Args&&... args) {
|
||||
return Values { std::forward<Args>(args)... };
|
||||
}
|
||||
|
||||
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)...);
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
void bind(const T&);
|
||||
|
||||
T current;
|
||||
UniformLocation location;
|
||||
// This exists only to provide a varags context for unpacking the assignments in `binder`.
|
||||
template <int...> static void noop(int...) {}
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
} 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.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 {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
const auto& vertexBuffer = tile.debugBucket->vertexBuffer;
|
||||
|
||||
context.depthTest = false;
|
||||
|
||||
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 };
|
||||
|
||||
@@ -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);
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
draw(2,
|
||||
parameters.shaders.fillOutlinePattern,
|
||||
gl::Segmented<gl::Lines>(
|
||||
*bucket.vertexBuffer,
|
||||
*bucket.lineIndexBuffer,
|
||||
bucket.lineSegments,
|
||||
2.0f));
|
||||
} 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;
|
||||
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
|
||||
});
|
||||
};
|
||||
|
||||
// Draw the actual triangles into the color & stencil buffer.
|
||||
setDepthSublayer(1);
|
||||
bucket.drawElements(plainShader, context, paintMode());
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
// 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));
|
||||
}
|
||||
|
||||
outlineShader.u_outline_color = fillColor;
|
||||
outlineShader.u_opacity = opacity;
|
||||
|
||||
// Draw the entire line
|
||||
outlineShader.u_world = worldSize;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
frameHistory.bind(context, 1);
|
||||
|
||||
// TODO remove the `true ||` when #1673 is implemented
|
||||
const bool drawAcrossEdges = (frame.mapMode == MapMode::Continuous) && (true || !(layout.textAllowOverlap || layout.iconAllowOverlap ||
|
||||
layout.textIgnorePlacement || layout.iconIgnorePlacement));
|
||||
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));
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
setDepthSublayer(0);
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
frameHistory.bind(context, 1);
|
||||
iconShader.u_fadetexture = 1;
|
||||
|
||||
bucket.drawIcons(iconShader, context, paintMode());
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (bucket.hasTextData()) {
|
||||
if (layout.textPitchAlignment == AlignmentType::Map) {
|
||||
context.depthFunc = gl::DepthTestFunction::LessEqual;
|
||||
context.depthTest = true;
|
||||
} else {
|
||||
context.depthTest = false;
|
||||
}
|
||||
|
||||
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);
|
||||
auto values = layer.impl->textPropertyValues(layout);
|
||||
|
||||
std::array<uint16_t, 2> texsize {{ glyphAtlas->width, glyphAtlas->height }};
|
||||
|
||||
if (values.hasHalo()) {
|
||||
draw(parameters.shaders.symbolGlyph,
|
||||
SymbolSDFUniforms::haloValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
|
||||
bucket.text,
|
||||
values);
|
||||
}
|
||||
|
||||
if (values.hasForeground()) {
|
||||
draw(parameters.shaders.symbolGlyph,
|
||||
SymbolSDFUniforms::foregroundValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
|
||||
bucket.text,
|
||||
values);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
23
src/mbgl/shader/circle_uniforms.hpp
Normal file
23
src/mbgl/shader/circle_uniforms.hpp
Normal file
@@ -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
|
||||
@@ -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)
|
||||
}};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
18
src/mbgl/shader/collision_box_uniforms.hpp
Normal file
18
src/mbgl/shader/collision_box_uniforms.hpp
Normal file
@@ -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
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
45
src/mbgl/shader/fill_uniforms.cpp
Normal file
45
src/mbgl/shader/fill_uniforms.cpp
Normal file
@@ -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
|
||||
63
src/mbgl/shader/fill_uniforms.hpp
Normal file
63
src/mbgl/shader/fill_uniforms.hpp
Normal file
@@ -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
|
||||
@@ -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)
|
||||
}};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
133
src/mbgl/shader/line_uniforms.cpp
Normal file
133
src/mbgl/shader/line_uniforms.cpp
Normal file
@@ -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
|
||||
109
src/mbgl/shader/line_uniforms.hpp
Normal file
109
src/mbgl/shader/line_uniforms.hpp
Normal file
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
37
src/mbgl/shader/raster_uniforms.hpp
Normal file
37
src/mbgl/shader/raster_uniforms.hpp
Normal file
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -48,11 +48,6 @@ public:
|
||||
SymbolSDFShader symbolGlyph;
|
||||
|
||||
CollisionBoxShader collisionBox;
|
||||
|
||||
gl::VertexArrayObject coveringPlainArray;
|
||||
gl::VertexArrayObject coveringRasterArray;
|
||||
gl::VertexArrayObject backgroundPatternArray;
|
||||
gl::VertexArrayObject backgroundArray;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
143
src/mbgl/shader/symbol_uniforms.cpp
Normal file
143
src/mbgl/shader/symbol_uniforms.cpp
Normal file
@@ -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
|
||||
76
src/mbgl/shader/symbol_uniforms.hpp
Normal file
76
src/mbgl/shader/symbol_uniforms.hpp
Normal file
@@ -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
|
||||
@@ -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),
|
||||
|
||||
33
src/mbgl/shader/uniforms.hpp
Normal file
33
src/mbgl/shader/uniforms.hpp
Normal file
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ private:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Faded {
|
||||
class Faded {
|
||||
public:
|
||||
T from;
|
||||
T to;
|
||||
float fromScale;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct SpriteAtlasElement;
|
||||
class SpriteAtlasElement;
|
||||
|
||||
namespace style {
|
||||
class SymbolLayoutProperties;
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user