[core] Fix overdraw mode on Linux

- Use glBindAttribLocation for GLSL attributes.
- Create a separate shader for each shader that supports overdraw.
  Needed because each uniform location must be known for every program.
- Create a separate VAO for each shader inside buckets.
  Needed because we can only bind a VAO to a specific shader.

Fixes #5435.
This commit is contained in:
Bruno de Oliveira Abinader
2016-06-21 17:22:51 -07:00
parent eb7cfea7ea
commit a17b0bcd82
41 changed files with 343 additions and 344 deletions

View File

@@ -23,7 +23,7 @@
"express": "^4.11.1",
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#59e998295d548f208ee3ec10cdd21ff2630e2079",
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#194fc55b6a7dd54c1e2cf2dd9048fbb5e836716d",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#cb733d358a95d46344c2212f1546ed94022718f7",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#2e5addbbd6b3eafaa2984bfd863fd28071f2e481",
"node-gyp": "^3.3.1",
"request": "^2.72.0",
"tape": "^4.5.1"

View File

@@ -119,48 +119,48 @@ bool FillBucket::needsClipping() const {
return true;
}
void FillBucket::drawElements(PlainShader& shader, gl::ObjectStore& store) {
void FillBucket::drawElements(PlainShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
assert(group);
group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
group->array[overdraw ? 1 : 0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * triangleElementsBuffer.itemSize;
}
}
void FillBucket::drawElements(PatternShader& shader, gl::ObjectStore& store) {
void FillBucket::drawElements(PatternShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
assert(group);
group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
group->array[overdraw ? 3 : 2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * triangleElementsBuffer.itemSize;
}
}
void FillBucket::drawVertices(OutlineShader& shader, gl::ObjectStore& store) {
void FillBucket::drawVertices(OutlineShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : lineGroups) {
assert(group);
group->array[0].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
group->array[overdraw ? 1 : 0].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_LINES, group->elements_length * 2, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * lineElementsBuffer.itemSize;
}
}
void FillBucket::drawVertices(OutlinePatternShader& shader, gl::ObjectStore& store) {
void FillBucket::drawVertices(OutlinePatternShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : lineGroups) {
assert(group);
group->array[1].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
group->array[overdraw? 3 : 2].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_LINES, group->elements_length * 2, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * lineElementsBuffer.itemSize;

View File

@@ -27,18 +27,18 @@ public:
void addGeometry(const GeometryCollection&);
void drawElements(PlainShader&, gl::ObjectStore&);
void drawElements(PatternShader&, gl::ObjectStore&);
void drawVertices(OutlineShader&, gl::ObjectStore&);
void drawVertices(OutlinePatternShader&, gl::ObjectStore&);
void drawElements(PlainShader&, gl::ObjectStore&, bool overdraw);
void drawElements(PatternShader&, gl::ObjectStore&, bool overdraw);
void drawVertices(OutlineShader&, gl::ObjectStore&, bool overdraw);
void drawVertices(OutlinePatternShader&, gl::ObjectStore&, bool overdraw);
private:
FillVertexBuffer vertexBuffer;
TriangleElementsBuffer triangleElementsBuffer;
LineElementsBuffer lineElementsBuffer;
typedef ElementGroup<2> TriangleGroup;
typedef ElementGroup<2> LineGroup;
typedef ElementGroup<4> TriangleGroup;
typedef ElementGroup<4> LineGroup;
std::vector<std::unique_ptr<TriangleGroup>> triangleGroups;
std::vector<std::unique_ptr<LineGroup>> lineGroups;

View File

@@ -460,7 +460,7 @@ bool LineBucket::needsClipping() const {
return true;
}
void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store) {
void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -468,7 +468,7 @@ void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store) {
if (!group->elements_length) {
continue;
}
group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
group->array[overdraw ? 1 : 0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
@@ -476,7 +476,7 @@ void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store) {
}
}
void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store) {
void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -484,7 +484,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store) {
if (!group->elements_length) {
continue;
}
group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
group->array[overdraw ? 3 : 2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
@@ -492,7 +492,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store) {
}
}
void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::ObjectStore& store) {
void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -500,7 +500,7 @@ void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::ObjectStore& st
if (!group->elements_length) {
continue;
}
group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
group->array[overdraw ? 5 : 4].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;

View File

@@ -18,7 +18,7 @@ class LineSDFShader;
class LinepatternShader;
class LineBucket : public Bucket {
using TriangleGroup = ElementGroup<3>;
using TriangleGroup = ElementGroup<6>;
public:
LineBucket(uint32_t overscaling);
@@ -32,9 +32,9 @@ public:
void addGeometry(const GeometryCollection&);
void addGeometry(const GeometryCoordinates& line);
void drawLines(LineShader&, gl::ObjectStore&);
void drawLineSDF(LineSDFShader&, gl::ObjectStore&);
void drawLinePatterns(LinepatternShader&, gl::ObjectStore&);
void drawLines(LineShader&, gl::ObjectStore&, bool overdraw);
void drawLineSDF(LineSDFShader&, gl::ObjectStore&, bool overdraw);
void drawLinePatterns(LinepatternShader&, gl::ObjectStore&, bool overdraw);
private:
struct TriangleElement {

View File

@@ -64,11 +64,25 @@ Painter::Painter(const TransformState& state_,
patternShader = std::make_unique<PatternShader>(store);
iconShader = std::make_unique<IconShader>(store);
rasterShader = std::make_unique<RasterShader>(store);
sdfGlyphShader = std::make_unique<SDFGlyphShader>(store);
sdfIconShader = std::make_unique<SDFIconShader>(store);
sdfGlyphShader = std::make_unique<SDFShader>(store);
sdfIconShader = std::make_unique<SDFShader>(store);
collisionBoxShader = std::make_unique<CollisionBoxShader>(store);
circleShader = std::make_unique<CircleShader>(store);
bool overdraw = true;
plainOverdrawShader = std::make_unique<PlainShader>(store, overdraw);
outlineOverdrawShader = std::make_unique<OutlineShader>(store, overdraw);
outlinePatternOverdrawShader = std::make_unique<OutlinePatternShader>(store, overdraw);
lineOverdrawShader = std::make_unique<LineShader>(store, overdraw);
linesdfOverdrawShader = std::make_unique<LineSDFShader>(store, overdraw);
linepatternOverdrawShader = std::make_unique<LinepatternShader>(store, overdraw);
patternOverdrawShader = std::make_unique<PatternShader>(store, overdraw);
iconOverdrawShader = std::make_unique<IconShader>(store, overdraw);
rasterOverdrawShader = std::make_unique<RasterShader>(store, overdraw);
sdfGlyphOverdrawShader = std::make_unique<SDFShader>(store, overdraw);
sdfIconOverdrawShader = std::make_unique<SDFShader>(store, overdraw);
circleOverdrawShader = std::make_unique<CircleShader>(store, overdraw);
// Reset GL values
config.reset();
}

View File

@@ -53,8 +53,6 @@ class CircleShader;
class PatternShader;
class IconShader;
class RasterShader;
class SDFGlyphShader;
class SDFIconShader;
class CollisionBoxShader;
struct ClipID;
@@ -137,7 +135,7 @@ private:
float scaleDivisor,
std::array<float, 2> texsize,
SDFShader& sdfShader,
void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&),
void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&, bool),
// Layout
style::AlignmentType rotationAlignment,
@@ -208,11 +206,24 @@ private:
std::unique_ptr<PatternShader> patternShader;
std::unique_ptr<IconShader> iconShader;
std::unique_ptr<RasterShader> rasterShader;
std::unique_ptr<SDFGlyphShader> sdfGlyphShader;
std::unique_ptr<SDFIconShader> sdfIconShader;
std::unique_ptr<SDFShader> sdfGlyphShader;
std::unique_ptr<SDFShader> sdfIconShader;
std::unique_ptr<CollisionBoxShader> collisionBoxShader;
std::unique_ptr<CircleShader> circleShader;
std::unique_ptr<PlainShader> plainOverdrawShader;
std::unique_ptr<OutlineShader> outlineOverdrawShader;
std::unique_ptr<OutlinePatternShader> outlinePatternOverdrawShader;
std::unique_ptr<LineShader> lineOverdrawShader;
std::unique_ptr<LineSDFShader> linesdfOverdrawShader;
std::unique_ptr<LinepatternShader> linepatternOverdrawShader;
std::unique_ptr<PatternShader> patternOverdrawShader;
std::unique_ptr<IconShader> iconOverdrawShader;
std::unique_ptr<RasterShader> rasterOverdrawShader;
std::unique_ptr<SDFShader> sdfGlyphOverdrawShader;
std::unique_ptr<SDFShader> sdfIconOverdrawShader;
std::unique_ptr<CircleShader> circleOverdrawShader;
// Set up the stencil quad we're using to generate the stencil mask.
StaticVertexBuffer tileStencilBuffer = {
// top left triangle
@@ -241,6 +252,8 @@ private:
};
VertexArrayObject tileBorderArray;
VertexArrayObject coveringRasterOverdrawArray;
};
} // namespace mbgl

