Co-authored-by: Bart Louwers <bart@emeel.net> 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
326f669568
commit
7f33ddfef4
@@ -530,6 +530,8 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/circle_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_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/render_background_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_circle_layer.cpp
|
||||
@@ -946,6 +948,7 @@ if(MLN_WITH_OPENGL)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline_pattern.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_pattern.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_raster.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background_pattern.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/circle.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/clipping_mask.hpp
|
||||
|
||||
@@ -60,6 +60,8 @@ protected:
|
||||
DrawableGL(std::unique_ptr<Impl>);
|
||||
|
||||
private:
|
||||
void uploadTextures() const;
|
||||
|
||||
void bindUniformBuffers() const;
|
||||
void unbindUniformBuffers() const;
|
||||
|
||||
|
||||
107
include/mbgl/shaders/gl/drawable_raster.hpp
Normal file
107
include/mbgl/shaders/gl/drawable_raster.hpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// Generated code, do not modify this file!
|
||||
#pragma once
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::RasterShader, gfx::Backend::Type::OpenGL> {
|
||||
static constexpr const char* name = "RasterShader";
|
||||
static constexpr const char* vertex = R"(layout (std140) uniform RasterDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec3 u_spin_weights;
|
||||
highp vec2 u_tl_parent;
|
||||
highp float u_scale_parent;
|
||||
highp float u_buffer_scale;
|
||||
highp float u_fade_t;
|
||||
highp float u_opacity;
|
||||
highp float u_brightness_low;
|
||||
highp float u_brightness_high;
|
||||
highp float u_saturation_factor;
|
||||
highp float u_contrast_factor;
|
||||
highp float pad1;
|
||||
highp float pad2;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
layout (location = 1) in vec2 a_texture_pos;
|
||||
|
||||
out vec2 v_pos0;
|
||||
out vec2 v_pos1;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
// We are using Int16 for texture position coordinates to give us enough precision for
|
||||
// fractional coordinates. We use 8192 to scale the texture coordinates in the buffer
|
||||
// as an arbitrarily high number to preserve adequate precision when rendering.
|
||||
// This is also the same value as the EXTENT we are using for our tile buffer pos coordinates,
|
||||
// so math for modifying either is consistent.
|
||||
v_pos0 = (((a_texture_pos / 8192.0) - 0.5) / u_buffer_scale ) + 0.5;
|
||||
v_pos1 = (v_pos0 * u_scale_parent) + u_tl_parent;
|
||||
}
|
||||
)";
|
||||
static constexpr const char* fragment = R"(layout (std140) uniform RasterDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec3 u_spin_weights;
|
||||
highp vec2 u_tl_parent;
|
||||
highp float u_scale_parent;
|
||||
highp float u_buffer_scale;
|
||||
highp float u_fade_t;
|
||||
highp float u_opacity;
|
||||
highp float u_brightness_low;
|
||||
highp float u_brightness_high;
|
||||
highp float u_saturation_factor;
|
||||
highp float u_contrast_factor;
|
||||
highp float pad1;
|
||||
highp float pad2;
|
||||
};
|
||||
uniform sampler2D u_image0;
|
||||
uniform sampler2D u_image1;
|
||||
|
||||
in vec2 v_pos0;
|
||||
in vec2 v_pos1;
|
||||
|
||||
void main() {
|
||||
|
||||
// read and cross-fade colors from the main and parent tiles
|
||||
vec4 color0 = texture(u_image0, v_pos0);
|
||||
vec4 color1 = texture(u_image1, v_pos1);
|
||||
if (color0.a > 0.0) {
|
||||
color0.rgb = color0.rgb / color0.a;
|
||||
}
|
||||
if (color1.a > 0.0) {
|
||||
color1.rgb = color1.rgb / color1.a;
|
||||
}
|
||||
vec4 color = mix(color0, color1, u_fade_t);
|
||||
color.a *= u_opacity;
|
||||
vec3 rgb = color.rgb;
|
||||
|
||||
// spin
|
||||
rgb = vec3(
|
||||
dot(rgb, u_spin_weights.xyz),
|
||||
dot(rgb, u_spin_weights.zxy),
|
||||
dot(rgb, u_spin_weights.yzx));
|
||||
|
||||
// saturation
|
||||
float average = (color.r + color.g + color.b) / 3.0;
|
||||
rgb += (average - rgb) * u_saturation_factor;
|
||||
|
||||
// contrast
|
||||
rgb = (rgb - 0.5) * u_contrast_factor + 0.5;
|
||||
|
||||
// brightness
|
||||
vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low);
|
||||
vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high);
|
||||
|
||||
fragColor = vec4(mix(u_high_vec, u_low_vec, rgb) * color.a, color.a);
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -28,6 +28,8 @@ public:
|
||||
const std::string& fragmentSource,
|
||||
const std::string& additionalDefines = "") noexcept(false);
|
||||
|
||||
std::optional<uint32_t> getSamplerLocation(const std::string& name) const override;
|
||||
|
||||
const gfx::UniformBlockArray& getUniformBlocks() const override { return uniformBlocks; }
|
||||
|
||||
const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; }
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mbgl/shaders/gl/drawable_fill_outline.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_fill_pattern.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_fill_outline_pattern.hpp>
|
||||
#include <mbgl/shaders/gl/drawable_raster.hpp>
|
||||
#include <mbgl/shaders/gl/prelude.hpp>
|
||||
#include <mbgl/shaders/gl/background.hpp>
|
||||
#include <mbgl/shaders/gl/background_pattern.hpp>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/util/identity.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
@@ -29,6 +30,10 @@ protected:
|
||||
public:
|
||||
const util::SimpleIdentity& getID() const { return shaderProgramID; }
|
||||
|
||||
/// @brief Gets the sampler location
|
||||
/// @param name uniform name
|
||||
virtual std::optional<uint32_t> getSamplerLocation(const std::string& name) const = 0;
|
||||
|
||||
/// Get the available uniform blocks attached to this shader
|
||||
virtual const gfx::UniformBlockArray& getUniformBlocks() const = 0;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ enum class BuiltIn {
|
||||
FillOutlineShader,
|
||||
FillPatternShader,
|
||||
FillOutlinePatternShader,
|
||||
RasterShader,
|
||||
Prelude,
|
||||
BackgroundProgram,
|
||||
BackgroundPatternProgram,
|
||||
|
||||
59
shaders/drawable.raster.fragment.glsl
Normal file
59
shaders/drawable.raster.fragment.glsl
Normal file
@@ -0,0 +1,59 @@
|
||||
layout (std140) uniform RasterDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec3 u_spin_weights;
|
||||
highp vec2 u_tl_parent;
|
||||
highp float u_scale_parent;
|
||||
highp float u_buffer_scale;
|
||||
highp float u_fade_t;
|
||||
highp float u_opacity;
|
||||
highp float u_brightness_low;
|
||||
highp float u_brightness_high;
|
||||
highp float u_saturation_factor;
|
||||
highp float u_contrast_factor;
|
||||
highp float pad1;
|
||||
highp float pad2;
|
||||
};
|
||||
uniform sampler2D u_image0;
|
||||
uniform sampler2D u_image1;
|
||||
|
||||
in vec2 v_pos0;
|
||||
in vec2 v_pos1;
|
||||
|
||||
void main() {
|
||||
|
||||
// read and cross-fade colors from the main and parent tiles
|
||||
vec4 color0 = texture(u_image0, v_pos0);
|
||||
vec4 color1 = texture(u_image1, v_pos1);
|
||||
if (color0.a > 0.0) {
|
||||
color0.rgb = color0.rgb / color0.a;
|
||||
}
|
||||
if (color1.a > 0.0) {
|
||||
color1.rgb = color1.rgb / color1.a;
|
||||
}
|
||||
vec4 color = mix(color0, color1, u_fade_t);
|
||||
color.a *= u_opacity;
|
||||
vec3 rgb = color.rgb;
|
||||
|
||||
// spin
|
||||
rgb = vec3(
|
||||
dot(rgb, u_spin_weights.xyz),
|
||||
dot(rgb, u_spin_weights.zxy),
|
||||
dot(rgb, u_spin_weights.yzx));
|
||||
|
||||
// saturation
|
||||
float average = (color.r + color.g + color.b) / 3.0;
|
||||
rgb += (average - rgb) * u_saturation_factor;
|
||||
|
||||
// contrast
|
||||
rgb = (rgb - 0.5) * u_contrast_factor + 0.5;
|
||||
|
||||
// brightness
|
||||
vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low);
|
||||
vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high);
|
||||
|
||||
fragColor = vec4(mix(u_high_vec, u_low_vec, rgb) * color.a, color.a);
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
fragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
32
shaders/drawable.raster.vertex.glsl
Normal file
32
shaders/drawable.raster.vertex.glsl
Normal file
@@ -0,0 +1,32 @@
|
||||
layout (std140) uniform RasterDrawableUBO {
|
||||
highp mat4 u_matrix;
|
||||
highp vec3 u_spin_weights;
|
||||
highp vec2 u_tl_parent;
|
||||
highp float u_scale_parent;
|
||||
highp float u_buffer_scale;
|
||||
highp float u_fade_t;
|
||||
highp float u_opacity;
|
||||
highp float u_brightness_low;
|
||||
highp float u_brightness_high;
|
||||
highp float u_saturation_factor;
|
||||
highp float u_contrast_factor;
|
||||
highp float pad1;
|
||||
highp float pad2;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 a_pos;
|
||||
layout (location = 1) in vec2 a_texture_pos;
|
||||
|
||||
out vec2 v_pos0;
|
||||
out vec2 v_pos1;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
// We are using Int16 for texture position coordinates to give us enough precision for
|
||||
// fractional coordinates. We use 8192 to scale the texture coordinates in the buffer
|
||||
// as an arbitrarily high number to preserve adequate precision when rendering.
|
||||
// This is also the same value as the EXTENT we are using for our tile buffer pos coordinates,
|
||||
// so math for modifying either is consistent.
|
||||
v_pos0 = (((a_texture_pos / 8192.0) - 0.5) / u_buffer_scale ) + 0.5;
|
||||
v_pos1 = (v_pos0 * u_scale_parent) + u_tl_parent;
|
||||
}
|
||||
@@ -48,6 +48,13 @@
|
||||
"glsl_frag": "drawable.fill_outline_pattern.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
{
|
||||
"name": "RasterShader",
|
||||
"header": "drawable_raster",
|
||||
"glsl_vert": "drawable.raster.vertex.glsl",
|
||||
"glsl_frag": "drawable.raster.fragment.glsl",
|
||||
"uses_ubos": true
|
||||
},
|
||||
|
||||
{
|
||||
"name": "Prelude",
|
||||
|
||||
@@ -178,6 +178,19 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) {
|
||||
glSeg.setVertexArray(std::move(vertexArray));
|
||||
};
|
||||
}
|
||||
|
||||
const bool texturesNeedUpload = std::any_of(
|
||||
textures.begin(), textures.end(), [](const auto& tex) { return tex.texture->needsUpload(); });
|
||||
|
||||
if (texturesNeedUpload) {
|
||||
uploadTextures();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableGL::uploadTextures() const {
|
||||
for (const auto& tex : textures) {
|
||||
std::static_pointer_cast<gl::Texture2D>(tex.texture)->upload();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableGL::bindTextures() const {
|
||||
|
||||
@@ -99,7 +99,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
|
||||
shaders::BuiltIn::FillShader,
|
||||
shaders::BuiltIn::FillOutlineShader,
|
||||
shaders::BuiltIn::FillOutlinePatternShader,
|
||||
shaders::BuiltIn::FillPatternShader>(shaders, static_cast<gl::Context&>(*context), programParameters);
|
||||
shaders::BuiltIn::FillPatternShader,
|
||||
shaders::BuiltIn::RasterShader>(shaders, static_cast<gl::Context&>(*context), programParameters);
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -148,6 +148,7 @@ void Texture2D::bind(int32_t location, int32_t textureUnit) noexcept {
|
||||
|
||||
// Link the bound texture unit with the requested sampler in the active shader
|
||||
glUniform1i(location, textureUnit);
|
||||
boundLocation = location;
|
||||
}
|
||||
|
||||
void Texture2D::unbind() noexcept {
|
||||
|
||||
86
src/mbgl/renderer/layers/raster_layer_tweaker.cpp
Normal file
86
src/mbgl/renderer/layers/raster_layer_tweaker.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <mbgl/renderer/layers/raster_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/raster_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
struct alignas(16) RasterDrawableUBO {
|
||||
std::array<float, 4 * 4> matrix;
|
||||
std::array<float, 4> spin_weights;
|
||||
std::array<float, 2> tl_parent;
|
||||
float scale_parent;
|
||||
float buffer_scale;
|
||||
float fade_t;
|
||||
float opacity;
|
||||
float brightness_low;
|
||||
float brightness_high;
|
||||
float saturation_factor;
|
||||
float contrast_factor;
|
||||
float pad1;
|
||||
float pad2;
|
||||
};
|
||||
static_assert(sizeof(RasterDrawableUBO) == 128);
|
||||
static_assert(sizeof(RasterDrawableUBO) % 16 == 0);
|
||||
|
||||
void RasterLayerTweaker::execute([[maybe_unused]] LayerGroup& layerGroup,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
[[maybe_unused]] const PaintParameters& parameters) {
|
||||
const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
|
||||
layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
|
||||
if (!drawable.getTileID()) {
|
||||
return;
|
||||
}
|
||||
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
|
||||
const auto matrix = parameters.matrixForTile(tileID, !parameters.state.isChanging());
|
||||
|
||||
auto spinWeights = [](float spin) -> std::array<float, 4> {
|
||||
spin = util::deg2radf(spin);
|
||||
float s = std::sin(spin);
|
||||
float c = std::cos(spin);
|
||||
std::array<float, 4> spin_weights = {
|
||||
{(2 * c + 1) / 3, (-std::sqrt(3.0f) * s - c + 1) / 3, (std::sqrt(3.0f) * s - c + 1) / 3, 0}};
|
||||
return spin_weights;
|
||||
};
|
||||
auto saturationFactor = [](float saturation) -> float {
|
||||
if (saturation > 0) {
|
||||
return 1.f - 1.f / (1.001f - saturation);
|
||||
} else {
|
||||
return -saturation;
|
||||
}
|
||||
};
|
||||
auto contrastFactor = [](float contrast) -> float {
|
||||
if (contrast > 0) {
|
||||
return 1 / (1 - contrast);
|
||||
} else {
|
||||
return 1 + contrast;
|
||||
}
|
||||
};
|
||||
|
||||
RasterDrawableUBO drawableUBO{/*.matrix = */ util::cast<float>(matrix),
|
||||
/*.spin_weigths = */ spinWeights(evaluated.get<RasterHueRotate>()),
|
||||
/*.tl_parent = */ {{0.0f, 0.0f}},
|
||||
/*.scale_parent = */ 1.0f,
|
||||
/*.buffer_scale = */ 1.0f,
|
||||
/*.fade_t = */ 1.0f,
|
||||
/*.opacity = */ evaluated.get<RasterOpacity>(),
|
||||
/*.brightness_low = */ evaluated.get<RasterBrightnessMin>(),
|
||||
/*.brightness_high = */ evaluated.get<RasterBrightnessMax>(),
|
||||
/*.saturation_factor = */ saturationFactor(evaluated.get<RasterSaturation>()),
|
||||
/*.contrast_factor = */ contrastFactor(evaluated.get<RasterContrast>()),
|
||||
0,
|
||||
0};
|
||||
auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
|
||||
drawable.mutableUniformBuffers().addOrReplace("RasterDrawableUBO", drawableUniformBuffer);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
29
src/mbgl/renderer/layers/raster_layer_tweaker.hpp
Normal file
29
src/mbgl/renderer/layers/raster_layer_tweaker.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace gfx {
|
||||
class UniformBuffer;
|
||||
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
|
||||
} // namespace gfx
|
||||
|
||||
/**
|
||||
Raster layer tweaker
|
||||
*/
|
||||
class RasterLayerTweaker : public LayerTweaker {
|
||||
public:
|
||||
RasterLayerTweaker(Immutable<style::LayerProperties> properties)
|
||||
: LayerTweaker(properties){};
|
||||
|
||||
public:
|
||||
~RasterLayerTweaker() override = default;
|
||||
|
||||
void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <mbgl/renderer/layers/render_raster_layer.hpp>
|
||||
#include <mbgl/renderer/layers/raster_layer_tweaker.hpp>
|
||||
#include <mbgl/renderer/buckets/raster_bucket.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
@@ -7,9 +9,12 @@
|
||||
#include <mbgl/programs/programs.hpp>
|
||||
#include <mbgl/programs/raster_program.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/math/angles.hpp>
|
||||
#include <mbgl/style/layers/raster_layer_impl.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -40,6 +45,10 @@ void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters)
|
||||
passes = properties->evaluated.get<style::RasterOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None;
|
||||
properties->renderPasses = mbgl::underlying_type(passes);
|
||||
evaluatedProperties = std::move(properties);
|
||||
|
||||
if (tileLayerGroup && tileLayerGroup->getLayerTweaker()) {
|
||||
tileLayerGroup->setLayerTweaker(std::make_shared<RasterLayerTweaker>(evaluatedProperties));
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderRasterLayer::hasTransition() const {
|
||||
@@ -197,4 +206,211 @@ void RenderRasterLayer::render(PaintParameters& parameters) {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderRasterLayer::layerRemoved(UniqueChangeRequestVec& changes) {
|
||||
// Remove everything
|
||||
if (tileLayerGroup) {
|
||||
changes.emplace_back(std::make_unique<RemoveLayerGroupRequest>(tileLayerGroup->getLayerIndex()));
|
||||
tileLayerGroup.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderRasterLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) {
|
||||
stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size();
|
||||
}
|
||||
|
||||
void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
const TransformState& /*state*/,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
[[maybe_unused]] UniqueChangeRequestVec& changes) {
|
||||
std::unique_lock<std::mutex> guard(mutex);
|
||||
|
||||
if ((!renderTiles || renderTiles->empty()) && !imageData) {
|
||||
if (tileLayerGroup) {
|
||||
stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount();
|
||||
tileLayerGroup->clearDrawables();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up a layer group
|
||||
if (!tileLayerGroup) {
|
||||
tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64);
|
||||
if (!tileLayerGroup) {
|
||||
return;
|
||||
}
|
||||
tileLayerGroup->setLayerTweaker(std::make_shared<RasterLayerTweaker>(evaluatedProperties));
|
||||
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true));
|
||||
}
|
||||
|
||||
auto renderPass = RenderPass::Translucent;
|
||||
|
||||
if (!rasterShader) {
|
||||
rasterShader = context.getGenericShader(shaders, "RasterShader");
|
||||
}
|
||||
|
||||
const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
RasterProgram::Binders paintAttributeData{evaluated, 0};
|
||||
|
||||
const gfx::TextureFilterType filter = evaluated.get<RasterResampling>() == RasterResamplingType::Nearest
|
||||
? gfx::TextureFilterType::Nearest
|
||||
: gfx::TextureFilterType::Linear;
|
||||
(void)filter;
|
||||
|
||||
if (imageData && !imageData->bucket->needsUpload()) {
|
||||
// TODO: implement arbitrary image
|
||||
RasterBucket& bucket = *imageData->bucket;
|
||||
assert(bucket.texture);
|
||||
|
||||
// size_t i = 0;
|
||||
for (const auto& matrix_ : imageData->matrices) {
|
||||
/*draw(matrix_,
|
||||
*bucket.vertexBuffer,
|
||||
*bucket.indexBuffer,
|
||||
bucket.segments,
|
||||
RasterProgram::TextureBindings{
|
||||
textures::image0::Value{bucket.texture->getResource(), filter},
|
||||
textures::image1::Value{bucket.texture->getResource(), filter},
|
||||
},
|
||||
std::to_string(i++));*/
|
||||
(void)matrix_;
|
||||
}
|
||||
} else if (renderTiles) {
|
||||
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
|
||||
// Has this tile dropped out of the cover set?
|
||||
if (const auto it = std::find_if(renderTiles->begin(),
|
||||
renderTiles->end(),
|
||||
[&drawable](const auto& renderTile) {
|
||||
return drawable->getTileID() == renderTile.get().getOverscaledTileID();
|
||||
});
|
||||
it == renderTiles->end()) {
|
||||
// remove it
|
||||
drawable.reset();
|
||||
++stats.tileDrawablesRemoved;
|
||||
}
|
||||
});
|
||||
|
||||
for (const RenderTile& tile : *renderTiles) {
|
||||
const auto& tileID = tile.getOverscaledTileID();
|
||||
auto* bucket_ = tile.getBucket(*baseImpl);
|
||||
if (!bucket_) {
|
||||
continue;
|
||||
}
|
||||
auto& bucket = static_cast<RasterBucket&>(*bucket_);
|
||||
|
||||
if (!bucket.hasData()) continue;
|
||||
|
||||
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) continue;
|
||||
|
||||
if (bucket.image) {
|
||||
std::unique_ptr<gfx::DrawableBuilder> builder{context.createDrawableBuilder("raster")};
|
||||
builder->setShader(rasterShader);
|
||||
builder->setRenderPass(renderPass);
|
||||
builder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None);
|
||||
builder->setSubLayerIndex(0);
|
||||
builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder->setVertexAttrName("a_pos");
|
||||
|
||||
// render data
|
||||
auto buildRenderData = [](const TileMask& mask,
|
||||
std::vector<std::array<int16_t, 2>>& vertices,
|
||||
std::vector<std::array<int16_t, 2>>& attributes,
|
||||
std::vector<uint16_t>& indices,
|
||||
std::vector<Segment<void>>& segments) {
|
||||
constexpr const uint16_t vertexLength = 4;
|
||||
|
||||
// Create the vertex buffer for the specified tile mask.
|
||||
for (const auto& id : mask) {
|
||||
// Create a quad for every masked tile.
|
||||
const int32_t vertexExtent = util::EXTENT >> id.z;
|
||||
|
||||
const Point<int16_t> tlVertex = {static_cast<int16_t>(id.x * vertexExtent),
|
||||
static_cast<int16_t>(id.y * vertexExtent)};
|
||||
const Point<int16_t> brVertex = {static_cast<int16_t>(tlVertex.x + vertexExtent),
|
||||
static_cast<int16_t>(tlVertex.y + vertexExtent)};
|
||||
|
||||
if (segments.empty() ||
|
||||
(segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max())) {
|
||||
// Move to a new segments because the old one can't hold the geometry.
|
||||
segments.emplace_back(vertices.size(), indices.size());
|
||||
}
|
||||
|
||||
vertices.emplace_back(std::array<int16_t, 2>{{tlVertex.x, tlVertex.y}});
|
||||
attributes.emplace_back(std::array<int16_t, 2>{{tlVertex.x, tlVertex.y}});
|
||||
|
||||
vertices.emplace_back(std::array<int16_t, 2>{{brVertex.x, tlVertex.y}});
|
||||
attributes.emplace_back(std::array<int16_t, 2>{{brVertex.x, tlVertex.y}});
|
||||
|
||||
vertices.emplace_back(std::array<int16_t, 2>{{tlVertex.x, brVertex.y}});
|
||||
attributes.emplace_back(std::array<int16_t, 2>{{tlVertex.x, brVertex.y}});
|
||||
|
||||
vertices.emplace_back(std::array<int16_t, 2>{{brVertex.x, brVertex.y}});
|
||||
attributes.emplace_back(std::array<int16_t, 2>{{brVertex.x, brVertex.y}});
|
||||
|
||||
auto& segment = segments.back();
|
||||
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
|
||||
const auto offset = static_cast<uint16_t>(segment.vertexLength);
|
||||
|
||||
// 0, 1, 2
|
||||
// 1, 2, 3
|
||||
indices.insert(indices.end(),
|
||||
{offset, static_cast<uint16_t>(offset + 1), static_cast<uint16_t>(offset + 2u)});
|
||||
indices.insert(indices.end(),
|
||||
{static_cast<uint16_t>(offset + 1),
|
||||
static_cast<uint16_t>(offset + 2),
|
||||
static_cast<uint16_t>(offset + 3)});
|
||||
|
||||
segment.vertexLength += vertexLength;
|
||||
segment.indexLength += 6;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::array<int16_t, 2>> vertices, attributes;
|
||||
std::vector<uint16_t> indices;
|
||||
std::vector<Segment<void>> segments;
|
||||
buildRenderData(bucket.mask, vertices, attributes, indices, segments);
|
||||
builder->addVertices(vertices, 0, vertices.size());
|
||||
builder->setSegments(gfx::Triangles(), indices, segments);
|
||||
|
||||
// attributes
|
||||
{
|
||||
gfx::VertexAttributeArray vertexAttrs;
|
||||
if (auto& attr = vertexAttrs.getOrAdd("a_texture_pos")) {
|
||||
std::size_t index{0};
|
||||
for (auto& a : attributes) {
|
||||
attr->set<gfx::VertexAttribute::int2>(index++, {a[0], a[1]});
|
||||
}
|
||||
}
|
||||
builder->setVertexAttributes(std::move(vertexAttrs));
|
||||
}
|
||||
|
||||
// textures
|
||||
// TODO: move texture creation into gfx::Context
|
||||
std::shared_ptr<gfx::Texture2D> tex0 = context.createTexture2D();
|
||||
tex0->setImage(bucket.image).create();
|
||||
auto location0 = rasterShader->getSamplerLocation("u_image0");
|
||||
if (location0.has_value()) {
|
||||
builder->setTexture(tex0, location0.value());
|
||||
}
|
||||
std::shared_ptr<gfx::Texture2D> tex1 = context.createTexture2D();
|
||||
tex1->setImage(bucket.image).create();
|
||||
auto location1 = rasterShader->getSamplerLocation("u_image1");
|
||||
if (location1.has_value()) {
|
||||
builder->setTexture(tex1, location1.value());
|
||||
}
|
||||
|
||||
// finish
|
||||
builder->flush();
|
||||
for (auto& drawable : builder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.tileDrawablesAdded;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -14,6 +14,15 @@ public:
|
||||
explicit RenderRasterLayer(Immutable<style::RasterLayer::Impl>);
|
||||
~RenderRasterLayer() override;
|
||||
|
||||
void layerRemoved(UniqueChangeRequestVec&) override;
|
||||
|
||||
/// Generate any changes needed by the layer
|
||||
void update(gfx::ShaderRegistry&,
|
||||
gfx::Context&,
|
||||
const TransformState&,
|
||||
const RenderTree&,
|
||||
UniqueChangeRequestVec&) override;
|
||||
|
||||
private:
|
||||
void transition(const TransitionParameters&) override;
|
||||
void evaluate(const PropertyEvaluationParameters&) override;
|
||||
@@ -22,12 +31,17 @@ private:
|
||||
void prepare(const LayerPrepareParameters&) override;
|
||||
void render(PaintParameters&) override;
|
||||
|
||||
/// Remove all drawables for the tile from the layer group
|
||||
void removeTile(RenderPass, const OverscaledTileID&);
|
||||
|
||||
// Paint properties
|
||||
style::RasterPaintProperties::Unevaluated unevaluated;
|
||||
const ImageSourceRenderData* imageData = nullptr;
|
||||
|
||||
// Programs
|
||||
std::shared_ptr<RasterProgram> rasterProgram;
|
||||
|
||||
gfx::ShaderProgramBasePtr rasterShader;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -111,7 +111,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
|
||||
});
|
||||
|
||||
// Give the layers a chance to do setup
|
||||
orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.preRender(orchestrator, parameters); });
|
||||
// orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.preRender(orchestrator, parameters);
|
||||
// });
|
||||
|
||||
// - UPLOAD PASS -------------------------------------------------------------------------------
|
||||
// Uploads all required buffers and images before we do any actual rendering.
|
||||
@@ -320,7 +321,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Give the layers a chance to do cleanup
|
||||
// Give the layers a chance to do cleanup
|
||||
orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.postRender(orchestrator, parameters); });
|
||||
|
||||
// Ends the RenderPass
|
||||
|
||||
@@ -111,6 +111,11 @@ static void addAttr(
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<uint32_t> ShaderProgramGL::getSamplerLocation(const std::string& name) const {
|
||||
GLint sampler_location = MBGL_CHECK_ERROR(glGetUniformLocation(glProgram, name.c_str()));
|
||||
return (sampler_location == -1) ? std::optional<uint32_t>{} : sampler_location;
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderProgramGL> ShaderProgramGL::create(Context& context,
|
||||
const ProgramParameters& programParameters,
|
||||
const std::string& /*name*/,
|
||||
|
||||
Reference in New Issue
Block a user