From 81ef2b8983f1f4e5defe3a11ae113ce475f8072a Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Wed, 12 Aug 2026 13:24:56 +0300 Subject: [PATCH] optimise bold labels a bit --- assets/shaders/glsl/map_font_f.glsl | 73 ++++++++++++++++------ src/map/map.cpp | 97 ++++++++++++++--------------- src/map/map.hpp | 6 +- src/map/map_state.cpp | 12 ---- 4 files changed, 103 insertions(+), 85 deletions(-) diff --git a/assets/shaders/glsl/map_font_f.glsl b/assets/shaders/glsl/map_font_f.glsl index 641105a60..ab4d1ba62 100644 --- a/assets/shaders/glsl/map_font_f.glsl +++ b/assets/shaders/glsl/map_font_f.glsl @@ -9,8 +9,12 @@ struct Curve { }; uniform isamplerBuffer glyphs; + uniform samplerBuffer curves; +uniform samplerBuffer bold_curves; + uniform vec4 color; +uniform vec4 outline_color; // Size of the window (in pixels) used for 1-dimensional anti-aliasing along each rays. @@ -45,6 +49,14 @@ Curve loadCurve(int index) { return result; } +Curve loadBoldCurve(int index) { + Curve result; + result.p0 = texelFetch(bold_curves, 3*index+0).xy; + result.p1 = texelFetch(bold_curves, 3*index+1).xy; + result.p2 = texelFetch(bold_curves, 3*index+2).xy; + return result; +} + float computeCoverage_real(float inverseDiameter, vec2 p0, vec2 p1, vec2 p2) { if (p0.y > 0 && p1.y > 0 && p2.y > 0) return 0.0; if (p0.y < 0 && p1.y < 0 && p2.y < 0) return 0.0; @@ -80,7 +92,7 @@ float computeCoverage_real(float inverseDiameter, vec2 p0, vec2 p1, vec2 p2) { } float alpha = 0; - + if (t0 >= 0 && t0 < 1) { float x = (a.x*t0 - 2.0*b.x)*t0 + c.x; alpha += clamp(x * inverseDiameter + 0.5, 0, 1); @@ -117,7 +129,7 @@ float computeCoverage(float inverseDiameter, vec2 p0, vec2 p1, vec2 p2) { } else { t0 = t; t1 = -1.0; - } + } float alpha = 0; @@ -125,12 +137,12 @@ float computeCoverage(float inverseDiameter, vec2 p0, vec2 p1, vec2 p2) { if (t0 >= 0 && t0 < 1) { float x = (a.x*t0 - 2.0*b.x)*t0 + c.x; alpha += clamp(x * inverseDiameter + 0.5, 0, 1); - } + } if (t1 >= 0 && t1 < 1) { float x = (a.x*t1 - 2.0*b.x)*t1 + c.x; alpha -= clamp(x * inverseDiameter + 0.5, 0, 1); - } + } return alpha; } @@ -141,18 +153,45 @@ vec2 rotate(vec2 v) { } void main() { - float alpha = 0; + float alpha_bold = 0.f; + float alpha = 0.f; + + vec2 dtex_dpixel = fwidth(uv); // Inverse of the diameter of a pixel in uv units for anti-aliasing. - vec2 inverseDiameter = 1.0 / (antiAliasingWindowSize * fwidth(uv)); + vec2 inverseDiameter = 1.0 / (antiAliasingWindowSize * dtex_dpixel); Glyph glyph = loadGlyph(bufferIndex); + vec2 adj_uv = uv; + + float alpha_bold_upper_limit = max(0.f, 1.f - (dtex_dpixel.x / (2.f / 64.f) + dtex_dpixel.y / (2.f / 64.f)) * 0.25f); + + if (outline_color.a > 0.f && alpha_bold_upper_limit > 0.f) { + for (int i = 0; i < glyph.count; i++) { + Curve curve = loadBoldCurve(glyph.start + i); + + vec2 p0 = curve.p0 - uv; + vec2 p1 = curve.p1 - uv; + vec2 p2 = curve.p2 - uv; + + alpha_bold += computeCoverage_real(inverseDiameter.x, p0, p1, p2); + } + + alpha_bold = clamp(alpha_bold, 0.0, 1.0) * alpha_bold_upper_limit; + if (alpha_bold == 0.f) { + discard; + } + adj_uv -= 2.f / 64.f; + } else { + alpha_bold = 0.f; + } + for (int i = 0; i < glyph.count; i++) { Curve curve = loadCurve(glyph.start + i); - vec2 p0 = curve.p0 - uv; - vec2 p1 = curve.p1 - uv; - vec2 p2 = curve.p2 - uv; + vec2 p0 = curve.p0 - adj_uv; + vec2 p1 = curve.p1 - adj_uv; + vec2 p2 = curve.p2 - adj_uv; alpha += computeCoverage_real(inverseDiameter.x, p0, p1, p2); if (enableSuperSamplingAntiAliasing) { @@ -164,15 +203,11 @@ void main() { alpha *= 0.5; } - result = color * clamp(alpha * opacity * color.a, 0.0, 1.0); - - //alpha = clamp(alpha * opacity, 0.0, 1.0); - //result = color * alpha; + alpha = clamp(alpha, 0.0, 1.0); - - // float t = 1.0f; - // float k = 1.0f; - // if(glyph.count < 10) { t = 0.0f; } - // if(bufferIndex < 10) { k = 0.0f; } - // result = vec4(1.0, t, k, color.a) * alpha; + if (alpha > 0.f) { + result = color * alpha * opacity * color.a; + } else { + result = outline_color * alpha_bold * opacity * color.a; + } } diff --git a/src/map/map.cpp b/src/map/map.cpp index d5651bff3..241890be1 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -775,8 +775,10 @@ void display_data::load_shaders(simple_fs::directory& root) { shader_uniforms[i][uniform_is_national_border] = glGetUniformLocation(shaders[i], "is_national_border"); shader_uniforms[i][uniform_graphics_mode] = glGetUniformLocation(shaders[i], "graphics_mode"); shader_uniforms[i][uniform_color] = glGetUniformLocation(shaders[i], "color"); + shader_uniforms[i][uniform_outline_color] = glGetUniformLocation(shaders[i], "outline_color"); shader_uniforms[i][uniform_glyphs] = glGetUniformLocation(shaders[i], "glyphs"); shader_uniforms[i][uniform_curves] = glGetUniformLocation(shaders[i], "curves"); + shader_uniforms[i][uniform_bold_curves] = glGetUniformLocation(shaders[i], "bold_curves"); shader_uniforms[i][uniform_printbrush] = glGetUniformLocation(shaders[i], "printbrush"); shader_uniforms[i][uniform_hatching] = glGetUniformLocation(shaders[i], "hatching"); shader_uniforms[i][uniform_watercolor] = glGetUniformLocation(shaders[i], "watercolor"); @@ -1859,6 +1861,8 @@ void display_data::render( //glDisable(GL_BLEND); auto color_location = shader_uniforms[shader_text_line][uniform_color]; + auto outline_color_location = shader_uniforms[shader_text_line][uniform_outline_color]; + /* if(state.user_settings.black_map_font) glUniform4f(location, 0.0f, 0.0f, 0.0f, 1.0f); @@ -1866,59 +1870,56 @@ void display_data::render( glUniform4f(location, 1.0f, 1.0f, 1.0f, 1.0f); */ - auto location = shader_uniforms[shader_text_line][uniform_glyphs]; - glUniform1i(location, 0); - - location = shader_uniforms[shader_text_line][uniform_curves]; - glUniform1i(location, 1); - + auto glyphs_location = shader_uniforms[shader_text_line][uniform_glyphs]; + glUniform1i(glyphs_location, 0); + auto curves_location = shader_uniforms[shader_text_line][uniform_curves]; + glUniform1i(curves_location, 1); + auto bold_curves_location = shader_uniforms[shader_text_line][uniform_bold_curves]; + glUniform1i(bold_curves_location, 2); - glUniform4f(color_location, 0.0f, 0.0f, 0.0f, 1.0f); - - //if (zoom > map::zoom_very_close) { - + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.glyph_texture); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.glyph_texture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.curve_texture); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.curve_texture); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.bold_curve_texture); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); + if(state.user_settings.black_map_font) { glUniform4f(color_location, 0.0f, 0.0f, 0.0f, 1.0f); + } else { + glUniform4f(color_location, 0.9f, 0.9f, 0.9f, 0.8f); + } + + glUniform4f(outline_color_location, 0.0f, 0.0f, 0.0f, 0.0f); + //if (zoom > map::zoom_very_close) { glBindVertexArray(vao_array[vo_province_text_line]); glBindBuffer(GL_ARRAY_BUFFER, vbo_array[vo_province_text_line]); glDrawArrays(GL_TRIANGLES, 0, (GLsizei)province_text_line_vertices.size()); - //} - if((!state.cheat_data.province_names || zoom < map::zoom_very_close) && !text_line_vertices.empty()) { - glUniform4f(color_location, 0.9f, 0.9f, 0.9f, 0.8f); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.bold_glyph_texture); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.bold_curve_texture); - - glActiveTexture(GL_TEXTURE0); - - glBindVertexArray(vao_array[vo_bold_text_line]); - glBindBuffer(GL_ARRAY_BUFFER, vbo_array[vo_bold_text_line]); - glDrawArrays(GL_TRIANGLES, 0, last_size_of_bold_text_line_vertices); - - glUniform4f(color_location, 0.0f, 0.0f, 0.0f, 1.0f); + if(state.user_settings.black_map_font) { + glUniform4f(outline_color_location, 0.9f, 0.9f, 0.9f, 0.8f); + } else { + glUniform4f(outline_color_location, 0.0f, 0.0f, 0.0f, 1.0f); + } + if((!state.cheat_data.province_names || zoom < map::zoom_very_close) && !text_line_vertices.empty()) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.glyph_texture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.curve_texture); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_BUFFER, state.font_collection.mfont.bold_curve_texture); + glActiveTexture(GL_TEXTURE0); glBindVertexArray(vao_array[vo_text_line]); @@ -3418,7 +3419,7 @@ void display_data::update_sprawl(sys::state& state) { float desired_font_size_index(float curve_length, float text_extent) { float size = (curve_length / text_extent) * 0.8f; float font_size_index = std::round(5.f * log(size) / log(1.618034f)); - if(font_size_index > 45.f) font_size_index = 45.f; + if(font_size_index > 30.f) font_size_index = 30.f; if(font_size_index > 5.f) font_size_index = 5.f * std::round(font_size_index / 5.f); return font_size_index; } @@ -3442,8 +3443,7 @@ float get_max_glyph_height(sys::state& state, text_line_generator_data const& e) } void push_polynomial_text_to_vertex_array(sys::state& state, display_data& display_data, text_line_generator_data const& e, - std::vector& out, - std::vector& bold_out + std::vector& out ) { float size_x = (float)display_data.size_x; float size_y = (float)display_data.size_y; @@ -3586,7 +3586,7 @@ void push_polynomial_text_to_vertex_array(sys::state& state, display_data& displ float x_bearing = float(gi.ft_x_bearing) * letter_scale; float y_bearing = float(gi.ft_y_bearing) * letter_scale; - float expansion = 1.f; + float expansion = 2.f / 64.f; auto embold_x = mult / 2.f; auto embold_y = mult / 2.f; @@ -3640,8 +3640,7 @@ void push_polynomial_text_to_vertex_array(sys::state& state, display_data& displ auto& bold_gi = state.font_collection.mfont.bold_glyphs[glyphid]; float x_advance = float(e.text.glyph_info[i].x_advance) * letter_scale; - push_glyph(gi, e.text.glyph_info[i], out, 0.f); - push_glyph(bold_gi, e.text.glyph_info[i], bold_out, (float)text::map_outline_embolden / 64.f); + push_glyph(bold_gi, e.text.glyph_info[i], out, (float)text::map_outline_embolden / 64.f); auto current_spacing = (i == glyph_count - 1) ? 0.f : letter_spacing_map; float glyph_advance = x_advance * size / 64.f; @@ -3665,8 +3664,6 @@ void push_polynomial_text_to_vertex_array(sys::state& state, display_data& displ void push_spherical_text_to_vertex_array( sys::state& state, display_data& display_data, text_line_generator_data const& e, std::vector& out, - std::vector& bold_out, - bool bold, int size_limit, int min_size_cutoff, float opacity_mult ) { float size_x = (float)display_data.size_x; @@ -3800,19 +3797,19 @@ void push_spherical_text_to_vertex_array( auto forward_sphere = sphere_tangent(sph_placement_runner, sph_direction); auto up_sphere = sphere_R3::rotate(forward_sphere); - float expansion = 1.f; + float expansion = 2.f / 64.f; float u0 = float(gi.ft_x_bearing) / (64.0f * text::dr_size) - expansion; float v0 = float(gi.ft_y_bearing - gi.ft_height) / (64.0f * text::dr_size) - expansion; - float u1 = float(gi.ft_x_bearing + gi.ft_width) / (64.0f * text::dr_size) + expansion; - float v1 = float(gi.ft_y_bearing) / (64.0f * text::dr_size) + expansion; + float u1 = float(gi.ft_x_bearing + gi.ft_width) / (64.0f * text::dr_size) + 2.f * expansion; + float v1 = float(gi.ft_y_bearing) / (64.0f * text::dr_size) + 2.f * expansion; auto embold_x = mult / 2.f; auto embold_y = mult / 2.f; auto left_base = sphere_shift(sph_placement_runner, sph_direction, -expansion * size - embold_x * size); - auto right_base = sphere_shift(sph_placement_runner, sph_direction, size / 64.f * glyph_width + expansion * size - embold_x * size); + auto right_base = sphere_shift(sph_placement_runner, sph_direction, size / 64.f * glyph_width + 2.f * expansion * size - embold_x * size); /* We want our great circle to be a central line -> we shift the bottom line by half of max glyph height "down". @@ -3820,7 +3817,7 @@ void push_spherical_text_to_vertex_array( Both lines have to be offset by y bearing (letter specific) and y offset (kerning specific) */ - auto shift_up = (-max_glyph_height / 2.f + y_bearing - y_offset + expansion * 64.f) * size / 64.f - embold_y * size; + auto shift_up = (-max_glyph_height / 2.f + y_bearing - y_offset + 2.f * expansion * 64.f) * size / 64.f - embold_y * size; auto shift_down = (-max_glyph_height / 2.f + y_bearing - y_offset - glyph_height - expansion * 64.f) * size / 64.f - embold_y * size; sphere_R3::point left_up_point = { sphere_shift(left_base, up_sphere.data, shift_up) }; @@ -3847,8 +3844,7 @@ void push_spherical_text_to_vertex_array( auto& gi = state.font_collection.mfont.glyphs[glyphid]; auto& bold_gi = state.font_collection.mfont.bold_glyphs[glyphid]; float x_advance = float(e.text.glyph_info[i].x_advance) * letter_scale; - push_glyph(gi, e.text.glyph_info[i], out, 0.f); - push_glyph(bold_gi, e.text.glyph_info[i], bold_out, (float)text::map_outline_embolden / 64.f); + push_glyph(bold_gi, e.text.glyph_info[i], out, (float)text::map_outline_embolden / 64.f); auto current_spacing = (i == glyph_count - 1) ? 0.f : letter_spacing_map; float glyph_advance = x_advance * size / 64.f; float D = glyph_advance + current_spacing; @@ -3859,7 +3855,6 @@ void push_spherical_text_to_vertex_array( void display_data::set_text_lines(sys::state& state) { // Clear previous text line vertices text_line_vertices.clear(); - bold_text_line_vertices.clear(); for(const auto& e : text_data) { // Skip invalid coefficients if(!std::isfinite(e.coeff[0]) || !std::isfinite(e.coeff[1]) || !std::isfinite(e.coeff[2]) || !std::isfinite(e.coeff[3])) @@ -3874,9 +3869,9 @@ void display_data::set_text_lines(sys::state& state) { bool is_spherical = state.user_settings.map_label == sys::map_label_mode::spherical; if(is_spherical) { - push_spherical_text_to_vertex_array(state, *this, e, text_line_vertices, bold_text_line_vertices, true, 70, -60, 1.f); + push_spherical_text_to_vertex_array(state, *this, e, text_line_vertices, -20, -60, 1.f); } else { - push_polynomial_text_to_vertex_array(state, *this, e, text_line_vertices, bold_text_line_vertices); + push_polynomial_text_to_vertex_array(state, *this, e, text_line_vertices); } } } @@ -3894,7 +3889,7 @@ void display_data::set_province_text_lines(sys::state& state) { if(e.text.glyph_info.empty()) continue; - push_spherical_text_to_vertex_array(state, *this, e, province_text_line_vertices, province_text_line_vertices, false, -65, -90, 0.25f); + push_spherical_text_to_vertex_array(state, *this, e, province_text_line_vertices, -65, -90, 0.25f); //push_spherical_text_to_vertex_array(state, *this, e, province_text_line_vertices, -40, -90, 0.25f); } diff --git a/src/map/map.hpp b/src/map/map.hpp index 455e3d13c..df50d8c9e 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -286,8 +286,6 @@ class display_data { // std::vector text_line_vertices; GLsizei last_size_of_text_line_vertices = 0; - std::vector bold_text_line_vertices; - GLsizei last_size_of_bold_text_line_vertices = 0; std::vector province_text_line_vertices; std::vector drag_box_vertices; std::vector terrain_id_map; @@ -450,7 +448,9 @@ class display_data { static constexpr uint32_t uniform_hatching = 50; static constexpr uint32_t uniform_watercolor = 51; static constexpr uint32_t uniform_railroad_level = 52; - static constexpr uint32_t uniform_count = 53; + static constexpr uint32_t uniform_bold_curves = 53; + static constexpr uint32_t uniform_outline_color = 54; + static constexpr uint32_t uniform_count = 55; GLint shader_uniforms[shader_count][uniform_count] = { }; // models: Textures for static meshes diff --git a/src/map/map_state.cpp b/src/map/map_state.cpp index 31eb8d2e8..882681512 100644 --- a/src/map/map_state.cpp +++ b/src/map/map_state.cpp @@ -1388,19 +1388,7 @@ void commit_text_lines(sys::state& state, display_data& map_data) { &map_data.text_line_vertices[0], GL_STATIC_DRAW ); - glBindBuffer( - GL_ARRAY_BUFFER, - map_data.vbo_array[map_data.vo_bold_text_line] - ); - glBufferData( - GL_ARRAY_BUFFER, - sizeof(text_line_vertex) - * map_data.bold_text_line_vertices.size(), - &map_data.bold_text_line_vertices[0], - GL_STATIC_DRAW - ); map_data.last_size_of_text_line_vertices = (GLsizei)map_data.text_line_vertices.size(); - map_data.last_size_of_bold_text_line_vertices = (GLsizei)map_data.bold_text_line_vertices.size(); glBindBuffer(GL_ARRAY_BUFFER, 0); } }