fix symbol rendering in perspective view
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user