Custom drawable layer v2 (#1754)
This commit is contained in:
@@ -201,9 +201,10 @@ public:
|
||||
/// Add a polyline. If the last point equals the first it will be closed, otherwise open
|
||||
void addPolyline(const GeometryCoordinates& coordinates, const gfx::PolylineGeneratorOptions&);
|
||||
|
||||
protected:
|
||||
/// return the curent vertex count
|
||||
std::size_t curVertexCount() const;
|
||||
|
||||
protected:
|
||||
/// Create an instance of the appropriate drawable type
|
||||
virtual UniqueDrawable createDrawable() const = 0;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/gfx/vertex_vector.hpp>
|
||||
@@ -40,8 +41,8 @@ struct PolylineGeneratorOptions {
|
||||
style::LineCapType beginCap{style::LineCapType::Butt};
|
||||
style::LineCapType endCap{style::LineCapType::Butt};
|
||||
float roundLimit{1.f};
|
||||
uint32_t overscaling{1}; // TODO: what is this???
|
||||
std::optional<PolylineGeneratorDistances> lineDistances;
|
||||
uint32_t overscaling{1};
|
||||
std::optional<PolylineGeneratorDistances> clipDistances;
|
||||
};
|
||||
|
||||
template <class PolylineLayoutVertex, class PolylineSegment>
|
||||
@@ -100,4 +101,4 @@ private:
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -6,30 +6,107 @@
|
||||
#include <mbgl/renderer/update_parameters.hpp>
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/renderer/change_request.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
class CustomDrawableLayerHost {
|
||||
public:
|
||||
class Interface;
|
||||
|
||||
public:
|
||||
virtual ~CustomDrawableLayerHost() = default;
|
||||
|
||||
virtual void initialize() = 0;
|
||||
|
||||
virtual void update(RenderLayer& proxyLayer,
|
||||
gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
const TransformState& state,
|
||||
const std::shared_ptr<UpdateParameters>&,
|
||||
const RenderTree& renderTree,
|
||||
UniqueChangeRequestVec& changes) = 0;
|
||||
virtual void update(Interface& interface) = 0;
|
||||
|
||||
virtual void deinitialize() = 0;
|
||||
};
|
||||
|
||||
class CustomDrawableLayerHost::Interface {
|
||||
public:
|
||||
struct LineOptions {
|
||||
Color color;
|
||||
float blur = 0.f;
|
||||
float opacity = 1.f;
|
||||
float gapWidth = 0.f;
|
||||
float offset = 0.f;
|
||||
float width = 1.f;
|
||||
gfx::PolylineGeneratorOptions geometry;
|
||||
};
|
||||
|
||||
public:
|
||||
/// @brief Construct a new Interface object (internal core use only)
|
||||
Interface(RenderLayer& layer,
|
||||
LayerGroupBasePtr& layerGroup,
|
||||
gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
const TransformState& state,
|
||||
const std::shared_ptr<UpdateParameters>& updateParameters,
|
||||
const RenderTree& renderTree,
|
||||
UniqueChangeRequestVec& changes);
|
||||
/**
|
||||
* @brief Get the drawable count
|
||||
*
|
||||
* @return std::size_t
|
||||
*/
|
||||
std::size_t getDrawableCount() const;
|
||||
|
||||
/**
|
||||
* @brief Set the Tile ID
|
||||
*
|
||||
* @param tileID
|
||||
*/
|
||||
void setTileID(OverscaledTileID tileID);
|
||||
|
||||
/**
|
||||
* @brief Set the line options
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
void setLineOptions(const LineOptions& options);
|
||||
|
||||
/**
|
||||
* @brief Add a polyline
|
||||
*
|
||||
* @param coordinates
|
||||
* @param options Polyline options
|
||||
*/
|
||||
void addPolyline(const GeometryCoordinates& coordinates);
|
||||
|
||||
/**
|
||||
* @brief Finishe the current drawable building session
|
||||
*
|
||||
*/
|
||||
void finish();
|
||||
|
||||
protected:
|
||||
gfx::ShaderPtr lineShaderDefault() const;
|
||||
|
||||
std::unique_ptr<gfx::DrawableBuilder> createBuilder(const std::string& name, gfx::ShaderPtr shader) const;
|
||||
|
||||
public:
|
||||
RenderLayer& layer;
|
||||
LayerGroupBasePtr& layerGroup;
|
||||
gfx::ShaderRegistry& shaders;
|
||||
gfx::Context& context;
|
||||
const TransformState& state;
|
||||
const std::shared_ptr<UpdateParameters>& updateParameters;
|
||||
const RenderTree& renderTree;
|
||||
UniqueChangeRequestVec& changes;
|
||||
|
||||
private:
|
||||
std::unique_ptr<gfx::DrawableBuilder> builder;
|
||||
std::optional<OverscaledTileID> tileID;
|
||||
LineOptions lineOptions;
|
||||
};
|
||||
|
||||
class CustomDrawableLayer final : public Layer {
|
||||
public:
|
||||
CustomDrawableLayer(const std::string& id, std::unique_ptr<CustomDrawableLayerHost> host);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
#include <mapbox/compatibility/value.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
|
||||
@@ -15,6 +15,11 @@ objc_library(
|
||||
"//conditions:default": [
|
||||
"//platform/darwin:darwin_objcpp_opengl_srcs",
|
||||
],
|
||||
}) + select({
|
||||
"//:legacy_renderer": [],
|
||||
"//conditions:default": [
|
||||
"//platform/darwin:darwin_objcpp_custom_drawable_srcs",
|
||||
],
|
||||
}),
|
||||
copts = CPP_FLAGS + MAPLIBRE_FLAGS + [
|
||||
"-fcxx-modules",
|
||||
@@ -165,6 +170,28 @@ objc_library(
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "app_custom_drawable_layer_objcpp_srcs",
|
||||
srcs = [
|
||||
"//platform/darwin:app/ExampleCustomDrawableStyleLayer.h",
|
||||
"//platform/darwin:app/ExampleCustomDrawableStyleLayer.mm",
|
||||
],
|
||||
copts = CPP_FLAGS + MAPLIBRE_FLAGS + WARNING_FLAGS["ios"] + [
|
||||
"-fcxx-modules",
|
||||
"-fmodules",
|
||||
"-Wno-c99-extensions",
|
||||
"-Wno-gnu-zero-variadic-macro-arguments",
|
||||
"-Wno-gnu-conditional-omitted-operand",
|
||||
"-Wno-gnu-statement-expression",
|
||||
"-Wno-deprecated-declarations",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//:mbgl-core",
|
||||
":ios-sdk",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "iosapp",
|
||||
srcs = [
|
||||
@@ -183,7 +210,6 @@ objc_library(
|
||||
includes = [
|
||||
"darwin/app",
|
||||
"darwin/src",
|
||||
"ios/src",
|
||||
],
|
||||
sdk_frameworks = [
|
||||
] + select({
|
||||
@@ -196,7 +222,12 @@ objc_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":ios-sdk",
|
||||
],
|
||||
] + select({
|
||||
"//:legacy_renderer": [],
|
||||
"//conditions:default": [
|
||||
":app_custom_drawable_layer_objcpp_srcs",
|
||||
],
|
||||
}),
|
||||
)
|
||||
|
||||
objc_library(
|
||||
@@ -242,6 +273,11 @@ sh_binary(
|
||||
"//conditions:default": [
|
||||
"//platform/darwin:darwin_objcpp_opengl_srcs",
|
||||
],
|
||||
}) + select({
|
||||
"//:legacy_renderer": [],
|
||||
"//conditions:default": [
|
||||
"//platform/darwin:darwin_objcpp_custom_drawable_srcs",
|
||||
],
|
||||
}),
|
||||
deps = [
|
||||
"//platform/darwin:generated_code",
|
||||
|
||||
@@ -6,6 +6,7 @@ load(
|
||||
"MLN_DARWIN_PRIVATE_HEADERS",
|
||||
"MLN_DARWIN_PUBLIC_OBJCPP_SOURCE",
|
||||
"MLN_DARWIN_PUBLIC_OBJCPP_OPENGL_SOURCE",
|
||||
"MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE",
|
||||
"MLN_DARWIN_PUBLIC_OBJC_SOURCE",
|
||||
"MLN_GENERATED_DARWIN_STYLE_HEADERS",
|
||||
"MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS",
|
||||
@@ -47,6 +48,12 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "darwin_objcpp_custom_drawable_srcs",
|
||||
srcs = MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE,
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "darwin_objc_srcs",
|
||||
srcs = MLN_DARWIN_PUBLIC_OBJC_SOURCE,
|
||||
@@ -324,12 +331,15 @@ exports_files(
|
||||
"test/MLNSDKTestHelpers.swift",
|
||||
"app/LimeGreenStyleLayer.h",
|
||||
"app/LimeGreenStyleLayer.m",
|
||||
"app/ExampleCustomDrawableStyleLayer.h",
|
||||
"app/ExampleCustomDrawableStyleLayer.mm",
|
||||
"include/mbgl/util/image+MLNAdditions.hpp",
|
||||
"scripts/check-public-symbols.js",
|
||||
"scripts/check-public-symbols.sh",
|
||||
] + MLN_DARWIN_PUBLIC_OBJC_SOURCE +
|
||||
MLN_DARWIN_PUBLIC_OBJCPP_SOURCE +
|
||||
MLN_DARWIN_PUBLIC_OBJCPP_OPENGL_SOURCE +
|
||||
MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE +
|
||||
MLN_DARWIN_PRIVATE_HEADERS +
|
||||
MLN_DARWIN_OBJC_HEADERS +
|
||||
MLN_DARWIN_OBJCPP_HEADERS,
|
||||
|
||||
12
platform/darwin/app/ExampleCustomDrawableStyleLayer.h
Normal file
12
platform/darwin/app/ExampleCustomDrawableStyleLayer.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#import "Mapbox.h"
|
||||
|
||||
#import "MLNFoundation.h"
|
||||
#import "MLNStyleValue.h"
|
||||
#import "MLNStyleLayer.h"
|
||||
#import "MLNGeometry.h"
|
||||
|
||||
@interface ExampleCustomDrawableStyleLayer : MLNStyleLayer
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSString *)identifier;
|
||||
|
||||
@end
|
||||
100
platform/darwin/app/ExampleCustomDrawableStyleLayer.mm
Normal file
100
platform/darwin/app/ExampleCustomDrawableStyleLayer.mm
Normal file
@@ -0,0 +1,100 @@
|
||||
#import "ExampleCustomDrawableStyleLayer.h"
|
||||
#import "MLNStyleLayer.h"
|
||||
|
||||
#import "MLNCustomDrawableStyleLayer_Private.h"
|
||||
#import "MLNStyle_Private.h"
|
||||
#import "MLNStyleLayer_Private.h"
|
||||
#import "MLNGeometry_Private.h"
|
||||
|
||||
#include <mbgl/layermanager/layer_factory.hpp>
|
||||
#include <mbgl/style/layer.hpp>
|
||||
#include <mbgl/style/layers/custom_drawable_layer.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
|
||||
class ExampleCustomDrawableStyleLayerHost;
|
||||
|
||||
@implementation ExampleCustomDrawableStyleLayer
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSString *)identifier {
|
||||
auto layer = std::make_unique<mbgl::style::CustomDrawableLayer>(identifier.UTF8String,
|
||||
std::make_unique<ExampleCustomDrawableStyleLayerHost>(self));
|
||||
return self = [super initWithPendingLayer:std::move(layer)];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
class ExampleCustomDrawableStyleLayerHost : public mbgl::style::CustomDrawableLayerHost {
|
||||
public:
|
||||
ExampleCustomDrawableStyleLayerHost(ExampleCustomDrawableStyleLayer *styleLayer) {
|
||||
layerRef = styleLayer;
|
||||
layer = nil;
|
||||
}
|
||||
|
||||
void initialize() override {
|
||||
if (layerRef == nil) return;
|
||||
else if (layer == nil) layer = layerRef;
|
||||
}
|
||||
|
||||
void update(Interface& interface) override {
|
||||
|
||||
// if we have built our drawable(s) already, either update or skip
|
||||
if (interface.getDrawableCount())
|
||||
return;
|
||||
|
||||
// set tile
|
||||
interface.setTileID({11, 327, 791});
|
||||
|
||||
// add polylines
|
||||
using namespace mbgl;
|
||||
|
||||
constexpr auto numLines = 6;
|
||||
Interface::LineOptions options[numLines] {
|
||||
{/*color=*/Color::red(), /*blur=*/0.0f, /*opacity=*/1.0f, /*gapWidth=*/0.0f, /*offset=*/0.0f, /*width=*/8.0f, {} },
|
||||
{/*color=*/Color::blue(), /*blur=*/4.0f, /*opacity=*/1.0f, /*gapWidth=*/2.0f, /*offset=*/-1.0f, /*width=*/4.0f, {} },
|
||||
{/*color=*/Color(1.f, 0.5f, 0, 0.5f), /*blur=*/16.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/2.0f, /*width=*/16.0f, {} },
|
||||
{/*color=*/Color(1.f, 1.f, 0, 0.3f), /*blur=*/2.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/-2.0f, /*width=*/2.0f, {} },
|
||||
{/*color=*/Color::black(), /*blur=*/0.5f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/0.5f, /*width=*/0.5f, {} },
|
||||
{/*color=*/Color(1.f, 0, 1.f, 0.2f), /*blur=*/24.0f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/-5.0f, /*width=*/24.0f, {} },
|
||||
};
|
||||
for(auto& opt: options) {
|
||||
opt.geometry.beginCap = style::LineCapType::Round;
|
||||
opt.geometry.endCap = style::LineCapType::Round;
|
||||
opt.geometry.joinType = style::LineJoinType::Round;
|
||||
}
|
||||
|
||||
constexpr auto numPoints = 100;
|
||||
GeometryCoordinates polyline;
|
||||
for (auto ipoint{0}; ipoint < numPoints; ++ipoint) {
|
||||
polyline.emplace_back(ipoint * util::EXTENT / numPoints, std::sin(ipoint * 2 * M_PI / numPoints) * util::EXTENT / numLines / 2.f);
|
||||
}
|
||||
|
||||
for (auto index {0}; index < numLines; ++index) {
|
||||
for(auto &p : polyline) {
|
||||
p.y += util::EXTENT / numLines;
|
||||
}
|
||||
|
||||
// set property values
|
||||
interface.setLineOptions(options[index]);
|
||||
|
||||
// add polyline
|
||||
interface.addPolyline(polyline);
|
||||
}
|
||||
|
||||
// finish
|
||||
interface.finish();
|
||||
}
|
||||
|
||||
void deinitialize() override {
|
||||
if (layer == nil) return;
|
||||
|
||||
layerRef = layer;
|
||||
layer = nil;
|
||||
}
|
||||
private:
|
||||
__weak ExampleCustomDrawableStyleLayer * layerRef;
|
||||
ExampleCustomDrawableStyleLayer * layer = nil;
|
||||
};
|
||||
@@ -208,6 +208,11 @@ MLN_DARWIN_PUBLIC_OBJCPP_OPENGL_SOURCE = [
|
||||
"src/MLNOpenGLStyleLayer.h",
|
||||
"src/MLNOpenGLStyleLayer.mm",
|
||||
]
|
||||
MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE = [
|
||||
"src/MLNCustomDrawableStyleLayer_Private.h",
|
||||
"src/MLNCustomDrawableStyleLayer.h",
|
||||
"src/MLNCustomDrawableStyleLayer.mm",
|
||||
]
|
||||
MLN_DARWIN_PUBLIC_OBJC_SOURCE = [
|
||||
"src/MLNAttributedExpression.m",
|
||||
"src/MLNClockDirectionFormatter.m",
|
||||
|
||||
10
platform/darwin/src/MLNCustomDrawableStyleLayer.h
Normal file
10
platform/darwin/src/MLNCustomDrawableStyleLayer.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#import "MLNFoundation.h"
|
||||
#import "MLNStyleValue.h"
|
||||
#import "MLNStyleLayer.h"
|
||||
#import "MLNGeometry.h"
|
||||
|
||||
@interface MLNCustomDrawableStyleLayer : MLNStyleLayer
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSString *)identifier;
|
||||
|
||||
@end
|
||||
39
platform/darwin/src/MLNCustomDrawableStyleLayer.mm
Normal file
39
platform/darwin/src/MLNCustomDrawableStyleLayer.mm
Normal file
@@ -0,0 +1,39 @@
|
||||
#import "MLNCustomDrawableStyleLayer.h"
|
||||
#import "MLNStyleLayer.h"
|
||||
|
||||
#import "MLNCustomDrawableStyleLayer_Private.h"
|
||||
#import "MLNStyle_Private.h"
|
||||
#import "MLNStyleLayer_Private.h"
|
||||
#import "MLNGeometry_Private.h"
|
||||
|
||||
#include <mbgl/layermanager/custom_drawable_layer_factory.hpp>
|
||||
#include <mbgl/style/layers/custom_drawable_layer.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
|
||||
@implementation MLNCustomDrawableStyleLayer
|
||||
|
||||
/// @note
|
||||
/// Inherit MLNCustomDrawableStyleLayer class and override initWithIdentifier method to create and attach a valid CustomDrawableLayerHost instance
|
||||
/// Example:
|
||||
/// - (instancetype)initWithIdentifier:(NSString *)identifier {
|
||||
/// auto layer = std::make_unique<mbgl::style::CustomDrawableLayer>(identifier.UTF8String,
|
||||
/// std::make_unique<ExampleCustomDrawableStyleLayerHost>(self));
|
||||
/// return self = [super initWithPendingLayer:std::move(layer)];
|
||||
/// }
|
||||
///
|
||||
- (instancetype)initWithIdentifier:(NSString *)identifier {
|
||||
auto layer = std::make_unique<mbgl::style::CustomDrawableLayer>(identifier.UTF8String, nullptr);
|
||||
return self = [super initWithPendingLayer:std::move(layer)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
MLNStyleLayer* CustomDrawableStyleLayerPeerFactory::createPeer(style::Layer* rawLayer) {
|
||||
return [[MLNCustomDrawableStyleLayer alloc] initWithRawLayer:rawLayer];
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
15
platform/darwin/src/MLNCustomDrawableStyleLayer_Private.h
Normal file
15
platform/darwin/src/MLNCustomDrawableStyleLayer_Private.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "MLNStyleLayer_Private.h"
|
||||
|
||||
#include <mbgl/layermanager/custom_drawable_layer_factory.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class CustomDrawableStyleLayerPeerFactory : public LayerPeerFactory, public mbgl::CustomDrawableLayerFactory {
|
||||
// LayerPeerFactory overrides.
|
||||
LayerFactory* getCoreLayerFactory() final { return this; }
|
||||
virtual MLNStyleLayer* createPeer(style::Layer*) final;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -14,6 +14,10 @@
|
||||
#import "MLNOpenGLStyleLayer_Private.h"
|
||||
#endif
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
#import "MLNCustomDrawableStyleLayer_Private.h"
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -69,6 +73,14 @@ LayerManagerDarwin::LayerManagerDarwin() {
|
||||
#elif !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) && !MLN_RENDER_BACKEND_METAL
|
||||
addLayerType(std::make_unique<OpenGLStyleLayerPeerFactory>());
|
||||
#endif
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
#if defined(MLN_LAYER_CUSTOM_DRAWABLE_DISABLE_RUNTIME)
|
||||
addLayerTypeCoreOnly(std::make_unique<CustomDrawableLayerFactory>());
|
||||
#elif !defined(MLN_LAYER_CUSTOM_DRAWABLE_DISABLE_ALL)
|
||||
addLayerType(std::make_unique<CustomDrawableStyleLayerPeerFactory>());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
LayerManagerDarwin::~LayerManagerDarwin() = default;
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#import "LimeGreenStyleLayer.h"
|
||||
#endif
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
#import "ExampleCustomDrawableStyleLayer.h"
|
||||
#endif
|
||||
|
||||
#import "MBXFrameTimeGraphView.h"
|
||||
#import "MLNMapView_Experimental.h"
|
||||
#import <objc/runtime.h>
|
||||
@@ -108,6 +112,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
|
||||
MBXSettingsRuntimeStylingDDSPolygon,
|
||||
MBXSettingsRuntimeStylingCustomLatLonGrid,
|
||||
MBXSettingsRuntimeStylingLineGradient,
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
MBXSettingsRuntimeStylingCustomDrawableLayer,
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
@@ -441,6 +448,9 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
|
||||
@"Dynamically Style Polygon",
|
||||
@"Add Custom Lat/Lon Grid",
|
||||
@"Style Route line with gradient",
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
@"Add Custom Drawable Layer",
|
||||
#endif
|
||||
]];
|
||||
break;
|
||||
case MBXSettingsMiscellaneous:
|
||||
@@ -666,6 +676,11 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
|
||||
case MBXSettingsRuntimeStylingLineGradient:
|
||||
[self styleLineGradient];
|
||||
break;
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
case MBXSettingsRuntimeStylingCustomDrawableLayer:
|
||||
[self addCustomDrawableLayer];
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
NSAssert(NO, @"All runtime styling setting rows should be implemented");
|
||||
break;
|
||||
@@ -1564,6 +1579,18 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
|
||||
[self.mapView.style addLayer:routeLayer];
|
||||
}
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
- (void)addCustomDrawableLayer
|
||||
{
|
||||
// Create a CustomLayer that uses the Drawable/Builder toolkit to generate and render geometry
|
||||
ExampleCustomDrawableStyleLayer* layer = [[ExampleCustomDrawableStyleLayer alloc] initWithIdentifier:@"custom-drawable-layer"];
|
||||
|
||||
if (layer) {
|
||||
[self.mapView.style addLayer:layer];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)styleRouteLine
|
||||
{
|
||||
CLLocationCoordinate2D coords[] = {
|
||||
|
||||
@@ -77,3 +77,6 @@ FOUNDATION_EXPORT MLN_EXPORT const unsigned char MapboxVersionString[];
|
||||
#import "NSPredicate+MLNAdditions.h"
|
||||
#import "NSValue+MLNAdditions.h"
|
||||
#import "MLNUserLocationAnnotationViewStyle.h"
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
#import "MLNCustomDrawableStyleLayer.h"
|
||||
#endif
|
||||
|
||||
@@ -70,7 +70,7 @@ void DrawableBuilder::Impl::setupForPolylines(gfx::DrawableBuilder& builder) {
|
||||
|
||||
gfx::VertexAttributeArray attrs;
|
||||
using VertexVector = gfx::VertexVector<LineLayoutVertex>;
|
||||
std::shared_ptr<VertexVector> verts = std::make_shared<VertexVector>(polylineVertices);
|
||||
std::shared_ptr<VertexVector> verts = std::make_shared<VertexVector>(std::move(polylineVertices));
|
||||
|
||||
if (const auto& attr = attrs.add(idVertexAttribName)) {
|
||||
attr->setSharedRawData(verts,
|
||||
|
||||
@@ -65,6 +65,16 @@ public:
|
||||
return std::max(rawVerticesCount, std::max(vertices.elements(), polylineVertices.elements()));
|
||||
}
|
||||
|
||||
void clear() {
|
||||
vertices.clear();
|
||||
rawVertices.clear();
|
||||
rawVerticesCount = 0;
|
||||
polylineVertices.clear();
|
||||
polylineIndexes.clear();
|
||||
buildIndexes.clear();
|
||||
segments.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
LineLayoutVertex layoutVertex(
|
||||
Point<int16_t> p, Point<double> e, bool round, bool up, int8_t dir, int32_t linesofar = 0);
|
||||
|
||||
@@ -227,7 +227,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
prevCoordinate = newPrevVertex;
|
||||
}
|
||||
}
|
||||
@@ -279,7 +279,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
|
||||
} else if (middleVertex && currentJoin == style::LineJoinType::FlipBevel) {
|
||||
// miter is too big, flip the direction to make a beveled join
|
||||
@@ -302,7 +302,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
|
||||
addCurrentVertex(*currentCoordinate,
|
||||
distance,
|
||||
@@ -312,7 +312,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
} else if (middleVertex &&
|
||||
(currentJoin == style::LineJoinType::Bevel || currentJoin == style::LineJoinType::FakeRound)) {
|
||||
const bool lineTurnsLeft = (prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x) > 0;
|
||||
@@ -338,7 +338,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
}
|
||||
|
||||
if (currentJoin == style::LineJoinType::FakeRound) {
|
||||
@@ -369,7 +369,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
lineTurnsLeft,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
}
|
||||
|
||||
} else if (!middleVertex && currentCap == style::LineCapType::Butt) {
|
||||
@@ -397,7 +397,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
}
|
||||
|
||||
// Start next segment with a butt
|
||||
@@ -410,7 +410,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
}
|
||||
|
||||
} else if (!middleVertex && currentCap == style::LineCapType::Square) {
|
||||
@@ -424,7 +424,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
|
||||
// The segment is done. Unset vertices to disconnect segments.
|
||||
e1 = e2 = -1;
|
||||
@@ -440,7 +440,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
}
|
||||
|
||||
} else if (middleVertex ? currentJoin == style::LineJoinType::Round : currentCap == style::LineCapType::Round) {
|
||||
@@ -454,7 +454,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
|
||||
// Add round cap or linejoin at end of segment
|
||||
addCurrentVertex(*currentCoordinate,
|
||||
@@ -465,7 +465,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
true,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
|
||||
// The segment is done. Unset vertices to disconnect segments.
|
||||
e1 = e2 = -1;
|
||||
@@ -482,7 +482,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
true,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
|
||||
addCurrentVertex(*currentCoordinate,
|
||||
distance,
|
||||
@@ -492,7 +492,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
false,
|
||||
startVertex,
|
||||
triangleStore,
|
||||
options.lineDistances);
|
||||
options.clipDistances);
|
||||
currentCoordinate = newCurrentVertex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,10 @@ void DrawableGLBuilder::init() {
|
||||
if (!impl->sharedIndexes && !impl->buildIndexes.empty()) {
|
||||
impl->sharedIndexes = std::make_shared<gfx::IndexVectorBase>(std::move(impl->buildIndexes));
|
||||
}
|
||||
assert(impl->sharedIndexes && impl->sharedIndexes->elements());
|
||||
drawableGL.setIndexData(std::move(impl->sharedIndexes), std::move(impl->segments));
|
||||
|
||||
impl->buildIndexes.clear();
|
||||
impl->segments.clear();
|
||||
impl->vertices.clear();
|
||||
impl->clear();
|
||||
textures.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ void DrawableBuilder::init() {
|
||||
if (impl->rawVerticesCount) {
|
||||
auto raw = impl->rawVertices;
|
||||
drawable.setVertices(std::move(raw), impl->rawVerticesCount, impl->rawVerticesType);
|
||||
impl->rawVerticesCount = 0;
|
||||
} else {
|
||||
const auto& verts = impl->vertices.vector();
|
||||
constexpr auto vertSize = sizeof(std::remove_reference<decltype(verts)>::type::value_type);
|
||||
@@ -41,9 +42,7 @@ void DrawableBuilder::init() {
|
||||
assert(impl->sharedIndexes && impl->sharedIndexes->elements());
|
||||
drawable.setIndexData(std::move(impl->sharedIndexes), std::move(impl->segments));
|
||||
|
||||
impl->buildIndexes.clear();
|
||||
impl->segments.clear();
|
||||
impl->vertices.clear();
|
||||
impl->clear();
|
||||
textures.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates,
|
||||
total_length += util::dist<double>(coordinates[i], coordinates[i + 1]);
|
||||
}
|
||||
|
||||
options.lineDistances = gfx::PolylineGeneratorDistances{
|
||||
options.clipDistances = gfx::PolylineGeneratorDistances{
|
||||
*numericValue<double>(clip_start_it->second), *numericValue<double>(clip_end_it->second), total_length};
|
||||
}
|
||||
|
||||
|
||||
@@ -52,10 +52,6 @@ bool RenderCustomDrawableLayer::hasCrossfade() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenderCustomDrawableLayer::markContextDestroyed() {
|
||||
contextDestroyed = true;
|
||||
}
|
||||
|
||||
void RenderCustomDrawableLayer::prepare(const LayerPrepareParameters&) {}
|
||||
|
||||
#if MLN_LEGACY_RENDERER
|
||||
@@ -84,9 +80,12 @@ void RenderCustomDrawableLayer::update(gfx::ShaderRegistry& shaders,
|
||||
|
||||
// delegate the call to the custom layer
|
||||
if (host) {
|
||||
host->update(*this, shaders, context, state, updateParameters, renderTree, changes);
|
||||
CustomDrawableLayerHost::Interface interface(
|
||||
*this, layerGroup, shaders, context, state, updateParameters, renderTree, changes);
|
||||
host->update(interface);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -25,14 +25,12 @@ private:
|
||||
void evaluate(const PropertyEvaluationParameters&) override;
|
||||
bool hasTransition() const override;
|
||||
bool hasCrossfade() const override;
|
||||
void markContextDestroyed() override;
|
||||
void prepare(const LayerPrepareParameters&) override;
|
||||
|
||||
#if MLN_LEGACY_RENDERER
|
||||
void render(PaintParameters&) override;
|
||||
#endif
|
||||
|
||||
bool contextDestroyed = false;
|
||||
std::shared_ptr<style::CustomDrawableLayerHost> host;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
#include <mbgl/style/layers/custom_drawable_layer.hpp>
|
||||
#include <mbgl/style/layers/custom_drawable_layer_impl.hpp>
|
||||
|
||||
#include <mbgl/renderer/layers/render_custom_drawable_layer.hpp>
|
||||
#include <mbgl/style/layer_observer.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/renderer/change_request.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/drawable_tweaker.hpp>
|
||||
#include <mbgl/shaders/line_layer_ubo.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
@@ -53,5 +66,185 @@ const LayerTypeInfo* CustomDrawableLayer::Impl::staticTypeInfo() noexcept {
|
||||
return &typeInfoCustomDrawable;
|
||||
}
|
||||
|
||||
// CustomDrawableLayerHost::Interface
|
||||
|
||||
class LineDrawableTweaker : public gfx::DrawableTweaker {
|
||||
public:
|
||||
LineDrawableTweaker(const shaders::LinePropertiesUBO& properties)
|
||||
: linePropertiesUBO(properties) {}
|
||||
~LineDrawableTweaker() override = default;
|
||||
|
||||
void init(gfx::Drawable&) override{};
|
||||
|
||||
void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override {
|
||||
if (!drawable.getTileID().has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
|
||||
const auto zoom = parameters.state.getZoom();
|
||||
mat4 tileMatrix;
|
||||
parameters.state.matrixFor(/*out*/ tileMatrix, tileID);
|
||||
|
||||
const auto matrix = LayerTweaker::getTileMatrix(
|
||||
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false);
|
||||
|
||||
static const StringIdentity idLineUBOName = stringIndexer().get("LineUBO");
|
||||
const shaders::LineUBO lineUBO{
|
||||
/*matrix = */ util::cast<float>(matrix),
|
||||
/*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]},
|
||||
/*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, zoom),
|
||||
/*device_pixel_ratio = */ parameters.pixelRatio};
|
||||
|
||||
static const StringIdentity idLinePropertiesUBOName = stringIndexer().get("LinePropertiesUBO");
|
||||
|
||||
static const StringIdentity idLineInterpolationUBOName = stringIndexer().get("LineInterpolationUBO");
|
||||
const shaders::LineInterpolationUBO lineInterpolationUBO{/*color_t =*/0.f,
|
||||
/*blur_t =*/0.f,
|
||||
/*opacity_t =*/0.f,
|
||||
/*gapwidth_t =*/0.f,
|
||||
/*offset_t =*/0.f,
|
||||
/*width_t =*/0.f,
|
||||
0,
|
||||
0};
|
||||
auto& uniforms = drawable.mutableUniformBuffers();
|
||||
uniforms.createOrUpdate(idLineUBOName, &lineUBO, parameters.context);
|
||||
uniforms.createOrUpdate(idLinePropertiesUBOName, &linePropertiesUBO, parameters.context);
|
||||
uniforms.createOrUpdate(idLineInterpolationUBOName, &lineInterpolationUBO, parameters.context);
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
static const StringIdentity idExpressionInputsUBOName = stringIndexer().get("ExpressionInputsUBO");
|
||||
const auto expressionUBO = LayerTweaker::buildExpressionUBO(zoom, parameters.frameCount);
|
||||
uniforms.createOrUpdate(idExpressionInputsUBOName, &expressionUBO, parameters.context);
|
||||
|
||||
static const StringIdentity idLinePermutationUBOName = stringIndexer().get("LinePermutationUBO");
|
||||
const shaders::LinePermutationUBO permutationUBO = {
|
||||
/* .color = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .blur = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .opacity = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .gapwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .offset = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .width = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .floorwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .pattern_from = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .pattern_to = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .overdrawInspector = */ false,
|
||||
/* .pad = */ 0,
|
||||
0,
|
||||
0,
|
||||
0};
|
||||
uniforms.createOrUpdate(idLinePermutationUBOName, &permutationUBO, parameters.context);
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
};
|
||||
|
||||
private:
|
||||
shaders::LinePropertiesUBO linePropertiesUBO;
|
||||
};
|
||||
|
||||
CustomDrawableLayerHost::Interface::Interface(RenderLayer& layer_,
|
||||
LayerGroupBasePtr& layerGroup_,
|
||||
gfx::ShaderRegistry& shaders_,
|
||||
gfx::Context& context_,
|
||||
const TransformState& state_,
|
||||
const std::shared_ptr<UpdateParameters>& updateParameters_,
|
||||
const RenderTree& renderTree_,
|
||||
UniqueChangeRequestVec& changes_)
|
||||
: layer(layer_),
|
||||
layerGroup(layerGroup_),
|
||||
shaders(shaders_),
|
||||
context(context_),
|
||||
state(state_),
|
||||
updateParameters(updateParameters_),
|
||||
renderTree(renderTree_),
|
||||
changes(changes_) {
|
||||
// ensure we have a default layer group set up
|
||||
if (!layerGroup) {
|
||||
if (auto aLayerGroup = context.createTileLayerGroup(
|
||||
/*layerIndex*/ layer.getLayerIndex(), /*initialCapacity=*/64, layer.getID())) {
|
||||
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(aLayerGroup));
|
||||
layerGroup = std::move(aLayerGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t CustomDrawableLayerHost::Interface::getDrawableCount() const {
|
||||
return layerGroup->getDrawableCount();
|
||||
}
|
||||
|
||||
void CustomDrawableLayerHost::Interface::setTileID(OverscaledTileID tileID_) {
|
||||
tileID = tileID_;
|
||||
}
|
||||
|
||||
void CustomDrawableLayerHost::Interface::setLineOptions(const LineOptions& options) {
|
||||
finish();
|
||||
lineOptions = options;
|
||||
}
|
||||
|
||||
void CustomDrawableLayerHost::Interface::addPolyline(const GeometryCoordinates& coordinates) {
|
||||
if (!builder) {
|
||||
builder = createBuilder("thick-lines", lineShaderDefault());
|
||||
} else {
|
||||
// TODO: check builder
|
||||
}
|
||||
builder->addPolyline(coordinates, lineOptions.geometry);
|
||||
}
|
||||
|
||||
void CustomDrawableLayerHost::Interface::finish() {
|
||||
if (builder && builder->curVertexCount()) {
|
||||
// create tweaker
|
||||
const shaders::LinePropertiesUBO linePropertiesUBO{lineOptions.color,
|
||||
lineOptions.blur,
|
||||
lineOptions.opacity,
|
||||
lineOptions.gapWidth,
|
||||
lineOptions.offset,
|
||||
lineOptions.width,
|
||||
0,
|
||||
0,
|
||||
0};
|
||||
|
||||
auto tweaker = std::make_shared<LineDrawableTweaker>(linePropertiesUBO);
|
||||
|
||||
// finish
|
||||
builder->flush();
|
||||
for (auto& drawable : builder->clearDrawables()) {
|
||||
assert(tileID.has_value());
|
||||
drawable->setTileID(tileID.value());
|
||||
drawable->addTweaker(tweaker);
|
||||
|
||||
TileLayerGroup* tileLayerGroup = static_cast<TileLayerGroup*>(layerGroup.get());
|
||||
tileLayerGroup->addDrawable(RenderPass::Translucent, tileID.value(), std::move(drawable));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx::ShaderPtr CustomDrawableLayerHost::Interface::lineShaderDefault() const {
|
||||
gfx::ShaderGroupPtr lineShaderGroup = shaders.getShaderGroup("LineShader");
|
||||
|
||||
const std::unordered_set<StringIdentity> propertiesAsUniforms{
|
||||
stringIndexer().get("a_color"),
|
||||
stringIndexer().get("a_blur"),
|
||||
stringIndexer().get("a_opacity"),
|
||||
stringIndexer().get("a_gapwidth"),
|
||||
stringIndexer().get("a_offset"),
|
||||
stringIndexer().get("a_width"),
|
||||
};
|
||||
|
||||
return lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
|
||||
}
|
||||
|
||||
std::unique_ptr<gfx::DrawableBuilder> CustomDrawableLayerHost::Interface::createBuilder(const std::string& name,
|
||||
gfx::ShaderPtr shader) const {
|
||||
std::unique_ptr<gfx::DrawableBuilder> builder_ = context.createDrawableBuilder(name);
|
||||
builder_->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(shader));
|
||||
builder_->setSubLayerIndex(0);
|
||||
builder_->setEnableDepth(false);
|
||||
builder_->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
builder_->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder_->setEnableStencil(false);
|
||||
builder_->setRenderPass(RenderPass::Translucent);
|
||||
|
||||
return builder_;
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -13,207 +13,106 @@
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
|
||||
#include <mbgl/style/layers/custom_drawable_layer.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/drawable_tweaker.hpp>
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#include <mbgl/gfx/color_mode.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/shaders/line_layer_ubo.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace mbgl;
|
||||
using namespace mbgl::style;
|
||||
|
||||
class TestDrawableTweaker : public gfx::DrawableTweaker {
|
||||
public:
|
||||
TestDrawableTweaker() {}
|
||||
~TestDrawableTweaker() override = default;
|
||||
|
||||
void init(gfx::Drawable&) override{};
|
||||
|
||||
void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override {
|
||||
if (!drawable.getTileID().has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
|
||||
const auto zoom = parameters.state.getZoom();
|
||||
mat4 tileMatrix;
|
||||
parameters.state.matrixFor(/*out*/ tileMatrix, tileID);
|
||||
|
||||
const auto matrix = LayerTweaker::getTileMatrix(
|
||||
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false);
|
||||
|
||||
static const StringIdentity idLineUBOName = stringIndexer().get("LineUBO");
|
||||
const shaders::LineUBO lineUBO{
|
||||
/*matrix = */ util::cast<float>(matrix),
|
||||
/*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]},
|
||||
/*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, zoom),
|
||||
/*device_pixel_ratio = */ parameters.pixelRatio};
|
||||
|
||||
static const StringIdentity idLinePropertiesUBOName = stringIndexer().get("LinePropertiesUBO");
|
||||
const shaders::LinePropertiesUBO linePropertiesUBO{/*color =*/Color(1.f, 0.f, 1.f, 1.f),
|
||||
/*blur =*/0.f,
|
||||
/*opacity =*/1.f,
|
||||
/*gapwidth =*/0.f,
|
||||
/*offset =*/0.f,
|
||||
/*width =*/8.f,
|
||||
0,
|
||||
0,
|
||||
0};
|
||||
|
||||
static const StringIdentity idLineInterpolationUBOName = stringIndexer().get("LineInterpolationUBO");
|
||||
const shaders::LineInterpolationUBO lineInterpolationUBO{/*color_t =*/0.f,
|
||||
/*blur_t =*/0.f,
|
||||
/*opacity_t =*/0.f,
|
||||
/*gapwidth_t =*/0.f,
|
||||
/*offset_t =*/0.f,
|
||||
/*width_t =*/0.f,
|
||||
0,
|
||||
0};
|
||||
auto& uniforms = drawable.mutableUniformBuffers();
|
||||
uniforms.createOrUpdate(idLineUBOName, &lineUBO, parameters.context);
|
||||
uniforms.createOrUpdate(idLinePropertiesUBOName, &linePropertiesUBO, parameters.context);
|
||||
uniforms.createOrUpdate(idLineInterpolationUBOName, &lineInterpolationUBO, parameters.context);
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
static const StringIdentity idExpressionInputsUBOName = stringIndexer().get("ExpressionInputsUBO");
|
||||
const auto expressionUBO = LayerTweaker::buildExpressionUBO(zoom, parameters.frameCount);
|
||||
uniforms.createOrUpdate(idExpressionInputsUBOName, &expressionUBO, parameters.context);
|
||||
|
||||
static const StringIdentity idLinePermutationUBOName = stringIndexer().get("LinePermutationUBO");
|
||||
const shaders::LinePermutationUBO permutationUBO = {
|
||||
/* .color = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .blur = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .opacity = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .gapwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .offset = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .width = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .floorwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .pattern_from = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .pattern_to = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}},
|
||||
/* .overdrawInspector = */ false,
|
||||
/* .pad = */ 0,
|
||||
0,
|
||||
0,
|
||||
0};
|
||||
uniforms.createOrUpdate(idLinePermutationUBOName, &permutationUBO, parameters.context);
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
};
|
||||
};
|
||||
#include <cmath>
|
||||
|
||||
class TestDrawableLayer : public mbgl::style::CustomDrawableLayerHost {
|
||||
public:
|
||||
void initialize() override {}
|
||||
|
||||
/**
|
||||
* @brief Create Drawables for the Custom Drawable Layer
|
||||
*
|
||||
* @param proxyLayer
|
||||
* @param shaders
|
||||
* @param context
|
||||
* @param state
|
||||
* @param updateParameters
|
||||
* @param renderTree
|
||||
* @param changes
|
||||
*/
|
||||
void update(RenderLayer& proxyLayer,
|
||||
gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
[[maybe_unused]] const TransformState& state,
|
||||
[[maybe_unused]] const std::shared_ptr<UpdateParameters>& updateParameters,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
UniqueChangeRequestVec& changes) override {
|
||||
// Set up a layer group
|
||||
if (!layerGroup) {
|
||||
if (auto layerGroup_ = context.createTileLayerGroup(
|
||||
/*layerIndex*/ proxyLayer.getLayerIndex(), /*initialCapacity=*/2, proxyLayer.getID())) {
|
||||
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(layerGroup_));
|
||||
layerGroup = std::move(layerGroup_);
|
||||
}
|
||||
}
|
||||
void update(Interface& interface) override {
|
||||
// if we have built our drawable(s) already, either update or skip
|
||||
if (interface.getDrawableCount()) return;
|
||||
|
||||
if (!layerGroup) return;
|
||||
|
||||
// if we have build our drawable(s) already, either update or skip
|
||||
if (layerGroup->getDrawableCount()) return;
|
||||
|
||||
// create drawable(s)
|
||||
const OverscaledTileID tileID{11, 327, 791};
|
||||
|
||||
auto createLineBuilder = [&](const std::string& name,
|
||||
gfx::ShaderPtr shader) -> std::unique_ptr<gfx::DrawableBuilder> {
|
||||
std::unique_ptr<gfx::DrawableBuilder> builder = context.createDrawableBuilder(name);
|
||||
builder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(shader));
|
||||
builder->setSubLayerIndex(0);
|
||||
builder->setEnableDepth(false);
|
||||
builder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder->setEnableStencil(false);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
|
||||
return builder;
|
||||
};
|
||||
|
||||
gfx::ShaderGroupPtr lineShaderGroup = shaders.getShaderGroup("LineShader");
|
||||
|
||||
const std::unordered_set<StringIdentity> propertiesAsUniforms{
|
||||
stringIndexer().get("a_color"),
|
||||
stringIndexer().get("a_blur"),
|
||||
stringIndexer().get("a_opacity"),
|
||||
stringIndexer().get("a_gapwidth"),
|
||||
stringIndexer().get("a_offset"),
|
||||
stringIndexer().get("a_width"),
|
||||
};
|
||||
|
||||
auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
|
||||
auto builder = createLineBuilder("thick-lines", shader);
|
||||
|
||||
auto* tileLayerGroup = static_cast<TileLayerGroup*>(layerGroup.get());
|
||||
// set tile
|
||||
interface.setTileID({11, 327, 791});
|
||||
|
||||
// add polylines
|
||||
const auto size{util::EXTENT};
|
||||
GeometryCoordinates geom{{0, 0}, {size, 0}, {0, size}, {size, size}, {size / 3, size / 3}};
|
||||
using namespace mbgl;
|
||||
|
||||
gfx::PolylineGeneratorOptions options;
|
||||
options.beginCap = style::LineCapType::Round;
|
||||
options.endCap = style::LineCapType::Round;
|
||||
options.joinType = style::LineJoinType::Round;
|
||||
builder->addPolyline(geom, options);
|
||||
constexpr auto numLines = 6;
|
||||
Interface::LineOptions options[numLines]{
|
||||
{/*color=*/Color::red(),
|
||||
/*blur=*/0.0f,
|
||||
/*opacity=*/1.0f,
|
||||
/*gapWidth=*/0.0f,
|
||||
/*offset=*/0.0f,
|
||||
/*width=*/8.0f,
|
||||
{}},
|
||||
{/*color=*/Color::blue(),
|
||||
/*blur=*/4.0f,
|
||||
/*opacity=*/1.0f,
|
||||
/*gapWidth=*/2.0f,
|
||||
/*offset=*/-1.0f,
|
||||
/*width=*/4.0f,
|
||||
{}},
|
||||
{/*color=*/Color(1.f, 0.5f, 0, 0.5f),
|
||||
/*blur=*/16.0f,
|
||||
/*opacity=*/1.0f,
|
||||
/*gapWidth=*/1.0f,
|
||||
/*offset=*/2.0f,
|
||||
/*width=*/16.0f,
|
||||
{}},
|
||||
{/*color=*/Color(1.f, 1.f, 0, 0.3f),
|
||||
/*blur=*/2.0f,
|
||||
/*opacity=*/1.0f,
|
||||
/*gapWidth=*/1.0f,
|
||||
/*offset=*/-2.0f,
|
||||
/*width=*/2.0f,
|
||||
{}},
|
||||
{/*color=*/Color::black(),
|
||||
/*blur=*/0.5f,
|
||||
/*opacity=*/0.5f,
|
||||
/*gapWidth=*/1.0f,
|
||||
/*offset=*/0.5f,
|
||||
/*width=*/0.5f,
|
||||
{}},
|
||||
{/*color=*/Color(1.f, 0, 1.f, 0.2f),
|
||||
/*blur=*/24.0f,
|
||||
/*opacity=*/0.5f,
|
||||
/*gapWidth=*/1.0f,
|
||||
/*offset=*/-5.0f,
|
||||
/*width=*/24.0f,
|
||||
{}},
|
||||
};
|
||||
for (auto& opt : options) {
|
||||
opt.geometry.beginCap = style::LineCapType::Round;
|
||||
opt.geometry.endCap = style::LineCapType::Round;
|
||||
opt.geometry.joinType = style::LineJoinType::Round;
|
||||
}
|
||||
|
||||
// create tweaker
|
||||
auto tweaker = std::make_shared<TestDrawableTweaker>();
|
||||
constexpr auto numPoints = 100;
|
||||
GeometryCoordinates polyline;
|
||||
for (auto ipoint{0}; ipoint < numPoints; ++ipoint) {
|
||||
polyline.emplace_back(ipoint * util::EXTENT / numPoints,
|
||||
std::sin(ipoint * 2 * M_PI / numPoints) * util::EXTENT / numLines / 2.f);
|
||||
}
|
||||
|
||||
for (auto index{0}; index < numLines; ++index) {
|
||||
for (auto& p : polyline) {
|
||||
p.y += util::EXTENT / numLines;
|
||||
}
|
||||
|
||||
// set property values
|
||||
interface.setLineOptions(options[index]);
|
||||
|
||||
// add polyline
|
||||
interface.addPolyline(polyline);
|
||||
}
|
||||
|
||||
// finish
|
||||
builder->flush();
|
||||
for (auto& drawable : builder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
drawable->addTweaker(tweaker);
|
||||
|
||||
tileLayerGroup->addDrawable(RenderPass::Translucent, tileID, std::move(drawable));
|
||||
}
|
||||
interface.finish();
|
||||
}
|
||||
|
||||
void deinitialize() override {
|
||||
// layerGroup->reset();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<TileLayerGroup> layerGroup;
|
||||
void deinitialize() override {}
|
||||
};
|
||||
|
||||
TEST(CustomDrawableLayer, Basic) {
|
||||
using namespace mbgl;
|
||||
using namespace mbgl::style;
|
||||
|
||||
util::RunLoop loop;
|
||||
|
||||
HeadlessFrontend frontend{1};
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 30 KiB |
Reference in New Issue
Block a user