render lines with the tessellated triangles
This commit is contained in:
@@ -180,32 +180,37 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
fill_color[2] *= properties.opacity;
|
||||
fill_color[3] *= properties.opacity;
|
||||
|
||||
bool outline = properties.antialias && properties.stroke_color != properties.fill_color;
|
||||
bool fringeline = properties.antialias && properties.stroke_color == properties.fill_color;
|
||||
|
||||
// Because we're drawing top-to-bottom, and we update the stencil mask
|
||||
// below, we have to draw the outline first (!)
|
||||
if (properties.antialias) {
|
||||
if (outline) {
|
||||
useProgram(outlineShader->program);
|
||||
outlineShader->setMatrix(matrix);
|
||||
lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
|
||||
|
||||
if (properties.stroke_color != properties.fill_color) {
|
||||
// If we defined a different color for the fill outline, we are
|
||||
// going to ignore the bits in 0x3F and just care about the global
|
||||
// clipping mask.
|
||||
glStencilFunc(GL_EQUAL, 0x80, 0x80);
|
||||
outlineShader->setColor(properties.stroke_color);
|
||||
} else {
|
||||
// Otherwise, we only want to draw the antialiased parts that are
|
||||
// *outside* the current shape. This is important in case the fill
|
||||
// or stroke color is translucent. If we wouldn't clip to outside
|
||||
// the current shape, some pixels from the outline stroke overlapped
|
||||
// the (non-antialiased) fill.
|
||||
glStencilFunc(GL_EQUAL, 0x80, 0xBF);
|
||||
outlineShader->setColor(fill_color);
|
||||
}
|
||||
outlineShader->setColor(properties.stroke_color);
|
||||
|
||||
// Draw the entire line
|
||||
outlineShader->setWorld({{ transform.fb_width, transform.fb_height }});
|
||||
bucket.drawVertices(*outlineShader);
|
||||
} else if (fringeline) {
|
||||
// We're only drawing to the first seven bits (== support a maximum of
|
||||
// 127 overlapping polygons in one place before we get rendering errors).
|
||||
glStencilMask(0x3F);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// Draw front facing triangles. Wherever the 0x80 bit is 1, we are
|
||||
// increasing the lower 7 bits by one if the triangle is a front-facing
|
||||
// triangle. This means that all visible polygons should be in CCW
|
||||
// orientation, while all holes (see below) are in CW orientation.
|
||||
glStencilFunc(GL_EQUAL, 0x80, 0x80);
|
||||
|
||||
// When we do a nonzero fill, we count the number of times a pixel is
|
||||
// covered by a counterclockwise polygon, and subtract the number of
|
||||
// times it is "uncovered" by a clockwise polygon.
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR_WRAP);
|
||||
}
|
||||
|
||||
if (false && properties.image.size() && *style.sprite) {
|
||||
@@ -216,14 +221,16 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
float mix = fmod(transform.getZoom(), 1.0);
|
||||
|
||||
std::array<float, 2> imageSize = {{
|
||||
imagePos.size.x * factor,
|
||||
imagePos.size.y * factor
|
||||
}};
|
||||
imagePos.size.x * factor,
|
||||
imagePos.size.y *factor
|
||||
}
|
||||
};
|
||||
|
||||
std::array<float, 2> offset = {{
|
||||
(float)fmod(id.x * 4096, imageSize[0]),
|
||||
(float)fmod(id.y * 4096, imageSize[1])
|
||||
}};
|
||||
(float)fmod(id.x * 4096, imageSize[0]),
|
||||
(float)fmod(id.y * 4096, imageSize[1])
|
||||
}
|
||||
};
|
||||
|
||||
useProgram(patternShader->program);
|
||||
patternShader->setMatrix(matrix);
|
||||
@@ -247,6 +254,32 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
// Draw the actual triangle fan into the stencil buffer.
|
||||
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) {
|
||||
useProgram(outlineShader->program);
|
||||
outlineShader->setMatrix(matrix);
|
||||
lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
|
||||
|
||||
// From now on, we don't want to update the stencil buffer anymore.
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilMask(0x0);
|
||||
|
||||
// Otherwise, we only want to draw the antialiased parts that are
|
||||
// *outside* the current shape. This is important in case the fill
|
||||
// or stroke color is translucent. If we wouldn't clip to outside
|
||||
// the current shape, some pixels from the outline stroke overlapped
|
||||
// the (non-antialiased) fill.
|
||||
glStencilFunc(GL_EQUAL, 0x80, 0xBF);
|
||||
outlineShader->setColor(fill_color);
|
||||
|
||||
// Draw the entire line
|
||||
outlineShader->setWorld({{ transform.fb_width, transform.fb_height }});
|
||||
bucket.drawVertices(*outlineShader);
|
||||
|
||||
glStencilFunc(GL_EQUAL, 0x80, 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& id) {
|
||||
@@ -276,20 +309,22 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
linejoinShader->setMatrix(matrix);
|
||||
linejoinShader->setColor(color);
|
||||
linejoinShader->setWorld({{
|
||||
transform.fb_width * 0.5f,
|
||||
transform.fb_height * 0.5f
|
||||
}});
|
||||
transform.fb_width * 0.5f,
|
||||
transform.fb_height * 0.5f
|
||||
}
|
||||
});
|
||||
linejoinShader->setLineWidth({{
|
||||
((outset - 0.25f) * transform.pixelRatio),
|
||||
((inset - 0.25f) * transform.pixelRatio)
|
||||
}});
|
||||
((outset - 0.25f) * transform.pixelRatio),
|
||||
((inset - 0.25f) * transform.pixelRatio)
|
||||
}
|
||||
});
|
||||
|
||||
float pointSize = ceil(transform.pixelRatio * outset * 2.0);
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
linejoinShader->setSize(pointSize);
|
||||
#else
|
||||
#else
|
||||
glPointSize(pointSize);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bucket.drawPoints(*linejoinShader);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user