From 4eb941980e0153275bb31e4954fd46e32405a8c5 Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Fri, 22 Sep 2023 12:47:40 +0300 Subject: [PATCH] Metal hillshade layer (#1546) Signed-off-by: dependabot[bot] Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: mwilsnd Co-authored-by: Tim Sylvester Co-authored-by: mwilsnd <53413200+mwilsnd@users.noreply.github.com> Co-authored-by: Stefan Karschti Co-authored-by: Bart Louwers Co-authored-by: Alex Cristici Co-authored-by: Bart Louwers Co-authored-by: Wei Chen Co-authored-by: Siarhei Fedartsou Co-authored-by: tdcosta100 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- CMakeLists.txt | 4 + bazel/core.bzl | 4 + include/mbgl/mtl/texture2d.hpp | 1 - .../mbgl/shaders/gl/drawable_fill_outline.hpp | 2 - .../mbgl/shaders/gl/drawable_hillshade.hpp | 8 + .../shaders/gl/drawable_hillshade_prepare.hpp | 8 + include/mbgl/shaders/hillshade_layer_ubo.hpp | 27 ++++ .../shaders/hillshade_prepare_layer_ubo.hpp | 22 +++ include/mbgl/shaders/mtl/common.hpp | 4 + include/mbgl/shaders/mtl/hillshade.hpp | 121 +++++++++++++++ .../mbgl/shaders/mtl/hillshade_prepare.hpp | 138 ++++++++++++++++++ shaders/drawable.hillshade.fragment.glsl | 4 + shaders/drawable.hillshade.vertex.glsl | 4 + .../drawable.hillshade_prepare.fragment.glsl | 4 + .../drawable.hillshade_prepare.vertex.glsl | 4 + src/mbgl/mtl/renderer_backend.cpp | 5 +- .../layers/hillshade_layer_tweaker.cpp | 25 ++-- .../hillshade_prepare_layer_tweaker.cpp | 22 +-- .../layers/render_hillshade_layer.cpp | 32 +++- .../layers/render_hillshade_layer.hpp | 13 +- 20 files changed, 413 insertions(+), 39 deletions(-) create mode 100644 include/mbgl/shaders/hillshade_layer_ubo.hpp create mode 100644 include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp create mode 100644 include/mbgl/shaders/mtl/hillshade.hpp create mode 100644 include/mbgl/shaders/mtl/hillshade_prepare.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 67a033ee3..3f35ec847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1114,6 +1114,8 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_extrusion_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_texture_layer_ubo.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_layer_ubo.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/line_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/raster_layer_ubo.hpp @@ -1177,6 +1179,8 @@ if(MBGL_WITH_METAL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap_texture.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade_prepare.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/line.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/line_gradient.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/raster.hpp diff --git a/bazel/core.bzl b/bazel/core.bzl index 5492605e2..6329df8eb 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -965,6 +965,8 @@ MLN_DRAWABLES_HEADERS = [ "include/mbgl/shaders/fill_extrusion_layer_ubo.hpp", "include/mbgl/shaders/heatmap_layer_ubo.hpp", "include/mbgl/shaders/heatmap_texture_layer_ubo.hpp", + "include/mbgl/shaders/hillshade_layer_ubo.hpp", + "include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp", "include/mbgl/shaders/layer_ubo.hpp", "include/mbgl/shaders/line_layer_ubo.hpp", "include/mbgl/shaders/raster_layer_ubo.hpp", @@ -1049,6 +1051,8 @@ MLN_DRAWABLES_MTL_HEADERS = [ "include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp", "include/mbgl/shaders/mtl/heatmap.hpp", "include/mbgl/shaders/mtl/heatmap_texture.hpp", + "include/mbgl/shaders/mtl/hillshade.hpp", + "include/mbgl/shaders/mtl/hillshade_prepare.hpp", "include/mbgl/shaders/mtl/line.hpp", "include/mbgl/shaders/mtl/line_gradient.hpp", "include/mbgl/shaders/mtl/raster.hpp", diff --git a/include/mbgl/mtl/texture2d.hpp b/include/mbgl/mtl/texture2d.hpp index 78d032e3a..8288fa187 100644 --- a/include/mbgl/mtl/texture2d.hpp +++ b/include/mbgl/mtl/texture2d.hpp @@ -45,7 +45,6 @@ public: bool needsUpload() const noexcept override { return !!image; }; -public: gfx::Texture2D& setUsage(MTL::TextureUsage usage_) noexcept; MTL::Texture* getMetalTexture() const noexcept; diff --git a/include/mbgl/shaders/gl/drawable_fill_outline.hpp b/include/mbgl/shaders/gl/drawable_fill_outline.hpp index 3aa6a8483..2e90ca776 100644 --- a/include/mbgl/shaders/gl/drawable_fill_outline.hpp +++ b/include/mbgl/shaders/gl/drawable_fill_outline.hpp @@ -11,8 +11,6 @@ struct ShaderSource { static constexpr const char* vertex = R"(layout (std140) uniform FillOutlineDrawableUBO { highp mat4 u_matrix; highp vec2 u_world; - highp float pad1; - highp float pad2; }; layout (std140) uniform FillOutlineEvaluatedPropsUBO { highp vec4 u_outline_color; diff --git a/include/mbgl/shaders/gl/drawable_hillshade.hpp b/include/mbgl/shaders/gl/drawable_hillshade.hpp index 3d706de1a..100ddc6e7 100644 --- a/include/mbgl/shaders/gl/drawable_hillshade.hpp +++ b/include/mbgl/shaders/gl/drawable_hillshade.hpp @@ -15,6 +15,10 @@ layout (std140) uniform HillshadeDrawableUBO { highp mat4 u_matrix; highp vec2 u_latrange; highp vec2 u_light; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; out vec2 v_pos; @@ -31,6 +35,10 @@ layout (std140) uniform HillshadeDrawableUBO { highp mat4 u_matrix; highp vec2 u_latrange; highp vec2 u_light; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; layout (std140) uniform HillshadeEvaluatedPropsUBO { diff --git a/include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp b/include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp index f08cc8b92..555e0fdb7 100644 --- a/include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp +++ b/include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp @@ -17,6 +17,10 @@ layout (std140) uniform HillshadePrepareDrawableUBO { highp vec2 u_dimension; highp float u_zoom; highp float u_maxzoom; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; out vec2 v_pos; @@ -42,6 +46,10 @@ layout (std140) uniform HillshadePrepareDrawableUBO { highp vec2 u_dimension; highp float u_zoom; highp float u_maxzoom; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; float getElevation(vec2 coord, float bias) { diff --git a/include/mbgl/shaders/hillshade_layer_ubo.hpp b/include/mbgl/shaders/hillshade_layer_ubo.hpp new file mode 100644 index 000000000..bf9fa455f --- /dev/null +++ b/include/mbgl/shaders/hillshade_layer_ubo.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include + +namespace mbgl { +namespace shaders { + +struct alignas(16) HillshadeDrawableUBO { + std::array matrix; + std::array latrange; + std::array light; + // overdrawInspector is used only in Metal, while in GL this is a 16 bytes empty padding. + bool overdrawInspector; + uint8_t pad1, pad2, pad3; + float pad4, pad5, pad6; +}; +static_assert(sizeof(HillshadeDrawableUBO) % 16 == 0); + +struct alignas(16) HillshadeEvaluatedPropsUBO { + Color highlight; + Color shadow; + Color accent; +}; +static_assert(sizeof(HillshadeEvaluatedPropsUBO) % 16 == 0); + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp b/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp new file mode 100644 index 000000000..68af948a4 --- /dev/null +++ b/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace mbgl { +namespace shaders { + +struct alignas(16) HillshadePrepareDrawableUBO { + std::array matrix; + std::array unpack; + std::array dimension; + float zoom; + float maxzoom; + // overdrawInspector is used only in Metal, while in GL this is a 16 bytes empty padding. + bool overdrawInspector; + uint8_t pad1, pad2, pad3; + float pad4, pad5, pad6; +}; +static_assert(sizeof(HillshadePrepareDrawableUBO) % 16 == 0); + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/mtl/common.hpp b/include/mbgl/shaders/mtl/common.hpp index 606f56cc4..04257e9d6 100644 --- a/include/mbgl/shaders/mtl/common.hpp +++ b/include/mbgl/shaders/mtl/common.hpp @@ -26,6 +26,10 @@ using namespace metal; template inline auto glMod(T1 x, T2 y) { return x - y * metal::floor(x/y); } +float radians(float degrees) { + return M_PI_F * degrees / 180.0; +} + enum class AttributeSource : int32_t { Constant, PerVertex, diff --git a/include/mbgl/shaders/mtl/hillshade.hpp b/include/mbgl/shaders/mtl/hillshade.hpp new file mode 100644 index 000000000..1fa97b3b8 --- /dev/null +++ b/include/mbgl/shaders/mtl/hillshade.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr auto name = "HillshadeShader"; + static constexpr auto vertexMainFunction = "vertexMain"; + static constexpr auto fragmentMainFunction = "fragmentMain"; + + static constexpr AttributeInfo attributes[] = { + {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, + }; + static constexpr UniformBlockInfo uniforms[] = { + MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadeDrawableUBO), + MLN_MTL_UNIFORM_BLOCK(3, false, true, HillshadeEvaluatedPropsUBO), + }; + static constexpr TextureInfo textures[] = { + {0, "u_image"}, + }; + + static constexpr auto source = R"( + +struct VertexStage { + short2 pos [[attribute(0)]]; + short2 texture_pos [[attribute(1)]]; +}; + +struct FragmentStage { + float4 position [[position, invariant]]; + float2 pos; +}; + +struct alignas(16) HillshadeDrawableUBO { + float4x4 matrix; + float2 latrange; + float2 light; + bool overdrawInspector; + uint8_t pad1, pad2, pad3; + float pad4, pad5, pad6; +}; + +struct alignas(16) HillshadeEvaluatedPropsUBO { + float4 highlight; + float4 shadow; + float4 accent; +}; + +FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], + device const HillshadeDrawableUBO& drawable [[buffer(2)]]) { + + const float4 position = drawable.matrix * float4(float2(vertx.pos), 0, 1); + float2 pos = float2(vertx.texture_pos) / 8192.0; + pos.y = 1.0 - pos.y; + + return { + .position = position, + .pos = pos, + }; +} + +half4 fragment fragmentMain(FragmentStage in [[stage_in]], + device const HillshadeDrawableUBO& drawable [[buffer(2)]], + device const HillshadeEvaluatedPropsUBO& props [[buffer(3)]], + texture2d image [[texture(0)]], + sampler image_sampler [[sampler(0)]]) { + + if (drawable.overdrawInspector) { + return half4(1.0); + } + + float4 pixel = image.sample(image_sampler, in.pos); + + float2 deriv = ((pixel.rg * 2.0) - 1.0); + + // We divide the slope by a scale factor based on the cosin of the pixel's approximate latitude + // to account for mercator projection distortion. see #4807 for details + float scaleFactor = cos(radians((drawable.latrange[0] - drawable.latrange[1]) * in.pos.y + drawable.latrange[1])); + // We also multiply the slope by an arbitrary z-factor of 1.25 + float slope = atan(1.25 * length(deriv) / scaleFactor); + float aspect = deriv.x != 0.0 ? atan2(deriv.y, -deriv.x) : M_PI_F / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0); + + float intensity = drawable.light.x; + // We add PI to make this property match the global light object, which adds PI/2 to the light's azimuthal + // position property to account for 0deg corresponding to north/the top of the viewport in the style spec + // and the original shader was written to accept (-illuminationDirection - 90) as the azimuthal. + float azimuth = drawable.light.y + M_PI_F; + + // We scale the slope exponentially based on intensity, using a calculation similar to + // the exponential interpolation function in the style spec: + // https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/expression/definitions/interpolate.js#L217-L228 + // so that higher intensity values create more opaque hillshading. + float base = 1.875 - intensity * 1.75; + float maxValue = 0.5 * M_PI_F; + float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope; + + // The accent color is calculated with the cosine of the slope while the shade color is calculated with the sine + // so that the accent color's rate of change eases in while the shade color's eases out. + float accent = cos(scaledSlope); + // We multiply both the accent and shade color by a clamped intensity value + // so that intensities >= 0.5 do not additionally affect the color values + // while intensity values < 0.5 make the overall color more transparent. + float4 accent_color = (1.0 - accent) * props.accent * clamp(intensity * 2.0, 0.0, 1.0); + float shade = abs(glMod((aspect + azimuth) / M_PI_F + 0.5, 2.0) - 1.0); + float4 shade_color = mix(props.shadow, props.highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0); + float4 color = accent_color * (1.0 - shade_color.a) + shade_color; + + return half4(color); +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/mtl/hillshade_prepare.hpp b/include/mbgl/shaders/mtl/hillshade_prepare.hpp new file mode 100644 index 000000000..be57aef91 --- /dev/null +++ b/include/mbgl/shaders/mtl/hillshade_prepare.hpp @@ -0,0 +1,138 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr auto name = "HillshadePrepareShader"; + static constexpr auto vertexMainFunction = "vertexMain"; + static constexpr auto fragmentMainFunction = "fragmentMain"; + + static constexpr AttributeInfo attributes[] = { + {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, + }; + static constexpr UniformBlockInfo uniforms[] = { + MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadePrepareDrawableUBO), + }; + static constexpr TextureInfo textures[] = { + {0, "u_image"}, + }; + static constexpr auto source = R"( + +struct VertexStage { + short2 pos [[attribute(0)]]; + short2 texture_pos [[attribute(1)]]; +}; + +struct FragmentStage { + float4 position [[position, invariant]]; + float2 pos; +}; + +struct alignas(16) HillshadePrepareDrawableUBO { + float4x4 matrix; + float4 unpack; + float2 dimension; + float zoom; + float maxzoom; + bool overdrawInspector; + uint8_t pad1, pad2, pad3; + float pad4, pad5, pad6; +}; + +FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], + device const HillshadePrepareDrawableUBO& drawable [[buffer(2)]]) { + + const float4 position = drawable.matrix * float4(float2(vertx.pos), 0, 1); + + float2 epsilon = 1.0 / drawable.dimension; + float scale = (drawable.dimension.x - 2.0) / drawable.dimension.x; + const float2 pos = (float2(vertx.texture_pos) / 8192.0) * scale + epsilon; + + return { + .position = position, + .pos = pos, + }; +} + +float getElevation(float2 coord, float bias, texture2d image, sampler image_sampler, float4 unpack) { + // Convert encoded elevation value to meters + float4 data = image.sample(image_sampler, coord) * 255.0; + data.a = -1.0; + return dot(data, unpack) / 4.0; +} + +half4 fragment fragmentMain(FragmentStage in [[stage_in]], + device const HillshadePrepareDrawableUBO& drawable [[buffer(2)]], + texture2d image [[texture(0)]], + sampler image_sampler [[sampler(0)]]) { + + if (drawable.overdrawInspector) { + return half4(1.0); + } + + float2 epsilon = 1.0 / drawable.dimension; + + // queried pixels: + // +-----------+ + // | | | | + // | a | b | c | + // | | | | + // +-----------+ + // | | | | + // | d | e | f | + // | | | | + // +-----------+ + // | | | | + // | g | h | i | + // | | | | + // +-----------+ + + float a = getElevation(in.pos + float2(-epsilon.x, -epsilon.y), 0.0, image, image_sampler, drawable.unpack); + float b = getElevation(in.pos + float2(0, -epsilon.y), 0.0, image, image_sampler, drawable.unpack); + float c = getElevation(in.pos + float2(epsilon.x, -epsilon.y), 0.0, image, image_sampler, drawable.unpack); + float d = getElevation(in.pos + float2(-epsilon.x, 0), 0.0, image, image_sampler, drawable.unpack); + float e = getElevation(in.pos, 0.0, image, image_sampler, drawable.unpack); + float f = getElevation(in.pos + float2(epsilon.x, 0), 0.0, image, image_sampler, drawable.unpack); + float g = getElevation(in.pos + float2(-epsilon.x, epsilon.y), 0.0, image, image_sampler, drawable.unpack); + float h = getElevation(in.pos + float2(0, epsilon.y), 0.0, image, image_sampler, drawable.unpack); + float i = getElevation(in.pos + float2(epsilon.x, epsilon.y), 0.0, image, image_sampler, drawable.unpack); + + // here we divide the x and y slopes by 8 * pixel size + // where pixel size (aka meters/pixel) is: + // circumference of the world / (pixels per tile * number of tiles) + // which is equivalent to: 8 * 40075016.6855785 / (512 * pow(2, u_zoom)) + // which can be reduced to: pow(2, 19.25619978527 - u_zoom) + // we want to vertically exaggerate the hillshading though, because otherwise + // it is barely noticeable at low zooms. to do this, we multiply this by some + // scale factor pow(2, (u_zoom - u_maxzoom) * a) where a is an arbitrary value + // Here we use a=0.3 which works out to the expression below. see + // nickidlugash's awesome breakdown for more info + // https://github.com/mapbox/mapbox-gl-js/pull/5286#discussion_r148419556 + float exaggeration = drawable.zoom < 2.0 ? 0.4 : drawable.zoom < 4.5 ? 0.35 : 0.3; + + float2 deriv = float2( + (c + f + f + i) - (a + d + d + g), + (g + h + h + i) - (a + b + b + c) + ) / pow(2.0, (drawable.zoom - drawable.maxzoom) * exaggeration + 19.2562 - drawable.zoom); + + float4 color = clamp(float4( + deriv.x / 2.0 + 0.5, + deriv.y / 2.0 + 0.5, + 1.0, + 1.0), 0.0, 1.0); + + return half4(color); +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/shaders/drawable.hillshade.fragment.glsl b/shaders/drawable.hillshade.fragment.glsl index ca3df9255..3e043b22f 100644 --- a/shaders/drawable.hillshade.fragment.glsl +++ b/shaders/drawable.hillshade.fragment.glsl @@ -5,6 +5,10 @@ layout (std140) uniform HillshadeDrawableUBO { highp mat4 u_matrix; highp vec2 u_latrange; highp vec2 u_light; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; layout (std140) uniform HillshadeEvaluatedPropsUBO { diff --git a/shaders/drawable.hillshade.vertex.glsl b/shaders/drawable.hillshade.vertex.glsl index 20fadb2f0..68df07fec 100644 --- a/shaders/drawable.hillshade.vertex.glsl +++ b/shaders/drawable.hillshade.vertex.glsl @@ -5,6 +5,10 @@ layout (std140) uniform HillshadeDrawableUBO { highp mat4 u_matrix; highp vec2 u_latrange; highp vec2 u_light; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; out vec2 v_pos; diff --git a/shaders/drawable.hillshade_prepare.fragment.glsl b/shaders/drawable.hillshade_prepare.fragment.glsl index ea9be647d..ee08d5fd9 100644 --- a/shaders/drawable.hillshade_prepare.fragment.glsl +++ b/shaders/drawable.hillshade_prepare.fragment.glsl @@ -11,6 +11,10 @@ layout (std140) uniform HillshadePrepareDrawableUBO { highp vec2 u_dimension; highp float u_zoom; highp float u_maxzoom; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; float getElevation(vec2 coord, float bias) { diff --git a/shaders/drawable.hillshade_prepare.vertex.glsl b/shaders/drawable.hillshade_prepare.vertex.glsl index a3aaad8d0..efee3fdc2 100644 --- a/shaders/drawable.hillshade_prepare.vertex.glsl +++ b/shaders/drawable.hillshade_prepare.vertex.glsl @@ -7,6 +7,10 @@ layout (std140) uniform HillshadePrepareDrawableUBO { highp vec2 u_dimension; highp float u_zoom; highp float u_maxzoom; + lowp float pad0_; + lowp float pad1_; + lowp float pad2_; + lowp float pad3_; }; out vec2 v_pos; diff --git a/src/mbgl/mtl/renderer_backend.cpp b/src/mbgl/mtl/renderer_backend.cpp index 080fa1d24..300edb850 100644 --- a/src/mbgl/mtl/renderer_backend.cpp +++ b/src/mbgl/mtl/renderer_backend.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -130,7 +132,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar shaders::BuiltIn::FillExtrusionPatternShader, shaders::BuiltIn::HeatmapShader, shaders::BuiltIn::HeatmapTextureShader, - // shaders::BuiltIn::HillshadeShader, + shaders::BuiltIn::HillshadeShader, + shaders::BuiltIn::HillshadePrepareShader, shaders::BuiltIn::LineShader, shaders::BuiltIn::LineGradientShader, // shaders::BuiltIn::LineSDFShader, diff --git a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp index d2c4cbbbd..088785304 100644 --- a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -12,20 +13,7 @@ namespace mbgl { using namespace style; - -struct alignas(16) HillshadeDrawableUBO { - std::array matrix; - std::array latrange; - std::array light; -}; -static_assert(sizeof(HillshadeDrawableUBO) % 16 == 0); - -struct alignas(16) HillshadeEvaluatedPropsUBO { - Color highlight; - Color shadow; - Color accent; -}; -static_assert(sizeof(HillshadeEvaluatedPropsUBO) % 16 == 0); +using namespace shaders; static const StringIdentity idHillshadeDrawableUBOName = StringIndexer::get("HillshadeDrawableUBO"); static const StringIdentity idHillshadeEvaluatedPropsUBOName = StringIndexer::get("HillshadeEvaluatedPropsUBO"); @@ -77,7 +65,14 @@ void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup, tileID, renderTree, parameters.state, {0.f, 0.f}, TranslateAnchorType::Viewport, false, false, true); HillshadeDrawableUBO drawableUBO = {/* .matrix = */ util::cast(matrix), /* .latrange = */ getLatRange(tileID), - /* .light = */ getLight(parameters, evaluated)}; + /* .light = */ getLight(parameters, evaluated), + /* .overdrawInspector = */ overdrawInspector, + /* .pad1/2/3 = */ 0, + 0, + 0, + /* .pad4/5/6 = */ 0, + 0, + 0}; drawable.mutableUniformBuffers().createOrUpdate(idHillshadeDrawableUBOName, &drawableUBO, parameters.context); }); diff --git a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp index 131402ef6..dfd33efe5 100644 --- a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -13,15 +14,7 @@ namespace mbgl { using namespace style; - -struct alignas(16) HillshadePrepareDrawableUBO { - std::array matrix; - std::array unpack; - std::array dimension; - float zoom; - float maxzoom; -}; -static_assert(sizeof(HillshadePrepareDrawableUBO) % 16 == 0); +using namespace shaders; static const StringIdentity idHillshadePrepareDrawableUBOName = StringIndexer::get("HillshadePrepareDrawableUBO"); @@ -56,7 +49,7 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& drawableData = static_cast(*drawable.getData()); mat4 matrix; - matrix::ortho(matrix, 0, util::EXTENT, -util::EXTENT, 0, 0, 1); + matrix::ortho(matrix, 0, util::EXTENT, -util::EXTENT, 0, -1, 1); matrix::translate(matrix, matrix, 0, -util::EXTENT, 0); HillshadePrepareDrawableUBO drawableUBO = { @@ -64,7 +57,14 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, /* .unpack = */ getUnpackVector(drawableData.encoding), /* .dimension = */ {static_cast(drawableData.stride), static_cast(drawableData.stride)}, /* .zoom = */ static_cast(tileID.canonical.z), - /* .maxzoom = */ static_cast(drawableData.maxzoom)}; + /* .maxzoom = */ static_cast(drawableData.maxzoom), + /* .overdrawInspector = */ overdrawInspector, + /* .pad1/2/3 = */ 0, + 0, + 0, + /* .pad4/5/6 = */ 0, + 0, + 0}; drawable.mutableUniformBuffers().createOrUpdate( idHillshadePrepareDrawableUBOName, &drawableUBO, parameters.context); diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index ca41a5aa0..04297439c 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -72,9 +73,7 @@ void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& paramete properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); - } + updateLayerTweaker(); #endif } @@ -285,10 +284,20 @@ static const StringIdentity idPosAttribName = StringIndexer::get("a_pos"); static const StringIdentity idTexturePosAttribName = StringIndexer::get("a_texture_pos"); static const StringIdentity idTexImageName = StringIndexer::get("u_image"); +#if MLN_DRAWABLE_RENDERER +void RenderHillshadeLayer::updateLayerTweaker() { + if (layerGroup) { + tweaker = std::make_shared(getID(), evaluatedProperties); + tweaker->enableOverdrawInspector(overdrawInspector); + layerGroup->setLayerTweaker(tweaker); + } +} +#endif // MLN_DRAWABLE_RENDERER + void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, [[maybe_unused]] const TransformState& state, - const std::shared_ptr&, + const std::shared_ptr& updateParameters, [[maybe_unused]] const RenderTree& renderTree, UniqueChangeRequestVec& changes) { std::unique_lock guard(mutex); @@ -304,8 +313,8 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, if (!layerGroup_) { return; } - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); + updateLayerTweaker(); } auto* tileLayerGroup = static_cast(layerGroup.get()); @@ -321,6 +330,14 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, return; } + const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); + if (overdrawInspector != overdraw) { + overdrawInspector = overdraw; + if (tweaker) { + tweaker->enableOverdrawInspector(overdrawInspector); + } + } + auto renderPass = RenderPass::Translucent; if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { return; @@ -372,8 +389,9 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, if (!singleTileLayerGroup) { return; } - singleTileLayerGroup->setLayerTweaker( - std::make_shared(getID(), evaluatedProperties)); + const auto prepareTweaker = std::make_shared(getID(), evaluatedProperties); + prepareTweaker->enableOverdrawInspector(overdrawInspector); + singleTileLayerGroup->setLayerTweaker(prepareTweaker); renderTarget->addLayerGroup(singleTileLayerGroup, /*replace=*/true); gfx::VertexAttributeArray hillshadePrepareVertexAttrs; diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.hpp b/src/mbgl/renderer/layers/render_hillshade_layer.hpp index ebf0baa7a..050ce023a 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.hpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.hpp @@ -9,8 +9,10 @@ namespace mbgl { -class HillshadeProgram; -class HillshadePrepareProgram; +#if MLN_DRAWABLE_RENDERER +class HillshadeLayerTweaker; +using HillshadeLayerTweakerPtr = std::shared_ptr; +#endif // MLN_DRAWABLE_RENDERER class RenderHillshadeLayer : public RenderLayer { public: @@ -41,6 +43,10 @@ private: void render(PaintParameters&) override; #endif +#if MLN_DRAWABLE_RENDERER + void updateLayerTweaker(); +#endif // MLN_DRAWABLE_RENDERER + void prepare(const LayerPrepareParameters&) override; #if MLN_DRAWABLE_RENDERER @@ -68,6 +74,9 @@ private: using HillshadeVertexVector = gfx::VertexVector; std::shared_ptr staticDataSharedVertices; + + HillshadeLayerTweakerPtr tweaker; + bool overdrawInspector = false; #endif };