View File

@@ -21,6 +21,9 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
optional<SpriteAtlasPosition> imagePosA;
optional<SpriteAtlasPosition> imagePosB;
const auto& shaderPattern = isOverdraw() ? patternOverdrawShader : patternShader;
const auto& shaderPlain = isOverdraw() ? plainOverdrawShader : plainShader;
if (isPatterned) {
imagePosA = spriteAtlas->getPosition(properties.backgroundPattern.value.from, true);
imagePosB = spriteAtlas->getPosition(properties.backgroundPattern.value.to, true);
@@ -28,24 +31,24 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
if (!imagePosA || !imagePosB)
return;
config.program = isOverdraw() ? patternShader->getOverdrawID() : 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.backgroundPattern.value.t;
patternShader->u_opacity = properties.backgroundOpacity;
config.program = shaderPattern->getID();
shaderPattern->u_matrix = identityMatrix;
shaderPattern->u_pattern_tl_a = imagePosA->tl;
shaderPattern->u_pattern_br_a = imagePosA->br;
shaderPattern->u_pattern_tl_b = imagePosB->tl;
shaderPattern->u_pattern_br_b = imagePosB->br;
shaderPattern->u_mix = properties.backgroundPattern.value.t;
shaderPattern->u_opacity = properties.backgroundOpacity;
spriteAtlas->bind(true, store);
backgroundPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
backgroundPatternArray.bind(*shaderPattern, tileStencilBuffer, BUFFER_OFFSET(0), store);
} else {
plainShader->u_color = properties.backgroundColor;
plainShader->u_opacity = properties.backgroundOpacity;
config.program = shaderPlain->getID();
shaderPlain->u_color = properties.backgroundColor;
shaderPlain->u_opacity = properties.backgroundOpacity;
config.program = isOverdraw() ? plainShader->getOverdrawID() : plainShader->getID();
backgroundArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
backgroundArray.bind(*shaderPlain, tileStencilBuffer, BUFFER_OFFSET(0), store);
}
config.stencilTest = GL_FALSE;
@@ -60,20 +63,20 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
matrix::multiply(vertexMatrix, projMatrix, vertexMatrix);
if (isPatterned) {
patternShader->u_matrix = vertexMatrix;
patternShader->u_pattern_size_a = imagePosA->size;
patternShader->u_pattern_size_b = imagePosB->size;
patternShader->u_scale_a = properties.backgroundPattern.value.fromScale;
patternShader->u_scale_b = properties.backgroundPattern.value.toScale;
patternShader->u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
shaderPattern->u_matrix = vertexMatrix;
shaderPattern->u_pattern_size_a = imagePosA->size;
shaderPattern->u_pattern_size_b = imagePosB->size;
shaderPattern->u_scale_a = properties.backgroundPattern.value.fromScale;
shaderPattern->u_scale_b = properties.backgroundPattern.value.toScale;
shaderPattern->u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
GLint pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
GLint pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
patternShader->u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
patternShader->u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
shaderPattern->u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
shaderPattern->u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
} else {
plainShader->u_matrix = vertexMatrix;
shaderPlain->u_matrix = vertexMatrix;
}
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)tileStencilBuffer.index()));

View File

@@ -27,17 +27,19 @@ void Painter::renderCircle(CircleBucket& bucket,
mat4 vtxMatrix = translatedMatrix(matrix, properties.circleTranslate, tileID,
properties.circleTranslateAnchor);
config.program = isOverdraw() ? circleShader->getOverdrawID() : circleShader->getID();
const auto& shader = isOverdraw() ? circleOverdrawShader : circleShader;
circleShader->u_matrix = vtxMatrix;
circleShader->u_extrude_scale = extrudeScale;
circleShader->u_devicepixelratio = frame.pixelRatio;
circleShader->u_color = properties.circleColor;
circleShader->u_radius = properties.circleRadius;
circleShader->u_blur = properties.circleBlur;
circleShader->u_opacity = properties.circleOpacity;
config.program = shader->getID();
bucket.drawCircles(*circleShader, store);
shader->u_matrix = vtxMatrix;
shader->u_extrude_scale = extrudeScale;
shader->u_devicepixelratio = frame.pixelRatio;
shader->u_color = properties.circleColor;
shader->u_radius = properties.circleRadius;
shader->u_blur = properties.circleBlur;
shader->u_opacity = properties.circleOpacity;
bucket.drawCircles(*shader, store);
}
} // namespace mbgl

