From f618927b5e4327a629ab37f16dc36b599f1af41e Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Sat, 30 Nov 2024 23:54:24 +0300 Subject: [PATCH 1/3] Add some kind of multisampling to map font shader and add quartercorners to sea borders --- assets/shaders/glsl/text_line_f.glsl | 61 +++++++++++++++++++++++----- src/map/map_borders.cpp | 53 ++++++++++++++++-------- 2 files changed, 88 insertions(+), 26 deletions(-) diff --git a/assets/shaders/glsl/text_line_f.glsl b/assets/shaders/glsl/text_line_f.glsl index de302a21a..e9c6ff6e5 100644 --- a/assets/shaders/glsl/text_line_f.glsl +++ b/assets/shaders/glsl/text_line_f.glsl @@ -12,6 +12,37 @@ vec4 gamma_correct(vec4 colour) { return vec4(pow(colour.rgb, vec3(1.f / gamma)), colour.a); } + +float clamp(float x, float lowerlimit = 0.0f, float upperlimit = 1.0f) { + if (x < lowerlimit) return lowerlimit; + if (x > upperlimit) return upperlimit; + return x; +} + +float smoothstep (float edge0, float edge1, float x) { + x = clamp((x - edge0) / (edge1 - edge0)); + + return x * x * (3.0f - 2.0f * x); +} + + +float get_value(float d) { + float value = 1.f; + if (d > 0.5f) { + return 0.f; + } else if ((d > 0.500f) && (d < 0.510f)) { + value = 1.f - smoothstep(0.500f, 0.510f, d); + } else { + value = 1.f; + } + return value; +} + +float get_opacity(float d) { + float t = max(0.0f, d * 16.0f - 7.0f); + return pow(t, 5.f); +} + void main() { float border_size = 0.022f; vec3 inner_color = vec3(1.0 - is_black, 1.0 - is_black, 1.0 - is_black); @@ -20,15 +51,25 @@ void main() { outer_color = mix(inner_color, outer_color, text_size * 40.f); vec4 color_in = texture(texture_sampler, vec2(tex_coord.rg)); - if(color_in.r > 0.5) { - frag_color = vec4(inner_color, 1.0f); - } else if(color_in.r > 0.495) { - frag_color = vec4(mix(inner_color, outer_color, 1.0f - (color_in.r - 0.5f) * 200.0f), 1.0f); - } else { - float t = max(0.0f, color_in.r * 16.0f - 7.0f); - frag_color = vec4(outer_color, pow(t, 5.f)); - } - - frag_color.a *= opacity; + + float dist = color_in.r; + vec2 ddist = vec2(dFdx(dist), dFdy(dist)); + float pixel_distance = length(ddist) * 0.1f; + + float average_value = 0.f; + for (int i = -5; i <= 5; i++) { + average_value += get_value(dist + i * pixel_distance); + } + + float average_opacity = 0.f; + for (int i = -5; i <= 5; i++) { + average_opacity += get_opacity(dist + i * pixel_distance); + } + + average_value /= 11.f; + average_opacity /= 11.f; + + + frag_color = vec4(mix(inner_color, outer_color, average_value), average_opacity * opacity); frag_color = gamma_correct(frag_color); } diff --git a/src/map/map_borders.cpp b/src/map/map_borders.cpp index 36c61a91f..d75023006 100644 --- a/src/map/map_borders.cpp +++ b/src/map/map_borders.cpp @@ -555,7 +555,7 @@ std::vector make_coastal_loop(display_data& dat, sys::state& state, s int32_t dropped_points_counter = 0; constexpr int32_t dropped_points_max = 64; - auto add_next = [&](int32_t i, int32_t j, bool& next_found) { + auto add_next = [&](int32_t i, int32_t j, bool& next_found, int32_t prev_i, int32_t prev_j, bool corner) { if(next_found) return glm::ivec2(0, 0); if(visited[i + j * dat.size_x]) @@ -567,7 +567,7 @@ std::vector make_coastal_loop(display_data& dat, sys::state& state, s // test for colinearity // this works, but it can result in the border textures being "slanted" because the normals are carried over between two corners - if(points.size() > 2) { + if(points.size() > 2 && !corner) { auto l = points[points.size() - 1]; auto n = points[points.size() - 2]; if(dropped_points_counter < dropped_points_max && @@ -579,6 +579,17 @@ std::vector make_coastal_loop(display_data& dat, sys::state& state, s dropped_points_counter = 0; } } + + if(corner) { + float prev_x = float(prev_i) + 0.5f; + float prev_y = 0.5f + float(prev_j) / 2.0f; + + float next_x = float(i); + float next_y = 0.5f + float(j) / 2.0f; + + points.push_back(glm::vec2((prev_x + next_x) / 2.f, prev_y)); + points.push_back(glm::vec2(next_x, (prev_y + next_y) / 2.f)); + } points.push_back(glm::vec2(float(i), 0.5f + float(j) / 2.0f)); next_found = true; @@ -591,7 +602,7 @@ std::vector make_coastal_loop(display_data& dat, sys::state& state, s // test for colinearity // this works, but it can result in the border textures being "slanted" because the normals are carried over between two corners - if(points.size() > 2) { + if(points.size() > 2 && !corner) { auto l = points[points.size() - 1]; auto n = points[points.size() - 2]; if(dropped_points_counter < dropped_points_max && @@ -603,6 +614,17 @@ std::vector make_coastal_loop(display_data& dat, sys::state& state, s dropped_points_counter = 0; } } + + if(corner) { + float prev_x = float(prev_i); + float prev_y = 0.5f + float(prev_j) / 2.0f; + + float next_x = float(i) + 0.5f; + float next_y = 0.5f + float(j) / 2.0f; + + points.push_back(glm::vec2(prev_x, (prev_y + next_y) / 2.f)); + points.push_back(glm::vec2((prev_x + next_x) / 2.f, next_y)); + } points.push_back(glm::vec2(float(i) + 0.5f, 0.5f + float(j) / 2.0f)); next_found = true; @@ -624,24 +646,24 @@ std::vector make_coastal_loop(display_data& dat, sys::state& state, s if(start_y % 2 == 0) { bool left_is_sea = dat.safe_get_province(glm::ivec2(start_x - 1, start_y / 2)) == 0 || province::from_map_id(dat.safe_get_province(glm::ivec2(start_x - 1, start_y / 2))).index() >= state.province_definitions.first_sea_province.index(); if(left_is_sea) { - temp += add_next(start_x, start_y + 1, progress); - temp += add_next(start_x, start_y + 2, progress); - temp += add_next(start_x - 1, start_y + 1, progress); + temp += add_next(start_x, start_y + 1, progress, start_x, start_y, true); + temp += add_next(start_x, start_y + 2, progress, start_x, start_y, false); + temp += add_next(start_x - 1, start_y + 1, progress, start_x, start_y, true); } else { - temp += add_next(start_x - 1, start_y - 1, progress); - temp += add_next(start_x, start_y - 2, progress); - temp += add_next(start_x, start_y - 1, progress); + temp += add_next(start_x - 1, start_y - 1, progress, start_x, start_y, true); + temp += add_next(start_x, start_y - 2, progress, start_x, start_y, false); + temp += add_next(start_x, start_y - 1, progress, start_x, start_y, true); } } else { bool top_is_sea = dat.safe_get_province(glm::ivec2(start_x, start_y / 2)) == 0 || province::from_map_id(dat.safe_get_province(glm::ivec2(start_x, start_y / 2))).index() >= state.province_definitions.first_sea_province.index(); if(top_is_sea) { - temp += add_next(start_x, start_y + 1, progress); - temp += add_next(start_x - 1, start_y, progress); - temp += add_next(start_x, start_y - 1, progress); + temp += add_next(start_x, start_y + 1, progress, start_x, start_y, true); + temp += add_next(start_x - 1, start_y, progress, start_x, start_y, false); + temp += add_next(start_x, start_y - 1, progress, start_x, start_y, true); } else { - temp += add_next(start_x + 1, start_y - 1, progress); - temp += add_next(start_x + 1, start_y, progress); - temp += add_next(start_x + 1, start_y + 1, progress); + temp += add_next(start_x + 1, start_y - 1, progress, start_x, start_y, true); + temp += add_next(start_x + 1, start_y, progress, start_x, start_y, false); + temp += add_next(start_x + 1, start_y + 1, progress, start_x, start_y, true); } } if(progress) { @@ -708,7 +730,6 @@ void add_coastal_loop_vertices(display_data& dat, std::vector const& raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); raw_dist.x *= 2.0f; distance += glm::length(raw_dist); - } // wrap-around From cfc8120fd15ce1f6c230976e95d6bc9dc0c71be8 Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Sun, 1 Dec 2024 00:37:35 +0300 Subject: [PATCH 2/3] remove default arguments --- assets/shaders/glsl/text_line_f.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/shaders/glsl/text_line_f.glsl b/assets/shaders/glsl/text_line_f.glsl index e9c6ff6e5..1272a200e 100644 --- a/assets/shaders/glsl/text_line_f.glsl +++ b/assets/shaders/glsl/text_line_f.glsl @@ -13,14 +13,14 @@ vec4 gamma_correct(vec4 colour) { } -float clamp(float x, float lowerlimit = 0.0f, float upperlimit = 1.0f) { +float clamp(float x, float lowerlimit, float upperlimit) { if (x < lowerlimit) return lowerlimit; if (x > upperlimit) return upperlimit; return x; } float smoothstep (float edge0, float edge1, float x) { - x = clamp((x - edge0) / (edge1 - edge0)); + x = clamp((x - edge0) / (edge1 - edge0), 0.1f, 1.f); return x * x * (3.0f - 2.0f * x); } From 723038caaa8fc17685b95df47b072aeaec77d1c5 Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Sun, 1 Dec 2024 12:37:36 +0300 Subject: [PATCH 3/3] adjust borders: remove a lot of sharp angles --- src/map/map.cpp | 4 +- src/map/map_borders.cpp | 138 +++++++++++++++++++++++++--------------- 2 files changed, 87 insertions(+), 55 deletions(-) diff --git a/src/map/map.cpp b/src/map/map.cpp index f77e0a65b..ab2989090 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -597,7 +597,6 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of //glMultiDrawArrays(GL_TRIANGLE_STRIP, coastal_starts.data(), coastal_counts.data(), GLsizei(coastal_starts.size())); - // impassible borders glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[texture_provinces]); glActiveTexture(GL_TEXTURE1); @@ -624,8 +623,9 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of } } } + // impassible borders { - glUniform1f(shader_uniforms[shader_borders][uniform_width], 0.00085f); // width + glUniform1f(shader_uniforms[shader_borders][uniform_width], 0.0004f); // width glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_imp_border]); for(auto b : borders) { diff --git a/src/map/map_borders.cpp b/src/map/map_borders.cpp index d75023006..0f1d28d72 100644 --- a/src/map/map_borders.cpp +++ b/src/map/map_borders.cpp @@ -279,15 +279,34 @@ bool order_indifferent_compare(uint16_t a, uint16_t b, uint16_t c, uint16_t d) { std::vector make_border_section(display_data& dat, sys::state& state, std::vector& visited, uint16_t prov_prim, uint16_t prov_sec, int32_t start_x, int32_t start_y) { std::vector points; - auto add_next = [&](int32_t i, int32_t j, bool& next_found) { + auto add_next = [&](glm::ivec2 prev, glm::ivec2 shift, glm::ivec2 prev_shift, bool& next_found, bool corner_candidate) { if(next_found) return glm::ivec2(0, 0); + + auto i = prev.x + shift.x; + auto j = prev.y + shift.y; + auto prev_i = prev.x; + auto prev_j = prev.y; + + bool corner = corner_candidate && (shift.x != prev_shift.x) && (shift.y != prev_shift.y) && !(prev_shift.y == 0 && prev_shift.x == 0); + if(visited[i + j * dat.size_x]) return glm::ivec2(0, 0); if(j % 2 == 0) { if(order_indifferent_compare(prov_prim, prov_sec, dat.safe_get_province(glm::ivec2(i, j / 2)), dat.safe_get_province(glm::ivec2(i - 1, j / 2)))) { visited[i + j * dat.size_x] = true; + if(corner) { + float prev_x = float(prev_i) + 0.5f; + float prev_y = 0.5f + float(prev_j) / 2.0f; + + float next_x = float(i); + float next_y = 0.5f + float(j) / 2.0f; + + points.push_back(glm::vec2((prev_x + next_x) / 2.f, prev_y)); + points.push_back(glm::vec2(next_x, (prev_y + next_y) / 2.f)); + } + points.push_back(glm::vec2(float(i), 0.5f + float(j) / 2.0f)); next_found = true; return glm::ivec2(i, j); @@ -296,6 +315,17 @@ std::vector make_border_section(display_data& dat, sys::state& state, if(order_indifferent_compare(prov_prim, prov_sec, dat.safe_get_province(glm::ivec2(i, j / 2)), dat.safe_get_province(glm::ivec2(i, j / 2 + 1)))) { visited[i + j * dat.size_x] = true; + if(corner) { + float prev_x = float(prev_i); + float prev_y = 0.5f + float(prev_j) / 2.0f; + + float next_x = float(i) + 0.5f; + float next_y = 0.5f + float(j) / 2.0f; + + points.push_back(glm::vec2(prev_x, (prev_y + next_y) / 2.f)); + points.push_back(glm::vec2((prev_x + next_x) / 2.f, next_y)); + } + points.push_back(glm::vec2(float(i) + 0.5f, 0.5f + float(j) / 2.0f)); next_found = true; return glm::ivec2(i, j); @@ -309,8 +339,8 @@ std::vector make_border_section(display_data& dat, sys::state& state, points.push_back(glm::vec2(float(start_x) + (start_y % 2 == 0 ? 0.0f : 0.5f), 0.5f + float(start_y) / 2.0f)); visited[start_x + start_y * dat.size_x] = true; - int32_t cur_x = start_x; - int32_t cur_y = start_y; + glm::ivec2 current{ start_x, start_y }; + glm::ivec2 prev_direction{ 0, 0 }; bool progress = false; // clockwise @@ -318,54 +348,56 @@ std::vector make_border_section(display_data& dat, sys::state& state, progress = false; glm::ivec2 temp{ 0, 0 }; - if(cur_y % 2 == 0) { - bool left_is_s = dat.safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec; + if(current.y % 2 == 0) { + bool left_is_s = dat.safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec; if(left_is_s) { - temp += add_next(cur_x, cur_y + 1, progress); - temp += add_next(cur_x, cur_y + 2, progress); - temp += add_next(cur_x - 1, cur_y + 1, progress); + temp += add_next(current, { 0, 1 }, prev_direction, progress, true); + temp += add_next(current, { 0, 2 }, prev_direction, progress, false); + temp += add_next(current, { -1, 1 }, prev_direction, progress, true); } else { - temp += add_next(cur_x - 1, cur_y - 1, progress); - temp += add_next(cur_x, cur_y - 2, progress); - temp += add_next(cur_x, cur_y - 1, progress); + temp += add_next(current, { -1, -1}, prev_direction, progress, true); + temp += add_next(current, { 0, -2}, prev_direction, progress, false); + temp += add_next(current, { 0, -1}, prev_direction, progress, true); } } else { - bool top_is_s = dat.safe_get_province(glm::ivec2(cur_x, cur_y / 2)) == prov_sec; + bool top_is_s = dat.safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec; if(top_is_s) { - temp += add_next(cur_x, cur_y + 1, progress); - temp += add_next(cur_x - 1, cur_y, progress); - temp += add_next(cur_x, cur_y - 1, progress); + temp += add_next(current, { 0, 1 }, prev_direction, progress, true); + temp += add_next(current, { -1, 0 }, prev_direction, progress, false); + temp += add_next(current, { 0, -1}, prev_direction, progress, true); } else { - temp += add_next(cur_x + 1, cur_y - 1, progress); - temp += add_next(cur_x + 1, cur_y, progress); - temp += add_next(cur_x + 1, cur_y + 1, progress); + temp += add_next(current, { +1, -1}, prev_direction, progress, true); + temp += add_next(current, { +1, 0}, prev_direction, progress, false); + temp += add_next(current, { +1, +1}, prev_direction, progress, true); } } if(progress) { - cur_x = temp.x; - cur_y = temp.y; + prev_direction = temp - current; + current = temp; } } while(progress); //terminal point - if(cur_y % 2 == 0) { - bool left_is_s = dat.safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec; + if(current.y % 2 == 0) { + bool left_is_s = dat.safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec; if(left_is_s) { - points.push_back(glm::vec2(float(cur_x), 1.0f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(float(current.x), 1.0f + float(current.y) / 2.0f)); } else { - points.push_back(glm::vec2(float(cur_x), 0.0f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(float(current.x), 0.0f + float(current.y) / 2.0f)); } } else { - bool top_is_s = dat.safe_get_province(glm::ivec2(cur_x, cur_y / 2)) == prov_sec; + bool top_is_s = dat.safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec; if(top_is_s) { - points.push_back(glm::vec2(float(cur_x), 0.5f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(float(current.x), 0.5f + float(current.y) / 2.0f)); } else { - points.push_back(glm::vec2(1.0f + float(cur_x), 0.5f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(1.0f + float(current.x), 0.5f + float(current.y) / 2.0f)); } } - cur_x = start_x; - cur_y = start_y; + current.x = start_x; + current.y = start_y; + prev_direction.x = 0; + prev_direction.y = 0; std::reverse(points.begin(), points.end()); //counter clockwise @@ -374,49 +406,49 @@ std::vector make_border_section(display_data& dat, sys::state& state, progress = false; glm::ivec2 temp{ 0, 0 }; - if(cur_y % 2 == 0) { - bool left_is_s = dat.safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec; + if(current.y % 2 == 0) { + bool left_is_s = dat.safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec; if(!left_is_s) { - temp += add_next(cur_x, cur_y + 1, progress); - temp += add_next(cur_x, cur_y + 2, progress); - temp += add_next(cur_x - 1, cur_y + 1, progress); + temp += add_next(current, { 0, 1 }, prev_direction, progress, true); + temp += add_next(current, { 0, 2 }, prev_direction, progress, false); + temp += add_next(current, { -1, 1 }, prev_direction, progress, true); } else { - temp += add_next(cur_x - 1, cur_y - 1, progress); - temp += add_next(cur_x, cur_y - 2, progress); - temp += add_next(cur_x, cur_y - 1, progress); + temp += add_next(current, { -1, -1 }, prev_direction, progress, true); + temp += add_next(current, { 0, -2 }, prev_direction, progress, false); + temp += add_next(current, { 0, -1 }, prev_direction, progress, true); } } else { - bool top_is_s = dat.safe_get_province(glm::ivec2(cur_x, cur_y / 2)) == prov_sec; + bool top_is_s = dat.safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec; if(!top_is_s) { - temp += add_next(cur_x, cur_y + 1, progress); - temp += add_next(cur_x - 1, cur_y, progress); - temp += add_next(cur_x, cur_y - 1, progress); + temp += add_next(current, { 0, 1 }, prev_direction, progress, true); + temp += add_next(current, { -1, 0 }, prev_direction, progress, false); + temp += add_next(current, { 0, -1 }, prev_direction, progress, true); } else { - temp += add_next(cur_x + 1, cur_y - 1, progress); - temp += add_next(cur_x + 1, cur_y, progress); - temp += add_next(cur_x + 1, cur_y + 1, progress); + temp += add_next(current, { +1, -1 }, prev_direction, progress, true); + temp += add_next(current, { +1, 0 }, prev_direction, progress, false); + temp += add_next(current, { +1, +1 }, prev_direction, progress, true); } } if(progress) { - cur_x = temp.x; - cur_y = temp.y; + prev_direction = temp - current; + current = temp; } } while(progress); //terminal point - if(cur_y % 2 == 0) { - bool left_is_s = dat.safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec; + if(current.y % 2 == 0) { + bool left_is_s = dat.safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec; if(!left_is_s) { - points.push_back(glm::vec2(float(cur_x), 1.0f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(float(current.x), 1.0f + float(current.y) / 2.0f)); } else { - points.push_back(glm::vec2(float(cur_x), 0.0f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(float(current.x), 0.0f + float(current.y) / 2.0f)); } } else { - bool top_is_s = dat.safe_get_province(glm::ivec2(cur_x, cur_y / 2)) == prov_sec; + bool top_is_s = dat.safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec; if(!top_is_s) { - points.push_back(glm::vec2(float(cur_x), 0.5f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(float(current.x), 0.5f + float(current.y) / 2.0f)); } else { - points.push_back(glm::vec2(1.0f + float(cur_x), 0.5f + float(cur_y) / 2.0f)); + points.push_back(glm::vec2(1.0f + float(current.x), 0.5f + float(current.y) / 2.0f)); } }