fix symbol rendering in perspective view

This commit is contained in:
Ansis Brammanis
2015-08-14 18:06:14 +03:00
parent be36ce0198
commit 494489f9a0
7 changed files with 82 additions and 19 deletions

View File

@@ -155,9 +155,7 @@ void Painter::changeMatrix() {
state.pixel_y() - state.getWidth() / 2.0f, 0);
// The extrusion matrix.
matrix::identity(extrudeMatrix);
matrix::multiply(extrudeMatrix, projMatrix, extrudeMatrix);
matrix::rotate_z(extrudeMatrix, extrudeMatrix, state.getAngle());
matrix::ortho(extrudeMatrix, 0, state.getWidth(), state.getHeight(), 0, 0, -1);
// The native matrix is a 1:1 matrix that paints the coordinates at the
// same screen position as the vertex specifies.

View File

@@ -28,25 +28,40 @@ void Painter::renderSDF(SymbolBucket &bucket,
{
mat4 vtxMatrix = translatedMatrix(matrix, styleProperties.translate, id, styleProperties.translate_anchor);
mat4 exMatrix;
matrix::copy(exMatrix, projMatrix);
bool aligned_with_map = (bucketProperties.rotation_alignment == RotationAlignmentType::Map);
const float angleOffset = aligned_with_map ? state.getAngle() : 0;
bool skewed = aligned_with_map;
mat4 exMatrix;
float s;
float gammaScale;
if (angleOffset) {
matrix::rotate_z(exMatrix, exMatrix, angleOffset);
if (skewed) {
matrix::identity(exMatrix);
s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z);
gammaScale = 1.0f / std::cos(state.getPitch());
} else {
exMatrix = extrudeMatrix;
s = state.getAltitude();
gammaScale = 1.0f;
}
matrix::scale(exMatrix, exMatrix, s, s, 1);
// If layerStyle.size > bucket.info.fontSize then labels may collide
float fontSize = styleProperties.size;
float fontScale = fontSize / sdfFontSize;
matrix::scale(exMatrix, exMatrix, fontScale, fontScale, 1.0f);
// calculate how much longer the real world distance is at the top of the screen
// than at the middle of the screen.
float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2)));
float x = state.getHeight() / 2.0f * std::tan(state.getPitch());
float extra = (topedgelength + x) / topedgelength - 1;
useProgram(sdfShader.program);
sdfShader.u_matrix = vtxMatrix;
sdfShader.u_exmatrix = exMatrix;
sdfShader.u_texsize = texsize;
sdfShader.u_skewed = skewed;
sdfShader.u_extra = extra;
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / bucketProperties.size) / std::log(2);
@@ -70,7 +85,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
// We're drawing in the translucent pass which is bottom-to-top, so we need
// to draw the halo first.
if (styleProperties.halo_color[3] > 0.0f && styleProperties.halo_width > 0.0f) {
sdfShader.u_gamma = styleProperties.halo_blur * blurOffset / fontScale / sdfPx + gamma;
sdfShader.u_gamma = (styleProperties.halo_blur * blurOffset / fontScale / sdfPx + gamma) * gammaScale;
if (styleProperties.opacity < 1.0f) {
Color color = styleProperties.halo_color;
@@ -91,7 +106,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
// Then, we draw the text/icon over the halo
if (styleProperties.color[3] > 0.0f) {
sdfShader.u_gamma = gamma;
sdfShader.u_gamma = gamma * gammaScale;
if (styleProperties.opacity < 1.0f) {
Color color = styleProperties.color;
@@ -120,7 +135,6 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
const auto &properties = layer_desc.getProperties<SymbolProperties>();
const auto &layout = bucket.layout;
config.depthTest = true;
config.depthMask = GL_FALSE;
if (bucket.hasCollisionBoxData()) {
@@ -150,6 +164,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
config.stencilTest = drawAcrossEdges ? false : true;
if (bucket.hasIconData()) {
config.depthTest = layout.icon.rotation_alignment == RotationAlignmentType::Map;
bool sdf = bucket.sdfIcons;
const float angleOffset =
@@ -160,7 +176,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
const float fontSize = properties.icon.size;
const float fontScale = fontSize / 1.0f;
spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line
|| angleOffset != 0 || fontScale != 1 || sdf || state.getPitch() != 0);
if (sdf) {
renderSDF(bucket,
@@ -175,19 +192,33 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
} else {
mat4 vtxMatrix = translatedMatrix(matrix, properties.icon.translate, id, properties.icon.translate_anchor);
bool skewed = layout.icon.rotation_alignment == RotationAlignmentType::Map;
mat4 exMatrix;
matrix::copy(exMatrix, projMatrix);
float s;
if (angleOffset) {
matrix::rotate_z(exMatrix, exMatrix, angleOffset);
if (skewed) {
matrix::identity(exMatrix);
s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z);
} else {
exMatrix = extrudeMatrix;
s = state.getAltitude();
}
matrix::scale(exMatrix, exMatrix, s, s, 1);
matrix::scale(exMatrix, exMatrix, fontScale, fontScale, 1.0f);
// calculate how much longer the real world distance is at the top of the screen
// than at the middle of the screen.
float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2)));
float x = state.getHeight() / 2.0f * std::tan(state.getPitch());
float extra = (topedgelength + x) / topedgelength - 1;
useProgram(iconShader->program);
iconShader->u_matrix = vtxMatrix;
iconShader->u_exmatrix = exMatrix;
iconShader->u_texsize = {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }};
iconShader->u_skewed = skewed;
iconShader->u_extra = extra;
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / layout.icon.size) / std::log(2);
@@ -205,6 +236,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
}
if (bucket.hasTextData()) {
config.depthTest = layout.text.rotation_alignment == RotationAlignmentType::Map;
glyphAtlas->bind();
renderSDF(bucket,

View File

@@ -14,6 +14,8 @@ uniform float u_minfadezoom;
uniform float u_maxfadezoom;
uniform float u_fadezoom;
uniform float u_opacity;
uniform bool u_skewed;
uniform float u_extra;
uniform vec2 u_texsize;
@@ -51,7 +53,15 @@ void main() {
// if label has been faded out, clip it
z += step(v_alpha, 0.0);
gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset / 64.0, z, 0);
if (u_skewed) {
vec4 extrude = u_exmatrix * vec4(a_offset / 64.0, 0, 0);
gl_Position = u_matrix * vec4(a_pos + extrude.xy, 0, 1);
gl_Position.z += z * gl_Position.w;
} else {
vec4 extrude = u_exmatrix * vec4(a_offset / 64.0, z, 0);
gl_Position = u_matrix * vec4(a_pos, 0, 1) + extrude;
}
v_tex = a_tex / u_texsize;
v_alpha *= u_opacity;

View File

@@ -21,6 +21,8 @@ public:
Uniform<float> u_fadezoom = {"u_fadezoom", *this};
Uniform<float> u_opacity = {"u_opacity", *this};
Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this};
Uniform<int32_t> u_skewed = {"u_skewed", *this};
Uniform<float> u_extra = {"u_extra", *this};
private:
int32_t a_pos = -1;

View File

@@ -5,9 +5,11 @@ uniform float u_gamma;
varying vec2 v_tex;
varying float v_alpha;
varying float v_gamma_scale;
void main() {
float dist = texture2D(u_texture, v_tex).a;
float alpha = smoothstep(u_buffer - u_gamma, u_buffer + u_gamma, dist) * v_alpha;
float gamma = u_gamma * v_gamma_scale;
float alpha = smoothstep(u_buffer - gamma, u_buffer + gamma, dist) * v_alpha;
gl_FragColor = u_color * alpha;
}

View File

@@ -13,11 +13,14 @@ uniform float u_fadedist;
uniform float u_minfadezoom;
uniform float u_maxfadezoom;
uniform float u_fadezoom;
uniform bool u_skewed;
uniform float u_extra;
uniform vec2 u_texsize;
varying vec2 v_tex;
varying float v_alpha;
varying float v_gamma_scale;
void main() {
vec2 a_tex = a_data1.xy;
@@ -48,6 +51,19 @@ void main() {
// if label has been faded out, clip it
show *= (1.0 - step(v_alpha, 0.0));
gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset * show / 64.0, 0, 0);
if (u_skewed) {
vec4 extrude = u_exmatrix * vec4(a_offset * show / 64.0, 0, 0);
gl_Position = u_matrix * vec4(a_pos + extrude.xy, 0, 1);
} else {
vec4 extrude = u_exmatrix * vec4(a_offset * show / 64.0, 0, 0);
gl_Position = u_matrix * vec4(a_pos, 0, 1) + extrude;
}
// position of y on the screen
float y = gl_Position.y / gl_Position.w;
// how much features are squished in all directions by the perspectiveness
float perspective_scale = 1.0 / (1.0 - y * u_extra);
v_gamma_scale = perspective_scale;
v_tex = a_tex / u_texsize;
}

View File

@@ -23,6 +23,8 @@ public:
Uniform<float> u_minfadezoom = {"u_minfadezoom", *this};
Uniform<float> u_maxfadezoom = {"u_maxfadezoom", *this};
Uniform<float> u_fadezoom = {"u_fadezoom", *this};
Uniform<int32_t> u_skewed = {"u_skewed", *this};
Uniform<float> u_extra = {"u_extra", *this};
protected:
int32_t a_pos = -1;