Hillshade layer (#1305)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Tim Sylvester <tim@wetdogweather.com> Co-authored-by: Alex Cristici <alex.cristici@gmail.com>
This commit is contained in:
committed by
Bart Louwers
parent
95f0cbed33
commit
3056f28756
@@ -174,6 +174,7 @@ if(MLN_DRAWABLE_RENDERER)
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder_impl.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_atlases_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/line_drawable_data.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/symbol_drawable_data.hpp
|
||||
@@ -194,16 +195,20 @@ if(MLN_DRAWABLE_RENDERER)
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/hillshade_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/line_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/line_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/raster_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/raster_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/shader_program_base.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/shader_program_mtl.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/identity.cpp
|
||||
@@ -266,7 +271,6 @@ list(APPEND INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/platform/thread.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/query.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_frontend.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_observer.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_state.hpp
|
||||
@@ -1011,6 +1015,8 @@ if(MLN_WITH_OPENGL)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_heatmap.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_heatmap_texture.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp
|
||||
${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
|
||||
|
||||
@@ -68,12 +68,14 @@ MLN_GENERATED_SHADER_HEADERS = [
|
||||
"include/mbgl/shaders/gl/drawable_fill_extrusion.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_fill_pattern.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_heatmap.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_heatmap_texture.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_hillshade.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_line_gradient.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_line_pattern.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_line_sdf.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_line.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_heatmap.hpp",
|
||||
"include/mbgl/shaders/gl/drawable_heatmap_texture.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",
|
||||
@@ -881,7 +883,7 @@ MLN_OPENGL_HEADERS = [
|
||||
"include/mbgl/gl/renderable_resource.hpp",
|
||||
"include/mbgl/gl/renderer_backend.hpp",
|
||||
"include/mbgl/layermanager/location_indicator_layer_factory.hpp",
|
||||
"include/mbgl/platform/gl_functions.hpp",
|
||||
"include/mbgl/platform/gl_functions.hpp"
|
||||
]
|
||||
|
||||
MLN_DRAWABLES_SOURCE = [
|
||||
@@ -890,6 +892,7 @@ MLN_DRAWABLES_SOURCE = [
|
||||
"src/mbgl/gfx/drawable_builder_impl.hpp",
|
||||
"src/mbgl/gfx/drawable_atlases_tweaker.cpp",
|
||||
"src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp",
|
||||
"src/mbgl/gfx/hillshade_prepare_drawable_data.hpp",
|
||||
"src/mbgl/gfx/image_drawable_data.hpp",
|
||||
"src/mbgl/gfx/line_drawable_data.hpp",
|
||||
"src/mbgl/gfx/symbol_drawable_data.hpp",
|
||||
@@ -913,6 +916,10 @@ MLN_DRAWABLES_SOURCE = [
|
||||
"src/mbgl/renderer/layers/heatmap_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/hillshade_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/line_layer_tweaker.cpp",
|
||||
"src/mbgl/renderer/layers/line_layer_tweaker.hpp",
|
||||
"src/mbgl/renderer/layers/raster_layer_tweaker.cpp",
|
||||
|
||||
@@ -151,6 +151,13 @@ public:
|
||||
virtual void setVertexAttributes(const gfx::VertexAttributeArray&) = 0;
|
||||
virtual void setVertexAttributes(gfx::VertexAttributeArray&&) = 0;
|
||||
|
||||
/// Provide raw data for vertices
|
||||
/// Incompatible with adding primitives
|
||||
virtual void setVertices(std::vector<uint8_t>&&, std::size_t, AttributeDataType) = 0;
|
||||
|
||||
/// Create a segment wrapper
|
||||
virtual void setIndexData(std::vector<std::uint16_t> indexes, std::vector<UniqueDrawSegment> segments) = 0;
|
||||
|
||||
/// Get the tweakers attached to this drawable
|
||||
const std::vector<DrawableTweakerPtr>& getTweakers() const { return tweakers; }
|
||||
void addTweaker(DrawableTweakerPtr value) { tweakers.emplace_back(std::move(value)); }
|
||||
|
||||
@@ -152,15 +152,15 @@ public:
|
||||
std::size_t indexLength,
|
||||
std::size_t baseIndex = 0);
|
||||
|
||||
/// Create a segment wrapper
|
||||
virtual std::unique_ptr<Drawable::DrawSegment> createSegment(gfx::DrawMode, SegmentBase&&) = 0;
|
||||
|
||||
protected:
|
||||
std::size_t curVertexCount() const;
|
||||
|
||||
/// Create an instance of the appropriate drawable type
|
||||
virtual UniqueDrawable createDrawable() const = 0;
|
||||
|
||||
/// Create a segment wrapper
|
||||
virtual std::unique_ptr<Drawable::DrawSegment> createSegment(gfx::DrawMode, SegmentBase&&) = 0;
|
||||
|
||||
/// Setup the SDK-specific aspects after all the values are present
|
||||
virtual void init() = 0;
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ public:
|
||||
void draw(PaintParameters&) const override;
|
||||
|
||||
struct DrawSegmentGL;
|
||||
void setIndexData(std::vector<std::uint16_t> indexes, std::vector<UniqueDrawSegment> segments);
|
||||
void setIndexData(std::vector<std::uint16_t> indexes, std::vector<UniqueDrawSegment> segments) override;
|
||||
|
||||
void setVertices(std::vector<uint8_t>&&, std::size_t, gfx::AttributeDataType);
|
||||
void setVertices(std::vector<uint8_t>&&, std::size_t, gfx::AttributeDataType) override;
|
||||
|
||||
const gfx::VertexAttributeArray& getVertexAttributes() const override;
|
||||
void setVertexAttributes(const gfx::VertexAttributeArray& value) override;
|
||||
|
||||
@@ -15,12 +15,12 @@ public:
|
||||
: gfx::DrawableBuilder(std::move(name_)) {}
|
||||
~DrawableGLBuilder() override = default;
|
||||
|
||||
protected:
|
||||
gfx::UniqueDrawable createDrawable() const override;
|
||||
|
||||
using DrawSegment = gfx::Drawable::DrawSegment;
|
||||
std::unique_ptr<DrawSegment> createSegment(gfx::DrawMode, SegmentBase&&) override;
|
||||
|
||||
protected:
|
||||
gfx::UniqueDrawable createDrawable() const override;
|
||||
|
||||
/// Setup the SDK-specific aspects after all the values are present
|
||||
void init() override;
|
||||
};
|
||||
|
||||
@@ -109,12 +109,12 @@ protected:
|
||||
*/
|
||||
class RemoveRenderTargetRequest : public ChangeRequest {
|
||||
public:
|
||||
RemoveRenderTargetRequest(const RenderTargetPtr &renderTarget_);
|
||||
RemoveRenderTargetRequest(RenderTargetPtr renderTarget_);
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
const RenderTargetPtr &renderTarget;
|
||||
RenderTargetPtr renderTarget;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -45,7 +45,8 @@ protected:
|
||||
const std::array<float, 2>& translation,
|
||||
style::TranslateAnchorType,
|
||||
bool nearClipped,
|
||||
bool inViewportPixelUnits);
|
||||
bool inViewportPixelUnits,
|
||||
bool aligned = false);
|
||||
|
||||
protected:
|
||||
Immutable<style::LayerProperties> evaluatedProperties;
|
||||
|
||||
89
include/mbgl/shaders/gl/drawable_hillshade.hpp
Normal file
89
include/mbgl/shaders/gl/drawable_hillshade.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// Generated code, do not modify this file!
|
||||
#pragma once
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::HillshadeShader, gfx::Backend::Type::OpenGL> {
|
||||
static constexpr const char* name = "HillshadeShader";
|
||||
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
|
||||
layout (location = 1) in vec2 a_texture_pos;
|
||||
|
||||
layout (std140) uniform HillshadeDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_latrange;
|
||||
highp vec2 u_light;
|
||||
};
|
||||
|
||||
out vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
v_pos = a_texture_pos / 8192.0;
|
||||
}
|
||||
)";
|
||||
static constexpr const char* fragment = R"(in vec2 v_pos;
|
||||
uniform sampler2D u_image;
|
||||
|
||||
layout (std140) uniform HillshadeDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_latrange;
|
||||
highp vec2 u_light;
|
||||
};
|
||||
|
||||
layout (std140) uniform HillshadeEvaluatedPropsUBO {
|
||||
highp vec4 u_highlight;
|
||||
highp vec4 u_shadow;
|
||||
highp vec4 u_accent;
|
||||
};
|
||||
|
||||
#define PI 3.141592653589793
|
||||
|
||||
void main() {
|
||||
vec4 pixel = texture(u_image, v_pos);
|
||||
|
||||
vec2 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((u_latrange[0] - u_latrange[1]) * (1.0 - v_pos.y) + u_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 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
||||
|
||||
float intensity = u_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 = u_light.y + PI;
|
||||
|
||||
// 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 * PI;
|
||||
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.
|
||||
vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);
|
||||
float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||
vec4 shade_color = mix(u_shadow, u_highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
||||
fragColor = accent_color * (1.0 - shade_color.a) + shade_color;
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
114
include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp
Normal file
114
include/mbgl/shaders/gl/drawable_hillshade_prepare.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
// Generated code, do not modify this file!
|
||||
#pragma once
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::HillshadePrepareShader, gfx::Backend::Type::OpenGL> {
|
||||
static constexpr const char* name = "HillshadePrepareShader";
|
||||
static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos;
|
||||
layout (location = 1) in vec2 a_texture_pos;
|
||||
|
||||
layout (std140) uniform HillshadePrepareDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec4 u_unpack;
|
||||
highp vec2 u_dimension;
|
||||
highp float u_zoom;
|
||||
highp float u_maxzoom;
|
||||
};
|
||||
|
||||
out vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
|
||||
highp vec2 epsilon = 1.0 / u_dimension;
|
||||
float scale = (u_dimension.x - 2.0) / u_dimension.x;
|
||||
v_pos = (a_texture_pos / 8192.0) * scale + epsilon;
|
||||
}
|
||||
)";
|
||||
static constexpr const char* fragment = R"(#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
in vec2 v_pos;
|
||||
uniform sampler2D u_image;
|
||||
|
||||
layout (std140) uniform HillshadePrepareDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec4 u_unpack;
|
||||
highp vec2 u_dimension;
|
||||
highp float u_zoom;
|
||||
highp float u_maxzoom;
|
||||
};
|
||||
|
||||
float getElevation(vec2 coord, float bias) {
|
||||
// Convert encoded elevation value to meters
|
||||
vec4 data = texture(u_image, coord) * 255.0;
|
||||
data.a = -1.0;
|
||||
return dot(data, u_unpack) / 4.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 epsilon = 1.0 / u_dimension;
|
||||
|
||||
// queried pixels:
|
||||
// +-----------+
|
||||
// | | | |
|
||||
// | a | b | c |
|
||||
// | | | |
|
||||
// +-----------+
|
||||
// | | | |
|
||||
// | d | e | f |
|
||||
// | | | |
|
||||
// +-----------+
|
||||
// | | | |
|
||||
// | g | h | i |
|
||||
// | | | |
|
||||
// +-----------+
|
||||
|
||||
float a = getElevation(v_pos + vec2(-epsilon.x, -epsilon.y), 0.0);
|
||||
float b = getElevation(v_pos + vec2(0, -epsilon.y), 0.0);
|
||||
float c = getElevation(v_pos + vec2(epsilon.x, -epsilon.y), 0.0);
|
||||
float d = getElevation(v_pos + vec2(-epsilon.x, 0), 0.0);
|
||||
float e = getElevation(v_pos, 0.0);
|
||||
float f = getElevation(v_pos + vec2(epsilon.x, 0), 0.0);
|
||||
float g = getElevation(v_pos + vec2(-epsilon.x, epsilon.y), 0.0);
|
||||
float h = getElevation(v_pos + vec2(0, epsilon.y), 0.0);
|
||||
float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y), 0.0);
|
||||
|
||||
// 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 = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;
|
||||
|
||||
vec2 deriv = vec2(
|
||||
(c + f + f + i) - (a + d + d + g),
|
||||
(g + h + h + i) - (a + b + b + c)
|
||||
) / pow(2.0, (u_zoom - u_maxzoom) * exaggeration + 19.2562 - u_zoom);
|
||||
|
||||
fragColor = clamp(vec4(
|
||||
deriv.x / 2.0 + 0.5,
|
||||
deriv.y / 2.0 + 0.5,
|
||||
1.0,
|
||||
1.0), 0.0, 1.0);
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <mbgl/shaders/gl/drawable_fill_extrusion_pattern.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_heatmap.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_heatmap_texture.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_hillshade_prepare.hpp>
|
||||
#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>
|
||||
|
||||
@@ -24,6 +24,8 @@ enum class BuiltIn {
|
||||
FillExtrusionPatternShader,
|
||||
HeatmapShader,
|
||||
HeatmapTextureShader,
|
||||
HillshadePrepareShader,
|
||||
HillshadeShader,
|
||||
RasterShader,
|
||||
SymbolIconShader,
|
||||
SymbolSDFTextShader,
|
||||
|
||||
58
shaders/drawable.hillshade.fragment.glsl
Normal file
58
shaders/drawable.hillshade.fragment.glsl
Normal file
@@ -0,0 +1,58 @@
|
||||
in vec2 v_pos;
|
||||
uniform sampler2D u_image;
|
||||
|
||||
layout (std140) uniform HillshadeDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_latrange;
|
||||
highp vec2 u_light;
|
||||
};
|
||||
|
||||
layout (std140) uniform HillshadeEvaluatedPropsUBO {
|
||||
highp vec4 u_highlight;
|
||||
highp vec4 u_shadow;
|
||||
highp vec4 u_accent;
|
||||
};
|
||||
|
||||
#define PI 3.141592653589793
|
||||
|
||||
void main() {
|
||||
vec4 pixel = texture(u_image, v_pos);
|
||||
|
||||
vec2 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((u_latrange[0] - u_latrange[1]) * (1.0 - v_pos.y) + u_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 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
||||
|
||||
float intensity = u_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 = u_light.y + PI;
|
||||
|
||||
// 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 * PI;
|
||||
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.
|
||||
vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);
|
||||
float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||
vec4 shade_color = mix(u_shadow, u_highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
||||
fragColor = accent_color * (1.0 - shade_color.a) + shade_color;
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
15
shaders/drawable.hillshade.vertex.glsl
Normal file
15
shaders/drawable.hillshade.vertex.glsl
Normal file
@@ -0,0 +1,15 @@
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
layout (location = 1) in vec2 a_texture_pos;
|
||||
|
||||
layout (std140) uniform HillshadeDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec2 u_latrange;
|
||||
highp vec2 u_light;
|
||||
};
|
||||
|
||||
out vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
v_pos = a_texture_pos / 8192.0;
|
||||
}
|
||||
78
shaders/drawable.hillshade_prepare.fragment.glsl
Normal file
78
shaders/drawable.hillshade_prepare.fragment.glsl
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
in vec2 v_pos;
|
||||
uniform sampler2D u_image;
|
||||
|
||||
layout (std140) uniform HillshadePrepareDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec4 u_unpack;
|
||||
highp vec2 u_dimension;
|
||||
highp float u_zoom;
|
||||
highp float u_maxzoom;
|
||||
};
|
||||
|
||||
float getElevation(vec2 coord, float bias) {
|
||||
// Convert encoded elevation value to meters
|
||||
vec4 data = texture(u_image, coord) * 255.0;
|
||||
data.a = -1.0;
|
||||
return dot(data, u_unpack) / 4.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 epsilon = 1.0 / u_dimension;
|
||||
|
||||
// queried pixels:
|
||||
// +-----------+
|
||||
// | | | |
|
||||
// | a | b | c |
|
||||
// | | | |
|
||||
// +-----------+
|
||||
// | | | |
|
||||
// | d | e | f |
|
||||
// | | | |
|
||||
// +-----------+
|
||||
// | | | |
|
||||
// | g | h | i |
|
||||
// | | | |
|
||||
// +-----------+
|
||||
|
||||
float a = getElevation(v_pos + vec2(-epsilon.x, -epsilon.y), 0.0);
|
||||
float b = getElevation(v_pos + vec2(0, -epsilon.y), 0.0);
|
||||
float c = getElevation(v_pos + vec2(epsilon.x, -epsilon.y), 0.0);
|
||||
float d = getElevation(v_pos + vec2(-epsilon.x, 0), 0.0);
|
||||
float e = getElevation(v_pos, 0.0);
|
||||
float f = getElevation(v_pos + vec2(epsilon.x, 0), 0.0);
|
||||
float g = getElevation(v_pos + vec2(-epsilon.x, epsilon.y), 0.0);
|
||||
float h = getElevation(v_pos + vec2(0, epsilon.y), 0.0);
|
||||
float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y), 0.0);
|
||||
|
||||
// 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 = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;
|
||||
|
||||
vec2 deriv = vec2(
|
||||
(c + f + f + i) - (a + d + d + g),
|
||||
(g + h + h + i) - (a + b + b + c)
|
||||
) / pow(2.0, (u_zoom - u_maxzoom) * exaggeration + 19.2562 - u_zoom);
|
||||
|
||||
fragColor = clamp(vec4(
|
||||
deriv.x / 2.0 + 0.5,
|
||||
deriv.y / 2.0 + 0.5,
|
||||
1.0,
|
||||
1.0), 0.0, 1.0);
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
20
shaders/drawable.hillshade_prepare.vertex.glsl
Normal file
20
shaders/drawable.hillshade_prepare.vertex.glsl
Normal file
@@ -0,0 +1,20 @@
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
layout (location = 1) in vec2 a_texture_pos;
|
||||
|
||||
layout (std140) uniform HillshadePrepareDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec4 u_unpack;
|
||||
highp vec2 u_dimension;
|
||||
highp float u_zoom;
|
||||
highp float u_maxzoom;
|
||||
};
|
||||
|
||||
out vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
|
||||
highp vec2 epsilon = 1.0 / u_dimension;
|
||||
float scale = (u_dimension.x - 2.0) / u_dimension.x;
|
||||
v_pos = (a_texture_pos / 8192.0) * scale + epsilon;
|
||||
}
|
||||
@@ -104,6 +104,20 @@
|
||||
"glsl_frag": "drawable.heatmap_texture.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "HillshadePrepareShader",
|
||||
"header": "drawable_hillshade_prepare",
|
||||
"glsl_vert": "drawable.hillshade_prepare.vertex.glsl",
|
||||
"glsl_frag": "drawable.hillshade_prepare.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "HillshadeShader",
|
||||
"header": "drawable_hillshade",
|
||||
"glsl_vert": "drawable.hillshade.vertex.glsl",
|
||||
"glsl_frag": "drawable.hillshade.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "RasterShader",
|
||||
"header": "drawable_raster",
|
||||
|
||||
@@ -7,13 +7,13 @@ DEMData::DEMData(const PremultipliedImage& _image, Tileset::DEMEncoding _encodin
|
||||
: dim(_image.size.height),
|
||||
// extra two pixels per row for border backfilling on either edge
|
||||
stride(dim + 2),
|
||||
encoding(_encoding),
|
||||
image({static_cast<uint32_t>(stride), static_cast<uint32_t>(stride)}) {
|
||||
encoding(_encoding) {
|
||||
image = std::make_shared<PremultipliedImage>(Size(static_cast<uint32_t>(stride), static_cast<uint32_t>(stride)));
|
||||
if (_image.size.height != _image.size.width) {
|
||||
throw std::runtime_error("raster-dem tiles must be square.");
|
||||
}
|
||||
|
||||
auto* dest = reinterpret_cast<uint32_t*>(image.data.get()) + stride + 1;
|
||||
auto* dest = reinterpret_cast<uint32_t*>(image->data.get()) + stride + 1;
|
||||
auto* source = reinterpret_cast<uint32_t*>(_image.data.get());
|
||||
for (int32_t y = 0; y < dim; y++) {
|
||||
memcpy(dest, source, dim * 4);
|
||||
@@ -27,7 +27,7 @@ DEMData::DEMData(const PremultipliedImage& _image, Tileset::DEMEncoding _encodin
|
||||
// tile's neighboring tiles are loaded and the accurate data can be
|
||||
// backfilled using DEMData#backfillBorder
|
||||
|
||||
auto* data = reinterpret_cast<uint32_t*>(image.data.get());
|
||||
auto* data = reinterpret_cast<uint32_t*>(image->data.get());
|
||||
for (int32_t x = 0; x < dim; x++) {
|
||||
auto rowOffset = stride * (x + 1);
|
||||
// left vertical border
|
||||
@@ -77,8 +77,8 @@ void DEMData::backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy
|
||||
int32_t ox = -dx * dim;
|
||||
int32_t oy = -dy * dim;
|
||||
|
||||
auto* dest = reinterpret_cast<uint32_t*>(image.data.get());
|
||||
auto* source = reinterpret_cast<uint32_t*>(o.image.data.get());
|
||||
auto* dest = reinterpret_cast<uint32_t*>(image->data.get());
|
||||
auto* source = reinterpret_cast<uint32_t*>(o.image->data.get());
|
||||
|
||||
for (int32_t y = yMin; y < yMax; y++) {
|
||||
for (int32_t x = xMin; x < xMax; x++) {
|
||||
@@ -89,7 +89,7 @@ void DEMData::backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy
|
||||
|
||||
int32_t DEMData::get(const int32_t x, const int32_t y) const {
|
||||
const auto& unpack = getUnpackVector();
|
||||
const uint8_t* value = image.data.get() + idx(x, y) * 4;
|
||||
const uint8_t* value = image->data.get() + idx(x, y) * 4;
|
||||
return static_cast<int32_t>(value[0] * unpack[0] + value[1] * unpack[1] + value[2] * unpack[2] - unpack[3]);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,15 @@ public:
|
||||
int32_t get(int32_t x, int32_t y) const;
|
||||
const std::array<float, 4>& getUnpackVector() const;
|
||||
|
||||
const PremultipliedImage* getImage() const { return ℑ }
|
||||
const PremultipliedImage* getImage() const { return &*image; }
|
||||
const std::shared_ptr<PremultipliedImage>& getImagePtr() const { return image; }
|
||||
|
||||
const int32_t dim;
|
||||
const int32_t stride;
|
||||
const Tileset::DEMEncoding encoding;
|
||||
|
||||
private:
|
||||
Tileset::DEMEncoding encoding;
|
||||
PremultipliedImage image;
|
||||
std::shared_ptr<PremultipliedImage> image;
|
||||
|
||||
size_t idx(const int32_t x, const int32_t y) const {
|
||||
assert(x >= -1);
|
||||
|
||||
27
src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
Normal file
27
src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/drawable_data.hpp>
|
||||
#include <mbgl/util/tileset.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class HillshadePrepareDrawableData : public DrawableData {
|
||||
public:
|
||||
HillshadePrepareDrawableData(int32_t stride_, Tileset::DEMEncoding encoding_, uint8_t maxzoom_)
|
||||
: stride(stride_),
|
||||
encoding(encoding_),
|
||||
maxzoom(maxzoom_) {}
|
||||
|
||||
int32_t stride;
|
||||
Tileset::DEMEncoding encoding;
|
||||
uint8_t maxzoom;
|
||||
};
|
||||
|
||||
using UniqueHillshadePrepareDrawableData = std::unique_ptr<HillshadePrepareDrawableData>;
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
@@ -108,6 +108,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
|
||||
shaders::BuiltIn::FillExtrusionPatternShader,
|
||||
shaders::BuiltIn::HeatmapShader,
|
||||
shaders::BuiltIn::HeatmapTextureShader,
|
||||
shaders::BuiltIn::HillshadePrepareShader,
|
||||
shaders::BuiltIn::HillshadeShader,
|
||||
shaders::BuiltIn::RasterShader,
|
||||
shaders::BuiltIn::SymbolIconShader,
|
||||
shaders::BuiltIn::SymbolSDFTextShader,
|
||||
|
||||
@@ -14,7 +14,9 @@ HillshadeBucket::HillshadeBucket(PremultipliedImage&& image_, Tileset::DEMEncodi
|
||||
HillshadeBucket::HillshadeBucket(DEMData&& demdata_)
|
||||
: demdata(std::move(demdata_)) {}
|
||||
|
||||
HillshadeBucket::~HillshadeBucket() = default;
|
||||
HillshadeBucket::~HillshadeBucket() {
|
||||
sharedVertices->release();
|
||||
}
|
||||
|
||||
const DEMData& HillshadeBucket::getDEMData() const {
|
||||
return demdata;
|
||||
|
||||
@@ -30,6 +30,11 @@ public:
|
||||
std::optional<gfx::Texture> dem;
|
||||
std::optional<gfx::Texture> texture;
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
RenderTargetPtr renderTarget;
|
||||
bool renderTargetPrepared = false;
|
||||
#endif
|
||||
|
||||
TileMask mask{{0, 0, 0}};
|
||||
|
||||
const DEMData& getDEMData() const;
|
||||
@@ -40,7 +45,10 @@ public:
|
||||
void setPrepared(bool preparedState) { prepared = preparedState; }
|
||||
|
||||
// Raster-DEM Tile Sources use the default buffers from Painter
|
||||
gfx::VertexVector<HillshadeLayoutVertex> vertices;
|
||||
using VertexVector = gfx::VertexVector<HillshadeLayoutVertex>;
|
||||
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
|
||||
VertexVector& vertices = *sharedVertices;
|
||||
|
||||
gfx::IndexVector<gfx::Triangles> indices;
|
||||
SegmentVector<HillshadeAttributes> segments;
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ void AddRenderTargetRequest::execute(RenderOrchestrator &orchestrator) {
|
||||
orchestrator.addRenderTarget(std::move(renderTarget));
|
||||
}
|
||||
|
||||
RemoveRenderTargetRequest::RemoveRenderTargetRequest(const RenderTargetPtr &renderTarget_)
|
||||
: renderTarget(renderTarget_) {}
|
||||
RemoveRenderTargetRequest::RemoveRenderTargetRequest(RenderTargetPtr renderTarget_)
|
||||
: renderTarget(std::move(renderTarget_)) {}
|
||||
|
||||
void RemoveRenderTargetRequest::execute(RenderOrchestrator &orchestrator) {
|
||||
orchestrator.removeRenderTarget(renderTarget);
|
||||
|
||||
@@ -17,14 +17,17 @@ mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID,
|
||||
const std::array<float, 2>& translation,
|
||||
style::TranslateAnchorType anchor,
|
||||
bool nearClipped,
|
||||
bool inViewportPixelUnits) {
|
||||
bool inViewportPixelUnits,
|
||||
bool aligned) {
|
||||
// from RenderTile::prepare
|
||||
mat4 tileMatrix;
|
||||
state.matrixFor(/*out*/ tileMatrix, tileID);
|
||||
|
||||
const auto& transformParams = renderTree.getParameters().transformParams;
|
||||
// nearClippedMatrix has near plane moved further, to enhance depth buffer precision
|
||||
const auto& params = renderTree.getParameters().transformParams;
|
||||
const auto& projMatrix = nearClipped ? params.nearClippedProjMatrix : params.projMatrix;
|
||||
const auto& projMatrix = aligned
|
||||
? transformParams.alignedProjMatrix
|
||||
: (nearClipped ? transformParams.nearClippedProjMatrix : transformParams.projMatrix);
|
||||
matrix::multiply(tileMatrix, projMatrix, tileMatrix);
|
||||
|
||||
return RenderTile::translateVtxMatrix(tileID, tileMatrix, translation, anchor, state, inViewportPixelUnits);
|
||||
|
||||
@@ -18,7 +18,6 @@ public:
|
||||
void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
gfx::UniformBufferPtr paintParamsUniformBuffer;
|
||||
gfx::UniformBufferPtr evaluatedPropsUniformBuffer;
|
||||
};
|
||||
|
||||
|
||||
85
src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp
Normal file
85
src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <mbgl/renderer/layers/hillshade_layer_tweaker.hpp>
|
||||
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
struct alignas(16) HillshadeDrawableUBO {
|
||||
std::array<float, 4 * 4> matrix;
|
||||
std::array<float, 2> latrange;
|
||||
std::array<float, 2> light;
|
||||
};
|
||||
static_assert(sizeof(HillshadeDrawableUBO) % 16 == 0);
|
||||
|
||||
struct alignas(16) HillshadeEvaluatedPropsUBO {
|
||||
Color highlight;
|
||||
Color shadow;
|
||||
Color accent;
|
||||
};
|
||||
static_assert(sizeof(HillshadeEvaluatedPropsUBO) % 16 == 0);
|
||||
|
||||
static constexpr std::string_view HillshadeDrawableUBOName = "HillshadeDrawableUBO";
|
||||
static constexpr std::string_view HillshadeEvaluatedPropsUBOName = "HillshadeEvaluatedPropsUBO";
|
||||
|
||||
std::array<float, 2> getLatRange(const UnwrappedTileID& id) {
|
||||
const LatLng latlng0 = LatLng(id);
|
||||
const LatLng latlng1 = LatLng(UnwrappedTileID(id.canonical.z, id.canonical.x, id.canonical.y + 1));
|
||||
return {{static_cast<float>(latlng0.latitude()), static_cast<float>(latlng1.latitude())}};
|
||||
}
|
||||
|
||||
std::array<float, 2> getLight(const PaintParameters& parameters,
|
||||
const HillshadePaintProperties::PossiblyEvaluated& evaluated) {
|
||||
float azimuthal = util::deg2radf(evaluated.get<HillshadeIlluminationDirection>());
|
||||
if (evaluated.get<HillshadeIlluminationAnchor>() == HillshadeIlluminationAnchorType::Viewport)
|
||||
azimuthal = azimuthal - static_cast<float>(parameters.state.getBearing());
|
||||
return {{evaluated.get<HillshadeExaggeration>(), azimuthal}};
|
||||
}
|
||||
|
||||
void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
const RenderTree& renderTree,
|
||||
const PaintParameters& parameters) {
|
||||
const auto& evaluated = static_cast<const HillshadeLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
|
||||
if (layerGroup.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
const auto label = layerGroup.getName() + "-update-uniforms";
|
||||
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
|
||||
#endif
|
||||
|
||||
if (!evaluatedPropsUniformBuffer) {
|
||||
HillshadeEvaluatedPropsUBO evaluatedPropsUBO = {/* .highlight = */ evaluated.get<HillshadeHighlightColor>(),
|
||||
/* .shadow = */ evaluated.get<HillshadeShadowColor>(),
|
||||
/* .accent = */ evaluated.get<HillshadeAccentColor>()};
|
||||
evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO,
|
||||
sizeof(evaluatedPropsUBO));
|
||||
}
|
||||
|
||||
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
|
||||
drawable.mutableUniformBuffers().addOrReplace(HillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer);
|
||||
|
||||
if (!drawable.getTileID()) {
|
||||
return;
|
||||
}
|
||||
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
|
||||
const auto matrix = getTileMatrix(
|
||||
tileID, renderTree, parameters.state, {0.f, 0.f}, TranslateAnchorType::Viewport, false, false, true);
|
||||
HillshadeDrawableUBO drawableUBO = {/* .matrix = */ util::cast<float>(matrix),
|
||||
/* .latrange = */ getLatRange(tileID),
|
||||
/* .light = */ getLight(parameters, evaluated)};
|
||||
|
||||
drawable.mutableUniformBuffers().createOrUpdate(HillshadeDrawableUBOName, &drawableUBO, parameters.context);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
24
src/mbgl/renderer/layers/hillshade_layer_tweaker.hpp
Normal file
24
src/mbgl/renderer/layers/hillshade_layer_tweaker.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
Hillshade layer specific tweaker
|
||||
*/
|
||||
class HillshadeLayerTweaker : public LayerTweaker {
|
||||
public:
|
||||
HillshadeLayerTweaker(Immutable<style::LayerProperties> properties)
|
||||
: LayerTweaker(properties){};
|
||||
|
||||
public:
|
||||
~HillshadeLayerTweaker() override = default;
|
||||
|
||||
void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
gfx::UniformBufferPtr evaluatedPropsUniformBuffer;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
73
src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp
Normal file
73
src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#include <mbgl/renderer/layers/hillshade_prepare_layer_tweaker.hpp>
|
||||
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/hillshade_prepare_drawable_data.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
struct alignas(16) HillshadePrepareDrawableUBO {
|
||||
std::array<float, 4 * 4> matrix;
|
||||
std::array<float, 4> unpack;
|
||||
std::array<float, 2> dimension;
|
||||
float zoom;
|
||||
float maxzoom;
|
||||
};
|
||||
static_assert(sizeof(HillshadePrepareDrawableUBO) % 16 == 0);
|
||||
|
||||
static constexpr std::string_view HillshadePrepareDrawableUBOName = "HillshadePrepareDrawableUBO";
|
||||
|
||||
const std::array<float, 4>& getUnpackVector(Tileset::DEMEncoding encoding) {
|
||||
// https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb
|
||||
static const std::array<float, 4> unpackMapbox = {{6553.6f, 25.6f, 0.1f, 10000.0f}};
|
||||
// https://aws.amazon.com/public-datasets/terrain/
|
||||
static const std::array<float, 4> unpackTerrarium = {{256.0f, 1.0f, 1.0f / 256.0f, 32768.0f}};
|
||||
|
||||
return encoding == Tileset::DEMEncoding::Terrarium ? unpackTerrarium : unpackMapbox;
|
||||
}
|
||||
|
||||
void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
const PaintParameters& parameters) {
|
||||
// const auto& evaluated = static_cast<const HillshadeLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
|
||||
if (layerGroup.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
const auto label = layerGroup.getName() + "-update-uniforms";
|
||||
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
|
||||
#endif
|
||||
|
||||
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
|
||||
if (!drawable.getTileID() || !drawable.getData()) {
|
||||
return;
|
||||
}
|
||||
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
|
||||
const auto& drawableData = static_cast<const gfx::HillshadePrepareDrawableData&>(*drawable.getData());
|
||||
|
||||
mat4 matrix;
|
||||
matrix::ortho(matrix, 0, util::EXTENT, -util::EXTENT, 0, 0, 1);
|
||||
matrix::translate(matrix, matrix, 0, -util::EXTENT, 0);
|
||||
|
||||
HillshadePrepareDrawableUBO drawableUBO = {
|
||||
/* .matrix = */ util::cast<float>(matrix),
|
||||
/* .unpack = */ getUnpackVector(drawableData.encoding),
|
||||
/* .dimension = */ {static_cast<float>(drawableData.stride), static_cast<float>(drawableData.stride)},
|
||||
/* .zoom = */ static_cast<float>(tileID.canonical.z),
|
||||
/* .maxzoom = */ static_cast<float>(drawableData.maxzoom)};
|
||||
|
||||
drawable.mutableUniformBuffers().createOrUpdate(
|
||||
HillshadePrepareDrawableUBOName, &drawableUBO, parameters.context);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
23
src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.hpp
Normal file
23
src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
Hillshade prepare layer specific tweaker
|
||||
*/
|
||||
class HillshadePrepareLayerTweaker : public LayerTweaker {
|
||||
public:
|
||||
HillshadePrepareLayerTweaker(Immutable<style::LayerProperties> properties)
|
||||
: LayerTweaker(properties){};
|
||||
|
||||
public:
|
||||
~HillshadePrepareLayerTweaker() override = default;
|
||||
|
||||
void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -237,6 +237,7 @@ bool RenderHeatmapLayer::queryIntersectsFeature(const GeometryCoordinates& query
|
||||
}
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
namespace {
|
||||
void activateRenderTarget(const RenderTargetPtr& renderTarget_, bool activate, UniqueChangeRequestVec& changes) {
|
||||
if (renderTarget_) {
|
||||
if (activate) {
|
||||
@@ -248,6 +249,7 @@ void activateRenderTarget(const RenderTargetPtr& renderTarget_, bool activate, U
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void RenderHeatmapLayer::markLayerRenderable(bool willRender, UniqueChangeRequestVec& changes) {
|
||||
RenderLayer::markLayerRenderable(willRender, changes);
|
||||
@@ -287,7 +289,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
const TransformState& state,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
[[maybe_unused]] UniqueChangeRequestVec& changes) {
|
||||
UniqueChangeRequestVec& changes) {
|
||||
std::unique_lock<std::mutex> guard(mutex);
|
||||
|
||||
if (!renderTiles || renderTiles->empty()) {
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/programs/programs.hpp>
|
||||
#include <mbgl/programs/hillshade_program.hpp>
|
||||
#include <mbgl/programs/hillshade_prepare_program.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer_impl.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
@@ -15,6 +13,19 @@
|
||||
#include <mbgl/math/angles.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
#include <mbgl/renderer/layers/hillshade_layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/layers/hillshade_prepare_layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/render_target.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/gfx/drawable_impl.hpp>
|
||||
#include <mbgl/gfx/hillshade_prepare_drawable_data.hpp>
|
||||
#include <mbgl/gfx/shader_group.hpp>
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
@@ -60,6 +71,11 @@ void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& paramete
|
||||
: RenderPass::None;
|
||||
properties->renderPasses = mbgl::underlying_type(passes);
|
||||
evaluatedProperties = std::move(properties);
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
if (layerGroup) {
|
||||
layerGroup->setLayerTweaker(std::make_shared<HillshadeLayerTweaker>(evaluatedProperties));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RenderHillshadeLayer::hasTransition() const {
|
||||
@@ -73,6 +89,10 @@ bool RenderHillshadeLayer::hasCrossfade() const {
|
||||
void RenderHillshadeLayer::prepare(const LayerPrepareParameters& params) {
|
||||
renderTiles = params.source->getRenderTiles();
|
||||
maxzoom = params.source->getMaxZoom();
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
updateRenderTileIDs();
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
}
|
||||
|
||||
#if MLN_LEGACY_RENDERER
|
||||
@@ -221,4 +241,267 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) {
|
||||
}
|
||||
#endif // MLN_LEGACY_RENDERER
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
namespace {
|
||||
void activateRenderTarget(const RenderTargetPtr& renderTarget_, bool activate, UniqueChangeRequestVec& changes) {
|
||||
if (renderTarget_) {
|
||||
if (activate) {
|
||||
// The RenderTree has determined this render target should be included in the renderable set for a frame
|
||||
changes.emplace_back(std::make_unique<AddRenderTargetRequest>(renderTarget_));
|
||||
} else {
|
||||
// The RenderTree is informing us we should not render anything
|
||||
changes.emplace_back(std::make_unique<RemoveRenderTargetRequest>(renderTarget_));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void RenderHillshadeLayer::markLayerRenderable(bool willRender, UniqueChangeRequestVec& changes) {
|
||||
RenderLayer::markLayerRenderable(willRender, changes);
|
||||
removeRenderTargets(changes);
|
||||
}
|
||||
|
||||
void RenderHillshadeLayer::layerRemoved(UniqueChangeRequestVec& changes) {
|
||||
RenderLayer::layerRemoved(changes);
|
||||
removeRenderTargets(changes);
|
||||
}
|
||||
|
||||
void RenderHillshadeLayer::addRenderTarget(const RenderTargetPtr& renderTarget, UniqueChangeRequestVec& changes) {
|
||||
activateRenderTarget(renderTarget, true, changes);
|
||||
activatedRenderTargets.emplace_back(renderTarget);
|
||||
}
|
||||
|
||||
void RenderHillshadeLayer::removeRenderTargets(UniqueChangeRequestVec& changes) {
|
||||
for (const auto& renderTarget : activatedRenderTargets) {
|
||||
activateRenderTarget(renderTarget, false, changes);
|
||||
}
|
||||
activatedRenderTargets.clear();
|
||||
}
|
||||
|
||||
static const std::string HillshadePrepareShaderGroupName = "HillshadePrepareShader";
|
||||
static const std::string HillshadeShaderGroupName = "HillshadeShader";
|
||||
|
||||
constexpr auto PosAttribName = "a_pos";
|
||||
constexpr auto TexturePosAttribName = "a_texture_pos";
|
||||
|
||||
void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
[[maybe_unused]] const TransformState& state,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
UniqueChangeRequestVec& changes) {
|
||||
std::unique_lock<std::mutex> guard(mutex);
|
||||
|
||||
if (!renderTiles || renderTiles->empty()) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up a layer group
|
||||
if (!layerGroup) {
|
||||
auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID());
|
||||
if (!layerGroup_) {
|
||||
return;
|
||||
}
|
||||
layerGroup_->setLayerTweaker(std::make_shared<HillshadeLayerTweaker>(evaluatedProperties));
|
||||
setLayerGroup(std::move(layerGroup_), changes);
|
||||
}
|
||||
|
||||
auto* tileLayerGroup = static_cast<TileLayerGroup*>(layerGroup.get());
|
||||
|
||||
if (!hillshadePrepareShader) {
|
||||
hillshadePrepareShader = context.getGenericShader(shaders, HillshadePrepareShaderGroupName);
|
||||
}
|
||||
if (!hillshadeShader) {
|
||||
hillshadeShader = context.getGenericShader(shaders, HillshadeShaderGroupName);
|
||||
}
|
||||
if (!hillshadePrepareShader || !hillshadeShader) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
auto renderPass = RenderPass::Translucent;
|
||||
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
|
||||
return;
|
||||
}
|
||||
|
||||
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
|
||||
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
|
||||
});
|
||||
|
||||
if (!staticDataSharedVertices) {
|
||||
staticDataSharedVertices = std::make_shared<HillshadeVertexVector>(RenderStaticData::rasterVertices());
|
||||
}
|
||||
const auto staticDataIndices = RenderStaticData::quadTriangleIndices();
|
||||
const auto staticDataSegments = RenderStaticData::rasterSegments();
|
||||
|
||||
std::unique_ptr<gfx::DrawableBuilder> hillshadeBuilder;
|
||||
std::unique_ptr<gfx::DrawableBuilder> hillshadePrepareBuilder;
|
||||
|
||||
for (const RenderTile& tile : *renderTiles) {
|
||||
const auto& tileID = tile.getOverscaledTileID();
|
||||
|
||||
auto* bucket_ = tile.getBucket(*baseImpl);
|
||||
if (!bucket_) {
|
||||
removeTile(renderPass, tileID);
|
||||
continue;
|
||||
}
|
||||
auto& bucket = static_cast<HillshadeBucket&>(*bucket_);
|
||||
|
||||
if (!bucket.hasData()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!bucket.renderTargetPrepared) {
|
||||
// Set up tile render target
|
||||
const uint16_t tilesize = bucket.getDEMData().dim;
|
||||
auto renderTarget = context.createRenderTarget({tilesize, tilesize},
|
||||
gfx::TextureChannelDataType::UnsignedByte);
|
||||
if (!renderTarget) {
|
||||
continue;
|
||||
}
|
||||
bucket.renderTarget = renderTarget;
|
||||
bucket.renderTargetPrepared = true;
|
||||
addRenderTarget(renderTarget, changes);
|
||||
|
||||
auto singleTileLayerGroup = context.createTileLayerGroup(0, /*initialCapacity=*/1, getID());
|
||||
if (!singleTileLayerGroup) {
|
||||
return;
|
||||
}
|
||||
singleTileLayerGroup->setLayerTweaker(std::make_shared<HillshadePrepareLayerTweaker>(evaluatedProperties));
|
||||
renderTarget->addLayerGroup(singleTileLayerGroup, /*replace=*/true);
|
||||
|
||||
gfx::VertexAttributeArray hillshadePrepareVertexAttrs;
|
||||
|
||||
if (const auto& attr = hillshadePrepareVertexAttrs.add(PosAttribName)) {
|
||||
attr->setSharedRawData(staticDataSharedVertices,
|
||||
offsetof(HillshadeLayoutVertex, a1),
|
||||
0,
|
||||
sizeof(HillshadeLayoutVertex),
|
||||
gfx::AttributeDataType::Short2);
|
||||
}
|
||||
if (const auto& attr = hillshadePrepareVertexAttrs.getOrAdd(TexturePosAttribName)) {
|
||||
attr->setSharedRawData(staticDataSharedVertices,
|
||||
offsetof(HillshadeLayoutVertex, a2),
|
||||
0,
|
||||
sizeof(HillshadeLayoutVertex),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
|
||||
hillshadePrepareBuilder = context.createDrawableBuilder("hillshadePrepare");
|
||||
hillshadePrepareBuilder->setShader(hillshadePrepareShader);
|
||||
hillshadePrepareBuilder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
hillshadePrepareBuilder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
hillshadePrepareBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
|
||||
hillshadePrepareBuilder->setRenderPass(renderPass);
|
||||
hillshadePrepareBuilder->setVertexAttributes(std::move(hillshadePrepareVertexAttrs));
|
||||
hillshadePrepareBuilder->setRawVertices(
|
||||
{}, staticDataSharedVertices->elements(), gfx::AttributeDataType::Short2);
|
||||
hillshadePrepareBuilder->setSegments(
|
||||
gfx::Triangles(), staticDataIndices.vector(), staticDataSegments.data(), staticDataSegments.size());
|
||||
|
||||
auto imageLocation = hillshadePrepareShader->getSamplerLocation("u_image");
|
||||
if (imageLocation.has_value()) {
|
||||
std::shared_ptr<gfx::Texture2D> texture = context.createTexture2D();
|
||||
texture->setImage(bucket.getDEMData().getImagePtr());
|
||||
texture->setSamplerConfiguration(
|
||||
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
|
||||
hillshadePrepareBuilder->setTexture(texture, imageLocation.value());
|
||||
}
|
||||
|
||||
hillshadePrepareBuilder->flush();
|
||||
|
||||
for (auto& drawable : hillshadePrepareBuilder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
drawable->setData(std::make_unique<gfx::HillshadePrepareDrawableData>(
|
||||
bucket.getDEMData().stride, bucket.getDEMData().encoding, maxzoom));
|
||||
singleTileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.drawablesAdded;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up tile drawable
|
||||
auto vertices = staticDataSharedVertices;
|
||||
auto* indices = &staticDataIndices;
|
||||
auto* segments = &staticDataSegments;
|
||||
|
||||
if (!bucket.vertices.empty() && !bucket.indices.empty() && !bucket.segments.empty()) {
|
||||
vertices = bucket.sharedVertices;
|
||||
indices = &bucket.indices;
|
||||
segments = &bucket.segments;
|
||||
}
|
||||
|
||||
gfx::VertexAttributeArray hillshadeVertexAttrs;
|
||||
|
||||
if (const auto& attr = hillshadeVertexAttrs.add(PosAttribName)) {
|
||||
attr->setSharedRawData(vertices,
|
||||
offsetof(HillshadeLayoutVertex, a1),
|
||||
0,
|
||||
sizeof(HillshadeLayoutVertex),
|
||||
gfx::AttributeDataType::Short2);
|
||||
}
|
||||
if (const auto& attr = hillshadeVertexAttrs.getOrAdd(TexturePosAttribName)) {
|
||||
attr->setSharedRawData(vertices,
|
||||
offsetof(HillshadeLayoutVertex, a2),
|
||||
0,
|
||||
sizeof(HillshadeLayoutVertex),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
|
||||
hillshadeBuilder = context.createDrawableBuilder("hillshade");
|
||||
|
||||
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
|
||||
tileLayerGroup->observeDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) {
|
||||
drawable.setVertexAttributes(std::move(hillshadeVertexAttrs));
|
||||
drawable.setVertices({}, vertices->elements(), gfx::AttributeDataType::Short2);
|
||||
|
||||
std::vector<std::unique_ptr<gfx::Drawable::DrawSegment>> drawSegments;
|
||||
for (std::size_t i = 0; i < segments->size(); ++i) {
|
||||
const auto& seg = segments->data()[i];
|
||||
auto segCopy = SegmentBase{
|
||||
// no copy constructor
|
||||
seg.vertexOffset,
|
||||
seg.indexOffset,
|
||||
seg.vertexLength,
|
||||
seg.indexLength,
|
||||
seg.sortKey,
|
||||
};
|
||||
drawSegments.emplace_back(hillshadeBuilder->createSegment(gfx::Triangles(), std::move(segCopy)));
|
||||
}
|
||||
drawable.setIndexData(std::move(indices->vector()), std::move(drawSegments));
|
||||
|
||||
auto imageLocation = hillshadeShader->getSamplerLocation("u_image");
|
||||
if (imageLocation.has_value()) {
|
||||
drawable.setTexture(bucket.renderTarget->getTexture(), imageLocation.value());
|
||||
}
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
hillshadeBuilder->setShader(hillshadeShader);
|
||||
hillshadeBuilder->setDepthType(gfx::DepthMaskType::ReadOnly);
|
||||
hillshadeBuilder->setColorMode(gfx::ColorMode::alphaBlended());
|
||||
hillshadeBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
|
||||
hillshadeBuilder->setRenderPass(renderPass);
|
||||
hillshadeBuilder->setVertexAttributes(std::move(hillshadeVertexAttrs));
|
||||
hillshadeBuilder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2);
|
||||
hillshadeBuilder->setSegments(gfx::Triangles(), indices->vector(), segments->data(), segments->size());
|
||||
|
||||
auto imageLocation = hillshadeShader->getSamplerLocation("u_image");
|
||||
if (imageLocation.has_value()) {
|
||||
hillshadeBuilder->setTexture(bucket.renderTarget->getTexture(), imageLocation.value());
|
||||
}
|
||||
|
||||
hillshadeBuilder->flush();
|
||||
|
||||
for (auto& drawable : hillshadeBuilder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.drawablesAdded;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/render_layer.hpp>
|
||||
#include <mbgl/programs/hillshade_program.hpp>
|
||||
#include <mbgl/programs/hillshade_prepare_program.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer_impl.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer_properties.hpp>
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
@@ -15,6 +17,19 @@ public:
|
||||
explicit RenderHillshadeLayer(Immutable<style::HillshadeLayer::Impl>);
|
||||
~RenderHillshadeLayer() override;
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
void markLayerRenderable(bool willRender, UniqueChangeRequestVec& changes) override;
|
||||
|
||||
void layerRemoved(UniqueChangeRequestVec&) override;
|
||||
|
||||
/// Generate any changes needed by the layer
|
||||
void update(gfx::ShaderRegistry&,
|
||||
gfx::Context&,
|
||||
const TransformState&,
|
||||
const RenderTree&,
|
||||
UniqueChangeRequestVec&) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void transition(const TransitionParameters&) override;
|
||||
void evaluate(const PropertyEvaluationParameters&) override;
|
||||
@@ -27,6 +42,11 @@ private:
|
||||
|
||||
void prepare(const LayerPrepareParameters&) override;
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
void addRenderTarget(const RenderTargetPtr&, UniqueChangeRequestVec&);
|
||||
void removeRenderTargets(UniqueChangeRequestVec&);
|
||||
#endif
|
||||
|
||||
// Paint properties
|
||||
style::HillshadePaintProperties::Unevaluated unevaluated;
|
||||
uint8_t maxzoom = util::TERRAIN_RGB_MAXZOOM;
|
||||
@@ -39,6 +59,15 @@ private:
|
||||
std::shared_ptr<HillshadeProgram> hillshadeProgram;
|
||||
std::shared_ptr<HillshadePrepareProgram> hillshadePrepareProgram;
|
||||
#endif
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
gfx::ShaderProgramBasePtr hillshadePrepareShader;
|
||||
gfx::ShaderProgramBasePtr hillshadeShader;
|
||||
std::vector<RenderTargetPtr> activatedRenderTargets;
|
||||
|
||||
using HillshadeVertexVector = gfx::VertexVector<HillshadeLayoutVertex>;
|
||||
std::shared_ptr<HillshadeVertexVector> staticDataSharedVertices;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -105,6 +105,9 @@ void RasterDEMTile::backfillBorder(const RasterDEMTile& borderTile, const DEMTil
|
||||
// mark HillshadeBucket.prepared as false so it runs through the prepare
|
||||
// render pass with the new texture data we just backfilled
|
||||
bucket->setPrepared(false);
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
bucket->renderTargetPrepared = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user