#include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { using namespace style; RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable _impl) : RenderLayer(style::LayerType::FillExtrusion, _impl), unevaluated(impl().paint.untransitioned()) { } const style::FillExtrusionLayer::Impl& RenderFillExtrusionLayer::impl() const { return static_cast(*baseImpl); } std::unique_ptr RenderFillExtrusionLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { return std::make_unique(parameters, layers); } void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters) { unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); } void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { evaluated = unevaluated.evaluate(parameters); passes = (evaluated.get() > 0) ? RenderPass::Translucent : RenderPass::None; } bool RenderFillExtrusionLayer::hasTransition() const { return unevaluated.hasTransition(); } void RenderFillExtrusionLayer::render(Painter& painter, PaintParameters& parameters, RenderSource*) { if (painter.pass == RenderPass::Opaque) { return; } const auto size = painter.context.viewport.getCurrentValue().size; if (!painter.extrusionTexture || painter.extrusionTexture->getSize() != size) { painter.extrusionTexture = OffscreenTexture(painter.context, size, OffscreenTextureAttachment::Depth); } painter.extrusionTexture->bind(); painter.context.setStencilMode(gl::StencilMode::disabled()); painter.context.setDepthMode(painter.depthModeForSublayer(0, gl::DepthMode::ReadWrite)); painter.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, 1.0f, {}); if (evaluated.get().from.empty()) { for (const RenderTile& tile : renderTiles) { assert(dynamic_cast(tile.tile.getBucket(*baseImpl))); FillExtrusionBucket& bucket = *reinterpret_cast(tile.tile.getBucket(*baseImpl)); parameters.programs.fillExtrusion.get(evaluated).draw( painter.context, gl::Triangles(), painter.depthModeForSublayer(0, gl::DepthMode::ReadWrite), gl::StencilMode::disabled(), painter.colorModeForRenderPass(), FillExtrusionUniforms::values( tile.translatedClipMatrix(evaluated.get(), evaluated.get(), painter.state), painter.state, painter.evaluatedLight ), *bucket.vertexBuffer, *bucket.indexBuffer, bucket.triangleSegments, bucket.paintPropertyBinders.at(getID()), evaluated, painter.state.getZoom(), getID()); } } else { optional imagePosA = painter.imageManager->getPattern(evaluated.get().from); optional imagePosB = painter.imageManager->getPattern(evaluated.get().to); if (!imagePosA || !imagePosB) { return; } painter.imageManager->bind(painter.context, 0); for (const RenderTile& tile : renderTiles) { assert(dynamic_cast(tile.tile.getBucket(*baseImpl))); FillExtrusionBucket& bucket = *reinterpret_cast(tile.tile.getBucket(*baseImpl)); parameters.programs.fillExtrusionPattern.get(evaluated).draw( painter.context, gl::Triangles(), painter.depthModeForSublayer(0, gl::DepthMode::ReadWrite), gl::StencilMode::disabled(), painter.colorModeForRenderPass(), FillExtrusionPatternUniforms::values( tile.translatedClipMatrix(evaluated.get(), evaluated.get(), painter.state), painter.imageManager->getPixelSize(), *imagePosA, *imagePosB, evaluated.get(), tile.id, painter.state, -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, painter.evaluatedLight ), *bucket.vertexBuffer, *bucket.indexBuffer, bucket.triangleSegments, bucket.paintPropertyBinders.at(getID()), evaluated, painter.state.getZoom(), getID()); } } parameters.view.bind(); painter.context.bindTexture(painter.extrusionTexture->getTexture()); mat4 viewportMat; matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); const Properties<>::PossiblyEvaluated properties; parameters.programs.extrusionTexture.draw( painter.context, gl::Triangles(), gl::DepthMode::disabled(), gl::StencilMode::disabled(), painter.colorModeForRenderPass(), ExtrusionTextureProgram::UniformValues{ uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size }, uniforms::u_image::Value{ 0 }, uniforms::u_opacity::Value{ evaluated.get() } }, painter.extrusionTextureVertexBuffer, painter.quadTriangleIndexBuffer, painter.extrusionTextureSegments, ExtrusionTextureProgram::PaintPropertyBinders{ properties, 0 }, properties, painter.state.getZoom(), getID()); } bool RenderFillExtrusionLayer::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