#include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { using namespace style; RenderFillLayer::RenderFillLayer(Immutable _impl) : RenderLayer(std::move(_impl)), unevaluated(impl().paint.untransitioned()) { } const style::FillLayer::Impl& RenderFillLayer::impl() const { return static_cast(*baseImpl); } void RenderFillLayer::transition(const TransitionParameters& parameters) { unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); } void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { evaluated = unevaluated.evaluate(parameters); crossfade = parameters.getCrossfadeParameters(); 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(); } bool RenderFillLayer::hasCrossfade() const { return crossfade.t != 1; } void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) { if (unevaluated.get().isUndefined()) { for (const RenderTile& tile : renderTiles) { auto bucket_ = tile.tile.getBucket(*baseImpl); if (!bucket_) { continue; } FillBucket& bucket = *bucket_; auto draw = [&] (auto& program, const auto& drawMode, const auto& depthMode, const auto& indexBuffer, const auto& segments) { auto& programInstance = program.get(evaluated); const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); const auto allUniformValues = programInstance.computeAllUniformValues( FillProgram::UniformValues { uniforms::u_matrix::Value( tile.translatedMatrix(evaluated.get(), evaluated.get(), parameters.state) ), uniforms::u_world::Value( parameters.context.viewport.getCurrentValue().size ), }, paintPropertyBinders, evaluated, parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( *bucket.vertexBuffer, paintPropertyBinders, evaluated ); checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); programInstance.draw( parameters.context, drawMode, depthMode, parameters.stencilModeForClipping(tile.clip), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), indexBuffer, segments, allUniformValues, allAttributeBindings, 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.getFillLayerPrograms().fill, gfx::Triangles(), parameters.depthModeForSublayer(1, parameters.pass == RenderPass::Opaque ? gfx::DepthMaskType::ReadWrite : gfx::DepthMaskType::ReadOnly), *bucket.triangleIndexBuffer, bucket.triangleSegments); } if (evaluated.get() && parameters.pass == RenderPass::Translucent) { draw(parameters.programs.getFillLayerPrograms().fillOutline, gfx::Lines{ 2.0f }, parameters.depthModeForSublayer( unevaluated.get().isUndefined() ? 2 : 0, gfx::DepthMaskType::ReadOnly), *bucket.lineIndexBuffer, bucket.lineSegments); } } } else { if (parameters.pass != RenderPass::Translucent) { return; } const auto fillPatternValue = evaluated.get().constantOr(Faded>{"", ""}); for (const RenderTile& tile : renderTiles) { assert(dynamic_cast(&tile.tile)); GeometryTile& geometryTile = static_cast(tile.tile); optional patternPosA = geometryTile.getPattern(fillPatternValue.from); optional patternPosB = geometryTile.getPattern(fillPatternValue.to); parameters.context.bindTexture(*geometryTile.iconAtlasTexture, 0, gl::TextureFilter::Linear); auto bucket_ = tile.tile.getBucket(*baseImpl); if (!bucket_) { continue; } FillBucket& bucket = *bucket_; auto draw = [&] (auto& program, const auto& drawMode, const auto& depthMode, const auto& indexBuffer, const auto& segments) { auto& programInstance = program.get(evaluated); const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); const auto allUniformValues = programInstance.computeAllUniformValues( FillPatternProgram::uniformValues( tile.translatedMatrix(evaluated.get(), evaluated.get(), parameters.state), parameters.context.viewport.getCurrentValue().size, geometryTile.iconAtlasTexture->size, crossfade, tile.id, parameters.state, parameters.pixelRatio ), paintPropertyBinders, evaluated, parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( *bucket.vertexBuffer, paintPropertyBinders, evaluated ); checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); programInstance.draw( parameters.context, drawMode, depthMode, parameters.stencilModeForClipping(tile.clip), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), indexBuffer, segments, allUniformValues, allAttributeBindings, getID() ); }; draw(parameters.programs.getFillLayerPrograms().fillPattern, gfx::Triangles(), parameters.depthModeForSublayer(1, gfx::DepthMaskType::ReadWrite), *bucket.triangleIndexBuffer, bucket.triangleSegments); if (evaluated.get() && unevaluated.get().isUndefined()) { draw(parameters.programs.getFillLayerPrograms().fillOutlinePattern, gfx::Lines { 2.0f }, parameters.depthModeForSublayer(2, gfx::DepthMaskType::ReadOnly), *bucket.lineIndexBuffer, bucket.lineSegments); } } } } bool RenderFillLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, const float, const TransformState& transformState, const float pixelsToTileUnits, const mat4&) const { auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, evaluated.get(), evaluated.get(), transformState.getBearing(), pixelsToTileUnits); return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); } } // namespace mbgl