View File

@@ -43,17 +43,24 @@ void Painter::renderFill(FillBucket& bucket,
config.depthMask = GL_TRUE;
config.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio!
const bool overdraw = isOverdraw();
const auto& shaderOutline = overdraw ? outlineOverdrawShader : outlineShader;
const auto& shaderPattern = overdraw ? patternOverdrawShader : patternShader;
const auto& shaderOutlinePattern = overdraw ? outlinePatternOverdrawShader : outlinePatternShader;
const auto& shaderPlain = overdraw ? plainOverdrawShader : plainShader;
// 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) {
config.program = isOverdraw() ? outlineShader->getOverdrawID() : outlineShader->getID();
outlineShader->u_matrix = vertexMatrix;
outlineShader->u_outline_color = strokeColor;
outlineShader->u_opacity = opacity;
config.program = shaderOutline->getID();
shaderOutline->u_matrix = vertexMatrix;
shaderOutline->u_outline_color = strokeColor;
shaderOutline->u_opacity = opacity;
// Draw the entire line
outlineShader->u_world = worldSize;
shaderOutline->u_world = worldSize;
if (isOutlineColorDefined) {
// If we defined a different color for the fill outline, we are
// going to ignore the bits in 0x07 and just care about the global
@@ -67,7 +74,7 @@ void Painter::renderFill(FillBucket& bucket,
// the (non-antialiased) fill.
setDepthSublayer(0); // OK
}
bucket.drawVertices(*outlineShader, store);
bucket.drawVertices(*shaderOutline, store, overdraw);
}
if (pattern) {
@@ -76,61 +83,61 @@ void Painter::renderFill(FillBucket& bucket,
// Image fill.
if (pass == RenderPass::Translucent && imagePosA && imagePosB) {
config.program = isOverdraw() ? patternShader->getOverdrawID() : patternShader->getID();
patternShader->u_matrix = vertexMatrix;
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_opacity = properties.fillOpacity;
patternShader->u_image = 0;
patternShader->u_mix = properties.fillPattern.value.t;
patternShader->u_pattern_size_a = imagePosA->size;
patternShader->u_pattern_size_b = imagePosB->size;
patternShader->u_scale_a = properties.fillPattern.value.fromScale;
patternShader->u_scale_b = properties.fillPattern.value.toScale;
patternShader->u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
config.program = shaderPattern->getID();
shaderPattern->u_matrix = vertexMatrix;
shaderPattern->u_pattern_tl_a = imagePosA->tl;
shaderPattern->u_pattern_br_a = imagePosA->br;
shaderPattern->u_pattern_tl_b = imagePosB->tl;
shaderPattern->u_pattern_br_b = imagePosB->br;
shaderPattern->u_opacity = properties.fillOpacity;
shaderPattern->u_image = 0;
shaderPattern->u_mix = properties.fillPattern.value.t;
shaderPattern->u_pattern_size_a = imagePosA->size;
shaderPattern->u_pattern_size_b = imagePosB->size;
shaderPattern->u_scale_a = properties.fillPattern.value.fromScale;
shaderPattern->u_scale_b = properties.fillPattern.value.toScale;
shaderPattern->u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
GLint pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
GLint pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
patternShader->u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
patternShader->u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
shaderPattern->u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
shaderPattern->u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
config.activeTexture = GL_TEXTURE0;
spriteAtlas->bind(true, store);
// Draw the actual triangles into the color & stencil buffer.
setDepthSublayer(0);
bucket.drawElements(*patternShader, store);
bucket.drawElements(*shaderPattern, store, overdraw);
if (properties.fillAntialias && !isOutlineColorDefined) {
config.program = isOverdraw() ? outlinePatternShader->getOverdrawID() : outlinePatternShader->getID();
outlinePatternShader->u_matrix = vertexMatrix;
config.program = shaderOutlinePattern->getID();
shaderOutlinePattern->u_matrix = vertexMatrix;
// Draw the entire line
outlineShader->u_world = worldSize;
shaderOutline->u_world = worldSize;
outlinePatternShader->u_pattern_tl_a = imagePosA->tl;
outlinePatternShader->u_pattern_br_a = imagePosA->br;
outlinePatternShader->u_pattern_tl_b = imagePosB->tl;
outlinePatternShader->u_pattern_br_b = imagePosB->br;
outlinePatternShader->u_opacity = properties.fillOpacity;
outlinePatternShader->u_image = 0;
outlinePatternShader->u_mix = properties.fillPattern.value.t;
outlinePatternShader->u_pattern_size_a = imagePosA->size;
outlinePatternShader->u_pattern_size_b = imagePosB->size;
outlinePatternShader->u_scale_a = properties.fillPattern.value.fromScale;
outlinePatternShader->u_scale_b = properties.fillPattern.value.toScale;
outlinePatternShader->u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
outlinePatternShader->u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
outlinePatternShader->u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
shaderOutlinePattern->u_pattern_tl_a = imagePosA->tl;
shaderOutlinePattern->u_pattern_br_a = imagePosA->br;
shaderOutlinePattern->u_pattern_tl_b = imagePosB->tl;
shaderOutlinePattern->u_pattern_br_b = imagePosB->br;
shaderOutlinePattern->u_opacity = properties.fillOpacity;
shaderOutlinePattern->u_image = 0;
shaderOutlinePattern->u_mix = properties.fillPattern.value.t;
shaderOutlinePattern->u_pattern_size_a = imagePosA->size;
shaderOutlinePattern->u_pattern_size_b = imagePosB->size;
shaderOutlinePattern->u_scale_a = properties.fillPattern.value.fromScale;
shaderOutlinePattern->u_scale_b = properties.fillPattern.value.toScale;
shaderOutlinePattern->u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
shaderOutlinePattern->u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
shaderOutlinePattern->u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
config.activeTexture = GL_TEXTURE0;
spriteAtlas->bind(true, store);
setDepthSublayer(2);
bucket.drawVertices(*outlinePatternShader, store);
bucket.drawVertices(*shaderOutlinePattern, store, overdraw);
}
}
} else {
@@ -140,31 +147,31 @@ void Painter::renderFill(FillBucket& bucket,
// fragments or when it's translucent and we're drawing translucent
// fragments
// Draw filling rectangle.
config.program = isOverdraw() ? plainShader->getOverdrawID() : plainShader->getID();
plainShader->u_matrix = vertexMatrix;
plainShader->u_color = fillColor;
plainShader->u_opacity = opacity;
config.program = shaderPlain->getID();
shaderPlain->u_matrix = vertexMatrix;
shaderPlain->u_color = fillColor;
shaderPlain->u_opacity = opacity;
// Draw the actual triangles into the color & stencil buffer.
setDepthSublayer(1);
bucket.drawElements(*plainShader, store);
bucket.drawElements(*shaderPlain, store, overdraw);
}
}
// 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) {
config.program = isOverdraw() ? outlineShader->getOverdrawID() : outlineShader->getID();
outlineShader->u_matrix = vertexMatrix;
config.program = shaderOutline->getID();
shaderOutline->u_matrix = vertexMatrix;
outlineShader->u_outline_color = fillColor;
outlineShader->u_opacity = opacity;
shaderOutline->u_outline_color = fillColor;
shaderOutline->u_opacity = opacity;
// Draw the entire line
outlineShader->u_world = worldSize;
shaderOutline->u_world = worldSize;
setDepthSublayer(2);
bucket.drawVertices(*outlineShader, store);
bucket.drawVertices(*shaderOutline, store, overdraw);
}
}

