[core] fix background-pattern rendering in perspective view

fix #3801
This commit is contained in:
Ansis Brammanis
2016-03-28 11:57:45 -07:00
parent 4522bf02c9
commit b352bb81d8
7 changed files with 123 additions and 112 deletions

View File

@@ -26,7 +26,7 @@
],
"devDependencies": {
"aws-sdk": "^2.2.21",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#8859b504ef241bca49d4c2f9a79ff4d0bfdf81a1",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#872753bf80fc026caf99e540b9f2089be8c06030",
"node-gyp": "^3.2.1",
"request": "^2.67.0",
"tape": "^4.2.2"

View File

@@ -33,7 +33,6 @@
#include <mbgl/shader/circle_shader.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/mat3.hpp>
#if defined(DEBUG)
#include <mbgl/util/stopwatch.hpp>
@@ -257,89 +256,6 @@ void Painter::renderPass(RenderPass pass_,
}
}
void Painter::renderBackground(const BackgroundLayer& layer) {
// Note that for bottommost layers without a pattern, the background color is drawn with
// glClear rather than this method.
const BackgroundPaintProperties& properties = layer.paint;
if (!properties.pattern.value.to.empty()) {
optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(properties.pattern.value.from, true);
optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(properties.pattern.value.to, true);
if (!imagePosA || !imagePosB)
return;
config.program = patternShader->getID();
patternShader->u_matrix = identityMatrix;
patternShader->u_pattern_tl_a = (*imagePosA).tl;
patternShader->u_pattern_br_a = (*imagePosA).br;
patternShader->u_pattern_tl_b = (*imagePosB).tl;
patternShader->u_pattern_br_b = (*imagePosB).br;
patternShader->u_mix = properties.pattern.value.t;
patternShader->u_opacity = properties.opacity;
LatLng latLng = state.getLatLng();
double centerX = state.lngX(latLng.longitude);
double centerY = state.latY(latLng.latitude);
float scale = 1 / std::pow(2, state.getZoomFraction());
std::array<float, 2> sizeA = (*imagePosA).size;
mat3 matrixA;
matrix::identity(matrixA);
matrix::scale(matrixA, matrixA,
1.0f / (sizeA[0] * properties.pattern.value.fromScale),
1.0f / (sizeA[1] * properties.pattern.value.fromScale));
matrix::translate(matrixA, matrixA,
std::fmod(centerX, sizeA[0] * properties.pattern.value.fromScale),
std::fmod(centerY, sizeA[1] * properties.pattern.value.fromScale));
matrix::rotate(matrixA, matrixA, -state.getAngle());
matrix::scale(matrixA, matrixA,
scale * state.getWidth() / 2,
-scale * state.getHeight() / 2);
std::array<float, 2> sizeB = (*imagePosB).size;
mat3 matrixB;
matrix::identity(matrixB);
matrix::scale(matrixB, matrixB,
1.0f / (sizeB[0] * properties.pattern.value.toScale),
1.0f / (sizeB[1] * properties.pattern.value.toScale));
matrix::translate(matrixB, matrixB,
std::fmod(centerX, sizeB[0] * properties.pattern.value.toScale),
std::fmod(centerY, sizeB[1] * properties.pattern.value.toScale));
matrix::rotate(matrixB, matrixB, -state.getAngle());
matrix::scale(matrixB, matrixB,
scale * state.getWidth() / 2,
-scale * state.getHeight() / 2);
patternShader->u_patternmatrix_a = matrixA;
patternShader->u_patternmatrix_b = matrixB;
VertexArrayObject::Unbind();
backgroundBuffer.bind(glObjectStore);
patternShader->bind(0);
spriteAtlas->bind(true, glObjectStore);
} else {
Color color = properties.color;
color[0] *= properties.opacity;
color[1] *= properties.opacity;
color[2] *= properties.opacity;
color[3] *= properties.opacity;
config.program = plainShader->getID();
plainShader->u_matrix = identityMatrix;
plainShader->u_color = color;
backgroundArray.bind(*plainShader, backgroundBuffer, BUFFER_OFFSET(0), glObjectStore);
}
config.stencilTest = GL_FALSE;
config.depthFunc.reset();
config.depthTest = GL_TRUE;
config.depthMask = GL_FALSE;
setDepthSublayer(0);
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const TileID &id, TranslateAnchorType anchor) {
if (translation[0] == 0 && translation[1] == 0) {
return matrix;

View File

@@ -181,13 +181,6 @@ private:
std::unique_ptr<CollisionBoxShader> collisionBoxShader;
std::unique_ptr<CircleShader> circleShader;
StaticVertexBuffer backgroundBuffer = {
{ -1, -1 }, { 1, -1 },
{ -1, 1 }, { 1, 1 }
};
VertexArrayObject backgroundArray;
// Set up the stencil quad we're using to generate the stencil mask.
StaticVertexBuffer tileStencilBuffer = {
// top left triangle
@@ -203,6 +196,8 @@ private:
VertexArrayObject coveringPlainArray;
VertexArrayObject coveringRasterArray;
VertexArrayObject backgroundPatternArray;
VertexArrayObject backgroundArray;
// Set up the tile boundary lines we're using to draw the tile outlines.
StaticVertexBuffer tileBorderBuffer = {

View File

@@ -0,0 +1,105 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/layer/background_layer.hpp>
#include <mbgl/shader/pattern_shader.hpp>
#include <mbgl/shader/plain_shader.hpp>
#include <mbgl/util/mat4.hpp>
#include <mbgl/util/tile_cover.hpp>
using namespace mbgl;
void Painter::renderBackground(const BackgroundLayer& layer) {
// Note that for bottommost layers without a pattern, the background color is drawn with
// glClear rather than this method.
const BackgroundPaintProperties& properties = layer.paint;
const bool isPatterned = !properties.pattern.value.to.empty();// && false;
optional<SpriteAtlasPosition> imagePosA;
optional<SpriteAtlasPosition> imagePosB;
if (isPatterned) {
imagePosA = spriteAtlas->getPosition(properties.pattern.value.from, true);
imagePosB = spriteAtlas->getPosition(properties.pattern.value.to, true);
if (!imagePosA || !imagePosB)
return;
config.program = patternShader->getID();
patternShader->u_matrix = identityMatrix;
patternShader->u_pattern_tl_a = (*imagePosA).tl;
patternShader->u_pattern_br_a = (*imagePosA).br;
patternShader->u_pattern_tl_b = (*imagePosB).tl;
patternShader->u_pattern_br_b = (*imagePosB).br;
patternShader->u_mix = properties.pattern.value.t;
patternShader->u_opacity = properties.opacity;
spriteAtlas->bind(true, glObjectStore);
backgroundPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0), glObjectStore);
} else {
Color color = properties.color;
color[0] *= properties.opacity;
color[1] *= properties.opacity;
color[2] *= properties.opacity;
color[3] *= properties.opacity;
config.program = plainShader->getID();
plainShader->u_color = color;
backgroundArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0), glObjectStore);
}
config.stencilTest = GL_FALSE;
config.depthFunc.reset();
config.depthTest = GL_TRUE;
config.depthMask = GL_FALSE;
setDepthSublayer(0);
auto tileIDs = tileCover(state, state.getIntegerZoom(), state.getIntegerZoom());
for (auto &id: tileIDs) {
mat4 vtxMatrix;
state.matrixFor(vtxMatrix, id, id.z);
matrix::multiply(vtxMatrix, projMatrix, vtxMatrix);
if (isPatterned) {
patternShader->u_matrix = vtxMatrix;
const float factor = util::EXTENT / util::tileSize;
std::array<int, 2> imageSizeScaledA = {{
(int)((*imagePosA).size[0] * properties.pattern.value.fromScale),
(int)((*imagePosA).size[1] * properties.pattern.value.fromScale)
}};
std::array<int, 2> imageSizeScaledB = {{
(int)((*imagePosB).size[0] * properties.pattern.value.toScale),
(int)((*imagePosB).size[1] * properties.pattern.value.toScale)
}};
patternShader->u_patternscale_a = {{
1.0f / (factor * imageSizeScaledA[0]),
1.0f / (factor * imageSizeScaledA[1])
}};
patternShader->u_patternscale_b = {{
1.0f / (factor * imageSizeScaledB[0]),
1.0f / (factor * imageSizeScaledB[1])
}};
float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * id.x) / (float)imageSizeScaledA[0];
float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * id.y) / (float)imageSizeScaledA[1];
float offsetBx = (std::fmod(util::tileSize, imageSizeScaledB[0]) * id.x) / (float)imageSizeScaledB[0];
float offsetBy = (std::fmod(util::tileSize, imageSizeScaledB[1]) * id.y) / (float)imageSizeScaledB[1];
patternShader->u_offset_a = std::array<float, 2>{{offsetAx, offsetAy}};
patternShader->u_offset_b = std::array<float, 2>{{offsetBx, offsetBy}};
} else {
plainShader->u_matrix = vtxMatrix;
Color color = properties.color;
plainShader->u_color = color;
}
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)tileStencilBuffer.index()));
}
}

