[core] Refactor wireframe to match JS overdraw mode
This commit is contained in:
@@ -794,7 +794,7 @@ void Map::cycleDebugOptions() {
|
||||
impl->debugOptions = MapDebugOptions::NoDebug;
|
||||
#endif // GL_ES_VERSION_2_0
|
||||
else if (impl->debugOptions & MapDebugOptions::Collision)
|
||||
impl->debugOptions = MapDebugOptions::Collision | MapDebugOptions::Wireframe;
|
||||
impl->debugOptions = MapDebugOptions::Wireframe;
|
||||
else if (impl->debugOptions & MapDebugOptions::Timestamps)
|
||||
impl->debugOptions = impl->debugOptions | MapDebugOptions::Collision;
|
||||
else if (impl->debugOptions & MapDebugOptions::ParseStatus)
|
||||
|
||||
@@ -92,7 +92,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
spriteAtlas = style.spriteAtlas.get();
|
||||
lineAtlas = style.lineAtlas.get();
|
||||
|
||||
RenderData renderData = style.getRenderData();
|
||||
RenderData renderData = style.getRenderData(frame.debugOptions);
|
||||
const std::vector<RenderItem>& order = renderData.order;
|
||||
const std::set<Source*>& sources = renderData.sources;
|
||||
const Color& background = renderData.backgroundColor;
|
||||
@@ -144,7 +144,12 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
config.depthTest = GL_FALSE;
|
||||
config.depthMask = GL_TRUE;
|
||||
config.colorMask = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE };
|
||||
if (frame.debugOptions & MapDebugOptions::Wireframe) {
|
||||
|
||||
if (isWireframe()) {
|
||||
config.blend = GL_TRUE;
|
||||
config.blendFunc = { GL_CONSTANT_COLOR, GL_ONE };
|
||||
const float overdraw = 1.0f / 8.0f;
|
||||
config.blendColor = { overdraw, overdraw, overdraw, 0.0f };
|
||||
config.clearColor = Color::black();
|
||||
} else {
|
||||
config.clearColor = background;
|
||||
@@ -243,7 +248,9 @@ void Painter::renderPass(RenderPass pass_,
|
||||
if (!layer.baseImpl->hasRenderPass(pass))
|
||||
continue;
|
||||
|
||||
if (pass == RenderPass::Translucent) {
|
||||
if (isWireframe()) {
|
||||
config.blend = GL_TRUE;
|
||||
} else if (pass == RenderPass::Translucent) {
|
||||
config.blendFunc.reset();
|
||||
config.blend = GL_TRUE;
|
||||
} else {
|
||||
|
||||
@@ -156,6 +156,8 @@ private:
|
||||
|
||||
void setDepthSublayer(int n);
|
||||
|
||||
bool isWireframe() const { return frame.debugOptions & MapDebugOptions::Wireframe; }
|
||||
|
||||
mat4 projMatrix;
|
||||
mat4 nativeMatrix;
|
||||
|
||||
|
||||
@@ -21,9 +21,6 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
|
||||
optional<SpriteAtlasPosition> imagePosA;
|
||||
optional<SpriteAtlasPosition> imagePosB;
|
||||
|
||||
bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe;
|
||||
isPatterned &= !wireframe;
|
||||
|
||||
if (isPatterned) {
|
||||
imagePosA = spriteAtlas->getPosition(properties.backgroundPattern.value.from, true);
|
||||
imagePosB = spriteAtlas->getPosition(properties.backgroundPattern.value.to, true);
|
||||
@@ -31,7 +28,7 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
|
||||
if (!imagePosA || !imagePosB)
|
||||
return;
|
||||
|
||||
config.program = patternShader->getID();
|
||||
config.program = isWireframe() ? patternShader->getOverdrawID() : patternShader->getID();
|
||||
patternShader->u_matrix = identityMatrix;
|
||||
patternShader->u_pattern_tl_a = imagePosA->tl;
|
||||
patternShader->u_pattern_br_a = imagePosA->br;
|
||||
@@ -44,15 +41,10 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
|
||||
backgroundPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
|
||||
|
||||
} else {
|
||||
if (wireframe) {
|
||||
plainShader->u_color = Color::black();
|
||||
plainShader->u_opacity = 1.0f;
|
||||
} else {
|
||||
plainShader->u_color = properties.backgroundColor;
|
||||
plainShader->u_opacity = properties.backgroundOpacity;
|
||||
}
|
||||
plainShader->u_color = properties.backgroundColor;
|
||||
plainShader->u_opacity = properties.backgroundOpacity;
|
||||
|
||||
config.program = plainShader->getID();
|
||||
config.program = isWireframe() ? plainShader->getOverdrawID() : plainShader->getID();
|
||||
backgroundArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ void Painter::renderCircle(CircleBucket& bucket,
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, properties.circleTranslate, tileID,
|
||||
properties.circleTranslateAnchor);
|
||||
|
||||
config.program = circleShader->getID();
|
||||
config.program = isWireframe() ? circleShader->getOverdrawID() : circleShader->getID();
|
||||
|
||||
circleShader->u_matrix = vtxMatrix;
|
||||
circleShader->u_extrude_scale = extrudeScale;
|
||||
|
||||
@@ -36,16 +36,6 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
bool outline = properties.fillAntialias && !pattern && isOutlineColorDefined;
|
||||
bool fringeline = properties.fillAntialias && !pattern && !isOutlineColorDefined;
|
||||
|
||||
bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe;
|
||||
if (wireframe) {
|
||||
fillColor = Color::white();
|
||||
strokeColor = Color::white();
|
||||
opacity = 1.0f;
|
||||
pattern = false;
|
||||
outline = true;
|
||||
fringeline = true;
|
||||
}
|
||||
|
||||
config.stencilOp.reset();
|
||||
config.stencilTest = GL_TRUE;
|
||||
config.depthFunc.reset();
|
||||
@@ -56,7 +46,7 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
// 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 = outlineShader->getID();
|
||||
config.program = isWireframe() ? outlineShader->getOverdrawID() : outlineShader->getID();
|
||||
outlineShader->u_matrix = vertexMatrix;
|
||||
|
||||
outlineShader->u_outline_color = strokeColor;
|
||||
@@ -86,7 +76,7 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
|
||||
// Image fill.
|
||||
if (pass == RenderPass::Translucent && imagePosA && imagePosB) {
|
||||
config.program = patternShader->getID();
|
||||
config.program = isWireframe() ? patternShader->getOverdrawID() : patternShader->getID();
|
||||
patternShader->u_matrix = vertexMatrix;
|
||||
patternShader->u_pattern_tl_a = imagePosA->tl;
|
||||
patternShader->u_pattern_br_a = imagePosA->br;
|
||||
@@ -115,7 +105,7 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
bucket.drawElements(*patternShader, store);
|
||||
|
||||
if (properties.fillAntialias && !isOutlineColorDefined) {
|
||||
config.program = outlinePatternShader->getID();
|
||||
config.program = isWireframe() ? outlinePatternShader->getOverdrawID() : outlinePatternShader->getID();
|
||||
outlinePatternShader->u_matrix = vertexMatrix;
|
||||
|
||||
// Draw the entire line
|
||||
@@ -143,14 +133,14 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
bucket.drawVertices(*outlinePatternShader, store);
|
||||
}
|
||||
}
|
||||
} else if (!wireframe) {
|
||||
} else {
|
||||
// No image fill.
|
||||
if ((fillColor.a >= 1.0f && opacity >= 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.
|
||||
config.program = plainShader->getID();
|
||||
config.program = isWireframe() ? plainShader->getOverdrawID() : plainShader->getID();
|
||||
plainShader->u_matrix = vertexMatrix;
|
||||
plainShader->u_color = fillColor;
|
||||
plainShader->u_opacity = opacity;
|
||||
@@ -164,7 +154,7 @@ void Painter::renderFill(FillBucket& bucket,
|
||||
// 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 = outlineShader->getID();
|
||||
config.program = isWireframe() ? outlineShader->getOverdrawID() : outlineShader->getID();
|
||||
outlineShader->u_matrix = vertexMatrix;
|
||||
|
||||
outlineShader->u_outline_color = fillColor;
|
||||
|
||||
@@ -33,17 +33,10 @@ void Painter::renderLine(LineBucket& bucket,
|
||||
// Retina devices need a smaller distance to avoid aliasing.
|
||||
float antialiasing = 1.0 / frame.pixelRatio;
|
||||
|
||||
bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe;
|
||||
|
||||
float blur = properties.lineBlur + antialiasing;
|
||||
|
||||
Color color = Color::white();
|
||||
float opacity = 1.0f;
|
||||
if (!wireframe) {
|
||||
color = properties.lineColor;
|
||||
opacity = properties.lineOpacity;
|
||||
}
|
||||
|
||||
const Color color = properties.lineColor;
|
||||
const float opacity = properties.lineOpacity;
|
||||
const float ratio = 1.0 / tileID.pixelsToTileUnits(1.0, state.getZoom());
|
||||
|
||||
mat2 antialiasingMatrix;
|
||||
@@ -64,7 +57,7 @@ void Painter::renderLine(LineBucket& bucket,
|
||||
|
||||
if (!properties.lineDasharray.value.from.empty()) {
|
||||
|
||||
config.program = linesdfShader->getID();
|
||||
config.program = isWireframe() ? linesdfShader->getOverdrawID() : linesdfShader->getID();
|
||||
|
||||
linesdfShader->u_matrix = vtxMatrix;
|
||||
linesdfShader->u_linewidth = properties.lineWidth / 2;
|
||||
@@ -109,7 +102,7 @@ void Painter::renderLine(LineBucket& bucket,
|
||||
if (!imagePosA || !imagePosB)
|
||||
return;
|
||||
|
||||
config.program = linepatternShader->getID();
|
||||
config.program = isWireframe() ? linepatternShader->getOverdrawID() : linepatternShader->getID();
|
||||
|
||||
linepatternShader->u_matrix = vtxMatrix;
|
||||
linepatternShader->u_linewidth = properties.lineWidth / 2;
|
||||
@@ -145,7 +138,7 @@ void Painter::renderLine(LineBucket& bucket,
|
||||
bucket.drawLinePatterns(*linepatternShader, store);
|
||||
|
||||
} else {
|
||||
config.program = lineShader->getID();
|
||||
config.program = isWireframe() ? lineShader->getOverdrawID() : lineShader->getID();
|
||||
|
||||
lineShader->u_matrix = vtxMatrix;
|
||||
lineShader->u_linewidth = properties.lineWidth / 2;
|
||||
|
||||
@@ -18,7 +18,7 @@ void Painter::renderRaster(RasterBucket& bucket,
|
||||
const RasterPaintProperties& properties = layer.impl->paint;
|
||||
|
||||
if (bucket.hasData()) {
|
||||
config.program = rasterShader->getID();
|
||||
config.program = isWireframe() ? rasterShader->getOverdrawID() : rasterShader->getID();
|
||||
rasterShader->u_matrix = matrix;
|
||||
rasterShader->u_buffer = 0;
|
||||
rasterShader->u_opacity = properties.rasterOpacity;
|
||||
|
||||
@@ -58,7 +58,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
exScale = {{ exScale[0] * scale, exScale[1] * scale }};
|
||||
}
|
||||
|
||||
config.program = sdfShader.getID();
|
||||
config.program = isWireframe() ? sdfShader.getOverdrawID() : sdfShader.getID();
|
||||
sdfShader.u_matrix = vtxMatrix;
|
||||
sdfShader.u_extrude_scale = exScale;
|
||||
sdfShader.u_texsize = texsize;
|
||||
@@ -199,7 +199,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
|
||||
exScale = {{ exScale[0] * scale, exScale[1] * scale }};
|
||||
}
|
||||
|
||||
config.program = iconShader->getID();
|
||||
config.program = isWireframe() ? 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 }};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -21,12 +22,12 @@ Shader::Shader(const char* name_, const char* vertexSource, const char* fragment
|
||||
{
|
||||
util::stopwatch stopwatch("shader compilation", Event::Shader);
|
||||
|
||||
if (!compileShader(vertexShader, &vertexSource)) {
|
||||
if (!compileShader(vertexShader, vertexSource)) {
|
||||
Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertexSource);
|
||||
throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
|
||||
}
|
||||
|
||||
if (!compileShader(fragmentShader, &fragmentSource)) {
|
||||
if (!compileShader(fragmentShader, fragmentSource)) {
|
||||
Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragmentSource);
|
||||
throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
|
||||
}
|
||||
@@ -35,32 +36,50 @@ 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()));
|
||||
|
||||
{
|
||||
// Link program
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glLinkProgram(program.get()));
|
||||
linkProgram(program);
|
||||
|
||||
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));
|
||||
const auto log = std::make_unique<GLchar[]>(logLength);
|
||||
if (logLength > 0) {
|
||||
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());
|
||||
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"));
|
||||
}
|
||||
|
||||
bool Shader::compileShader(gl::UniqueShader& shader, const GLchar *source[]) {
|
||||
void Shader::linkProgram(gl::UniqueProgram& program_) {
|
||||
// Link program
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glLinkProgram(program_.get()));
|
||||
|
||||
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));
|
||||
const auto log = std::make_unique<GLchar[]>(logLength);
|
||||
if (logLength > 0) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
bool Shader::compileShader(gl::UniqueShader& shader, const GLchar *source) {
|
||||
GLint status = 0;
|
||||
|
||||
const GLsizei lengths = static_cast<GLsizei>(std::strlen(*source));
|
||||
MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, source, &lengths));
|
||||
const GLsizei lengths = static_cast<GLsizei>(std::strlen(source));
|
||||
MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, &source, &lengths));
|
||||
|
||||
MBGL_CHECK_ERROR(glCompileShader(shader.get()));
|
||||
|
||||
@@ -90,6 +109,10 @@ 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
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/gl/object_store.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -15,6 +16,10 @@ public:
|
||||
return program.get();
|
||||
}
|
||||
|
||||
GLuint getOverdrawID() const {
|
||||
return programOverdraw ? *programOverdraw : 0;
|
||||
}
|
||||
|
||||
virtual void bind(GLbyte *offset) = 0;
|
||||
|
||||
protected:
|
||||
@@ -22,11 +27,15 @@ protected:
|
||||
GLint a_pos = -1;
|
||||
|
||||
private:
|
||||
bool compileShader(gl::UniqueShader&, const GLchar *source[]);
|
||||
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
|
||||
|
||||
@@ -258,7 +258,7 @@ bool Style::isLoaded() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderData Style::getRenderData() const {
|
||||
RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
|
||||
RenderData result;
|
||||
|
||||
for (const auto& source : sources) {
|
||||
@@ -272,6 +272,11 @@ RenderData Style::getRenderData() const {
|
||||
continue;
|
||||
|
||||
if (const BackgroundLayer* background = layer->as<BackgroundLayer>()) {
|
||||
if (debugOptions & MapDebugOptions::Wireframe) {
|
||||
// We want to skip glClear optimization in wireframe mode.
|
||||
result.order.emplace_back(*layer);
|
||||
continue;
|
||||
}
|
||||
const BackgroundPaintProperties& paint = background->impl->paint;
|
||||
if (layer.get() == layers[0].get() && paint.backgroundPattern.value.from.empty()) {
|
||||
// This is a solid background. We can use glClear().
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
void setClasses(const std::vector<std::string>&, const TransitionOptions& = {});
|
||||
std::vector<std::string> getClasses() const;
|
||||
|
||||
RenderData getRenderData() const;
|
||||
RenderData getRenderData(MapDebugOptions) const;
|
||||
|
||||
std::vector<Feature> queryRenderedFeatures(const QueryParameters&) const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user