Topic/metal symbol rebase (#1640)
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: mwilsnd <mwilsnd@gmail.com> Co-authored-by: Alex Cristici <alex.cristici@gmail.com> Co-authored-by: Stefan Karschti <stefan.karschti@gmail.com> Co-authored-by: Bart Louwers <bart@emeel.net> Co-authored-by: Alex Cristici <alex@skoon.energy> Co-authored-by: Bart Louwers <bart.louwers@gmail.com> Co-authored-by: Wei Chen <alanchenboy@gmail.com> Co-authored-by: Siarhei Fedartsou <siarhei.fedartsou@gmail.com> Co-authored-by: tdcosta100 <tdcosta100@gmail.com>
This commit is contained in:
@@ -1018,8 +1018,7 @@ if(MLN_WITH_OPENGL)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_hillshade.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_raster.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_symbol_icon.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_symbol_sdf_text.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_symbol_sdf_icon.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_symbol_sdf.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background_pattern.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/circle.hpp
|
||||
@@ -1043,8 +1042,8 @@ if(MLN_WITH_OPENGL)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/raster.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_icon.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_sdf_text.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_sdf_icon.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_sdf_text.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_text_and_icon.hpp
|
||||
)
|
||||
list(APPEND
|
||||
@@ -1183,6 +1182,9 @@ if(MBGL_WITH_METAL)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/raster.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_group.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/symbol_icon.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/symbol_sdf.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp
|
||||
)
|
||||
list(APPEND
|
||||
SRC_FILES
|
||||
|
||||
@@ -84,8 +84,7 @@ MLN_GENERATED_OPENGL_SHADER_HEADERS = [
|
||||
"include/mbgl/shaders/gl/drawable_line.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_raster.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_symbol_icon.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_symbol_sdf_text.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_symbol_sdf_icon.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_symbol_sdf.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp",
|
||||
"include/mbgl/shaders/gl/fill_extrusion_pattern.hpp",
|
||||
"include/mbgl/shaders/gl/fill_extrusion.hpp",
|
||||
@@ -970,7 +969,9 @@ MLN_DRAWABLES_HEADERS = [
|
||||
"include/mbgl/shaders/line_layer_ubo.hpp",
|
||||
"include/mbgl/shaders/raster_layer_ubo.hpp",
|
||||
"include/mbgl/shaders/shader_program_base.hpp",
|
||||
"include/mbgl/shaders/symbol_layer_ubo.hpp",
|
||||
"include/mbgl/util/identity.hpp",
|
||||
"include/mbgl/util/suppress_copies.hpp"
|
||||
]
|
||||
|
||||
MLN_DRAWABLES_GL_SOURCE = [
|
||||
@@ -1053,4 +1054,7 @@ MLN_DRAWABLES_MTL_HEADERS = [
|
||||
"include/mbgl/shaders/mtl/raster.hpp",
|
||||
"include/mbgl/shaders/mtl/shader_group.hpp",
|
||||
"include/mbgl/shaders/mtl/shader_program.hpp",
|
||||
"include/mbgl/shaders/mtl/symbol_icon.hpp",
|
||||
"include/mbgl/shaders/mtl/symbol_sdf.hpp",
|
||||
"include/mbgl/shaders/mtl/symbol_text_and_icon.hpp",
|
||||
]
|
||||
|
||||
@@ -182,7 +182,70 @@ struct alignas(16) LineGradientInterpolationUBO {
|
||||
float pad1, pad2, pad3;
|
||||
};
|
||||
|
||||
// interpolated packed pattern
|
||||
struct alignas(16) SymbolDrawableTilePropsUBO {
|
||||
/*bool*/ int is_text;
|
||||
/*bool*/ int is_halo;
|
||||
/*bool*/ int pitch_with_map;
|
||||
/*bool*/ int is_size_zoom_constant;
|
||||
/*bool*/ int is_size_feature_constant;
|
||||
float size_t;
|
||||
float size;
|
||||
float padding;
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableTilePropsUBO) == 2 * 16, "unexpected padding");
|
||||
|
||||
struct alignas(16) SymbolDrawableInterpolateUBO {
|
||||
float fill_color_t;
|
||||
float halo_color_t;
|
||||
float opacity_t;
|
||||
float halo_width_t;
|
||||
float halo_blur_t;
|
||||
float pad1, pad2, pad3;
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableInterpolateUBO) == 32, "unexpected padding");
|
||||
|
||||
struct alignas(16) SymbolDrawableUBO {
|
||||
float4x4 matrix;
|
||||
float4x4 label_plane_matrix;
|
||||
float4x4 coord_matrix;
|
||||
|
||||
float2 texsize;
|
||||
float2 texsize_icon;
|
||||
|
||||
float gamma_scale;
|
||||
float device_pixel_ratio;
|
||||
|
||||
float camera_to_center_distance;
|
||||
float pitch;
|
||||
/*bool*/ int rotate_symbol;
|
||||
float aspect_ratio;
|
||||
float fade_change;
|
||||
float pad;
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableUBO) == 15 * 16, "unexpected padding");
|
||||
|
||||
struct alignas(16) SymbolDrawablePaintUBO {
|
||||
float4 fill_color;
|
||||
float4 halo_color;
|
||||
float opacity;
|
||||
float halo_width;
|
||||
float halo_blur;
|
||||
float padding;
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawablePaintUBO) == 3 * 16, "unexpected padding");
|
||||
|
||||
struct alignas(16) SymbolPermutationUBO {
|
||||
Attribute fill_color;
|
||||
Attribute halo_color;
|
||||
Attribute opacity;
|
||||
Attribute halo_width;
|
||||
Attribute halo_blur;
|
||||
int32_t /*bool*/ overdrawInspector;
|
||||
float pad1, pad2, pad3;
|
||||
};
|
||||
static_assert(sizeof(SymbolPermutationUBO) == 4 * 16, "unexpected padding");
|
||||
|
||||
|
||||
float4 patternFor(device const Attribute& attrib,
|
||||
device const float4& constValue,
|
||||
thread const ushort4& vertexValue,
|
||||
|
||||
148
include/mbgl/shaders/mtl/symbol_icon.hpp
Normal file
148
include/mbgl/shaders/mtl/symbol_icon.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/shaders/mtl/common.hpp>
|
||||
#include <mbgl/shaders/mtl/shader_program.hpp>
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
#include <mbgl/shaders/symbol_layer_ubo.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal> {
|
||||
static constexpr auto name = "SymbolIconShader";
|
||||
static constexpr auto vertexMainFunction = "vertexMain";
|
||||
static constexpr auto fragmentMainFunction = "fragmentMain";
|
||||
|
||||
static constexpr AttributeInfo attributes[] = {
|
||||
// always attributes
|
||||
{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
|
||||
{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
|
||||
{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"},
|
||||
{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
|
||||
{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
|
||||
|
||||
// sometimes uniforms
|
||||
{5, gfx::AttributeDataType::Float, 1, "a_opacity"},
|
||||
};
|
||||
static constexpr UniformBlockInfo uniforms[] = {
|
||||
MLN_MTL_UNIFORM_BLOCK(8, true, true, SymbolDrawableUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawablePaintUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawableTilePropsUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawableInterpolateUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolPermutationUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(13, true, false, ExpressionInputsUBO),
|
||||
};
|
||||
static constexpr TextureInfo textures[] = {
|
||||
{0, "u_texture"},
|
||||
};
|
||||
|
||||
static constexpr auto source = R"(
|
||||
struct VertexStage {
|
||||
float4 pos_offset [[attribute(0)]];
|
||||
float4 data [[attribute(1)]];
|
||||
float4 pixeloffset [[attribute(2)]];
|
||||
float3 projected_pos [[attribute(3)]];
|
||||
float fade_opacity [[attribute(4)]];
|
||||
float opacity [[attribute(5)]];
|
||||
};
|
||||
|
||||
struct FragmentStage {
|
||||
float4 position [[position, invariant]];
|
||||
float2 tex;
|
||||
float fade_opacity;
|
||||
float opacity;
|
||||
};
|
||||
|
||||
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
device const SymbolDrawableUBO& drawable [[buffer(8)]],
|
||||
device const SymbolDrawablePaintUBO& paint [[buffer(9)]],
|
||||
device const SymbolDrawableTilePropsUBO& props [[buffer(10)]],
|
||||
device const SymbolDrawableInterpolateUBO& interp [[buffer(11)]],
|
||||
device const SymbolPermutationUBO& permutation [[buffer(12)]],
|
||||
device const ExpressionInputsUBO& expr [[buffer(13)]]) {
|
||||
|
||||
const auto opacity = valueFor(permutation.opacity, paint.opacity, vertx.opacity, interp.opacity_t, expr);
|
||||
|
||||
const float2 a_pos = vertx.pos_offset.xy;
|
||||
const float2 a_offset = vertx.pos_offset.zw;
|
||||
|
||||
const float2 a_tex = vertx.data.xy;
|
||||
const float2 a_size = vertx.data.zw;
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const float2 a_pxoffset = vertx.pixeloffset.xy;
|
||||
const float2 a_minFontScale = vertx.pixeloffset.zw / 256.0;
|
||||
|
||||
const float segment_angle = -vertx.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!props.is_size_zoom_constant && !props.is_size_feature_constant) {
|
||||
size = mix(a_size_min, a_size[1], props.size_t) / 128.0;
|
||||
} else if (props.is_size_zoom_constant && !props.is_size_feature_constant) {
|
||||
size = a_size_min / 128.0;
|
||||
} else {
|
||||
size = props.size;
|
||||
}
|
||||
|
||||
const float4 projectedPoint = drawable.matrix * float4(a_pos, 0, 1);
|
||||
const float camera_to_anchor_distance = projectedPoint.w;
|
||||
// See comments in symbol_sdf.vertex
|
||||
const float distance_ratio = props.pitch_with_map ?
|
||||
camera_to_anchor_distance / drawable.camera_to_center_distance :
|
||||
drawable.camera_to_center_distance / camera_to_anchor_distance;
|
||||
const float perspective_ratio = clamp(
|
||||
0.5 + 0.5 * distance_ratio,
|
||||
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
|
||||
4.0);
|
||||
|
||||
size *= perspective_ratio;
|
||||
|
||||
const float fontScale = props.is_text ? size / 24.0 : size;
|
||||
|
||||
float symbol_rotation = 0.0;
|
||||
if (drawable.rotate_symbol) {
|
||||
// See comments in symbol_sdf.vertex
|
||||
const float4 offsetProjectedPoint = drawable.matrix * float4(a_pos + float2(1, 0), 0, 1);
|
||||
|
||||
const float2 a = projectedPoint.xy / projectedPoint.w;
|
||||
const float2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;
|
||||
symbol_rotation = atan2((b.y - a.y) / drawable.aspect_ratio, b.x - a.x);
|
||||
}
|
||||
|
||||
const float angle_sin = sin(segment_angle + symbol_rotation);
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const float2x2 rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0);
|
||||
const float2 pos0 = projected_pos.xy / projected_pos.w;
|
||||
const float2 posOffset = a_offset * max(a_minFontScale, fontScale) / 32.0 + a_pxoffset / 16.0;
|
||||
const float4 position = drawable.coord_matrix * float4(pos0 + rotation_matrix * posOffset, 0.0, 1.0);
|
||||
|
||||
const float2 fade_opacity = unpack_opacity(vertx.fade_opacity);
|
||||
const float fade_change = fade_opacity[1] > 0.5 ? drawable.fade_change : -drawable.fade_change;
|
||||
|
||||
return {
|
||||
.position = position,
|
||||
.tex = a_tex / drawable.texsize,
|
||||
.fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change)),
|
||||
.opacity = opacity,
|
||||
};
|
||||
}
|
||||
|
||||
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
||||
device const SymbolDrawableUBO& drawable [[buffer(8)]],
|
||||
device const SymbolPermutationUBO& permutation [[buffer(12)]],
|
||||
texture2d<float, access::sample> image [[texture(0)]],
|
||||
sampler image_sampler [[sampler(0)]]) {
|
||||
if (permutation.overdrawInspector) {
|
||||
return half4(1.0);
|
||||
}
|
||||
|
||||
return half4(image.sample(image_sampler, in.tex) * (in.opacity * in.fade_opacity));
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
201
include/mbgl/shaders/mtl/symbol_sdf.hpp
Normal file
201
include/mbgl/shaders/mtl/symbol_sdf.hpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/shaders/mtl/common.hpp>
|
||||
#include <mbgl/shaders/mtl/shader_program.hpp>
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
#include <mbgl/shaders/symbol_layer_ubo.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::SymbolSDFIconShader, gfx::Backend::Type::Metal> {
|
||||
static constexpr auto name = "SymbolSDFIconShader";
|
||||
static constexpr auto vertexMainFunction = "vertexMain";
|
||||
static constexpr auto fragmentMainFunction = "fragmentMain";
|
||||
|
||||
static constexpr AttributeInfo attributes[] = {
|
||||
// always attributes
|
||||
{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
|
||||
{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
|
||||
{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"},
|
||||
{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
|
||||
{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
|
||||
|
||||
// sometimes uniforms
|
||||
{5, gfx::AttributeDataType::Float4, 1, "a_fill_color"},
|
||||
{6, gfx::AttributeDataType::Float4, 1, "a_halo_color"},
|
||||
{7, gfx::AttributeDataType::Float, 1, "a_opacity"},
|
||||
{8, gfx::AttributeDataType::Float, 1, "a_halo_width"},
|
||||
{9, gfx::AttributeDataType::Float, 1, "a_halo_blur"},
|
||||
};
|
||||
static constexpr UniformBlockInfo uniforms[] = {
|
||||
MLN_MTL_UNIFORM_BLOCK(10, true, true, SymbolDrawableUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawablePaintUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolDrawableTilePropsUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(13, true, false, SymbolDrawableInterpolateUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(14, true, true, SymbolPermutationUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(15, true, false, ExpressionInputsUBO),
|
||||
};
|
||||
static constexpr TextureInfo textures[] = {
|
||||
{0, "u_texture"},
|
||||
};
|
||||
|
||||
static constexpr auto source = R"(
|
||||
struct VertexStage {
|
||||
float4 pos_offset [[attribute(0)]];
|
||||
float4 data [[attribute(1)]];
|
||||
float4 pixeloffset [[attribute(2)]];
|
||||
float3 projected_pos [[attribute(3)]];
|
||||
float fade_opacity [[attribute(4)]];
|
||||
|
||||
float4 fill_color [[attribute(5)]];
|
||||
float4 halo_color [[attribute(6)]];
|
||||
float opacity [[attribute(7)]];
|
||||
float halo_width [[attribute(8)]];
|
||||
float halo_blur [[attribute(9)]];
|
||||
};
|
||||
|
||||
struct FragmentStage {
|
||||
float4 position [[position, invariant]];
|
||||
float4 fill_color;
|
||||
float4 halo_color;
|
||||
float halo_width;
|
||||
float halo_blur;
|
||||
float opacity;
|
||||
float2 data0;
|
||||
float3 data1;
|
||||
};
|
||||
|
||||
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
device const SymbolDrawableUBO& drawable [[buffer(10)]],
|
||||
device const SymbolDrawablePaintUBO& paint [[buffer(11)]],
|
||||
device const SymbolDrawableTilePropsUBO& props [[buffer(12)]],
|
||||
device const SymbolDrawableInterpolateUBO& interp [[buffer(13)]],
|
||||
device const SymbolPermutationUBO& permutation [[buffer(14)]],
|
||||
device const ExpressionInputsUBO& expr [[buffer(15)]]) {
|
||||
|
||||
const auto fill_color = colorFor(permutation.fill_color, paint.fill_color, vertx.fill_color, interp.fill_color_t, expr);
|
||||
const auto halo_color = colorFor(permutation.halo_color, paint.halo_color, vertx.halo_color, interp.halo_color_t, expr);
|
||||
const auto opacity = valueFor(permutation.opacity, paint.opacity, vertx.opacity, interp.opacity_t, expr);
|
||||
const auto halo_width = valueFor(permutation.halo_width, paint.halo_width, vertx.halo_width, interp.halo_width_t, expr);
|
||||
const auto halo_blur = valueFor(permutation.halo_blur, paint.halo_blur, vertx.halo_blur, interp.halo_blur_t, expr);
|
||||
|
||||
const float2 a_pos = vertx.pos_offset.xy;
|
||||
const float2 a_offset = vertx.pos_offset.zw;
|
||||
|
||||
const float2 a_tex = vertx.data.xy;
|
||||
const float2 a_size = vertx.data.zw;
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const float2 a_pxoffset = vertx.pixeloffset.xy;
|
||||
|
||||
const float segment_angle = -vertx.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!props.is_size_zoom_constant && !props.is_size_feature_constant) {
|
||||
size = mix(a_size_min, a_size[1], props.size_t) / 128.0;
|
||||
} else if (props.is_size_zoom_constant && !props.is_size_feature_constant) {
|
||||
size = a_size_min / 128.0;
|
||||
} else {
|
||||
size = props.size;
|
||||
}
|
||||
|
||||
const float4 projectedPoint = drawable.matrix * float4(a_pos, 0, 1);
|
||||
const float camera_to_anchor_distance = projectedPoint.w;
|
||||
// If the label is pitched with the map, layout is done in pitched space,
|
||||
// which makes labels in the distance smaller relative to viewport space.
|
||||
// We counteract part of that effect by multiplying by the perspective ratio.
|
||||
// If the label isn't pitched with the map, we do layout in viewport space,
|
||||
// which makes labels in the distance larger relative to the features around
|
||||
// them. We counteract part of that effect by dividing by the perspective ratio.
|
||||
const float distance_ratio = props.pitch_with_map ?
|
||||
camera_to_anchor_distance / drawable.camera_to_center_distance :
|
||||
drawable.camera_to_center_distance / camera_to_anchor_distance;
|
||||
const float perspective_ratio = clamp(
|
||||
0.5 + 0.5 * distance_ratio,
|
||||
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
|
||||
4.0);
|
||||
|
||||
size *= perspective_ratio;
|
||||
|
||||
const float fontScale = props.is_text ? size / 24.0 : size;
|
||||
|
||||
float symbol_rotation = 0.0;
|
||||
if (drawable.rotate_symbol) {
|
||||
// Point labels with 'rotation-alignment: map' are horizontal with respect to tile units
|
||||
// To figure out that angle in projected space, we draw a short horizontal line in tile
|
||||
// space, project it, and measure its angle in projected space.
|
||||
const float4 offsetProjectedPoint = drawable.matrix * float4(a_pos + float2(1, 0), 0, 1);
|
||||
|
||||
const float2 a = projectedPoint.xy / projectedPoint.w;
|
||||
const float2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;
|
||||
|
||||
symbol_rotation = atan2((b.y - a.y) / drawable.aspect_ratio, b.x - a.x);
|
||||
}
|
||||
|
||||
const float angle_sin = sin(segment_angle + symbol_rotation);
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const float2x2 rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0);
|
||||
const float2 pos_rot = a_offset / 32.0 * fontScale + a_pxoffset;
|
||||
const float2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
const float4 position = drawable.coord_matrix * float4(pos0, 0.0, 1.0);
|
||||
const float gamma_scale = position.w;
|
||||
|
||||
const float2 fade_opacity = unpack_opacity(vertx.fade_opacity);
|
||||
const float fade_change = (fade_opacity[1] > 0.5) ? drawable.fade_change : -drawable.fade_change;
|
||||
const float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));
|
||||
|
||||
return {
|
||||
.position = position,
|
||||
.fill_color = fill_color,
|
||||
.halo_color = halo_color,
|
||||
.halo_width = halo_width,
|
||||
.halo_blur = halo_blur,
|
||||
.opacity = opacity,
|
||||
.data0 = a_tex / drawable.texsize,
|
||||
.data1 = float3(gamma_scale, size, interpolated_fade_opacity),
|
||||
};
|
||||
}
|
||||
|
||||
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
||||
device const SymbolDrawableUBO& drawable [[buffer(10)]],
|
||||
device const SymbolDrawableTilePropsUBO& props [[buffer(12)]],
|
||||
device const SymbolPermutationUBO& permutation [[buffer(14)]],
|
||||
texture2d<float, access::sample> image [[texture(0)]],
|
||||
sampler image_sampler [[sampler(0)]]) {
|
||||
if (permutation.overdrawInspector) {
|
||||
return half4(1.0);
|
||||
}
|
||||
|
||||
const float EDGE_GAMMA = 0.105 / drawable.device_pixel_ratio;
|
||||
|
||||
const float2 tex = in.data0.xy;
|
||||
const float gamma_scale = in.data1.x;
|
||||
const float size = in.data1.y;
|
||||
const float fade_opacity = in.data1[2];
|
||||
|
||||
const float fontScale = props.is_text ? size / 24.0 : size;
|
||||
|
||||
float4 color = in.fill_color;
|
||||
float gamma = EDGE_GAMMA / (fontScale * drawable.gamma_scale);
|
||||
float buff = (256.0 - 64.0) / 256.0;
|
||||
if (props.is_halo) {
|
||||
color = in.halo_color;
|
||||
gamma = (in.halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * drawable.gamma_scale);
|
||||
buff = (6.0 - in.halo_width / fontScale) / SDF_PX;
|
||||
}
|
||||
|
||||
const float dist = image.sample(image_sampler, tex).a;
|
||||
const float gamma_scaled = gamma * gamma_scale;
|
||||
const float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);
|
||||
|
||||
return half4(color * (alpha * in.opacity * fade_opacity));
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
212
include/mbgl/shaders/mtl/symbol_text_and_icon.hpp
Normal file
212
include/mbgl/shaders/mtl/symbol_text_and_icon.hpp
Normal file
@@ -0,0 +1,212 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/shaders/mtl/common.hpp>
|
||||
#include <mbgl/shaders/mtl/shader_program.hpp>
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
#include <mbgl/shaders/symbol_layer_ubo.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal> {
|
||||
static constexpr auto name = "SymbolTextAndIconShader";
|
||||
static constexpr auto vertexMainFunction = "vertexMain";
|
||||
static constexpr auto fragmentMainFunction = "fragmentMain";
|
||||
|
||||
static constexpr AttributeInfo attributes[] = {
|
||||
// always attributes
|
||||
{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
|
||||
{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
|
||||
{2, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
|
||||
{3, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
|
||||
|
||||
// sometimes uniforms
|
||||
{4, gfx::AttributeDataType::Float4, 1, "a_fill_color"},
|
||||
{5, gfx::AttributeDataType::Float4, 1, "a_halo_color"},
|
||||
{6, gfx::AttributeDataType::Float, 1, "a_opacity"},
|
||||
{7, gfx::AttributeDataType::Float, 1, "a_halo_width"},
|
||||
{8, gfx::AttributeDataType::Float, 1, "a_halo_blur"},
|
||||
};
|
||||
static constexpr UniformBlockInfo uniforms[] = {
|
||||
MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawableUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawablePaintUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(11, true, true, SymbolDrawableTilePropsUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(12, true, false, SymbolDrawableInterpolateUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(13, true, true, SymbolPermutationUBO),
|
||||
MLN_MTL_UNIFORM_BLOCK(14, true, false, ExpressionInputsUBO),
|
||||
};
|
||||
static constexpr TextureInfo textures[] = {
|
||||
{0, "u_texture"},
|
||||
{1, "u_texture_icon"},
|
||||
};
|
||||
|
||||
static constexpr auto source = R"(
|
||||
#define SDF 1.0
|
||||
#define ICON 0.0
|
||||
|
||||
struct VertexStage {
|
||||
float4 pos_offset [[attribute(0)]];
|
||||
float4 data [[attribute(1)]];
|
||||
float3 projected_pos [[attribute(2)]];
|
||||
float fade_opacity [[attribute(3)]];
|
||||
|
||||
float4 fill_color [[attribute(4)]];
|
||||
float4 halo_color [[attribute(5)]];
|
||||
float opacity [[attribute(6)]];
|
||||
float halo_width [[attribute(7)]];
|
||||
float halo_blur [[attribute(8)]];
|
||||
};
|
||||
|
||||
struct FragmentStage {
|
||||
float4 position [[position, invariant]];
|
||||
float4 fill_color;
|
||||
float4 halo_color;
|
||||
float halo_width;
|
||||
float halo_blur;
|
||||
float opacity;
|
||||
float4 data0;
|
||||
float4 data1;
|
||||
};
|
||||
|
||||
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
device const SymbolDrawableUBO& drawable [[buffer(9)]],
|
||||
device const SymbolDrawablePaintUBO& paint [[buffer(10)]],
|
||||
device const SymbolDrawableTilePropsUBO& props [[buffer(11)]],
|
||||
device const SymbolDrawableInterpolateUBO& interp [[buffer(12)]],
|
||||
device const SymbolPermutationUBO& permutation [[buffer(13)]],
|
||||
device const ExpressionInputsUBO& expr [[buffer(14)]]) {
|
||||
|
||||
const auto fill_color = colorFor(permutation.fill_color, paint.fill_color, vertx.fill_color, interp.fill_color_t, expr);
|
||||
const auto halo_color = colorFor(permutation.halo_color, paint.halo_color, vertx.halo_color, interp.halo_color_t, expr);
|
||||
const auto opacity = valueFor(permutation.opacity, paint.opacity, vertx.opacity, interp.opacity_t, expr);
|
||||
const auto halo_width = valueFor(permutation.halo_width, paint.halo_width, vertx.halo_width, interp.halo_width_t, expr);
|
||||
const auto halo_blur = valueFor(permutation.halo_blur, paint.halo_blur, vertx.halo_blur, interp.halo_blur_t, expr);
|
||||
|
||||
const float2 a_pos = vertx.pos_offset.xy;
|
||||
const float2 a_offset = vertx.pos_offset.zw;
|
||||
|
||||
const float2 a_tex = vertx.data.xy;
|
||||
const float2 a_size = vertx.data.zw;
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const float is_sdf = a_size[0] - 2.0 * a_size_min;
|
||||
|
||||
const float segment_angle = -vertx.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!props.is_size_zoom_constant && !props.is_size_feature_constant) {
|
||||
size = mix(a_size_min, a_size[1], props.size_t) / 128.0;
|
||||
} else if (props.is_size_zoom_constant && !props.is_size_feature_constant) {
|
||||
size = a_size_min / 128.0;
|
||||
} else {
|
||||
size = props.size;
|
||||
}
|
||||
|
||||
const float4 projectedPoint = drawable.matrix * float4(a_pos, 0, 1);
|
||||
const float camera_to_anchor_distance = projectedPoint.w;
|
||||
// If the label is pitched with the map, layout is done in pitched space,
|
||||
// which makes labels in the distance smaller relative to viewport space.
|
||||
// We counteract part of that effect by multiplying by the perspective ratio.
|
||||
// If the label isn't pitched with the map, we do layout in viewport space,
|
||||
// which makes labels in the distance larger relative to the features around
|
||||
// them. We counteract part of that effect by dividing by the perspective ratio.
|
||||
const float distance_ratio = props.pitch_with_map ?
|
||||
camera_to_anchor_distance / drawable.camera_to_center_distance :
|
||||
drawable.camera_to_center_distance / camera_to_anchor_distance;
|
||||
const float perspective_ratio = clamp(
|
||||
0.5 + 0.5 * distance_ratio,
|
||||
0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
|
||||
4.0);
|
||||
|
||||
size *= perspective_ratio;
|
||||
|
||||
const float fontScale = size / 24.0;
|
||||
|
||||
float symbol_rotation = 0.0;
|
||||
if (drawable.rotate_symbol) {
|
||||
// Point labels with 'rotation-alignment: map' are horizontal with respect to tile units
|
||||
// To figure out that angle in projected space, we draw a short horizontal line in tile
|
||||
// space, project it, and measure its angle in projected space.
|
||||
const float4 offsetProjectedPoint = drawable.matrix * float4(a_pos + float2(1, 0), 0, 1);
|
||||
|
||||
const float2 a = projectedPoint.xy / projectedPoint.w;
|
||||
const float2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;
|
||||
|
||||
symbol_rotation = atan2((b.y - a.y) / drawable.aspect_ratio, b.x - a.x);
|
||||
}
|
||||
|
||||
const float angle_sin = sin(segment_angle + symbol_rotation);
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const float2x2 rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0);
|
||||
const float2 pos_rot = a_offset / 32.0 * fontScale + a_pxoffset;
|
||||
const float2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
const float4 position = drawable.coord_matrix * float4(pos0, 0.0, 1.0);
|
||||
const float gamma_scale = position.w;
|
||||
|
||||
const float2 fade_opacity = unpack_opacity(vertx.fade_opacity);
|
||||
const float fade_change = (fade_opacity[1] > 0.5) ? drawable.fade_change : -drawable.fade_change;
|
||||
const float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));
|
||||
|
||||
return {
|
||||
.position = position,
|
||||
.fill_color = fill_color,
|
||||
.halo_color = halo_color,
|
||||
.halo_width = halo_width,
|
||||
.halo_blur = halo_blur,
|
||||
.opacity = opacity,
|
||||
.data0 = float4(a_tex / drawable.texsize, a_tex / drawable.texsize_icon),
|
||||
.data1 = float4(gamma_scale, size, interpolated_fade_opacity, is_sdf),
|
||||
};
|
||||
}
|
||||
|
||||
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
||||
device const SymbolDrawableUBO& drawable [[buffer(9)]],
|
||||
device const SymbolDrawableTilePropsUBO& props [[buffer(11)]],
|
||||
device const SymbolPermutationUBO& permutation [[buffer(13)]],
|
||||
texture2d<float, access::sample> glyph_image [[texture(0)]],
|
||||
texture2d<float, access::sample> icon_image [[texture(1)]],
|
||||
sampler glyph_sampler [[sampler(0)]],
|
||||
sampler icon_sampler [[sampler(1)]]) {
|
||||
if (permutation.overdrawInspector) {
|
||||
return half4(1.0);
|
||||
}
|
||||
|
||||
const float fade_opacity = in.data1[2];
|
||||
|
||||
if (in.data1.w == ICON) {
|
||||
const float2 tex_icon = in.data0.zw;
|
||||
const float alpha = opacity * fade_opacity;
|
||||
return half4(icon_image.sample(icon_sampler, tex_icon) * alpha);
|
||||
}
|
||||
|
||||
const float2 tex = in.data0.xy;
|
||||
const float EDGE_GAMMA = 0.105 / drawable.device_pixel_ratio;
|
||||
|
||||
const float gamma_scale = in.data1.x;
|
||||
const float size = in.data1.y;
|
||||
|
||||
const float fontScale = size / 24.0;
|
||||
|
||||
float4 color = in.fill_color;
|
||||
float gamma = EDGE_GAMMA / (fontScale * drawable.gamma_scale);
|
||||
float buff = (256.0 - 64.0) / 256.0;
|
||||
if (props.is_halo) {
|
||||
color = in.halo_color;
|
||||
gamma = (in.halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * drawable.gamma_scale);
|
||||
buff = (6.0 - in.halo_width / fontScale) / SDF_PX;
|
||||
}
|
||||
|
||||
const float dist = glyph_image.sample(glyph_sampler, tex).a;
|
||||
const float gamma_scaled = gamma * gamma_scale;
|
||||
const float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);
|
||||
|
||||
return half4(color * (alpha * in.opacity * fade_opacity));
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -25,8 +25,7 @@
|
||||
#include <mbgl/shaders/gl/drawable_hillshade.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_raster.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_symbol_icon.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_symbol_sdf_text.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_symbol_sdf_icon.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_symbol_sdf.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp>
|
||||
#include <mbgl/shaders/gl/prelude.hpp>
|
||||
#include <mbgl/shaders/gl/background.hpp>
|
||||
|
||||
@@ -31,7 +31,6 @@ enum class BuiltIn {
|
||||
HillshadeShader,
|
||||
RasterShader,
|
||||
SymbolIconShader,
|
||||
SymbolSDFTextShader,
|
||||
SymbolSDFIconShader,
|
||||
SymbolTextAndIconShader,
|
||||
Prelude,
|
||||
|
||||
88
include/mbgl/shaders/symbol_layer_ubo.hpp
Normal file
88
include/mbgl/shaders/symbol_layer_ubo.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/shaders/layer_ubo.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
/// Evaluated properties that depend on the tile
|
||||
struct alignas(16) SymbolDrawableTilePropsUBO {
|
||||
/* 0 */ /*bool*/ int is_text;
|
||||
/* 4 */ /*bool*/ int is_halo;
|
||||
/* 8 */ /*bool*/ int pitch_with_map;
|
||||
/* 12 */ /*bool*/ int is_size_zoom_constant;
|
||||
/* 16 */ /*bool*/ int is_size_feature_constant;
|
||||
/* 20 */ float size_t;
|
||||
/* 24 */ float size;
|
||||
/* 28 */ float padding;
|
||||
/* 32 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableTilePropsUBO) == 2 * 16);
|
||||
|
||||
/// Attribute interpolations
|
||||
struct alignas(16) SymbolDrawableInterpolateUBO {
|
||||
/* 0 */ float fill_color_t;
|
||||
/* 4 */ float halo_color_t;
|
||||
/* 8 */ float opacity_t;
|
||||
/* 12 */ float halo_width_t;
|
||||
/* 16 */ float halo_blur_t;
|
||||
/* 20 */ float pad1, pad2, pad3;
|
||||
/* 32 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableInterpolateUBO) == 32);
|
||||
|
||||
struct alignas(16) SymbolDrawableUBO {
|
||||
/* 0 */ std::array<float, 4 * 4> matrix;
|
||||
/* 64 */ std::array<float, 4 * 4> label_plane_matrix;
|
||||
/* 128 */ std::array<float, 4 * 4> coord_matrix;
|
||||
|
||||
/* 192 */ std::array<float, 2> texsize;
|
||||
/* 200 */ std::array<float, 2> texsize_icon;
|
||||
|
||||
/* 208 */ float gamma_scale;
|
||||
/* 212 */ float device_pixel_ratio;
|
||||
|
||||
/* 216 */ float camera_to_center_distance;
|
||||
/* 220 */ float pitch;
|
||||
/* 224 */ /*bool*/ int rotate_symbol;
|
||||
/* 228 */ float aspect_ratio;
|
||||
/* 232 */ std::array<float, 2> pad;
|
||||
/* 240 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableUBO) == 15 * 16);
|
||||
|
||||
/// Dynamic UBO
|
||||
struct alignas(16) SymbolDynamicUBO {
|
||||
/* 0 */ float fade_change;
|
||||
/* 4 */ float pad1;
|
||||
/* 8 */ std::array<float, 2> pad2;
|
||||
/* 16 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDynamicUBO) == 16);
|
||||
|
||||
/// Evaluated properties that do not depend on the tile
|
||||
struct alignas(16) SymbolDrawablePaintUBO {
|
||||
/* 0 */ Color fill_color;
|
||||
/* 16 */ Color halo_color;
|
||||
/* 32 */ float opacity;
|
||||
/* 36 */ float halo_width;
|
||||
/* 40 */ float halo_blur;
|
||||
/* 44 */ float padding;
|
||||
/* 48 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawablePaintUBO) == 3 * 16);
|
||||
|
||||
struct alignas(16) SymbolPermutationUBO {
|
||||
/* 0 */ Attribute fill_color;
|
||||
/* 8 */ Attribute halo_color;
|
||||
/* 16 */ Attribute opacity;
|
||||
/* 24 */ Attribute halo_width;
|
||||
/* 40 */ Attribute halo_blur;
|
||||
/* 48 */ int32_t /*bool*/ overdrawInspector;
|
||||
/* 52 */ float pad1, pad2, pad3;
|
||||
/* 64 */
|
||||
};
|
||||
static_assert(sizeof(SymbolPermutationUBO) == 4 * 16);
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -4,7 +4,6 @@ namespace mbgl {
|
||||
namespace bench {
|
||||
|
||||
const std::vector<Location> locations = {
|
||||
{ "boston", -71.07766, 42.36513, 16, 0.0 },
|
||||
{ "paris", 2.3411, 48.8664, 11, 0.0 },
|
||||
{ "paris2", 2.3516, 48.8356, 13, 273.8 },
|
||||
{ "alps", 10.6107, 46.9599, 6, 0.0 },
|
||||
|
||||
@@ -153,16 +153,9 @@
|
||||
"glsl_frag": "drawable.symbol_icon.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "SymbolSDFTextShader",
|
||||
"header": "drawable_symbol_sdf_text",
|
||||
"glsl_vert": "drawable.symbol_sdf.vertex.glsl",
|
||||
"glsl_frag": "drawable.symbol_sdf.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "SymbolSDFIconShader",
|
||||
"header": "drawable_symbol_sdf_icon",
|
||||
"header": "drawable_symbol_sdf",
|
||||
"glsl_vert": "drawable.symbol_sdf.vertex.glsl",
|
||||
"glsl_frag": "drawable.symbol_sdf.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
|
||||
@@ -115,7 +115,6 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
|
||||
shaders::BuiltIn::HillshadeShader,
|
||||
shaders::BuiltIn::RasterShader,
|
||||
shaders::BuiltIn::SymbolIconShader,
|
||||
shaders::BuiltIn::SymbolSDFTextShader,
|
||||
shaders::BuiltIn::SymbolSDFIconShader,
|
||||
shaders::BuiltIn::SymbolTextAndIconShader>(shaders, programParameters);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,11 @@
|
||||
#include <mbgl/shaders/mtl/heatmap_texture.hpp>
|
||||
#include <mbgl/shaders/mtl/line.hpp>
|
||||
#include <mbgl/shaders/mtl/line_gradient.hpp>
|
||||
#include <mbgl/shaders/mtl/fill.hpp>
|
||||
#include <mbgl/shaders/mtl/raster.hpp>
|
||||
#include <mbgl/shaders/mtl/symbol_icon.hpp>
|
||||
#include <mbgl/shaders/mtl/symbol_sdf.hpp>
|
||||
#include <mbgl/shaders/mtl/symbol_text_and_icon.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
@@ -126,17 +130,15 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
|
||||
shaders::BuiltIn::FillExtrusionPatternShader,
|
||||
shaders::BuiltIn::HeatmapShader,
|
||||
shaders::BuiltIn::HeatmapTextureShader,
|
||||
// shaders::BuiltIn::HillshadeShader,
|
||||
shaders::BuiltIn::LineShader,
|
||||
shaders::BuiltIn::LineGradientShader,
|
||||
shaders::BuiltIn::RasterShader/*,
|
||||
shaders::BuiltIn::LineSDFShader,
|
||||
shaders::BuiltIn::LinePatternShader,
|
||||
shaders::BuiltIn::HillshadePrepareShader,
|
||||
shaders::BuiltIn::HillshadeShader,
|
||||
// shaders::BuiltIn::LineSDFShader,
|
||||
// shaders::BuiltIn::LinePatternShader,
|
||||
shaders::BuiltIn::RasterShader,
|
||||
shaders::BuiltIn::SymbolIconShader,
|
||||
shaders::BuiltIn::SymbolSDFTextShader,
|
||||
shaders::BuiltIn::SymbolSDFIconShader,
|
||||
shaders::BuiltIn::SymbolTextAndIconShader*/>(shaders, programParameters);
|
||||
shaders::BuiltIn::SymbolTextAndIconShader>(shaders, programParameters);
|
||||
}
|
||||
|
||||
} // namespace mtl
|
||||
|
||||
@@ -22,7 +22,6 @@ using namespace shaders;
|
||||
using namespace style;
|
||||
|
||||
namespace {
|
||||
|
||||
const StringIdentity idFillExtrusionDrawableUBOName = StringIndexer::get("FillExtrusionDrawableUBO");
|
||||
const StringIdentity idFillExtrusionDrawablePropsUBOName = StringIndexer::get("FillExtrusionDrawablePropsUBO");
|
||||
const StringIdentity idExpressionInputsUBOName = StringIndexer::get("ExpressionInputsUBO");
|
||||
|
||||
@@ -38,7 +38,6 @@ using namespace shaders;
|
||||
namespace {
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
|
||||
static const StringIdentity idPosAttribName = StringIndexer::get("a_pos");
|
||||
static const StringIdentity idNormAttribName = StringIndexer::get("a_normal_ed");
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/layers/symbol_layer_tweaker.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/shaders/symbol_layer_ubo.hpp>
|
||||
#include <mbgl/gfx/collision_drawable_data.hpp>
|
||||
#include <mbgl/renderer/layers/collision_layer_tweaker.hpp>
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
@@ -40,13 +41,13 @@
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
namespace {
|
||||
using namespace shaders;
|
||||
|
||||
namespace {
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
|
||||
constexpr std::string_view SymbolIconShaderName = "SymbolIconShader";
|
||||
constexpr std::string_view SymbolSDFIconShaderName = "SymbolSDFTextShader";
|
||||
constexpr std::string_view SymbolSDFTextShaderName = "SymbolSDFIconShader";
|
||||
constexpr std::string_view SymbolSDFIconShaderName = "SymbolSDFIconShader";
|
||||
constexpr std::string_view SymbolTextAndIconShaderName = "SymbolTextAndIconShader";
|
||||
constexpr std::string_view CollisionBoxShaderName = "CollisionBoxShader";
|
||||
constexpr std::string_view CollisionCircleShaderName = "CollisionCircleShader";
|
||||
@@ -379,6 +380,9 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters)
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
if (layerGroup && layerGroup->getLayerTweaker()) {
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
layerGroup->getLayerTweaker()->setPropertiesAsUniforms(propertiesAsUniforms);
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
layerGroup->getLayerTweaker()->updateProperties(evaluatedProperties);
|
||||
}
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
@@ -1002,7 +1006,11 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
// Set up a layer group
|
||||
if (!layerGroup) {
|
||||
if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) {
|
||||
layerGroup_->setLayerTweaker(std::make_shared<SymbolLayerTweaker>(getID(), evaluatedProperties));
|
||||
tweaker = std::make_shared<SymbolLayerTweaker>(getID(), evaluatedProperties);
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
tweaker->setPropertiesAsUniforms(propertiesAsUniforms);
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
layerGroup_->setLayerTweaker(tweaker);
|
||||
setLayerGroup(std::move(layerGroup_), changes);
|
||||
}
|
||||
}
|
||||
@@ -1022,11 +1030,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (!symbolIconGroup) {
|
||||
symbolIconGroup = shaders.getShaderGroup(std::string(SymbolIconShaderName));
|
||||
}
|
||||
if (!symbolSDFIconGroup) {
|
||||
symbolSDFIconGroup = shaders.getShaderGroup(std::string(SymbolSDFIconShaderName));
|
||||
}
|
||||
if (!symbolSDFTextGroup) {
|
||||
symbolSDFTextGroup = shaders.getShaderGroup(std::string(SymbolSDFTextShaderName));
|
||||
if (!symbolSDFGroup) {
|
||||
symbolSDFGroup = shaders.getShaderGroup(std::string(SymbolSDFIconShaderName));
|
||||
}
|
||||
if (!symbolTextAndIconGroup) {
|
||||
symbolTextAndIconGroup = shaders.getShaderGroup(std::string(SymbolTextAndIconShaderName));
|
||||
@@ -1263,6 +1268,13 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::VertexAttributeArray attribs;
|
||||
const auto uniformProps = updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, attribs);
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
propertiesAsUniforms = uniformProps;
|
||||
if (tweaker) {
|
||||
tweaker->setPropertiesAsUniforms(propertiesAsUniforms);
|
||||
}
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
|
||||
const auto textHalo = evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0.0f &&
|
||||
evaluated.get<style::TextHaloWidth>().constantOr(1);
|
||||
const auto textFill = evaluated.get<style::TextColor>().constantOr(Color::black()).a > 0.0f;
|
||||
@@ -1382,21 +1394,21 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
}
|
||||
} else {
|
||||
if (textHalo) {
|
||||
draw(symbolSDFTextGroup, /* isHalo = */ true, "halo");
|
||||
draw(symbolSDFGroup, /* isHalo = */ true, "halo");
|
||||
}
|
||||
|
||||
if (textFill) {
|
||||
draw(symbolSDFTextGroup, /* isHalo = */ false, "fill");
|
||||
draw(symbolSDFGroup, /* isHalo = */ false, "fill");
|
||||
}
|
||||
}
|
||||
} else { // icons
|
||||
if (sdfIcons) {
|
||||
if (iconHalo) {
|
||||
draw(symbolSDFIconGroup, /* isHalo = */ true, "halo");
|
||||
draw(symbolSDFGroup, /* isHalo = */ true, "halo");
|
||||
}
|
||||
|
||||
if (iconFill) {
|
||||
draw(symbolSDFIconGroup, /* isHalo = */ false, "fill");
|
||||
draw(symbolSDFGroup, /* isHalo = */ false, "fill");
|
||||
}
|
||||
} else {
|
||||
draw(symbolIconGroup, /* isHalo = */ false, "icon");
|
||||
|
||||
@@ -65,6 +65,11 @@ class SymbolTextAndIconProgram;
|
||||
class CollisionBoxProgram;
|
||||
class CollisionCircleProgram;
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
class SymbolLayerTweaker;
|
||||
using SymbolLayerTweakerPtr = std::shared_ptr<SymbolLayerTweaker>;
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
|
||||
class RenderSymbolLayer final : public RenderLayer {
|
||||
public:
|
||||
struct Programs {
|
||||
@@ -146,15 +151,20 @@ private:
|
||||
#endif // MLN_LEGACY_RENDERER
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
SymbolLayerTweakerPtr tweaker;
|
||||
|
||||
gfx::ShaderGroupPtr symbolIconGroup;
|
||||
gfx::ShaderGroupPtr symbolSDFIconGroup;
|
||||
gfx::ShaderGroupPtr symbolSDFTextGroup;
|
||||
gfx::ShaderGroupPtr symbolSDFGroup;
|
||||
gfx::ShaderGroupPtr symbolTextAndIconGroup;
|
||||
|
||||
gfx::ShaderGroupPtr collisionBoxGroup;
|
||||
gfx::ShaderGroupPtr collisionCircleGroup;
|
||||
std::shared_ptr<TileLayerGroup> collisionTileLayerGroup;
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
std::vector<std::string> propertiesAsUniforms;
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -12,57 +12,22 @@
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/paint_property_binder.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/shaders/symbol_layer_ubo.hpp>
|
||||
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#include <mbgl/shaders/mtl/symbol_icon.hpp>
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
using namespace shaders;
|
||||
|
||||
namespace {
|
||||
|
||||
struct alignas(16) SymbolDrawableUBO {
|
||||
/* 0 */ std::array<float, 4 * 4> matrix;
|
||||
/* 64 */ std::array<float, 4 * 4> label_plane_matrix;
|
||||
/* 128 */ std::array<float, 4 * 4> coord_matrix;
|
||||
|
||||
/* 192 */ std::array<float, 2> texsize;
|
||||
/* 200 */ std::array<float, 2> texsize_icon;
|
||||
|
||||
/* 208 */ float gamma_scale;
|
||||
/* 212 */ float device_pixel_ratio;
|
||||
|
||||
/* 216 */ float camera_to_center_distance;
|
||||
/* 220 */ float pitch;
|
||||
/* 224 */ /*bool*/ int rotate_symbol;
|
||||
/* 228 */ float aspect_ratio;
|
||||
/* 232 */ std::array<float, 2> pad;
|
||||
/* 240 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableUBO) == 15 * 16);
|
||||
|
||||
/// Dynamic UBO
|
||||
struct alignas(16) SymbolDynamicUBO {
|
||||
/* 0 */ float fade_change;
|
||||
/* 4 */ float pad1;
|
||||
/* 8 */ std::array<float, 2> pad2;
|
||||
/* 16 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDynamicUBO) == 16);
|
||||
|
||||
/// Evaluated properties that do not depend on the tile
|
||||
struct alignas(16) SymbolDrawablePaintUBO {
|
||||
/* 0 */ Color fill_color;
|
||||
/* 16 */ Color halo_color;
|
||||
/* 32 */ float opacity;
|
||||
/* 36 */ float halo_width;
|
||||
/* 40 */ float halo_blur;
|
||||
/* 44 */ float padding;
|
||||
/* 48 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawablePaintUBO) == 3 * 16);
|
||||
|
||||
Size getTexSize(const gfx::Drawable& drawable, const StringIdentity nameId) {
|
||||
if (const auto& shader = drawable.getShader()) {
|
||||
if (const auto index = shader->getSamplerLocation(nameId)) {
|
||||
@@ -78,8 +43,10 @@ std::array<float, 2> toArray(const Size& s) {
|
||||
return util::cast<float>(std::array<uint32_t, 2>{s.width, s.height});
|
||||
}
|
||||
|
||||
static const StringIdentity idTexUniformName = StringIndexer::get("u_texture");
|
||||
static const StringIdentity idTexIconUniformName = StringIndexer::get("u_texture_icon");
|
||||
const StringIdentity idTexUniformName = StringIndexer::get("u_texture");
|
||||
const StringIdentity idTexIconUniformName = StringIndexer::get("u_texture_icon");
|
||||
const StringIdentity idExpressionInputsUBOName = StringIndexer::get("ExpressionInputsUBO");
|
||||
const StringIdentity idSymbolPermutationUBOName = StringIndexer::get("SymbolPermutationUBO");
|
||||
|
||||
SymbolDrawablePaintUBO buildPaintUBO(bool isText, const SymbolPaintProperties::PossiblyEvaluated& evaluated) {
|
||||
return {
|
||||
@@ -120,6 +87,35 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
|
||||
#endif
|
||||
|
||||
const auto zoom = parameters.state.getZoom();
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
if (propertiesChanged) {
|
||||
const SymbolPermutationUBO permutationUBO = {
|
||||
/* .fill_color = */ {/*.source=*/getAttributeSource("a_fill_color"), /*.expression=*/{}},
|
||||
/* .halo_color = */ {/*.source=*/getAttributeSource("a_halo_color"), /*.expression=*/{}},
|
||||
/* .opacity = */ {/*.source=*/getAttributeSource("a_opacity"), /*.expression=*/{}},
|
||||
/* .halo_width = */ {/*.source=*/getAttributeSource("a_halo_width"), /*.expression=*/{}},
|
||||
/* .halo_blur = */ {/*.source=*/getAttributeSource("a_halo_blur"), /*.expression=*/{}},
|
||||
/* .overdrawInspector = */ overdrawInspector,
|
||||
/* .pad = */ 0,
|
||||
0,
|
||||
0};
|
||||
|
||||
if (permutationUniformBuffer) {
|
||||
permutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO));
|
||||
} else {
|
||||
permutationUniformBuffer = context.createUniformBuffer(&permutationUBO, sizeof(permutationUBO));
|
||||
}
|
||||
|
||||
propertiesChanged = false;
|
||||
}
|
||||
if (!expressionUniformBuffer) {
|
||||
const auto expressionUBO = buildExpressionUBO(zoom, parameters.frameCount);
|
||||
expressionUniformBuffer = context.createUniformBuffer(&expressionUBO, sizeof(expressionUBO));
|
||||
}
|
||||
#endif
|
||||
|
||||
layerGroup.visitDrawables([&](gfx::Drawable& drawable) {
|
||||
if (!drawable.getTileID() || !drawable.getData()) {
|
||||
return;
|
||||
@@ -148,7 +144,7 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
tileID, renderTree, state, translate, anchor, nearClipped, inViewportPixelUnits);
|
||||
|
||||
// from symbol_program, makeValues
|
||||
const auto currentZoom = static_cast<float>(state.getZoom());
|
||||
const auto currentZoom = static_cast<float>(zoom);
|
||||
const float pixelsToTileUnits = tileID.pixelsToTileUnits(1.f, currentZoom);
|
||||
const bool pitchWithMap = symbolData.pitchAlignment == style::AlignmentType::Map;
|
||||
const bool rotateWithMap = symbolData.rotationAlignment == style::AlignmentType::Map;
|
||||
@@ -198,6 +194,11 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
uniforms.createOrUpdate(idSymbolDrawableUBOName, &drawableUBO, context);
|
||||
uniforms.createOrUpdate(idSymbolDynamicUBOName, &dynamicUBO, context);
|
||||
uniforms.addOrReplace(idSymbolDrawablePaintUBOName, isText ? textPaintBuffer : iconPaintBuffer);
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
uniforms.addOrReplace(idExpressionInputsUBOName, expressionUniformBuffer);
|
||||
uniforms.addOrReplace(idSymbolPermutationUBOName, permutationUniformBuffer);
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -29,32 +29,11 @@ public:
|
||||
private:
|
||||
gfx::UniformBufferPtr textPaintBuffer;
|
||||
gfx::UniformBufferPtr iconPaintBuffer;
|
||||
};
|
||||
|
||||
/// Evaluated properties that depend on the tile
|
||||
struct alignas(16) SymbolDrawableTilePropsUBO {
|
||||
/* 0 */ /*bool*/ int is_text;
|
||||
/* 4 */ /*bool*/ int is_halo;
|
||||
/* 8 */ /*bool*/ int pitch_with_map;
|
||||
/* 12 */ /*bool*/ int is_size_zoom_constant;
|
||||
/* 16 */ /*bool*/ int is_size_feature_constant;
|
||||
/* 20 */ float size_t;
|
||||
/* 24 */ float size;
|
||||
/* 28 */ float padding;
|
||||
/* 32 */
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
gfx::UniformBufferPtr permutationUniformBuffer;
|
||||
gfx::UniformBufferPtr expressionUniformBuffer;
|
||||
#endif // MLN_RENDER_BACKEND_METAL
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableTilePropsUBO) == 2 * 16);
|
||||
|
||||
/// Attribute interpolations
|
||||
struct alignas(16) SymbolDrawableInterpolateUBO {
|
||||
/* 0 */ float fill_color_t;
|
||||
/* 4 */ float halo_color_t;
|
||||
/* 8 */ float opacity_t;
|
||||
/* 12 */ float halo_width_t;
|
||||
/* 16 */ float halo_blur_t;
|
||||
/* 20 */ float pad1, pad2, pad3;
|
||||
/* 32 */
|
||||
};
|
||||
static_assert(sizeof(SymbolDrawableInterpolateUBO) == 32);
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
Reference in New Issue
Block a user