View File

@@ -55,18 +55,22 @@ void Painter::renderLine(LineBucket& bucket,
setDepthSublayer(0);
const bool overdraw = isOverdraw();
const auto& shaderLineSDF = overdraw ? linesdfOverdrawShader : linesdfShader;
const auto& shaderLinePattern = overdraw ? linepatternOverdrawShader : linepatternShader;
const auto& shaderLine = overdraw ? lineOverdrawShader : lineShader;
if (!properties.lineDasharray.value.from.empty()) {
config.program = shaderLineSDF->getID();
config.program = isOverdraw() ? linesdfShader->getOverdrawID() : linesdfShader->getID();
linesdfShader->u_matrix = vtxMatrix;
linesdfShader->u_linewidth = properties.lineWidth / 2;
linesdfShader->u_gapwidth = properties.lineGapWidth / 2;
linesdfShader->u_antialiasing = antialiasing / 2;
linesdfShader->u_ratio = ratio;
linesdfShader->u_blur = blur;
linesdfShader->u_color = color;
linesdfShader->u_opacity = opacity;
shaderLineSDF->u_matrix = vtxMatrix;
shaderLineSDF->u_linewidth = properties.lineWidth / 2;
shaderLineSDF->u_gapwidth = properties.lineGapWidth / 2;
shaderLineSDF->u_antialiasing = antialiasing / 2;
shaderLineSDF->u_ratio = ratio;
shaderLineSDF->u_blur = blur;
shaderLineSDF->u_color = color;
shaderLineSDF->u_opacity = opacity;
LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, layout.lineCap == LineCapType::Round, store);
LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, layout.lineCap == LineCapType::Round, store);
@@ -79,21 +83,21 @@ void Painter::renderLine(LineBucket& bucket,
float scaleXB = 1.0 / tileID.pixelsToTileUnits(widthB, state.getIntegerZoom());
float scaleYB = -posB.height / 2.0;
linesdfShader->u_patternscale_a = {{ scaleXA, scaleYA }};
linesdfShader->u_tex_y_a = posA.y;
linesdfShader->u_patternscale_b = {{ scaleXB, scaleYB }};
linesdfShader->u_tex_y_b = posB.y;
linesdfShader->u_sdfgamma = lineAtlas->width / (std::min(widthA, widthB) * 256.0 * frame.pixelRatio) / 2;
linesdfShader->u_mix = properties.lineDasharray.value.t;
linesdfShader->u_extra = extra;
linesdfShader->u_offset = -properties.lineOffset;
linesdfShader->u_antialiasingmatrix = antialiasingMatrix;
shaderLineSDF->u_patternscale_a = {{ scaleXA, scaleYA }};
shaderLineSDF->u_tex_y_a = posA.y;
shaderLineSDF->u_patternscale_b = {{ scaleXB, scaleYB }};
shaderLineSDF->u_tex_y_b = posB.y;
shaderLineSDF->u_sdfgamma = lineAtlas->width / (std::min(widthA, widthB) * 256.0 * frame.pixelRatio) / 2;
shaderLineSDF->u_mix = properties.lineDasharray.value.t;
shaderLineSDF->u_extra = extra;
shaderLineSDF->u_offset = -properties.lineOffset;
shaderLineSDF->u_antialiasingmatrix = antialiasingMatrix;
linesdfShader->u_image = 0;
shaderLineSDF->u_image = 0;
config.activeTexture = GL_TEXTURE0;
lineAtlas->bind(store);
bucket.drawLineSDF(*linesdfShader, store);
bucket.drawLineSDF(*shaderLineSDF, store, overdraw);
} else if (!properties.linePattern.value.from.empty()) {
optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(properties.linePattern.value.from, true);
@@ -102,58 +106,58 @@ void Painter::renderLine(LineBucket& bucket,
if (!imagePosA || !imagePosB)
return;
config.program = isOverdraw() ? linepatternShader->getOverdrawID() : linepatternShader->getID();
config.program = shaderLinePattern->getID();
linepatternShader->u_matrix = vtxMatrix;
linepatternShader->u_linewidth = properties.lineWidth / 2;
linepatternShader->u_gapwidth = properties.lineGapWidth / 2;
linepatternShader->u_antialiasing = antialiasing / 2;
linepatternShader->u_ratio = ratio;
linepatternShader->u_blur = blur;
shaderLinePattern->u_matrix = vtxMatrix;
shaderLinePattern->u_linewidth = properties.lineWidth / 2;
shaderLinePattern->u_gapwidth = properties.lineGapWidth / 2;
shaderLinePattern->u_antialiasing = antialiasing / 2;
shaderLinePattern->u_ratio = ratio;
shaderLinePattern->u_blur = blur;
linepatternShader->u_pattern_size_a = {{
shaderLinePattern->u_pattern_size_a = {{
tileID.pixelsToTileUnits((*imagePosA).size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
(*imagePosA).size[1]
}};
linepatternShader->u_pattern_tl_a = (*imagePosA).tl;
linepatternShader->u_pattern_br_a = (*imagePosA).br;
shaderLinePattern->u_pattern_tl_a = (*imagePosA).tl;
shaderLinePattern->u_pattern_br_a = (*imagePosA).br;
linepatternShader->u_pattern_size_b = {{
shaderLinePattern->u_pattern_size_b = {{
tileID.pixelsToTileUnits((*imagePosB).size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
(*imagePosB).size[1]
}};
linepatternShader->u_pattern_tl_b = (*imagePosB).tl;
linepatternShader->u_pattern_br_b = (*imagePosB).br;
shaderLinePattern->u_pattern_tl_b = (*imagePosB).tl;
shaderLinePattern->u_pattern_br_b = (*imagePosB).br;
linepatternShader->u_fade = properties.linePattern.value.t;
linepatternShader->u_opacity = properties.lineOpacity;
linepatternShader->u_extra = extra;
linepatternShader->u_offset = -properties.lineOffset;
linepatternShader->u_antialiasingmatrix = antialiasingMatrix;
shaderLinePattern->u_fade = properties.linePattern.value.t;
shaderLinePattern->u_opacity = properties.lineOpacity;
shaderLinePattern->u_extra = extra;
shaderLinePattern->u_offset = -properties.lineOffset;
shaderLinePattern->u_antialiasingmatrix = antialiasingMatrix;
linepatternShader->u_image = 0;
shaderLinePattern->u_image = 0;
config.activeTexture = GL_TEXTURE0;
spriteAtlas->bind(true, store);
bucket.drawLinePatterns(*linepatternShader, store);
bucket.drawLinePatterns(*shaderLinePattern, store, overdraw);
} else {
config.program = isOverdraw() ? lineShader->getOverdrawID() : lineShader->getID();
config.program = shaderLine->getID();
lineShader->u_matrix = vtxMatrix;
lineShader->u_linewidth = properties.lineWidth / 2;
lineShader->u_gapwidth = properties.lineGapWidth / 2;
lineShader->u_antialiasing = antialiasing / 2;
lineShader->u_ratio = ratio;
lineShader->u_blur = blur;
lineShader->u_extra = extra;
lineShader->u_offset = -properties.lineOffset;
lineShader->u_antialiasingmatrix = antialiasingMatrix;
shaderLine->u_matrix = vtxMatrix;
shaderLine->u_linewidth = properties.lineWidth / 2;
shaderLine->u_gapwidth = properties.lineGapWidth / 2;
shaderLine->u_antialiasing = antialiasing / 2;
shaderLine->u_ratio = ratio;
shaderLine->u_blur = blur;
shaderLine->u_extra = extra;
shaderLine->u_offset = -properties.lineOffset;
shaderLine->u_antialiasingmatrix = antialiasingMatrix;
lineShader->u_color = color;
lineShader->u_opacity = opacity;
shaderLine->u_color = color;
shaderLine->u_opacity = opacity;
bucket.drawLines(*lineShader, store);
bucket.drawLines(*shaderLine, store, overdraw);
}
}

View File

@@ -18,26 +18,28 @@ void Painter::renderRaster(RasterBucket& bucket,
const RasterPaintProperties& properties = layer.impl->paint;
if (bucket.hasData()) {
config.program = isOverdraw() ? rasterShader->getOverdrawID() : rasterShader->getID();
rasterShader->u_matrix = matrix;
rasterShader->u_buffer = 0;
rasterShader->u_opacity = properties.rasterOpacity;
rasterShader->u_brightness_low = properties.rasterBrightnessMin;
rasterShader->u_brightness_high = properties.rasterBrightnessMax;
rasterShader->u_saturation_factor = saturationFactor(properties.rasterSaturation);
rasterShader->u_contrast_factor = contrastFactor(properties.rasterContrast);
rasterShader->u_spin_weights = spinWeights(properties.rasterHueRotate);
const auto& shaderRaster = isOverdraw() ? rasterOverdrawShader : rasterShader;
auto& vaoRaster = isOverdraw() ? coveringRasterOverdrawArray : coveringRasterArray;
config.program = shaderRaster->getID();
shaderRaster->u_matrix = matrix;
shaderRaster->u_buffer = 0;
shaderRaster->u_opacity = properties.rasterOpacity;
shaderRaster->u_brightness_low = properties.rasterBrightnessMin;
shaderRaster->u_brightness_high = properties.rasterBrightnessMax;
shaderRaster->u_saturation_factor = saturationFactor(properties.rasterSaturation);
shaderRaster->u_contrast_factor = contrastFactor(properties.rasterContrast);
shaderRaster->u_spin_weights = spinWeights(properties.rasterHueRotate);
config.stencilTest = GL_FALSE;
rasterShader->u_image = 0;
shaderRaster->u_image = 0;
config.activeTexture = GL_TEXTURE0;
config.depthFunc.reset();
config.depthTest = GL_TRUE;
config.depthMask = GL_FALSE;
setDepthSublayer(0);
bucket.drawRaster(*rasterShader, tileStencilBuffer, coveringRasterArray, store);
bucket.drawRaster(*shaderRaster, tileStencilBuffer, vaoRaster, store);
}
}

View File

@@ -21,7 +21,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
float sdfFontSize,
std::array<float, 2> texsize,
SDFShader& sdfShader,
void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&),
void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&, bool),
// Layout
AlignmentType rotationAlignment,
@@ -58,7 +58,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
exScale = {{ exScale[0] * scale, exScale[1] * scale }};
}
config.program = isOverdraw() ? sdfShader.getOverdrawID() : sdfShader.getID();
config.program = sdfShader.getID();
sdfShader.u_matrix = vtxMatrix;
sdfShader.u_extrude_scale = exScale;
sdfShader.u_texsize = texsize;
@@ -95,7 +95,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
sdfShader.u_buffer = (haloOffset - haloWidth / fontScale) / sdfPx;
setDepthSublayer(0);
(bucket.*drawSDF)(sdfShader, store);
(bucket.*drawSDF)(sdfShader, store, isOverdraw());
}
// Then, we draw the text/icon over the halo
@@ -106,7 +106,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f;
setDepthSublayer(1);
(bucket.*drawSDF)(sdfShader, store);
(bucket.*drawSDF)(sdfShader, store, isOverdraw());
}
}
@@ -170,7 +170,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
matrix,
1.0f,
{{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }},
*sdfIconShader,
isOverdraw() ? *sdfIconOverdrawShader : *sdfIconShader,
&SymbolBucket::drawIcons,
layout.iconRotationAlignment,
// icon-pitch-alignment is not yet implemented
@@ -199,24 +199,27 @@ void Painter::renderSymbol(SymbolBucket& bucket,
exScale = {{ exScale[0] * scale, exScale[1] * scale }};
}
config.program = isOverdraw() ? iconShader->getOverdrawID() : iconShader->getID();
iconShader->u_matrix = vtxMatrix;
iconShader->u_extrude_scale = exScale;
iconShader->u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }};
iconShader->u_rotate_with_map = alignedWithMap;
iconShader->u_texture = 0;
const bool overdraw = isOverdraw();
const auto& shaderIcon = overdraw ? iconOverdrawShader : iconShader;
config.program = shaderIcon->getID();
shaderIcon->u_matrix = vtxMatrix;
shaderIcon->u_extrude_scale = exScale;
shaderIcon->u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }};
shaderIcon->u_rotate_with_map = alignedWithMap;
shaderIcon->u_texture = 0;
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / layout.iconSize) / std::log(2);
iconShader->u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
iconShader->u_opacity = paint.iconOpacity;
shaderIcon->u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
shaderIcon->u_opacity = paint.iconOpacity;
config.activeTexture = GL_TEXTURE1;
frameHistory.bind(store);
iconShader->u_fadetexture = 1;
shaderIcon->u_fadetexture = 1;
setDepthSublayer(0);
bucket.drawIcons(*iconShader, store);
bucket.drawIcons(*shaderIcon, store, overdraw);
}
}
@@ -236,7 +239,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
matrix,
24.0f,
{{ float(glyphAtlas->width) / 4, float(glyphAtlas->height) / 4 }},
*sdfGlyphShader,
isOverdraw() ? *sdfGlyphOverdrawShader : *sdfGlyphShader,
&SymbolBucket::drawGlyphs,
layout.textRotationAlignment,
layout.textPitchAlignment,

