#include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { using namespace style; RenderTile::RenderTile(UnwrappedTileID id_, Tile& tile_) : id(id_), tile(tile_) {} RenderTile::~RenderTile() = default; mat4 RenderTile::translateVtxMatrix(const UnwrappedTileID& id, const mat4& tileMatrix, const std::array& translation, TranslateAnchorType anchor, const TransformState& state, const bool inViewportPixelUnits) { if (translation[0] == 0 && translation[1] == 0) { return tileMatrix; } mat4 vtxMatrix; const float angle = inViewportPixelUnits ? (anchor == TranslateAnchorType::Map ? static_cast(state.getBearing()) : 0.0f) : (anchor == TranslateAnchorType::Viewport ? static_cast(-state.getBearing()) : 0.0f); Point translate = util::rotate(Point{translation[0], translation[1]}, angle); if (inViewportPixelUnits) { matrix::translate(vtxMatrix, tileMatrix, translate.x, translate.y, 0); } else { matrix::translate(vtxMatrix, tileMatrix, id.pixelsToTileUnits(translate.x, static_cast(state.getZoom())), id.pixelsToTileUnits(translate.y, static_cast(state.getZoom())), 0); } return vtxMatrix; } mat4 RenderTile::translateVtxMatrix(const mat4& tileMatrix, const std::array& translation, TranslateAnchorType anchor, const TransformState& state, const bool inViewportPixelUnits) const { return translateVtxMatrix(id, tileMatrix, translation, anchor, state, inViewportPixelUnits); } mat4 RenderTile::translatedMatrix(const std::array& translation, TranslateAnchorType anchor, const TransformState& state) const { return translateVtxMatrix(matrix, translation, anchor, state, false); } mat4 RenderTile::translatedClipMatrix(const std::array& translation, TranslateAnchorType anchor, const TransformState& state) const { return translateVtxMatrix(nearClippedMatrix, translation, anchor, state, false); } const OverscaledTileID& RenderTile::getOverscaledTileID() const { return tile.id; } bool RenderTile::holdForFade() const { return tile.holdForFade(); } Bucket* RenderTile::getBucket(const style::Layer::Impl& impl) const { assert(renderData); return renderData->getBucket(impl); } const LayerRenderData* RenderTile::getLayerRenderData(const style::Layer::Impl& impl) const { assert(renderData); return renderData->getLayerRenderData(impl); } std::optional RenderTile::getPattern(const std::string& pattern) const { assert(renderData); return renderData->getPattern(pattern); } static const gfx::Texture2DPtr noTexture; bool RenderTile::hasGlyphAtlasTexture() const { return renderData && renderData->getGlyphAtlasTexture(); } const gfx::Texture2DPtr& RenderTile::getGlyphAtlasTexture() const { return renderData ? renderData->getGlyphAtlasTexture() : noTexture; } gfx::TextureBinding RenderTile::getGlyphAtlasTextureBinding(gfx::TextureFilterType filter) const { assert(renderData && renderData->getGlyphAtlasTexture()); return {getGlyphAtlasTexture()->getResource(), filter}; } bool RenderTile::hasIconAtlasTexture() const { return renderData && renderData->getIconAtlasTexture(); } const gfx::Texture2DPtr& RenderTile::getIconAtlasTexture() const { return renderData ? renderData->getIconAtlasTexture() : noTexture; } gfx::TextureBinding RenderTile::getIconAtlasTextureBinding(gfx::TextureFilterType filter) const { assert(renderData && renderData->getIconAtlasTexture()); return {getIconAtlasTexture()->getResource(), filter}; } static const std::shared_ptr noAtlas; const std::shared_ptr& RenderTile::getAtlasTextures() const { return renderData ? renderData->getAtlasTextures() : noAtlas; } void RenderTile::upload(gfx::UploadPass& uploadPass) const { assert(renderData); renderData->upload(uploadPass); if (debugBucket) { debugBucket->upload(uploadPass); } } void RenderTile::prepare(const SourcePrepareParameters& parameters) { renderData = tile.createRenderData(); assert(renderData); renderData->prepare(parameters); needsRendering = tile.usedByRenderedLayers; if (parameters.debugOptions != MapDebugOptions::NoDebug && (!debugBucket || debugBucket->renderable != tile.isRenderable() || debugBucket->complete != tile.isComplete() || !(debugBucket->modified == tile.modified) || !(debugBucket->expires == tile.expires) || debugBucket->debugMode != parameters.debugOptions)) { debugBucket = std::make_unique( tile.id, tile.isRenderable(), tile.isComplete(), tile.modified, tile.expires, parameters.debugOptions); } else if (parameters.debugOptions == MapDebugOptions::NoDebug) { debugBucket.reset(); } // Calculate two matrices for this tile: matrix is the standard tile matrix; // nearClippedMatrix has near plane moved further, to enhance depth buffer // precision const auto& transform = parameters.transform; transform.state.matrixFor(matrix, id); transform.state.matrixFor(nearClippedMatrix, id); matrix::multiply(matrix, transform.projMatrix, matrix); matrix::multiply(nearClippedMatrix, transform.nearClippedProjMatrix, nearClippedMatrix); } void RenderTile::finishRender(PaintParameters& parameters) const { if (!needsRendering || parameters.debugOptions == MapDebugOptions::NoDebug) return; static const style::Properties<>::PossiblyEvaluated properties{}; static const DebugProgram::Binders paintAttributeData(properties, 0); auto program = parameters.shaders.getLegacyGroup().get(); if (!program) { return; } if (parameters.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) { assert(debugBucket); const auto allAttributeBindings = DebugProgram::computeAllAttributeBindings( *debugBucket->vertexBuffer, paintAttributeData, properties); program->draw(parameters.context, *parameters.renderPass, gfx::Lines{4.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *debugBucket->indexBuffer, debugBucket->segments, DebugProgram::computeAllUniformValues( DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), uniforms::color::Value(Color::white()), uniforms::overlay_scale::Value(1.0f)}, paintAttributeData, properties, static_cast(parameters.state.getZoom())), allAttributeBindings, DebugProgram::TextureBindings{textures::image::Value{debugBucket->texture->getResource()}}, "text-outline"); program->draw(parameters.context, *parameters.renderPass, gfx::Lines{2.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *debugBucket->indexBuffer, debugBucket->segments, DebugProgram::computeAllUniformValues( DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), uniforms::color::Value(Color::black()), uniforms::overlay_scale::Value(1.0f)}, paintAttributeData, properties, static_cast(parameters.state.getZoom())), allAttributeBindings, DebugProgram::TextureBindings{textures::image::Value{debugBucket->texture->getResource()}}, "text"); } if (parameters.debugOptions & MapDebugOptions::TileBorders) { assert(debugBucket); if (debugBucket->tileBorderSegments.empty()) { debugBucket->tileBorderSegments = RenderStaticData::tileBorderSegments(); } program->draw(parameters.context, *parameters.renderPass, gfx::LineStrip{4.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *parameters.staticData.tileBorderIndexBuffer, debugBucket->tileBorderSegments, DebugProgram::computeAllUniformValues( DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), uniforms::color::Value(Color::red()), uniforms::overlay_scale::Value(1.0f)}, paintAttributeData, properties, static_cast(parameters.state.getZoom())), DebugProgram::computeAllAttributeBindings( *parameters.staticData.tileVertexBuffer, paintAttributeData, properties), DebugProgram::TextureBindings{textures::image::Value{debugBucket->texture->getResource()}}, "border"); } } void RenderTile::setFeatureState(const LayerFeatureStates& states) { tile.setFeatureState(states); } } // namespace mbgl