Files
MapLibreParticleLab/src/mbgl/renderer/layers/render_raster_layer.cpp
2019-03-01 09:33:37 +01:00

176 lines
6.4 KiB
C++

#include <mbgl/renderer/layers/render_raster_layer.hpp>
#include <mbgl/renderer/buckets/raster_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/sources/render_image_source.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/raster_program.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
namespace mbgl {
using namespace style;
RenderRasterLayer::RenderRasterLayer(Immutable<style::RasterLayer::Impl> _impl)
: RenderLayer(std::move(_impl)),
unevaluated(impl().paint.untransitioned()) {
}
const style::RasterLayer::Impl& RenderRasterLayer::impl() const {
return static_cast<const style::RasterLayer::Impl&>(*baseImpl);
}
void RenderRasterLayer::transition(const TransitionParameters& parameters) {
unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
}
void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) {
evaluated = unevaluated.evaluate(parameters);
passes = evaluated.get<style::RasterOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None;
}
bool RenderRasterLayer::hasTransition() const {
return unevaluated.hasTransition();
}
bool RenderRasterLayer::hasCrossfade() const {
return false;
}
static float saturationFactor(float saturation) {
if (saturation > 0) {
return 1 - 1 / (1.001 - saturation);
} else {
return -saturation;
}
}
static float contrastFactor(float contrast) {
if (contrast > 0) {
return 1 / (1 - contrast);
} else {
return 1 + contrast;
}
}
static std::array<float, 3> spinWeights(float spin) {
spin *= util::DEG2RAD;
float s = std::sin(spin);
float c = std::cos(spin);
std::array<float, 3> spin_weights = {{
(2 * c + 1) / 3,
(-std::sqrt(3.0f) * s - c + 1) / 3,
(std::sqrt(3.0f) * s - c + 1) / 3
}};
return spin_weights;
}
void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source) {
if (parameters.pass != RenderPass::Translucent)
return;
RasterProgram::Binders paintAttributeData{ evaluated, 0 };
auto draw = [&] (const mat4& matrix,
const auto& vertexBuffer,
const auto& indexBuffer,
const auto& segments) {
auto& programInstance = parameters.programs.getRasterLayerPrograms().raster;
const auto allUniformValues = programInstance.computeAllUniformValues(
RasterProgram::UniformValues {
uniforms::u_matrix::Value( matrix ),
uniforms::u_image0::Value( 0 ),
uniforms::u_image1::Value( 1 ),
uniforms::u_opacity::Value( evaluated.get<RasterOpacity>() ),
uniforms::u_fade_t::Value( 1 ),
uniforms::u_brightness_low::Value( evaluated.get<RasterBrightnessMin>() ),
uniforms::u_brightness_high::Value( evaluated.get<RasterBrightnessMax>() ),
uniforms::u_saturation_factor::Value( saturationFactor(evaluated.get<RasterSaturation>()) ),
uniforms::u_contrast_factor::Value( contrastFactor(evaluated.get<RasterContrast>()) ),
uniforms::u_spin_weights::Value( spinWeights(evaluated.get<RasterHueRotate>()) ),
uniforms::u_buffer_scale::Value( 1.0f ),
uniforms::u_scale_parent::Value( 1.0f ),
uniforms::u_tl_parent::Value( std::array<float, 2> {{ 0.0f, 0.0f }} ),
},
paintAttributeData,
evaluated,
parameters.state.getZoom()
);
const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
vertexBuffer,
paintAttributeData,
evaluated
);
checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
programInstance.draw(
parameters.context,
gfx::Triangles(),
parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly),
gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
gl::CullFaceMode::disabled(),
indexBuffer,
segments,
allUniformValues,
allAttributeBindings,
getID()
);
};
const gl::TextureFilter filter = evaluated.get<RasterResampling>() == RasterResamplingType::Nearest ? gl::TextureFilter::Nearest : gl::TextureFilter::Linear;
if (RenderImageSource* imageSource = source->as<RenderImageSource>()) {
if (imageSource->isEnabled() && imageSource->isLoaded() && !imageSource->bucket->needsUpload()) {
RasterBucket& bucket = *imageSource->bucket;
assert(bucket.texture);
parameters.context.bindTexture(*bucket.texture, 0, filter);
parameters.context.bindTexture(*bucket.texture, 1, filter);
for (auto matrix_ : imageSource->matrices) {
draw(matrix_,
*bucket.vertexBuffer,
*bucket.indexBuffer,
bucket.segments);
}
}
} else {
for (const RenderTile& tile : renderTiles) {
auto bucket_ = tile.tile.getBucket<RasterBucket>(*baseImpl);
if (!bucket_) {
continue;
}
RasterBucket& bucket = *bucket_;
if (!bucket.hasData())
continue;
assert(bucket.texture);
parameters.context.bindTexture(*bucket.texture, 0, filter);
parameters.context.bindTexture(*bucket.texture, 1, filter);
if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) {
// Draw only the parts of the tile that aren't drawn by another tile in the layer.
draw(parameters.matrixForTile(tile.id, true),
*bucket.vertexBuffer,
*bucket.indexBuffer,
bucket.segments);
} else {
// Draw the full tile.
draw(parameters.matrixForTile(tile.id, true),
parameters.staticData.rasterVertexBuffer,
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.rasterSegments);
}
}
}
}
} // namespace mbgl