View File

@@ -601,39 +601,39 @@ void SymbolBucket::swapRenderData() {
}
}
void SymbolBucket::drawGlyphs(SDFShader& shader, gl::ObjectStore& store) {
void SymbolBucket::drawGlyphs(SDFShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte *vertex_index = BUFFER_OFFSET_0;
GLbyte *elements_index = BUFFER_OFFSET_0;
auto& text = renderData->text;
for (auto &group : text.groups) {
assert(group);
group->array[0].bind(shader, text.vertices, text.triangles, vertex_index, store);
group->array[overdraw ? 1 : 0].bind(shader, text.vertices, text.triangles, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * text.vertices.itemSize;
elements_index += group->elements_length * text.triangles.itemSize;
}
}
void SymbolBucket::drawIcons(SDFShader& shader, gl::ObjectStore& store) {
void SymbolBucket::drawIcons(SDFShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte *vertex_index = BUFFER_OFFSET_0;
GLbyte *elements_index = BUFFER_OFFSET_0;
auto& icon = renderData->icon;
for (auto &group : icon.groups) {
assert(group);
group->array[0].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
group->array[overdraw ? 1 : 0].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * icon.vertices.itemSize;
elements_index += group->elements_length * icon.triangles.itemSize;
}
}
void SymbolBucket::drawIcons(IconShader& shader, gl::ObjectStore& store) {
void SymbolBucket::drawIcons(IconShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte *vertex_index = BUFFER_OFFSET_0;
GLbyte *elements_index = BUFFER_OFFSET_0;
auto& icon = renderData->icon;
for (auto &group : icon.groups) {
assert(group);
group->array[1].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
group->array[overdraw ? 3 : 2].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * icon.vertices.itemSize;
elements_index += group->elements_length * icon.triangles.itemSize;

View File

@@ -61,8 +61,8 @@ class SymbolInstance {
};
class SymbolBucket : public Bucket {
typedef ElementGroup<1> TextElementGroup;
typedef ElementGroup<2> IconElementGroup;
typedef ElementGroup<2> TextElementGroup;
typedef ElementGroup<4> IconElementGroup;
typedef ElementGroup<1> CollisionBoxElementGroup;
public:
@@ -82,9 +82,9 @@ public:
GlyphAtlas&,
GlyphStore&);
void drawGlyphs(SDFShader&, gl::ObjectStore&);
void drawIcons(SDFShader&, gl::ObjectStore&);
void drawIcons(IconShader&, gl::ObjectStore&);
void drawGlyphs(SDFShader&, gl::ObjectStore&, bool overdraw);
void drawIcons(SDFShader&, gl::ObjectStore&, bool overdraw);
void drawIcons(IconShader&, gl::ObjectStore&, bool overdraw);
void drawCollisionBoxes(CollisionBoxShader&, gl::ObjectStore&);
void parseFeatures(const GeometryTileLayer&, const style::Filter&);

View File

@@ -5,8 +5,11 @@
namespace mbgl {
CircleShader::CircleShader(gl::ObjectStore& store)
: Shader(shaders::circle::name, shaders::circle::vertex, shaders::circle::fragment, store) {
CircleShader::CircleShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::circle::name,
shaders::circle::vertex,
shaders::circle::fragment,
store, overdraw) {
}
void CircleShader::bind(GLbyte* offset) {

View File

@@ -8,7 +8,7 @@ namespace mbgl {
class CircleShader : public Shader {
public:
CircleShader(gl::ObjectStore&);
CircleShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;

View File

@@ -9,9 +9,7 @@ CollisionBoxShader::CollisionBoxShader(gl::ObjectStore& store)
: Shader(shaders::collisionbox::name,
shaders::collisionbox::vertex,
shaders::collisionbox::fragment,
store),
a_extrude(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_extrude"))),
a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
store) {
}
void CollisionBoxShader::bind(GLbyte *offset) {
@@ -25,7 +23,6 @@ void CollisionBoxShader::bind(GLbyte *offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 2, GL_UNSIGNED_BYTE, false, stride, offset + 8));
}
} // namespace mbgl

View File

@@ -16,10 +16,6 @@ public:
Uniform<GLfloat> u_scale = {"u_scale", *this};
Uniform<GLfloat> u_zoom = {"u_zoom", *this};
Uniform<GLfloat> u_maxzoom = {"u_maxzoom", *this};
protected:
GLint a_extrude = -1;
GLint a_data = -1;
};
} // namespace mbgl

View File

@@ -5,11 +5,11 @@
namespace mbgl {
IconShader::IconShader(gl::ObjectStore& store)
: Shader(shaders::icon::name, shaders::icon::vertex, shaders::icon::fragment, store),
a_offset(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_offset"))),
a_data1(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data1"))),
a_data2(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data2"))) {
IconShader::IconShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::icon::name,
shaders::icon::vertex,
shaders::icon::fragment,
store, overdraw) {
}
void IconShader::bind(GLbyte* offset) {

View File

@@ -7,7 +7,7 @@ namespace mbgl {
class IconShader : public Shader {
public:
IconShader(gl::ObjectStore&);
IconShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;
@@ -19,11 +19,6 @@ public:
Uniform<GLint> u_rotate_with_map = {"u_rotate_with_map", *this};
Uniform<GLint> u_texture = {"u_texture", *this};
Uniform<GLint> u_fadetexture = {"u_fadetexture", *this};
protected:
GLint a_offset = -1;
GLint a_data1 = -1;
GLint a_data2 = -1;
};
} // namespace mbgl

View File

@@ -5,9 +5,11 @@
namespace mbgl {
LineShader::LineShader(gl::ObjectStore& store)
: Shader(shaders::line::name, shaders::line::vertex, shaders::line::fragment, store),
a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
LineShader::LineShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::line::name,
shaders::line::vertex,
shaders::line::fragment,
store, overdraw) {
}
void LineShader::bind(GLbyte* offset) {

View File

@@ -8,7 +8,7 @@ namespace mbgl {
class LineShader : public Shader {
public:
LineShader(gl::ObjectStore&);
LineShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;
@@ -23,9 +23,6 @@ public:
Uniform<GLfloat> u_extra = {"u_extra", *this};
Uniform<GLfloat> u_offset = {"u_offset", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
private:
GLint a_data = -1;
};

View File

@@ -5,12 +5,11 @@
namespace mbgl {
LinepatternShader::LinepatternShader(gl::ObjectStore& store)
LinepatternShader::LinepatternShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::linepattern::name,
shaders::linepattern::vertex,
shaders::linepattern::fragment,
store),
a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
store, overdraw) {
}
void LinepatternShader::bind(GLbyte* offset) {

View File

@@ -7,7 +7,7 @@ namespace mbgl {
class LinepatternShader : public Shader {
public:
LinepatternShader(gl::ObjectStore&);
LinepatternShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;
@@ -30,8 +30,6 @@ public:
Uniform<GLfloat> u_offset = {"u_offset", *this};
Uniform<GLint> u_image = {"u_image", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
private:
GLint a_data = -1;
};
} // namespace mbgl

View File

@@ -5,12 +5,11 @@
namespace mbgl {
LineSDFShader::LineSDFShader(gl::ObjectStore& store)
LineSDFShader::LineSDFShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::linesdfpattern::name,
shaders::linesdfpattern::vertex,
shaders::linesdfpattern::fragment,
store),
a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
store, overdraw) {
}
void LineSDFShader::bind(GLbyte* offset) {

View File

@@ -8,7 +8,7 @@ namespace mbgl {
class LineSDFShader : public Shader {
public:
LineSDFShader(gl::ObjectStore&);
LineSDFShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;
@@ -30,9 +30,6 @@ public:
Uniform<GLfloat> u_extra = {"u_extra", *this};
Uniform<GLfloat> u_offset = {"u_offset", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
private:
GLint a_data = -1;
};

View File

@@ -5,8 +5,11 @@
namespace mbgl {
OutlineShader::OutlineShader(gl::ObjectStore& store)
: Shader(shaders::outline::name, shaders::outline::vertex, shaders::outline::fragment, store) {
OutlineShader::OutlineShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::outline::name,
shaders::outline::vertex,
shaders::outline::fragment,
store, overdraw) {
}
void OutlineShader::bind(GLbyte* offset) {

View File

@@ -8,7 +8,7 @@ namespace mbgl {
class OutlineShader : public Shader {
public:
OutlineShader(gl::ObjectStore&);
OutlineShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;

View File

@@ -5,11 +5,11 @@
namespace mbgl {
OutlinePatternShader::OutlinePatternShader(gl::ObjectStore& store)
OutlinePatternShader::OutlinePatternShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::outlinepattern::name,
shaders::outlinepattern::vertex,
shaders::outlinepattern::fragment,
store) {
store, overdraw) {
}
void OutlinePatternShader::bind(GLbyte *offset) {

View File

@@ -7,7 +7,7 @@ namespace mbgl {
class OutlinePatternShader : public Shader {
public:
OutlinePatternShader(gl::ObjectStore&);
OutlinePatternShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;

View File

@@ -5,8 +5,11 @@
namespace mbgl {
PatternShader::PatternShader(gl::ObjectStore& store)
: Shader(shaders::pattern::name, shaders::pattern::vertex, shaders::pattern::fragment, store) {
PatternShader::PatternShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::pattern::name,
shaders::pattern::vertex,
shaders::pattern::fragment,
store, overdraw) {
}
void PatternShader::bind(GLbyte *offset) {

View File

@@ -7,7 +7,7 @@ namespace mbgl {
class PatternShader : public Shader {
public:
PatternShader(gl::ObjectStore&);
PatternShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;

View File

@@ -5,8 +5,11 @@
namespace mbgl {
PlainShader::PlainShader(gl::ObjectStore& store)
: Shader(shaders::fill::name, shaders::fill::vertex, shaders::fill::fragment, store) {
PlainShader::PlainShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::fill::name,
shaders::fill::vertex,
shaders::fill::fragment,
store, overdraw) {
}
void PlainShader::bind(GLbyte* offset) {

View File

@@ -8,7 +8,7 @@ namespace mbgl {
class PlainShader : public Shader {
public:
PlainShader(gl::ObjectStore&);
PlainShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;

View File

@@ -5,8 +5,11 @@
namespace mbgl {
RasterShader::RasterShader(gl::ObjectStore& store)
: Shader(shaders::raster::name, shaders::raster::vertex, shaders::raster::fragment, store) {
RasterShader::RasterShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::raster::name,
shaders::raster::vertex,
shaders::raster::fragment,
store, overdraw) {
}
void RasterShader::bind(GLbyte* offset) {

View File

@@ -7,7 +7,7 @@ namespace mbgl {
class RasterShader : public Shader {
public:
RasterShader(gl::ObjectStore&);
RasterShader(gl::ObjectStore&, bool overdraw = false);
void bind(GLbyte *offset) final;

View File

@@ -5,30 +5,14 @@
namespace mbgl {
SDFShader::SDFShader(gl::ObjectStore& store)
: Shader(shaders::sdf::name, shaders::sdf::vertex, shaders::sdf::fragment, store),
a_offset(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_offset"))),
a_data1(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data1"))),
a_data2(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data2"))) {
SDFShader::SDFShader(gl::ObjectStore& store, bool overdraw)
: Shader(shaders::sdf::name,
shaders::sdf::vertex,
shaders::sdf::fragment,
store, overdraw) {
}
void SDFGlyphShader::bind(GLbyte* offset) {
const int stride = 16;
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, stride, offset + 0));
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_offset));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_offset, 2, GL_SHORT, false, stride, offset + 4));
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data1));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data1, 4, GL_UNSIGNED_BYTE, false, stride, offset + 8));
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data2));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data2, 4, GL_UNSIGNED_BYTE, false, stride, offset + 12));
}
void SDFIconShader::bind(GLbyte* offset) {
void SDFShader::bind(GLbyte* offset) {
const int stride = 16;
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));

View File

@@ -8,7 +8,7 @@ namespace mbgl {
class SDFShader : public Shader {
public:
SDFShader(gl::ObjectStore&);
SDFShader(gl::ObjectStore&, bool overdraw = false);
UniformMatrix<4> u_matrix = {"u_matrix", *this};
Uniform<std::array<GLfloat, 2>> u_extrude_scale = {"u_extrude_scale", *this};
@@ -26,21 +26,6 @@ public:
Uniform<GLint> u_texture = {"u_texture", *this};
Uniform<GLint> u_fadetexture = {"u_fadetexture", *this};
protected:
GLint a_offset = -1;
GLint a_data1 = -1;
GLint a_data2 = -1;
};
class SDFGlyphShader : public SDFShader {
public:
SDFGlyphShader(gl::ObjectStore& store) : SDFShader(store) {}
void bind(GLbyte *offset) final;
};
class SDFIconShader : public SDFShader {
public:
SDFIconShader(gl::ObjectStore& store) : SDFShader(store) {}
void bind(GLbyte *offset) final;
};

View File

@@ -11,10 +11,11 @@
#include <string>
#include <fstream>
#include <cstdio>
#include <cassert>
namespace mbgl {
Shader::Shader(const char* name_, const char* vertexSource, const char* fragmentSource, gl::ObjectStore& store)
Shader::Shader(const char* name_, const char* vertexSource, const char* fragmentSource, gl::ObjectStore& store, bool overdraw)
: name(name_)
, program(store.createProgram())
, vertexShader(store.createShader(GL_VERTEX_SHADER))
@@ -27,7 +28,13 @@ Shader::Shader(const char* name_, const char* vertexSource, const char* fragment
throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
}
if (!compileShader(fragmentShader, fragmentSource)) {
std::string fragment(fragmentSource);
if (overdraw) {
assert(fragment.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos);
fragment.replace(fragment.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
}
if (!compileShader(fragmentShader, fragment.c_str())) {
Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragmentSource);
throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
}
@@ -36,39 +43,25 @@ Shader::Shader(const char* name_, const char* vertexSource, const char* fragment
MBGL_CHECK_ERROR(glAttachShader(program.get(), vertexShader.get()));
MBGL_CHECK_ERROR(glAttachShader(program.get(), fragmentShader.get()));
linkProgram(program);
// Bind attribute variables
MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_pos, "a_pos"));
MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_extrude, "a_extrude"));
MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_offset, "a_offset"));
MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_data, "a_data"));
MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_data1, "a_data1"));
MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_data2, "a_data2"));
std::string overdrawSource(fragmentSource);
if (overdrawSource.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos) {
programOverdraw = store.createProgram();
overdrawShader = store.createShader(GL_FRAGMENT_SHADER);
overdrawSource.replace(overdrawSource.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
if (!compileShader(*overdrawShader, overdrawSource.c_str())) {
Log::Error(Event::Shader, "Overdraw shader %s failed to compile: %s", name, overdrawSource.c_str());
throw util::ShaderException(std::string { "Overdraw shader " } + name + " failed to compile");
}
MBGL_CHECK_ERROR(glAttachShader(*programOverdraw, vertexShader.get()));
MBGL_CHECK_ERROR(glAttachShader(*programOverdraw, *overdrawShader));
linkProgram(*programOverdraw);
}
a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.get(), "a_pos"));
}
void Shader::linkProgram(gl::UniqueProgram& program_) {
// Link program
GLint status;
MBGL_CHECK_ERROR(glLinkProgram(program_.get()));
MBGL_CHECK_ERROR(glLinkProgram(program.get()));
MBGL_CHECK_ERROR(glGetProgramiv(program_.get(), GL_LINK_STATUS, &status));
MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status));
if (status == 0) {
GLint logLength;
MBGL_CHECK_ERROR(glGetProgramiv(program_.get(), GL_INFO_LOG_LENGTH, &logLength));
MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength));
const auto log = std::make_unique<GLchar[]>(logLength);
if (logLength > 0) {
MBGL_CHECK_ERROR(glGetProgramInfoLog(program_.get(), logLength, &logLength, log.get()));
MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get()));
Log::Error(Event::Shader, "Program failed to link: %s", log.get());
}
throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
@@ -109,10 +102,6 @@ Shader::~Shader() {
MBGL_CHECK_ERROR(glDetachShader(program.get(), vertexShader.get()));
MBGL_CHECK_ERROR(glDetachShader(program.get(), fragmentShader.get()));
}
if (programOverdraw) {
MBGL_CHECK_ERROR(glDetachShader(*programOverdraw, vertexShader.get()));
MBGL_CHECK_ERROR(glDetachShader(*programOverdraw, *overdrawShader));
}
}
} // namespace mbgl

View File

@@ -16,26 +16,24 @@ public:
return program.get();
}
GLuint getOverdrawID() const {
return programOverdraw ? *programOverdraw : 0;
}
virtual void bind(GLbyte *offset) = 0;
protected:
Shader(const char* name_, const char* vertex, const char* fragment, gl::ObjectStore&);
GLint a_pos = -1;
Shader(const char* name_, const char* vertex, const char* fragment, gl::ObjectStore&, bool overdraw = false);
static constexpr GLint a_pos = 0;
static constexpr GLint a_extrude = 1;
static constexpr GLint a_offset = 2;
static constexpr GLint a_data = 3;
static constexpr GLint a_data1 = 4;
static constexpr GLint a_data2 = 5;
private:
bool compileShader(gl::UniqueShader&, const GLchar *source);
void linkProgram(gl::UniqueProgram&);
gl::UniqueProgram program;
gl::UniqueShader vertexShader;
gl::UniqueShader fragmentShader;
mbgl::optional<gl::UniqueProgram> programOverdraw;
mbgl::optional<gl::UniqueShader> overdrawShader;
};
} // namespace mbgl