#include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { using namespace style; RenderFillLayer::RenderFillLayer(Immutable _impl) : RenderLayer(style::LayerType::Fill, _impl), unevaluated(impl().paint.untransitioned()) { } const style::FillLayer::Impl& RenderFillLayer::impl() const { return static_cast(*baseImpl); } std::unique_ptr RenderFillLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { return std::make_unique(parameters, layers); } void RenderFillLayer::transition(const TransitionParameters& parameters) { unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); } void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { evaluated = unevaluated.evaluate(parameters); if (unevaluated.get().isUndefined()) { evaluated.get() = evaluated.get(); } passes = RenderPass::None; if (evaluated.get()) { passes |= RenderPass::Translucent; } if (!unevaluated.get().isUndefined() || evaluated.get().constantOr(Color()).a < 1.0f || evaluated.get().constantOr(0) < 1.0f) { passes |= RenderPass::Translucent; } else { passes |= RenderPass::Opaque; } } bool RenderFillLayer::hasTransition() const { return unevaluated.hasTransition(); } void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) { if (evaluated.get().from.empty()) { for (const RenderTile& tile : renderTiles) { assert(dynamic_cast(tile.tile.getBucket(*baseImpl))); FillBucket& bucket = *reinterpret_cast(tile.tile.getBucket(*baseImpl)); auto draw = [&] (auto& program, const auto& drawMode, const auto& depthMode, const auto& indexBuffer, const auto& segments) { program.get(evaluated).draw( parameters.context, drawMode, depthMode, parameters.stencilModeForClipping(tile.clip), parameters.colorModeForRenderPass(), FillProgram::UniformValues { uniforms::u_matrix::Value{ tile.translatedMatrix(evaluated.get(), evaluated.get(), parameters.state) }, uniforms::u_world::Value{ parameters.context.viewport.getCurrentValue().size }, }, *bucket.vertexBuffer, indexBuffer, segments, bucket.paintPropertyBinders.at(getID()), evaluated, parameters.state.getZoom(), getID() ); }; // Only draw the fill when it's opaque and we're drawing opaque fragments, // or when it's translucent and we're drawing translucent fragments. if ((evaluated.get().constantOr(Color()).a >= 1.0f && evaluated.get().constantOr(0) >= 1.0f) == (parameters.pass == RenderPass::Opaque)) { draw(parameters.programs.fill, gl::Triangles(), parameters.depthModeForSublayer(1, parameters.pass == RenderPass::Opaque ? gl::DepthMode::ReadWrite : gl::DepthMode::ReadOnly), *bucket.triangleIndexBuffer, bucket.triangleSegments); } if (evaluated.get() && parameters.pass == RenderPass::Translucent) { draw(parameters.programs.fillOutline, gl::Lines{ 2.0f }, parameters.depthModeForSublayer( unevaluated.get().isUndefined() ? 2 : 0, gl::DepthMode::ReadOnly), *bucket.lineIndexBuffer, bucket.lineSegments); } } } else { if (parameters.pass != RenderPass::Translucent) { return; } optional imagePosA = parameters.imageManager.getPattern(evaluated.get().from); optional imagePosB = parameters.imageManager.getPattern(evaluated.get().to); if (!imagePosA || !imagePosB) { return; } parameters.imageManager.bind(parameters.context, 0); for (const RenderTile& tile : renderTiles) { assert(dynamic_cast(tile.tile.getBucket(*baseImpl))); FillBucket& bucket = *reinterpret_cast(tile.tile.getBucket(*baseImpl)); auto draw = [&] (auto& program, const auto& drawMode, const auto& depthMode, const auto& indexBuffer, const auto& segments) { program.get(evaluated).draw( parameters.context, drawMode, depthMode, parameters.stencilModeForClipping(tile.clip), parameters.colorModeForRenderPass(), FillPatternUniforms::values( tile.translatedMatrix(evaluated.get(), evaluated.get(), parameters.state), parameters.context.viewport.getCurrentValue().size, parameters.imageManager.getPixelSize(), *imagePosA, *imagePosB, evaluated.get(), tile.id, parameters.state ), *bucket.vertexBuffer, indexBuffer, segments, bucket.paintPropertyBinders.at(getID()), evaluated, parameters.state.getZoom(), getID() ); }; draw(parameters.programs.fillPattern, gl::Triangles(), parameters.depthModeForSublayer(1, gl::DepthMode::ReadWrite), *bucket.triangleIndexBuffer, bucket.triangleSegments); if (evaluated.get() && unevaluated.get().isUndefined()) { draw(parameters.programs.fillOutlinePattern, gl::Lines { 2.0f }, parameters.depthModeForSublayer(2, gl::DepthMode::ReadOnly), *bucket.lineIndexBuffer, bucket.lineSegments); } } } } bool RenderFillLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, const float, const float bearing, const float pixelsToTileUnits) const { auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, evaluated.get(), evaluated.get(), bearing, pixelsToTileUnits); return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); } } // namespace mbgl