Files
MapLibreParticleLab/src/mbgl/renderer/painter_fill.cpp
Ansis Brammanis 9e68e49c89 fix depth clipping in perspective view
The depth range is now set slightly differently. Both ends of the range
are shifted for each layer to solve some precision issues.

Some layers draw multiple things at different depths. For example, fill
layers draw fills and antialiasing separately. To handle this case, I
added setDepthSublayer(n) which a
2015-08-24 18:41:51 -04:00

139 lines
5.4 KiB
C++

#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/style/style_layout.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/map/tile_id.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#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;
void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix) {
const FillProperties &properties = layer_desc.getProperties<FillProperties>();
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
Color fill_color = properties.fill_color;
fill_color[0] *= properties.opacity;
fill_color[1] *= properties.opacity;
fill_color[2] *= properties.opacity;
fill_color[3] *= properties.opacity;
Color stroke_color = properties.stroke_color;
if (stroke_color[3] < 0) {
stroke_color = fill_color;
} else {
stroke_color[0] *= properties.opacity;
stroke_color[1] *= properties.opacity;
stroke_color[2] *= properties.opacity;
stroke_color[3] *= properties.opacity;
}
const bool pattern = !properties.image.from.empty();
bool outline = properties.antialias && !pattern && stroke_color != fill_color;
bool fringeline = properties.antialias && !pattern && stroke_color == fill_color;
config.stencilTest = true;
config.depthTest = true;
// Because we're drawing top-to-bottom, and we update the stencil mask
// befrom, we have to draw the outline first (!)
if (outline && pass == RenderPass::Translucent) {
useProgram(outlineShader->program);
outlineShader->u_matrix = vtxMatrix;
lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
outlineShader->u_color = stroke_color;
// Draw the entire line
outlineShader->u_world = {{
static_cast<float>(frame.framebufferSize[0]),
static_cast<float>(frame.framebufferSize[1])
}};
setDepthSublayer(0);
bucket.drawVertices(*outlineShader);
}
if (pattern) {
// Image fill.
if (pass == RenderPass::Translucent) {
const SpriteAtlasPosition posA = spriteAtlas->getPosition(properties.image.from, true);
const SpriteAtlasPosition posB = spriteAtlas->getPosition(properties.image.to, true);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z) / id.overscaling;
mat3 patternMatrixA;
matrix::identity(patternMatrixA);
matrix::scale(patternMatrixA, patternMatrixA,
1.0f / (posA.size[0] * factor * properties.image.fromScale),
1.0f / (posA.size[1] * factor * properties.image.fromScale));
mat3 patternMatrixB;
matrix::identity(patternMatrixB);
matrix::scale(patternMatrixB, patternMatrixB,
1.0f / (posB.size[0] * factor * properties.image.toScale),
1.0f / (posB.size[1] * factor * properties.image.toScale));
useProgram(patternShader->program);
patternShader->u_matrix = vtxMatrix;
patternShader->u_pattern_tl_a = posA.tl;
patternShader->u_pattern_br_a = posA.br;
patternShader->u_pattern_tl_b = posB.tl;
patternShader->u_pattern_br_b = posB.br;
patternShader->u_opacity = properties.opacity;
patternShader->u_image = 0;
patternShader->u_mix = properties.image.t;
patternShader->u_patternmatrix_a = patternMatrixA;
patternShader->u_patternmatrix_b = patternMatrixB;
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
spriteAtlas->bind(true);
// Draw the actual triangles into the color & stencil buffer.
config.depthMask = GL_TRUE;
setDepthSublayer(0);
bucket.drawElements(*patternShader);
}
}
else {
// No image fill.
if ((fill_color[3] >= 1.0f) == (pass == RenderPass::Opaque)) {
// Only draw the fill when it's either opaque and we're drawing opaque
// fragments or when it's translucent and we're drawing translucent
// fragments
// Draw filling rectangle.
useProgram(plainShader->program);
plainShader->u_matrix = vtxMatrix;
plainShader->u_color = fill_color;
// Draw the actual triangles into the color & stencil buffer.
config.depthMask = GL_TRUE;
setDepthSublayer(1);
bucket.drawElements(*plainShader);
}
}
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
if (fringeline && pass == RenderPass::Translucent) {
useProgram(outlineShader->program);
outlineShader->u_matrix = vtxMatrix;
lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
outlineShader->u_color = fill_color;
// Draw the entire line
outlineShader->u_world = {{
static_cast<float>(frame.framebufferSize[0]),
static_cast<float>(frame.framebufferSize[1])
}};
setDepthSublayer(2);
bucket.drawVertices(*outlineShader);
}
}