Render map with a copy of TransformState

This commit is contained in:
John Firebaugh
2014-10-21 15:00:44 -07:00
parent 4f7bc80664
commit da8aa391d0
12 changed files with 248 additions and 233 deletions

View File

@@ -55,8 +55,6 @@ public:
// Triggers a lazy rerender: only performs a render when the map is not clean.
void rerender();
void renderLayer(util::ptr<StyleLayer> layer_desc, RenderPass pass, const Tile::ID* id = nullptr, const mat4* matrix = nullptr);
// Forces a map update: always triggers a rerender.
void update();
@@ -156,18 +154,14 @@ private:
void updateSources();
void updateSources(const util::ptr<StyleLayerGroup> &group);
void updateRenderState();
size_t countLayers(const std::vector<LayerDescription>& layers);
// Prepares a map render by updating the tiles we need for the current view, as well as updating
// the stylesheet.
void prepare();
// Unconditionally performs a render with the current map state.
void render();
void renderLayers(util::ptr<StyleLayerGroup> group);
private:
bool async = false;
@@ -224,8 +218,6 @@ private:
bool debug = false;
timestamp animationTime = 0;
int indent = 0;
std::set<util::ptr<StyleSource>> activeSources;
};

View File

@@ -33,6 +33,7 @@ public:
float lngX(float lon) const;
float latY(float lat) const;
std::array<float, 2> locationCoordinate(float lon, float lat) const;
void getLonLat(double &lon, double &lat) const;
// Zoom
float getNormalizedZoom() const;
@@ -69,7 +70,7 @@ private:
// map position
double x = 0, y = 0;
double angle = 0;
double scale = std::numeric_limits<double>::infinity();
double scale = 1;
};
}

View File

@@ -35,9 +35,12 @@ enum class RenderPass : bool { Opaque, Translucent };
class Transform;
class Style;
class Tile;
class Sprite;
class SpriteAtlas;
class GlyphAtlas;
class Source;
class StyleSource;
class StyleLayerGroup;
class FillBucket;
class LineBucket;
@@ -53,10 +56,9 @@ class RasterTileData;
class Painter : private util::noncopyable {
public:
Painter(Map &map);
Painter(SpriteAtlas&, GlyphAtlas&);
~Painter();
void setup();
// Perform cleanup tasks that prepare shutting down the app. This doesn't mean that the
@@ -73,6 +75,14 @@ public:
// Updates the default matrices to the current viewport dimensions.
void changeMatrix();
void render(const Style& style,
const std::set<util::ptr<StyleSource>>& sources,
TransformState state,
timestamp time);
void renderLayers(util::ptr<StyleLayerGroup> group);
void renderLayer(util::ptr<StyleLayer> layer_desc, RenderPass pass, const Tile::ID* id = nullptr, const mat4* matrix = nullptr);
// Renders a particular layer from a tile.
void renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc, const mat4 &matrix);
@@ -167,9 +177,10 @@ public:
}();
private:
Map& map;
TransformState state;
bool debug = false;
int indent = 0;
uint32_t gl_program = 0;
float gl_lineWidth = 0;
@@ -183,6 +194,9 @@ private:
public:
FrameHistory frameHistory;
SpriteAtlas& spriteAtlas;
GlyphAtlas& glyphAtlas;
std::unique_ptr<PlainShader> plainShader;
std::unique_ptr<OutlineShader> outlineShader;
std::unique_ptr<LineShader> lineShader;

View File