View File

@@ -6,7 +6,6 @@
#include <mbgl/shader/outline_shader.hpp>
#include <mbgl/shader/pattern_shader.hpp>
#include <mbgl/shader/plain_shader.hpp>
#include <mbgl/util/mat3.hpp>
using namespace mbgl;
@@ -68,17 +67,6 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI
const float factor =
(util::EXTENT / util::tileSize / std::pow(2, state.getIntegerZoom() - id.sourceZ));
mat3 patternMatrixA;
matrix::identity(patternMatrixA);
matrix::scale(patternMatrixA, patternMatrixA,
1.0f / ((*posA).size[0] * factor * properties.pattern.value.fromScale),
1.0f / ((*posA).size[1] * factor * properties.pattern.value.fromScale));
mat3 patternMatrixB;
matrix::identity(patternMatrixB);
matrix::scale(patternMatrixB, patternMatrixB,
1.0f / ((*posB).size[0] * factor * properties.pattern.value.toScale),
1.0f / ((*posB).size[1] * factor * properties.pattern.value.toScale));
config.program = patternShader->getID();
patternShader->u_matrix = vtxMatrix;
patternShader->u_pattern_tl_a = (*posA).tl;
@@ -88,8 +76,6 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI
patternShader->u_opacity = properties.opacity;
patternShader->u_image = 0;
patternShader->u_mix = properties.pattern.value.t;
patternShader->u_patternmatrix_a = patternMatrixA;
patternShader->u_patternmatrix_b = patternMatrixB;
std::array<int, 2> imageSizeScaledA = {{
(int)((*posA).size[0] * properties.pattern.value.fromScale),
@@ -100,6 +86,15 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI
(int)((*posB).size[1] * properties.pattern.value.toScale)
}};
patternShader->u_patternscale_a = {{
1.0f / (factor * imageSizeScaledA[0]),
1.0f / (factor * imageSizeScaledA[1])
}};
patternShader->u_patternscale_b = {{
1.0f / (factor * imageSizeScaledB[0]),
1.0f / (factor * imageSizeScaledB[1])
}};
float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * id.x) / (float)imageSizeScaledA[0];
float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * id.y) / (float)imageSizeScaledA[1];