@@ -44,7 +44,7 @@ Map::Map(View& view_)
glyphAtlas(std::make_shared<GlyphAtlas>(1024, 1024)),
spriteAtlas(std::make_shared<SpriteAtlas>(512, 512)),
texturepool(std::make_shared<Texturepool>()),
painter(*this) {
painter(*spriteAtlas, *glyphAtlas) {
view.initialize(this);
@@ -598,15 +598,6 @@ void Map::updateTiles() {
}
}
void Map::updateRenderState() {
// Update all clipping IDs.
ClipIDGenerator generator;
for (const util::ptr<StyleSource> &source : getActiveSources()) {
generator.update(source->source->getLoadedTiles());
source->source->updateMatrices(painter.projMatrix, state);
}
}
void Map::prepare() {
if (!fileSource) {
fileSource = std::make_shared<FileSource>(**loop, platform::defaultCacheDatabase());
@@ -654,152 +645,13 @@ void Map::prepare() {
void Map::render() {
view.make_active();
painter.clear();
painter.resize();
painter.changeMatrix();
updateRenderState();
painter.drawClippingMasks(getActiveSources());
painter.frameHistory.record(getAnimationTime(), getState().getNormalizedZoom());
// Actually render the layers
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
renderLayers(style->layers);
if (debug::renderTree) { std::cout << "}" << std::endl; indent--; }
// Finalize the rendering, e.g. by calling debug render calls per tile.
// This guarantees that we have at least one function per tile called.
// When only rendering layers via the stylesheet, it's possible that we don't
// ever visit a tile during rendering.
for (const util::ptr<StyleSource> &source : getActiveSources()) {
source->source->finishRender(painter);
}
painter.render(*style, getActiveSources(),
getState(), getAnimationTime());
// Schedule another rerender when we definitely need a next frame.
if (transform.needsTransition() || style->hasTransitions()) {
update();
}
glFlush();
view.make_inactive();
}
void Map::renderLayers(util::ptr<StyleLayerGroup> group) {
if (!group) {
// Make sure that we actually do have a layer group.
return;
}
// TODO: Correctly compute the number of layers recursively beforehand.
float strata_thickness = 1.0f / (group->layers.size() + 1);
// - FIRST PASS ------------------------------------------------------------
// Render everything top-to-bottom by using reverse iterators. Render opaque
// objects first.
if (debug::renderTree) {
std::cout << std::string(indent++ * 4, ' ') << "OPAQUE {" << std::endl;
}
int i = 0;
for (auto it = group->layers.rbegin(), end = group->layers.rend(); it != end; ++it, ++i) {
painter.setOpaque();
painter.setStrata(i * strata_thickness);
renderLayer(*it, RenderPass::Opaque);
}
if (debug::renderTree) {
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
}
// - SECOND PASS -----------------------------------------------------------
// Make a second pass, rendering translucent objects. This time, we render
// bottom-to-top.
if (debug::renderTree) {
std::cout << std::string(indent++ * 4, ' ') << "TRANSLUCENT {" << std::endl;
}
--i;
for (auto it = group->layers.begin(), end = group->layers.end(); it != end; ++it, --i) {
painter.setTranslucent();
painter.setStrata(i * strata_thickness);
renderLayer(*it, RenderPass::Translucent);
}
if (debug::renderTree) {
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
}
}
void Map::renderLayer(util::ptr<StyleLayer> layer_desc, RenderPass pass, const Tile::ID* id, const mat4* matrix) {
if (layer_desc->type == StyleLayerType::Background) {
// This layer defines a background color/image.
if (debug::renderTree) {
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
<< layer_desc->type << ")" << std::endl;
}
painter.renderBackground(layer_desc);
} else {
// This is a singular layer.
if (!layer_desc->bucket) {
fprintf(stderr, "[WARNING] layer '%s' is missing bucket\n", layer_desc->id.c_str());
return;
}
if (!layer_desc->bucket->style_source) {
fprintf(stderr, "[WARNING] can't find source for layer '%s'\n", layer_desc->id.c_str());
return;
}
StyleSource &style_source = *layer_desc->bucket->style_source;
// Skip this layer if there is no data.
if (!style_source.source) {
return;
}
// Skip this layer if it's outside the range of min/maxzoom.
// This may occur when there /is/ a bucket created for this layer, but the min/max-zoom
// is set to a fractional value, or value that is larger than the source maxzoom.
const double zoom = state.getZoom();
if (layer_desc->bucket->min_zoom > zoom ||
layer_desc->bucket->max_zoom <= zoom) {
return;
}
// Abort early if we can already deduce from the bucket type that
// we're not going to render anything anyway during this pass.
switch (layer_desc->type) {
case StyleLayerType::Fill:
if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
break;
case StyleLayerType::Line:
if (pass == RenderPass::Opaque) return;
if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
break;
case StyleLayerType::Symbol:
if (pass == RenderPass::Opaque) return;
if (!layer_desc->getProperties<SymbolProperties>().isVisible()) return;
break;
case StyleLayerType::Raster:
if (pass == RenderPass::Opaque) return;
if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
break;
default:
break;
}
if (debug::renderTree) {
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
<< layer_desc->type << ")" << std::endl;
}
if (!id) {
style_source.source->render(painter, layer_desc);
} else {
style_source.source->render(painter, layer_desc, *id, *matrix);
}
}
}

View File

@@ -13,13 +13,13 @@
using namespace mbgl;
const double D2R = M_PI / 180.0;
const double R2D = 180.0 / M_PI;
const double M2PI = 2 * M_PI;
const double MIN_ROTATE_SCALE = 8;
Transform::Transform(View &view_) : view(view_), mtx(std::make_unique<uv::rwlock>()) {
setScale(current.scale);
setAngle(current.angle);
Transform::Transform(View &view_)
: view(view_)
, mtx(std::make_unique<uv::rwlock>())
{
}
#pragma mark - Map View
@@ -123,8 +123,7 @@ void Transform::setLonLatZoom(const double lon, const double lat, const double z
void Transform::getLonLat(double &lon, double &lat) const {
uv::readlock lock(mtx);
lon = -final.x / Bc;
lat = R2D * (2 * std::atan(std::exp(final.y / Cc)) - 0.5 * M_PI);
final.getLonLat(lon, lat);
}
void Transform::getLonLatZoom(double &lon, double &lat, double &zoom) const {

View File

@@ -3,6 +3,8 @@
using namespace mbgl;
const double R2D = 180.0 / M_PI;
#pragma mark - Matrix
void TransformState::matrixFor(mat4& matrix, const Tile::ID& id) const {
@@ -108,6 +110,15 @@ std::array<float, 2> TransformState::locationCoordinate(float lon, float lat) co
}};
}
void TransformState::getLonLat(double &lon, double &lat) const {
const double s = scale * util::tileSize;
const double Bc = s / 360;
const double Cc = s / (2 * M_PI);
lon = -x / Bc;
lat = R2D * (2 * std::atan(std::exp(y / Cc)) - 0.5 * M_PI);
}
#pragma mark - Zoom

View File

@@ -1,7 +1,8 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/style/style_layer_group.hpp>
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/time.hpp>
@@ -9,6 +10,7 @@
#include <mbgl/util/constants.hpp>
#include <mbgl/util/mat3.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/map/source.hpp>
#if defined(DEBUG)
#include <mbgl/util/timer.hpp>
@@ -16,13 +18,16 @@
#include <cassert>
#include <algorithm>
#include <iostream>
using namespace mbgl;
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
Painter::Painter(Map &map_)
: map(map_) {
Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_)
: spriteAtlas(spriteAtlas_)
, glyphAtlas(glyphAtlas_)
{
}
Painter::~Painter() {
@@ -109,7 +114,6 @@ void Painter::terminate() {
}
void Painter::resize() {
const TransformState &state = map.getState();
if (gl_viewport != state.getFramebufferDimensions()) {
gl_viewport = state.getFramebufferDimensions();
assert(gl_viewport[0] > 0 && gl_viewport[1] > 0);
@@ -152,12 +156,12 @@ void Painter::depthRange(const float near, const float far) {
void Painter::changeMatrix() {
// Initialize projection matrix
matrix::ortho(projMatrix, 0, map.getState().getWidth(), map.getState().getHeight(), 0, 0, 1);
matrix::ortho(projMatrix, 0, state.getWidth(), state.getHeight(), 0, 0, 1);
// The extrusion matrix.
matrix::identity(extrudeMatrix);
matrix::multiply(extrudeMatrix, projMatrix, extrudeMatrix);
matrix::rotate_z(extrudeMatrix, extrudeMatrix, map.getState().getAngle());
matrix::rotate_z(extrudeMatrix, extrudeMatrix, state.getAngle());
// The native matrix is a 1:1 matrix that paints the coordinates at the
// same screen position as the vertex specifies.
@@ -200,6 +204,156 @@ void Painter::prepareTile(const Tile& tile) {
glStencilFunc(GL_EQUAL, ref, mask);
}
void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>& sources,
TransformState state_, timestamp time) {
state = state_;
clear();
resize();
changeMatrix();
// Update all clipping IDs.
ClipIDGenerator generator;
for (const util::ptr<StyleSource> &source : sources) {
generator.update(source->source->getLoadedTiles());
source->source->updateMatrices(projMatrix, state);
}
drawClippingMasks(sources);
frameHistory.record(time, state.getNormalizedZoom());
// Actually render the layers
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
renderLayers(style.layers);
if (debug::renderTree) { std::cout << "}" << std::endl; indent--; }
// Finalize the rendering, e.g. by calling debug render calls per tile.
// This guarantees that we have at least one function per tile called.
// When only rendering layers via the stylesheet, it's possible that we don't
// ever visit a tile during rendering.
for (const util::ptr<StyleSource> &source : sources) {
source->source->finishRender(*this);
}
glFlush();
}
void Painter::renderLayers(util::ptr<StyleLayerGroup> group) {
if (!group) {
// Make sure that we actually do have a layer group.
return;
}
// TODO: Correctly compute the number of layers recursively beforehand.
float strata_thickness = 1.0f / (group->layers.size() + 1);
// - FIRST PASS ------------------------------------------------------------
// Render everything top-to-bottom by using reverse iterators. Render opaque
// objects first.
if (debug::renderTree) {
std::cout << std::string(indent++ * 4, ' ') << "OPAQUE {" << std::endl;
}
int i = 0;
for (auto it = group->layers.rbegin(), end = group->layers.rend(); it != end; ++it, ++i) {
setOpaque();
setStrata(i * strata_thickness);
renderLayer(*it, RenderPass::Opaque);
}
if (debug::renderTree) {
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
}
// - SECOND PASS -----------------------------------------------------------
// Make a second pass, rendering translucent objects. This time, we render
// bottom-to-top.
if (debug::renderTree) {
std::cout << std::string(indent++ * 4, ' ') << "TRANSLUCENT {" << std::endl;
}
--i;
for (auto it = group->layers.begin(), end = group->layers.end(); it != end; ++it, --i) {
setTranslucent();
setStrata(i * strata_thickness);
renderLayer(*it, RenderPass::Translucent);
}
if (debug::renderTree) {
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
}
}
void Painter::renderLayer(util::ptr<StyleLayer> layer_desc, RenderPass pass, const Tile::ID* id, const mat4* matrix) {
if (layer_desc->type == StyleLayerType::Background) {
// This layer defines a background color/image.
if (debug::renderTree) {
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
<< layer_desc->type << ")" << std::endl;
}
renderBackground(layer_desc);
} else {
// This is a singular layer.
if (!layer_desc->bucket) {
fprintf(stderr, "[WARNING] layer '%s' is missing bucket\n", layer_desc->id.c_str());
return;
}
if (!layer_desc->bucket->style_source) {
fprintf(stderr, "[WARNING] can't find source for layer '%s'\n", layer_desc->id.c_str());
return;
}
StyleSource &style_source = *layer_desc->bucket->style_source;
// Skip this layer if there is no data.
if (!style_source.source) {
return;
}
// Skip this layer if it's outside the range of min/maxzoom.
// This may occur when there /is/ a bucket created for this layer, but the min/max-zoom
// is set to a fractional value, or value that is larger than the source maxzoom.
const double zoom = state.getZoom();
if (layer_desc->bucket->min_zoom > zoom ||
layer_desc->bucket->max_zoom <= zoom) {
return;
}
// Abort early if we can already deduce from the bucket type that
// we're not going to render anything anyway during this pass.
switch (layer_desc->type) {
case StyleLayerType::Fill:
if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
break;
case StyleLayerType::Line:
if (pass == RenderPass::Opaque) return;
if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
break;
case StyleLayerType::Symbol:
if (pass == RenderPass::Opaque) return;
if (!layer_desc->getProperties<SymbolProperties>().isVisible()) return;
break;
case StyleLayerType::Raster:
if (pass == RenderPass::Opaque) return;
if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
break;
default:
break;
}
if (debug::renderTree) {
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
<< layer_desc->type << ")" << std::endl;
}
if (!id) {
style_source.source->render(*this, layer_desc);
} else {
style_source.source->render(*this, layer_desc, *id, *matrix);
}
}
}
void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc, const mat4 &matrix) {
assert(tile.data);
if (tile.data->hasData(layer_desc) || layer_desc->type == StyleLayerType::Raster) {
@@ -211,15 +365,13 @@ void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc
void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
const BackgroundProperties& properties = layer_desc->getProperties<BackgroundProperties>();
const std::shared_ptr<Sprite> sprite = map.getSprite();
if (properties.image.size() && sprite) {
if (properties.image.size()) {
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
return;
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
float zoomFraction = map.getState().getZoomFraction();
float zoomFraction = state.getZoomFraction();
useProgram(patternShader->program);
patternShader->u_matrix = identityMatrix;
@@ -230,8 +382,8 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
std::array<float, 2> size = imagePos.size;
double lon, lat;
map.getLonLat(lon, lat);
std::array<float, 2> center = map.getState().locationCoordinate(lon, lat);
state.getLonLat(lon, lat);
std::array<float, 2> center = state.locationCoordinate(lon, lat);
float scale = 1 / std::pow(2, zoomFraction);
mat3 matrix;
@@ -242,10 +394,10 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
matrix::translate(matrix, matrix,
std::fmod(center[0] * 512, size[0]),
std::fmod(center[1] * 512, size[1]));
matrix::rotate(matrix, matrix, -map.getState().getAngle());
matrix::rotate(matrix, matrix, -state.getAngle());
matrix::scale(matrix, matrix,
scale * map.getState().getWidth() / 2,
-scale * map.getState().getHeight() / 2);
scale * state.getWidth() / 2,
-scale * state.getHeight() / 2);
patternShader->u_patternmatrix = matrix;
backgroundBuffer.bind();
@@ -278,12 +430,12 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &t
return matrix;
} else {
// TODO: Get rid of the 8 (scaling from 4096 to tile size)
const double factor = ((double)(1 << id.z)) / map.getState().getScale() * (4096.0 / util::tileSize);
const double factor = ((double)(1 << id.z)) / state.getScale() * (4096.0 / util::tileSize);
mat4 vtxMatrix;
if (anchor == TranslateAnchorType::Viewport) {
const double sin_a = std::sin(-map.getState().getAngle());
const double cos_a = std::cos(-map.getState().getAngle());
const double sin_a = std::sin(-state.getAngle());
const double cos_a = std::cos(-state.getAngle());
matrix::translate(vtxMatrix, matrix,
factor * (translation[0] * cos_a - translation[1] * sin_a),
factor * (translation[0] * sin_a + translation[1] * cos_a),

View File

@@ -25,7 +25,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
// Draw white outline
plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
lineWidth(4.0f * map.getState().getPixelRatio());
lineWidth(4.0f * state.getPixelRatio());
bucket.drawLines(*plainShader);
#ifndef GL_ES_VERSION_2_0
@@ -36,7 +36,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
// Draw black text.
plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
lineWidth(2.0f * map.getState().getPixelRatio());
lineWidth(2.0f * state.getPixelRatio());
bucket.drawLines(*plainShader);
glEnable(GL_DEPTH_TEST);
@@ -56,7 +56,7 @@ void Painter::renderDebugFrame(const mat4 &matrix) {
// draw tile outline
tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0));
plainShader->u_color = {{ 1.0f, 0.0f, 0.0f, 1.0f }};
lineWidth(4.0f * map.getState().getPixelRatio());
lineWidth(4.0f * state.getPixelRatio());
glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index());
glEnable(GL_DEPTH_TEST);
@@ -87,14 +87,14 @@ void Painter::renderDebugText(const std::vector<std::string> &strings) {
VertexArrayObject debugFontArray;
debugFontArray.bind(*plainShader, debugFontBuffer, BUFFER_OFFSET(0));
plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
lineWidth(4.0f * map.getState().getPixelRatio());
lineWidth(4.0f * state.getPixelRatio());
glDrawArrays(GL_LINES, 0, (GLsizei)debugFontBuffer.index());
#ifndef GL_ES_VERSION_2_0
glPointSize(2);
glDrawArrays(GL_POINTS, 0, (GLsizei)debugFontBuffer.index());
#endif
plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
lineWidth(2.0f * map.getState().getPixelRatio());
lineWidth(2.0f * state.getPixelRatio());
glDrawArrays(GL_LINES, 0, (GLsizei)debugFontBuffer.index());
}

View File

@@ -49,8 +49,8 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
// Draw the entire line
outlineShader->u_world = {{
static_cast<float>(map.getState().getFramebufferWidth()),
static_cast<float>(map.getState().getFramebufferHeight())
static_cast<float>(state.getFramebufferWidth()),
static_cast<float>(state.getFramebufferHeight())
}};
depthRange(strata, 1.0f);
bucket.drawVertices(*outlineShader);
@@ -58,12 +58,10 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
if (pattern) {
// Image fill.
Sprite &sprite = *map.getSprite();
if (pass == RenderPass::Translucent && sprite) {
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
if (pass == RenderPass::Translucent) {
const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, true);
const float mix = std::fmod(float(map.getState().getZoom()), 1.0f);
const float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
const float mix = std::fmod(float(state.getZoom()), 1.0f);
const float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
mat3 patternMatrix;
matrix::identity(patternMatrix);
@@ -114,8 +112,8 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
// Draw the entire line
outlineShader->u_world = {{
static_cast<float>(map.getState().getFramebufferWidth()),
static_cast<float>(map.getState().getFramebufferHeight())
static_cast<float>(state.getFramebufferWidth()),
static_cast<float>(state.getFramebufferHeight())
}};
depthRange(strata + strata_epsilon, 1.0f);

View File

@@ -15,7 +15,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
const LineProperties &properties = layer_desc->getProperties<LineProperties>();
float antialiasing = 1 / map.getState().getPixelRatio();
float antialiasing = 1 / state.getPixelRatio();
float width = properties.width;
float offset = properties.offset / 2;
float blur = properties.blur + antialiasing;
@@ -34,7 +34,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
float dash_length = properties.dash_array[0];
float dash_gap = properties.dash_array[1];
float ratio = map.getState().getPixelRatio();
float ratio = state.getPixelRatio();
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
depthRange(strata, 1.0f);
@@ -45,15 +45,15 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
linejoinShader->u_matrix = vtxMatrix;
linejoinShader->u_color = color;
linejoinShader->u_world = {{
map.getState().getFramebufferWidth() * 0.5f,
map.getState().getFramebufferHeight() * 0.5f
state.getFramebufferWidth() * 0.5f,
state.getFramebufferHeight() * 0.5f
}};
linejoinShader->u_linewidth = {{
((outset - 0.25f) * map.getState().getPixelRatio()),
((inset - 0.25f) * map.getState().getPixelRatio())
((outset - 0.25f) * state.getPixelRatio()),
((inset - 0.25f) * state.getPixelRatio())
}};
float pointSize = std::ceil(map.getState().getPixelRatio() * outset * 2.0);
float pointSize = std::ceil(state.getPixelRatio() * outset * 2.0);
#if defined(GL_ES_VERSION_2_0)
linejoinShader->u_size = pointSize;
#else
@@ -62,12 +62,11 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
bucket.drawPoints(*linejoinShader);
}
const util::ptr<Sprite> &sprite = map.getSprite();
if (properties.image.size() && sprite) {
SpriteAtlasPosition imagePos = map.getSpriteAtlas()->getPosition(properties.image, *sprite);
if (properties.image.size()) {
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image);
float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
float fade = std::fmod(map.getState().getZoom(), 1.0);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
float fade = std::fmod(state.getZoom(), 1.0);
useProgram(linepatternShader->program);
@@ -82,7 +81,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
linepatternShader->u_pattern_br = imagePos.br;
linepatternShader->u_fade = fade;
map.getSpriteAtlas()->bind(true);
spriteAtlas.bind(true);
glDepthRange(strata + strata_epsilon, 1.0f); // may or may not matter
bucket.drawLinePatterns(*linepatternShader);

View File

@@ -31,14 +31,11 @@ void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_des
return vtxMatrix;
}();
// call updateTiles to get parsed data for sublayers
map.updateTiles();
for (const util::ptr<StyleLayer> &layer : layer_desc->layers->layers) {
setOpaque();
map.renderLayer(layer, RenderPass::Opaque, &id, &preMatrix);
renderLayer(layer, RenderPass::Opaque, &id, &preMatrix);
setTranslucent();
map.renderLayer(layer, RenderPass::Translucent, &id, &preMatrix);
renderLayer(layer, RenderPass::Translucent, &id, &preMatrix);
}
if (bucket.properties.blur > 0) {

View File

@@ -24,8 +24,9 @@ void Painter::renderSDF(SymbolBucket &bucket,
mat4 exMatrix;
matrix::copy(exMatrix, projMatrix);
bool aligned_with_map = (bucketProperties.rotation_alignment == RotationAlignmentType::Map);
const float angleOffset = aligned_with_map ? map.getState().getAngle() : 0;
const float angleOffset = aligned_with_map ? state.getAngle() : 0;
if (angleOffset) {
matrix::rotate_z(exMatrix, exMatrix, angleOffset);
@@ -42,24 +43,24 @@ void Painter::renderSDF(SymbolBucket &bucket,
sdfShader.u_texsize = texsize;
// Convert the -pi..pi to an int8 range.
float angle = std::round(map.getState().getAngle() / M_PI * 128);
float angle = std::round(state.getAngle() / M_PI * 128);
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / bucketProperties.max_size) / std::log(2);
sdfShader.u_flip = (aligned_with_map && bucketProperties.keep_upright) ? 1 : 0;
sdfShader.u_angle = (int32_t)(angle + 256) % 256;
sdfShader.u_zoom = (map.getState().getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
sdfShader.u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
FadeProperties f = frameHistory.getFadeProperties(300_milliseconds);
sdfShader.u_fadedist = f.fadedist * 10;
sdfShader.u_minfadezoom = std::floor(f.minfadezoom * 10);
sdfShader.u_maxfadezoom = std::floor(f.maxfadezoom * 10);
sdfShader.u_fadezoom = (map.getState().getNormalizedZoom() + f.bump) * 10;
sdfShader.u_fadezoom = (state.getNormalizedZoom() + f.bump) * 10;
// The default gamma value has to be adjust for the current pixelratio so that we're not
// drawing blurry font on retina screens.
const float gamma = 0.105 * sdfFontSize / fontSize / map.getState().getPixelRatio();
const float gamma = 0.105 * sdfFontSize / fontSize / state.getPixelRatio();
const float sdfPx = 8.0f;
const float blurOffset = 1.19f;
@@ -124,15 +125,14 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
const float angleOffset =
bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map
? map.getState().getAngle()
? state.getAngle()
: 0;
// If layerStyle.size > bucket.info.fontSize then labels may collide
const float fontSize = properties.icon.size != 0 ? properties.icon.size : bucket.properties.icon.max_size;
const float fontScale = fontSize / 1.0f;
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
spriteAtlas.bind(map.getState().isChanging() || bucket.properties.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
spriteAtlas.bind(state.isChanging() || bucket.properties.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
std::array<float, 2> texsize = {{
float(spriteAtlas.getWidth()),
@@ -167,7 +167,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
iconShader->u_texsize = texsize;
// Convert the -pi..pi to an int8 range.
const float angle = std::round(map.getState().getAngle() / M_PI * 128);
const float angle = std::round(state.getAngle() / M_PI * 128);
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / bucket.properties.icon.max_size) / std::log(2);
@@ -177,12 +177,12 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
bool flip = (bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map)
&& bucket.properties.icon.keep_upright;
iconShader->u_flip = flip ? 1 : 0;
iconShader->u_zoom = (map.getState().getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
iconShader->u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
iconShader->u_fadedist = 0 * 10;
iconShader->u_minfadezoom = map.getState().getNormalizedZoom() * 10;
iconShader->u_maxfadezoom = map.getState().getNormalizedZoom() * 10;
iconShader->u_fadezoom = map.getState().getNormalizedZoom() * 10;
iconShader->u_minfadezoom = state.getNormalizedZoom() * 10;
iconShader->u_maxfadezoom = state.getNormalizedZoom() * 10;
iconShader->u_fadezoom = state.getNormalizedZoom() * 10;
iconShader->u_opacity = properties.icon.opacity;
depthRange(strata, 1.0f);
@@ -191,7 +191,6 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
}
if (bucket.hasTextData()) {
GlyphAtlas &glyphAtlas = *map.getGlyphAtlas();
glyphAtlas.bind();
renderSDF(bucket,
@@ -204,5 +203,6 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
*sdfGlyphShader,
&SymbolBucket::drawGlyphs);
}
glEnable(GL_STENCIL_TEST);
}