View File

@@ -1,6 +1,6 @@
uniform mat4 u_matrix;
uniform mat3 u_patternmatrix_a;
uniform mat3 u_patternmatrix_b;
uniform vec2 u_patternscale_a;
uniform vec2 u_patternscale_b;
uniform vec2 u_offset_a;
uniform vec2 u_offset_b;
@@ -12,6 +12,6 @@ varying vec2 v_pos_b;
void main() {
gl_Position = u_matrix * vec4(a_pos, 0, 1);
v_pos_a = (u_patternmatrix_a * vec3(a_pos, 1)).xy + u_offset_a;
v_pos_b = (u_patternmatrix_b * vec3(a_pos, 1)).xy + u_offset_b;
v_pos_a = u_patternscale_a * a_pos + u_offset_a;
v_pos_b = u_patternscale_b * a_pos + u_offset_b;
}

View File

@@ -20,8 +20,8 @@ public:
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
Uniform<GLfloat> u_mix = {"u_mix", *this};
Uniform<GLint> u_image = {"u_image", *this};
UniformMatrix<3> u_patternmatrix_a = {"u_patternmatrix_a", *this};
UniformMatrix<3> u_patternmatrix_b = {"u_patternmatrix_b", *this};
Uniform<std::array<GLfloat, 2>> u_patternscale_a = {"u_patternscale_a", *this};
Uniform<std::array<GLfloat, 2>> u_patternscale_b = {"u_patternscale_b", *this};
Uniform<std::array<GLfloat, 2>> u_offset_a = {"u_offset_a", *this};
Uniform<std::array<GLfloat, 2>> u_offset_b = {"u_offset_b", *this};
};