From d94d341f2697914792a061d3bdbbf13b109826fb Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Tue, 21 Jan 2025 09:32:26 +0300 Subject: [PATCH 1/4] smooth borders, better border textures --- assets/imp_border.dds | Bin 282752 -> 282752 bytes assets/prov_border.dds | Bin 528 -> 6528 bytes src/economy/economy.cpp | 2 +- src/map/map.cpp | 4 ++-- src/map/map_borders.cpp | 29 +++++++++++++++++++++++++++++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/assets/imp_border.dds b/assets/imp_border.dds index 7dc0bde81d2a0c2e51e46f3d39b7b5d09201f26e..810f091207f1430b3d7da3e643006092167d7ef9 100644 GIT binary patch literal 282752 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 literal 282752 zcmeI$F|J%y635{S&saFZLIg+z_6Aslr6(Z=mXMsX19pH&Nyxq4N4JdwR1$&D?Nasm zf7bL2bBFf0PXDOyoql|L|N774IKF#%9DiT_^Z5Gm`u6%4$MMzW^~>9LzyAFA`2M#S z44p|Mls=T>d}GufHyTkC!vhz&Q<+f50*yJpbX<;pGf8 zaQg5Kh-{?WjR4P6OkudWCo7kj* zo(A}T;{NtMxSt7E8p!0nOl|k~?0)C$ocYgxclaR<6bUmQaEVJA=xKoeLw5hlz0rI3 z_}(Ft`!coN-?RIjvvcM@|K0zGG*BeWe843xX`rV8{twyx?(lou;a5J#Ozz9nc7M?40?}fA{|(4HOA8A8?6F8t7?& z|3h~F%DvHh_xSE0llwBY-QTnOowIZ1KmXnThcr+m%zVHlE@_~r0sar!{qFF4+~HR~ z$4u_a)OLT*?sv}4ng9HE{~yvokudWCm$;;Xo(A|oWcRP!8@+dr?+!A#FH_t7J-gpI zJ7@m$-~E3`14Y8j2VCNk26`Ic|B&794!_48e&ut_ zGaqn?OB(2Dfd4~w|H{45d-wS6Ad~wtwcX#d`<=6M=0E@4|A#bCB+PukB`#^8rvd&C z+5PVDd)(nyKF3V%%hYy%&+d25&YA!GcmE&KK#?%>0hhR>fu08VKV+#9`jkM9mL zxi3@O{XM(iIXh?m^WXh{NCQQ}%m-ZJk_LJj;Qx@_?+(Am9e(9=%;dgIZTI)=e&_6* z`Okm%{~-+&2{RvXiAx&jX@LJjcK^z~(R=s!?jV!8sPts-R};+#~ps?40?}fA{|(4HOA8A8?6F8t7?&|3h~F%DvHh_xSE0llwBY z-QTnOowIZ1KmXnThcr+m%zVHlE@_~r0sar!{qFF4+~HR~$4u_a)OLT*?sv}4ng9HE z{~yvokudWCm$;;Xo(A|oWcRP!8@+dr?+!A#FH_t7J-gpIJ7@m$-~E3`14Y8j2VCNk z26`Ic|B&794!_48e&ut_Gaqn?OB(2D;8g#Qr^_Ps zat0dEfCe<60S#zC0~*kP1~i}n4QN0E8qk0SG@t&rL`}em0`uY0x=>+WkbN0S-bdJ{s_|JboKg|F6f&ctxHnY!efdBmGKmYIL=ZmxV zpWlzE$qn$I|NQ4a|2dfKVCwAr=Rg1X&wu`>8kjsc|M|~<{_~&z$quH@&VT;%pa1;l zf2x7WbMv47{O3Ra`Je1y>g@dIKmYm9fBvT$m^?TC`Okm;^Pm684yMk|fBy5I|NQ5F zs)5OK^Pm6x=Rg1XpX^}j?EL3H|M|~<{-+w4JU9RO&wu{&pa01Yrq0fP{_~&z{O5nF zfys08pa1;lKmYlk>|pBb{O3Ra`Okm;ry7_%H~;z1fBy5I|H%%f&dz`S^Pm6x=YOh! z$#e6c|NQ4a|M{QnVCwAr=Rg1X&wu`>8kjsc|M|~<{_~&z$quH@&VT;%pa1;lf2x7W zbMv47{O3Ra`Je1y>g@dIKmYm9fBvT$m^?TC`Okm;^Pm684yMk|fBy5I|NQ5Fs)5OK z^Pm6x=Rg1XpX^}j?EL3H|M|~<{-+w4JU9RO&wu{&pa01Yrq0fP{_~&z{O5nFfys08 zpa1;lKmYlk>|pBb{O3Ra`Okm;ry7_%H~;z1fBy5I|H%%f&dz`S^Pm6x=YOh!$#e6c z|NQ4a|M{QnVCwAr=Rg1X&wu`>8kjsc|M|~<{_~&z$quH@&VT;%pa1;lf2x7WbMv47 z{O3Ra`Je1y>g@dIKmYm9fBvT$m^?TC`Okm;^Pm684yMk|fBy5I|NQ5Fs)5OK^Pm6x z=Rg1XpX^}j?EL3H|M|~<{-+w4JU9RO&wu{&pa01Yrq0fP{_~&z{O5nFfys08pa1;l zKmYlk>|pBb{O3Ra`Okm;ry7_%_rt@(;pGf8FuQ?!@%h$&PMyx~)aT>#(SQataBc&) zcJ*F;~?|=Ue|dbvnCKpU-`LKK}sbE&ose diff --git a/assets/prov_border.dds b/assets/prov_border.dds index e1d2edd38e4139138a2ab2315dae8759fc8c12dc..5f486379361a3088b3cb635448dcd01bf62661b0 100644 GIT binary patch literal 6528 zcmeI0U5HLw7=ZT|PLpURb4*S7`J5BUB=U1X5*ke!I>Utggrbm(xgr;Clq4fk>YSu= zaSEfz#YyKBQl}`nP`D5sj=$t5zlHoi&$gF7d-i-YpP!ne@6Ge=wcht#?_Te_*IIjz z`ugVlhA4_EtD@*fu1zo{#}DGAVaBYck@fY>xu{31EB2GeI5lyw9YycLzYiVmQI>KA z{wEda#XS3f+oCqXwmNNJA{7h{v5gtxsxL*{qUl)G=!{)ztlo^Ngc=C>x?|OslCQpw z831FU0X$a3wmNO4#$`y<6U=QejDu+f*jKMzzs^LTzL1CU5Mp_RImfQXGGFWV6HJ7e z5b`x<9r%2IfX*bu8jfQlv_LEDPOz;`n?ByRtIx)K`$HYfhSjjS0Q>5->sPFX-qUq5 z66U}f2(dQNUIo9v2r&1KVud)P@mT=tU>AgZH_~1SlOYeTnPQ^dx;UpTa2U?O#RS{x zwCSU7XEAY!rHbD$&uz5Z;8X$j)tiTY`e#WFWj`1Li(oq(fDr2>?R~Hn=EEqcge+0- zT3rUe!e4M6Lcagd-VbYGI=Jtwd6uZx-U!y`7+izL@GQZ$I&J#sTP!B#SStAa8LW*p zIu2LiK0HdU_SJ_P>hHL;_`HUJwc7zF;6E_dL%0W5;3!zbdEnkm$1=`PSOV7WG~9-# z@Epwf0a(j}U=1fgHDpO2ls=0VI1JY51-yZ`3AWW~(??&&IJTI$huj0};RxIS=lB|o z>D9h^?fU8OxI)R%se!4m0se+tP#EhKeRIDKf5JML1nInu?fJG5dnz_A8p-!7V`Z^|^C#sL)*)tI4!Y()mPaqxJzIyHY>F>D0 zv&(ts!FBu_TmbXSisc;7!cJ(00nh`245DE@euqn7&8=BFU!TVv@L8>eG2q%wOD&2f z*bNt6HLvRybLb`VLeKwvkp0BP|_i(v>U%!6t!SeoXzXrRyf6MQWFMEG@ zCV0j+!WK9N*T8ewvqWsG)25HUj&W=;@!P@k#&drg90$*?`|!PdzmQ6NE)M592dt0Z zD86TXSBPzO+Vs&k>nugxPO8w1hET&c+Tokmt9@&$T|fP^B!{ve_#RvY-R1k4sl@B3 zlB;!bZM8rv_?{Kp>a^*jZ)a-{msouF^@lo`4gS5hxd8j>wd)t&l{DLl_pE{L_V=3; zb#AUH_vKjdozj$GTb(w2x>`G2W3eWlvx8wA`28BNuU>nx+F_1GpYHbm2g%gpi?uNq z-^;ZLw$+tdH->y774$-EV}`iuOA+^SI#xA0W0xAs_27PTU59)930A0KU|`@EU|`?^(jcq>#2~;3#O|KH0lF?O!7-f7U@?4z0#MQsssO}hVE7M1 h5Dw4|A^}h%NHYq?rWIWch>s17s>2p4sNo9^BLFbMI?Mn7 diff --git a/src/economy/economy.cpp b/src/economy/economy.cpp index 835ded893..f9cfbf93d 100644 --- a/src/economy/economy.cpp +++ b/src/economy/economy.cpp @@ -1203,7 +1203,7 @@ void presimulate(sys::state& state) { #ifdef NDEBUG uint32_t steps = 365; #else - uint32_t steps = 20; + uint32_t steps = 2; #endif for(uint32_t i = 0; i < steps; i++) { update_factory_employment(state); diff --git a/src/map/map.cpp b/src/map/map.cpp index a45171281..b73faf63f 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -603,7 +603,7 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glBindTexture(GL_TEXTURE_2D, textures[texture_province_fow]); if(zoom > map::zoom_close) { if(zoom > map::zoom_very_close) { // Render province borders - glUniform1f(shader_uniforms[shader_borders][uniform_width], 0.0001f); // width + glUniform1f(shader_uniforms[shader_borders][uniform_width], 0.0003f); // width glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_prov_border]); @@ -766,7 +766,7 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of } // coasts { - glUniform1f(shader_uniforms[shader_borders][uniform_width], 0.0004f); // width + glUniform1f(shader_uniforms[shader_borders][uniform_width], 0.0006f); // width glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_coastal_border]); glBindVertexArray(vao_array[vo_coastal]); diff --git a/src/map/map_borders.cpp b/src/map/map_borders.cpp index 0f1d28d72..e19cfa7f8 100644 --- a/src/map/map_borders.cpp +++ b/src/map/map_borders.cpp @@ -102,6 +102,31 @@ bool extend_if_possible(uint32_t x, int32_t border_id, direction dir, std::vecto return true; }; +void smooth_points(std::vector& vertices) { + std::vector vertices_copy = vertices; + + auto start = int(0); + auto end = start + int(vertices.size()); + for(int i = start + 1; i < end - 1; i++) { + glm::vec2 new_position{ 0.f, 0.f }; + float count = 0.f; + bool smooth = true; + for(int shift = -2; shift <= 2; shift++) { + if(i + shift < start) { + continue; + }; + if(i + shift >= end) { + continue; + }; + count += 1.f / (float(std::abs(shift)) + 1.f); + new_position += (vertices_copy[i + shift]) * 1.f / (float(std::abs(shift)) + 1.f); + } + if((count > 0) && smooth) { + vertices[i] = new_position / count; + } + } +} + // Get the index of the border from the province ids and create a new one if one doesn't exist int32_t get_border_index(uint16_t map_province_id1, uint16_t map_province_id2, parsers::scenario_building_context& context) { auto province_id1 = province::from_map_id(map_province_id1); @@ -547,6 +572,7 @@ void display_data::make_borders(sys::state& state, std::vector& visited) { borders[border_index].start_index = int32_t(border_vertices.size()); auto res = make_border_section(*this, state, visited, province::to_map_id(prim), province::to_map_id(sec), i, j * 2); + smooth_points(res); add_border_segment_vertices(*this, res); borders[border_index].count = int32_t(border_vertices.size() - borders[border_index].start_index); @@ -572,6 +598,7 @@ void display_data::make_borders(sys::state& state, std::vector& visited) { borders[border_index].start_index = int32_t(border_vertices.size()); auto res = make_border_section(*this, state, visited, province::to_map_id(prim), province::to_map_id(sec), i, j * 2 + 1); + smooth_points(res); add_border_segment_vertices(*this, res); borders[border_index].count = int32_t(border_vertices.size() - borders[border_index].start_index); @@ -793,6 +820,7 @@ void display_data::make_coastal_borders(sys::state& state, std::vector& vi bool was_visited = visited[i + (j * 2) * size_x]; if(!was_visited && coastal_point(state, safe_get_province(glm::ivec2(i, j)), safe_get_province(glm::ivec2(i - 1, j)))) { auto res = make_coastal_loop(*this, state, visited, i, j * 2); + smooth_points(res); add_coastal_loop_vertices(*this, res); } } @@ -802,6 +830,7 @@ void display_data::make_coastal_borders(sys::state& state, std::vector& vi bool was_visited = visited[i + (j * 2 + 1) * size_x]; if(!was_visited && coastal_point(state, safe_get_province(glm::ivec2(i, j)), safe_get_province(glm::ivec2(i, j + 1)))) { auto res = make_coastal_loop(*this, state, visited, i, j * 2 + 1); + smooth_points(res); add_coastal_loop_vertices(*this, res); } } From a03d5dfc4d7f12c87e5fb51792c84f7c8c62f85f Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Wed, 22 Jan 2025 02:21:43 +0300 Subject: [PATCH 2/4] implement borders for no-province blobs --- assets/shaders/glsl/map_f.glsl | 17 +- assets/shaders/glsl/map_provinces_f.glsl | 10 + assets/shaders/glsl/textured_line_b_f.glsl | 3 +- .../glsl/textured_line_b_provinces_f.glsl | 9 + assets/shaders/glsl/textured_line_b_v.glsl | 46 ++-- .../shaders/glsl/textured_line_river_f.glsl | 6 +- src/gamestate/system_state.cpp | 3 + src/graphics/opengl_wrapper.cpp | 38 +++ src/graphics/opengl_wrapper.hpp | 10 + src/map/map.cpp | 205 +++++++++++---- src/map/map.hpp | 19 +- src/map/map_borders.cpp | 240 +++++++++++++----- src/map/map_state.cpp | 2 +- 13 files changed, 476 insertions(+), 132 deletions(-) create mode 100644 assets/shaders/glsl/map_provinces_f.glsl create mode 100644 assets/shaders/glsl/textured_line_b_provinces_f.glsl diff --git a/assets/shaders/glsl/map_f.glsl b/assets/shaders/glsl/map_f.glsl index 322242335..6ed7bd048 100644 --- a/assets/shaders/glsl/map_f.glsl +++ b/assets/shaders/glsl/map_f.glsl @@ -13,12 +13,14 @@ uniform sampler2D colormap_political; uniform sampler2D province_highlight; uniform sampler2D stripes_texture; uniform sampler2D province_fow; +uniform sampler2D provinces_sea_mask; uniform usampler2D diag_border_identifier; uniform uint subroutines_index_2; // location 0 : offset // location 1 : zoom // location 2 : screen_size uniform vec2 map_size; +uniform vec2 screen_size; uniform float time; uniform float gamma; vec4 gamma_correct(vec4 colour) { @@ -40,7 +42,7 @@ vec2 get_corrected_coords(vec2 coords) { // The water effect vec4 get_water_terrain() { - vec2 prov_id = texture(provinces_texture_sampler, tex_coord).xy; + vec2 prov_id = texture(provinces_texture_sampler, gl_FragCoord.xy / screen_size).xy; // Water effect taken from Vic2 fx/water/PixelShader_HoiWater_2_0 const float WRAP = 0.8; @@ -120,9 +122,16 @@ vec4 get_water_political() { // The terrain color from the current texture coordinate offset with one pixel in the "corner" direction vec4 get_terrain(vec2 corner, vec2 offset) { + vec2 prov_id = texture(provinces_texture_sampler, gl_FragCoord.xy / screen_size).xy; float index = texture(terrain_texture_sampler, floor(tex_coord * map_size + vec2(0.5, 0.5)) / map_size + 0.5 * pix * corner).r; index = floor(index * 256); - float is_water = step(64, index); + + float is_water = 0.f; //step(64, index); + + if (texture(provinces_sea_mask, prov_id).x > 0.0f || (prov_id.x == 0.f && prov_id.y == 0.f)) { + is_water = 1.f; + } + vec4 colour = texture(terrainsheet_texture_sampler, vec3(offset, index)); return mix(colour, vec4(0.), is_water); } @@ -171,7 +180,7 @@ vec4 get_land_political_close() { rounded_tex_coords.y += ((int(test >> shift) & 1) != 0) && (abs(rel_coord.x) + abs(rel_coord.y) > 0.5) ? sign(rel_coord.y) / map_size.y : 0; - vec2 prov_id = texture(provinces_texture_sampler, rounded_tex_coords).xy; + vec2 prov_id = texture(provinces_texture_sampler, gl_FragCoord.xy / screen_size).xy; // The primary and secondary map mode province colors vec4 prov_color = texture(province_color, vec3(prov_id, 0.)); @@ -197,7 +206,7 @@ vec4 get_land_political_close() { vec4 get_land_political_far() { vec4 terrain = get_terrain(vec2(0, 0), vec2(0)); float is_land = terrain.a; - vec2 prov_id = texture(provinces_texture_sampler, tex_coord).xy; + vec2 prov_id = texture(provinces_texture_sampler, gl_FragCoord.xy / screen_size).xy; // The primary and secondary map mode province colors vec4 prov_color = texture(province_color, vec3(prov_id, 0.)); diff --git a/assets/shaders/glsl/map_provinces_f.glsl b/assets/shaders/glsl/map_provinces_f.glsl new file mode 100644 index 000000000..151c5460d --- /dev/null +++ b/assets/shaders/glsl/map_provinces_f.glsl @@ -0,0 +1,10 @@ +in vec2 tex_coord; +layout(location = 0) out vec4 frag_color; + +uniform sampler2D real_provinces_texture_sampler; + +// Only province id is used here +void main() { + vec2 prov_id = texture(real_provinces_texture_sampler, tex_coord).xy; + frag_color = vec4(prov_id, 0.f, 1.f); +} diff --git a/assets/shaders/glsl/textured_line_b_f.glsl b/assets/shaders/glsl/textured_line_b_f.glsl index 7b7d6ef31..a48fd50cc 100644 --- a/assets/shaders/glsl/textured_line_b_f.glsl +++ b/assets/shaders/glsl/textured_line_b_f.glsl @@ -4,6 +4,7 @@ in vec2 map_coord; out vec4 frag_color; uniform float gamma; +uniform vec2 screen_size; uniform sampler2D provinces_texture_sampler; uniform sampler2D province_fow; @@ -19,7 +20,7 @@ void main() { vec4 out_color = texture(line_texture, vec2(o_dist, tex_coord)); - vec2 prov_id = texture(provinces_texture_sampler, map_coord).xy; + vec2 prov_id = texture(provinces_texture_sampler, gl_FragCoord.xy / screen_size).xy; out_color.rgb *= texture(province_fow, prov_id).rgb; frag_color = gamma_correct(out_color); } diff --git a/assets/shaders/glsl/textured_line_b_provinces_f.glsl b/assets/shaders/glsl/textured_line_b_provinces_f.glsl new file mode 100644 index 000000000..7380e836c --- /dev/null +++ b/assets/shaders/glsl/textured_line_b_provinces_f.glsl @@ -0,0 +1,9 @@ +in float tex_coord; +in float o_dist; +in vec2 map_coord; +flat in vec2 frag_province_index; +layout(location = 0) out vec4 frag_color; + +void main() { + frag_color = vec4(frag_province_index, 0.f, 1.f); +} diff --git a/assets/shaders/glsl/textured_line_b_v.glsl b/assets/shaders/glsl/textured_line_b_v.glsl index b9343d001..26d37d9c5 100644 --- a/assets/shaders/glsl/textured_line_b_v.glsl +++ b/assets/shaders/glsl/textured_line_b_v.glsl @@ -2,12 +2,14 @@ layout (location = 0) in vec2 vertex_position; layout (location = 1) in vec2 prev_point; layout (location = 2) in vec2 next_point; -layout (location = 3) in float texture_coord; -layout (location = 4) in float distance; +layout (location = 3) in vec2 province_index; +layout (location = 4) in float texture_coord; +layout (location = 5) in float distance; out float tex_coord; out float o_dist; out vec2 map_coord; +flat out vec2 frag_province_index; uniform vec2 offset; uniform float aspect_ratio; @@ -99,28 +101,32 @@ default: break; void main() { vec4 central_pos = calc_gl_position(vertex_position); - vec2 bpt = central_pos.xy; - vec2 apt = calc_gl_position(prev_point).xy; - vec2 cpt = calc_gl_position(next_point).xy; + vec2 corner_shift = vec2(0.f, 0.f); - // we want to thicken the line in "perceived" coordinates, so - // transform to perceived coordinates + depth - bpt.x *= aspect_ratio; - apt.x *= aspect_ratio; - cpt.x *= aspect_ratio; + if((texture_coord > 0.5f) || (texture_coord < -0.5f) ) { + vec2 bpt = central_pos.xy; + vec2 apt = calc_gl_position(prev_point).xy; + vec2 cpt = calc_gl_position(next_point).xy; - // calculate normals in perceived coordinates + depth - vec2 adir = normalize(bpt - apt); - vec2 bdir = normalize(cpt - bpt); + // we want to thicken the line in "perceived" coordinates, so + // transform to perceived coordinates + depth + bpt.x *= aspect_ratio; + apt.x *= aspect_ratio; + cpt.x *= aspect_ratio; - vec2 anorm = vec2(-adir.y, adir.x); - vec2 bnorm = vec2(-bdir.y, bdir.x); - vec2 corner_normal = normalize(anorm + bnorm); + // calculate normals in perceived coordinates + depth + vec2 adir = normalize(bpt - apt); + vec2 bdir = normalize(cpt - bpt); - vec2 corner_shift = corner_normal * zoom * width / (1.0f + max(-0.5f, dot(anorm, bnorm))); + vec2 anorm = vec2(-adir.y, adir.x); + vec2 bnorm = vec2(-bdir.y, bdir.x); + vec2 corner_normal = normalize(anorm + bnorm); - // transform result back to screen + depth coordinates - corner_shift.x /= aspect_ratio; + corner_shift = corner_normal * zoom * width / (1.0f + max(-0.5f, dot(anorm, bnorm))); + + // transform result back to screen + depth coordinates + corner_shift.x /= aspect_ratio; + } gl_Position = central_pos + vec4(corner_shift.x, corner_shift.y, 0.0f, 0.0f); @@ -128,4 +134,6 @@ void main() { tex_coord = texture_coord; o_dist = distance / (2.0f * width); map_coord = vertex_position; + + frag_province_index = province_index; } diff --git a/assets/shaders/glsl/textured_line_river_f.glsl b/assets/shaders/glsl/textured_line_river_f.glsl index 6027ce513..cd7d06cf6 100644 --- a/assets/shaders/glsl/textured_line_river_f.glsl +++ b/assets/shaders/glsl/textured_line_river_f.glsl @@ -5,6 +5,8 @@ out vec4 frag_color; uniform float gamma; +uniform vec2 screen_size; + uniform sampler2D line_texture; uniform sampler2D colormap_water; uniform sampler2D province_fow; @@ -17,8 +19,8 @@ vec4 gamma_correct(vec4 colour) { void main() { vec4 out_color = texture(colormap_water, map_coord) * texture(line_texture, vec2(tex_coord, o_dist)); - vec2 prov_id = texture(provinces_texture_sampler, map_coord).xy; - if (texture(provinces_sea_mask, prov_id).x > 0) { + vec2 prov_id = texture(provinces_texture_sampler, gl_FragCoord.xy / screen_size).xy; + if (texture(provinces_sea_mask, prov_id).x > 0 || (prov_id.x == 0.f && prov_id.y == 0.f)) { discard; } float is_sea = texture(provinces_sea_mask, prov_id).x * 1000.f; diff --git a/src/gamestate/system_state.cpp b/src/gamestate/system_state.cpp index 647f52118..aaab5aa90 100644 --- a/src/gamestate/system_state.cpp +++ b/src/gamestate/system_state.cpp @@ -390,6 +390,9 @@ void state::on_resize(int32_t x, int32_t y, window::window_state win_state) { ogl::deinitialize_msaa(*this); ogl::initialize_msaa(*this, x, y); + ogl::deinitialize_framebuffer_for_province_indices(*this); + ogl::initialize_framebuffer_for_province_indices(*this, x, y); + if(win_state != window::window_state::minimized) { ui_state.root->base_data.size.x = int16_t(x / user_settings.ui_scale); ui_state.root->base_data.size.y = int16_t(y / user_settings.ui_scale); diff --git a/src/graphics/opengl_wrapper.cpp b/src/graphics/opengl_wrapper.cpp index 0522117d5..7a7cdfae2 100644 --- a/src/graphics/opengl_wrapper.cpp +++ b/src/graphics/opengl_wrapper.cpp @@ -180,6 +180,42 @@ std::string_view framebuffer_error(GLenum e) { return "???"; } +void initialize_framebuffer_for_province_indices(sys::state& state, int32_t size_x, int32_t size_y) { + // prepare textures for rendering + glGenTextures(1, &state.open_gl.province_map_rendertexture); + glBindTexture(GL_TEXTURE_2D, state.open_gl.province_map_rendertexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG, size_x, size_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + // framebuffer + glGenFramebuffers(1, &state.open_gl.province_map_framebuffer); + state.console_log(ogl::opengl_get_error_name(glGetError())); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, state.open_gl.province_map_framebuffer); + state.console_log(ogl::opengl_get_error_name(glGetError())); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, state.open_gl.province_map_rendertexture, 0); + state.console_log(ogl::opengl_get_error_name(glGetError())); + + // drawbuffers + GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, DrawBuffers); + + auto check = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + + if(check != GL_FRAMEBUFFER_COMPLETE) { + state.console_log(ogl::framebuffer_error(check)); + } else { + state.console_log("provincial framebuffer is ready"); + } +} + +void deinitialize_framebuffer_for_province_indices(sys::state& state) { + if(state.open_gl.province_map_rendertexture) + glDeleteTextures(1, &state.open_gl.province_map_rendertexture); + if(state.open_gl.province_map_framebuffer) + glDeleteFramebuffers(1, &state.open_gl.province_map_framebuffer); +} + void initialize_msaa(sys::state& state, int32_t size_x, int32_t size_y) { if(state.user_settings.antialias_level == 0) return; @@ -323,6 +359,8 @@ void initialize_opengl(sys::state& state) { load_special_icons(state); initialize_msaa(state, window::creation_parameters().size_x, window::creation_parameters().size_y); + + initialize_framebuffer_for_province_indices(state, window::creation_parameters().size_x, window::creation_parameters().size_y); } static const GLfloat global_square_data[] = { diff --git a/src/graphics/opengl_wrapper.hpp b/src/graphics/opengl_wrapper.hpp index dc1a5a401..7fdbe08b1 100644 --- a/src/graphics/opengl_wrapper.hpp +++ b/src/graphics/opengl_wrapper.hpp @@ -205,6 +205,9 @@ struct data { bool legacy_mode = false; GLuint ui_shader_program = 0; + GLuint province_map_framebuffer; + GLuint province_map_rendertexture; + GLuint ui_shader_d_rect_uniform = 0; GLuint ui_shader_subroutines_index_uniform = 0; GLuint ui_shader_inner_color_uniform = 0; @@ -254,6 +257,7 @@ struct data { }; void notify_user_of_fatal_opengl_error(std::string message); +std::string_view opengl_get_error_name(GLenum t); void create_opengl_context(sys::state& state); // you shouldn't call this directly; only initialize_opengl should call it void initialize_opengl(sys::state& state); @@ -299,6 +303,9 @@ class lines { void set_y(float* v); void bind_buffer(); }; + +std::string_view framebuffer_error(GLenum e); + void render_colored_rect(sys::state const& state, float x, float y, float width, float height, float red, float green, float blue, ui::rotation r, bool flipped, bool rtl); void render_alpha_colored_rect(sys::state const& state, float x, float y, float width, float height, float red, float green, float blue, float alpha); void render_simple_rect(sys::state const& state, float x, float y, float width, float height, ui::rotation r, bool flipped, bool rtl); @@ -343,6 +350,9 @@ void render_text_commodity_icon( float font_size, text::font& f ); +void deinitialize_framebuffer_for_province_indices(sys::state& state); +void initialize_framebuffer_for_province_indices(sys::state& state, int32_t size_x, int32_t size_y); + bool msaa_enabled(sys::state const& state); void initialize_msaa(sys::state& state, int32_t x, int32_t y); void deinitialize_msaa(sys::state& state); diff --git a/src/map/map.cpp b/src/map/map.cpp index b73faf63f..5284741e8 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -173,18 +173,47 @@ void create_textured_line_b_vbo(GLuint vbo, std::vector& glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b, position)); glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b, previous_point)); glVertexAttribFormat(2, 2, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b, next_point)); - glVertexAttribFormat(3, 1, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b, texture_coordinate)); - glVertexAttribFormat(4, 1, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b, distance)); + glVertexAttribFormat(4, 1, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b, texture_coordinate)); + glVertexAttribFormat(5, 1, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b, distance)); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + //glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + glEnableVertexAttribArray(5); + glVertexAttribBinding(0, 0); + glVertexAttribBinding(1, 0); + glVertexAttribBinding(2, 0); + //glVertexAttribBinding(3, 0); + glVertexAttribBinding(4, 0); + glVertexAttribBinding(5, 0); +} + +void create_textured_line_b_vbo_enriched_with_province_index(GLuint vbo, std::vector& data) { + // Create and populate the border VBO + glBindBuffer(GL_ARRAY_BUFFER, vbo); + if(!data.empty()) + glBufferData(GL_ARRAY_BUFFER, sizeof(textured_line_vertex_b_enriched_with_province_index) * data.size(), data.data(), GL_STATIC_DRAW); + // Bind the VBO to 0 of the VAO + glBindVertexBuffer(0, vbo, 0, sizeof(textured_line_vertex_b_enriched_with_province_index)); + glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b_enriched_with_province_index, position)); + glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b_enriched_with_province_index, previous_point)); + glVertexAttribFormat(2, 2, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b_enriched_with_province_index, next_point)); + glVertexAttribFormat(3, 2, GL_UNSIGNED_BYTE, GL_TRUE, offsetof(textured_line_vertex_b_enriched_with_province_index, province_index)); + glVertexAttribFormat(4, 1, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b_enriched_with_province_index, texture_coordinate)); + glVertexAttribFormat(5, 1, GL_FLOAT, GL_FALSE, offsetof(textured_line_vertex_b_enriched_with_province_index, distance)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); + glEnableVertexAttribArray(5); glVertexAttribBinding(0, 0); glVertexAttribBinding(1, 0); glVertexAttribBinding(2, 0); glVertexAttribBinding(3, 0); glVertexAttribBinding(4, 0); + glVertexAttribBinding(5, 0); } void create_unit_arrow_vbo(GLuint vbo, std::vector& data) { @@ -277,7 +306,7 @@ void display_data::create_meshes() { add_vertex(land_vertices, pos); } } - + map_indices.clear(); for(int y = 0; y < sections.y; y++) { auto top_row_start = y * (sections.x + 1); @@ -307,7 +336,7 @@ void display_data::create_meshes() { // Fill and bind the VAOs and VBOs glBindVertexArray(vao_array[vo_border]); - create_textured_line_b_vbo(vbo_array[vo_border], border_vertices); + create_textured_line_b_vbo_enriched_with_province_index(vbo_array[vo_border], border_vertices); glBindVertexArray(vao_array[vo_river]); create_textured_line_vbo(vbo_array[vo_river], river_vertices); glBindVertexArray(vao_array[vo_railroad]); @@ -378,6 +407,7 @@ void display_data::load_shaders(simple_fs::directory& root) { // Map shaders auto map_vshader = try_load_shader(root, NATIVE("assets/shaders/glsl/map_v.glsl")); auto map_fshader = try_load_shader(root, NATIVE("assets/shaders/glsl/map_f.glsl")); + auto map_provinces_shader = try_load_shader(root, NATIVE("assets/shaders/glsl/map_provinces_f.glsl")); auto screen_vshader = try_load_shader(root, NATIVE("assets/shaders/glsl/screen_v.glsl")); auto white_color_fshader = try_load_shader(root, NATIVE("assets/shaders/glsl/white_color_f.glsl")); @@ -395,16 +425,19 @@ void display_data::load_shaders(simple_fs::directory& root) { auto tlineb_vshader = try_load_shader(root, NATIVE("assets/shaders/glsl/textured_line_b_v.glsl")); auto tlineb_fshader = try_load_shader(root, NATIVE("assets/shaders/glsl/textured_line_b_f.glsl")); + auto tlineb_provinces_fshader = try_load_shader(root, NATIVE("assets/shaders/glsl/textured_line_b_provinces_f.glsl")); auto model3d_vshader = try_load_shader(root, NATIVE("assets/shaders/glsl/model3d_v.glsl")); auto model3d_fshader = try_load_shader(root, NATIVE("assets/shaders/glsl/model3d_f.glsl")); shaders[shader_terrain] = create_program(*map_vshader, *map_fshader); + shaders[shader_provinces] = create_program(*map_vshader, *map_provinces_shader); shaders[shader_textured_line] = create_program(*tline_vshader, *tline_fshader); shaders[shader_textured_line_with_variable_width] = create_program(*tline_width_vshader, *river_fshader); shaders[shader_trade_flow] = create_program(*tline_width_vshader, *tlineb_fshader); shaders[shader_railroad_line] = create_program(*tline_vshader, *tlineb_fshader); shaders[shader_borders] = create_program(*tlineb_vshader, *tlineb_fshader); + shaders[shader_borders_provinces] = create_program(*tlineb_vshader, *tlineb_provinces_fshader); shaders[shader_line_unit_arrow] = create_program(*line_unit_arrow_vshader, *line_unit_arrow_fshader); shaders[shader_text_line] = create_program(*text_line_vshader, *text_line_fshader); shaders[shader_drag_box] = create_program(*screen_vshader, *white_color_fshader); @@ -414,11 +447,13 @@ void display_data::load_shaders(simple_fs::directory& root) { if(shaders[i] == 0) continue; shader_uniforms[i][uniform_provinces_texture_sampler] = glGetUniformLocation(shaders[i], "provinces_texture_sampler"); + shader_uniforms[i][uniform_provinces_real_texture_sampler] = glGetUniformLocation(shaders[i], "real_provinces_texture_sampler"); shader_uniforms[i][uniform_provinces_sea_mask] = glGetUniformLocation(shaders[i], "provinces_sea_mask"); shader_uniforms[i][uniform_offset] = glGetUniformLocation(shaders[i], "offset"); shader_uniforms[i][uniform_aspect_ratio] = glGetUniformLocation(shaders[i], "aspect_ratio"); shader_uniforms[i][uniform_zoom] = glGetUniformLocation(shaders[i], "zoom"); shader_uniforms[i][uniform_map_size] = glGetUniformLocation(shaders[i], "map_size"); + shader_uniforms[i][uniform_screen_size] = glGetUniformLocation(shaders[i], "screen_size"); shader_uniforms[i][uniform_rotation] = glGetUniformLocation(shaders[i], "rotation"); shader_uniforms[i][uniform_gamma] = glGetUniformLocation(shaders[i], "gamma"); shader_uniforms[i][uniform_subroutines_index] = glGetUniformLocation(shaders[i], "subroutines_index"); @@ -450,17 +485,67 @@ void display_data::load_shaders(simple_fs::directory& root) { } void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 offset, float zoom, map_view map_view_mode, map_mode::mode active_map_mode, glm::mat3 globe_rotation, float time_counter) { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + + + // Load general shader stuff, used by both land and borders + auto load_shader = [&](GLuint program) { + glUseProgram(shaders[program]); + glUniform2f(shader_uniforms[program][uniform_offset], offset.x + 0.f, offset.y); + glUniform1f(shader_uniforms[program][uniform_aspect_ratio], screen_size.x / screen_size.y); + glUniform2f(shader_uniforms[program][uniform_screen_size], screen_size.x, screen_size.y); + glUniform1f(shader_uniforms[program][uniform_zoom], zoom); + glUniform2f(shader_uniforms[program][uniform_map_size], GLfloat(size_x), GLfloat(size_y)); + glUniformMatrix3fv(shader_uniforms[program][uniform_rotation], 1, GL_FALSE, glm::value_ptr(glm::mat3(globe_rotation))); + glUniform1f(shader_uniforms[program][uniform_gamma], state.user_settings.gamma); + glUniform1ui(shader_uniforms[program][uniform_subroutines_index], GLuint(map_view_mode)); + glUniform1f(shader_uniforms[program][uniform_time], time_counter); + }; + + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(std::numeric_limits::max()); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, state.open_gl.province_map_framebuffer); + glViewport(0, 0, int(screen_size.x), int(screen_size.y)); + + glClearColor(0.5f, 0.5f, 0.5f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + + glActiveTexture(GL_TEXTURE12); + glBindTexture(GL_TEXTURE_2D, textures[texture_provinces]); + + load_shader(shader_provinces); + glUniform1i(shader_uniforms[shader_provinces][uniform_provinces_real_texture_sampler], 12); + glBindVertexArray(vao_array[vo_land]); + + glDisable(GL_CULL_FACE); + glDrawElements(GL_TRIANGLE_STRIP, GLsizei(map_indices.size() - 1), GL_UNSIGNED_SHORT, map_indices.data()); + glDisable(GL_PRIMITIVE_RESTART); + + // BORDERS TO FIX HUGE PIXELS + load_shader(shader_borders_provinces); + glUniform1i(shader_uniforms[shader_borders_provinces][uniform_provinces_real_texture_sampler], 12); + glBindVertexArray(vao_array[vo_border]); + glBindBuffer(GL_ARRAY_BUFFER, vbo_array[vo_border]); + glUniform1f(shader_uniforms[shader_borders_provinces][uniform_width], 0.001f); // width + + for(auto b : borders) { + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); + } + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + if(ogl::msaa_enabled(state)) { glBindFramebuffer(GL_FRAMEBUFFER, state.open_gl.msaa_framebuffer); glClearColor(1.f, 1.f, 1.f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + glDisable(GL_CULL_FACE); + glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, textures[texture_provinces]); + glBindTexture(GL_TEXTURE_2D, state.open_gl.province_map_rendertexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textures[texture_terrain]); glActiveTexture(GL_TEXTURE3); @@ -481,6 +566,8 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glBindTexture(GL_TEXTURE_2D, textures[texture_province_highlight]); glActiveTexture(GL_TEXTURE11); glBindTexture(GL_TEXTURE_2D, textures[texture_stripes]); + glActiveTexture(GL_TEXTURE12); + glBindTexture(GL_TEXTURE_2D, textures[texture_sea_mask]); glActiveTexture(GL_TEXTURE13); glBindTexture(GL_TEXTURE_2D, textures[texture_province_fow]); glActiveTexture(GL_TEXTURE14); @@ -488,23 +575,6 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE15); glBindTexture(GL_TEXTURE_2D, textures[texture_diag_border_identifier]); - // Load general shader stuff, used by both land and borders - auto load_shader = [&](GLuint program) { - glUseProgram(shaders[program]); - glUniform2f(shader_uniforms[program][uniform_offset], offset.x + 0.f, offset.y); - glUniform1f(shader_uniforms[program][uniform_aspect_ratio], screen_size.x / screen_size.y); - glUniform1f(shader_uniforms[program][uniform_zoom], zoom); - glUniform2f(shader_uniforms[program][uniform_map_size], GLfloat(size_x), GLfloat(size_y)); - glUniformMatrix3fv(shader_uniforms[program][uniform_rotation], 1, GL_FALSE, glm::value_ptr(glm::mat3(globe_rotation))); - glUniform1f(shader_uniforms[program][uniform_gamma], state.user_settings.gamma); - glUniform1ui(shader_uniforms[program][uniform_subroutines_index], GLuint(map_view_mode)); - glUniform1f(shader_uniforms[program][uniform_time], time_counter); - }; - - glEnable(GL_PRIMITIVE_RESTART); - //glDisable(GL_CULL_FACE); - glPrimitiveRestartIndex(std::numeric_limits::max()); - load_shader(shader_terrain); glUniform1i(shader_uniforms[shader_terrain][uniform_provinces_texture_sampler], 0); glUniform1i(shader_uniforms[shader_terrain][uniform_terrain_texture_sampler], 1); @@ -518,7 +588,7 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glUniform1i(shader_uniforms[shader_terrain][uniform_colormap_political], 9); glUniform1i(shader_uniforms[shader_terrain][uniform_province_highlight], 10); glUniform1i(shader_uniforms[shader_terrain][uniform_stripes_texture], 11); - //glUniform1i(shader_uniforms[shader_terrain][uniform_unused_texture_12], 12); + glUniform1i(shader_uniforms[shader_terrain][uniform_provinces_sea_mask], 12); glUniform1i(shader_uniforms[shader_terrain][uniform_province_fow], 13); //glUniform1i(shader_uniforms[shader_terrain][uniform_unused_texture_14], 14); glUniform1i(shader_uniforms[shader_terrain][uniform_diag_border_identifier], 15); @@ -536,9 +606,10 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glBindVertexArray(vao_array[vo_land]); glDrawElements(GL_TRIANGLE_STRIP, GLsizei(map_indices.size() - 1), GL_UNSIGNED_SHORT, map_indices.data()); - //glDrawArrays(GL_TRIANGLES, 0, land_vertex_count); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); glDisable(GL_PRIMITIVE_RESTART); - //glEnable(GL_CULL_FACE); + // Draw the rivers if(state.user_settings.rivers_enabled) { glActiveTexture(GL_TEXTURE0); @@ -548,7 +619,7 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_sea_mask]); glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, textures[texture_provinces]); + glBindTexture(GL_TEXTURE_2D, state.open_gl.province_map_rendertexture); load_shader(shader_textured_line_with_variable_width); @@ -562,6 +633,8 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glMultiDrawArrays(GL_TRIANGLE_STRIP, river_starts.data(), river_counts.data(), GLsizei(river_starts.size())); } + + // Draw the railroads if(zoom > map::zoom_close && !railroad_vertices.empty()) { glActiveTexture(GL_TEXTURE0); @@ -608,8 +681,10 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glBindTexture(GL_TEXTURE_2D, textures[texture_prov_border]); for(auto b : borders) { + if(!b.adj) continue; if((state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::impassible_bit | province::border::national_bit | province::border::state_bit)) == 0) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -618,8 +693,10 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_state_border]); for(auto b : borders) { + if(!b.adj) continue; if((state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::impassible_bit | province::border::national_bit | province::border::state_bit)) == province::border::state_bit) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -629,8 +706,10 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_imp_border]); for(auto b : borders) { + if(!b.adj) continue; if((state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::impassible_bit)) == province::border::impassible_bit) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -640,8 +719,10 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_national_border]); for(auto b : borders) { + if(!b.adj) continue; if((state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::national_bit | province::border::impassible_bit)) == province::border::national_bit) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -651,8 +732,10 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_prov_border]); for(auto b : borders) { + if(!b.adj) continue; if((state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::national_bit | province::border::state_bit)) == 0) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -661,8 +744,10 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_state_border]); for(auto b : borders) { + if(!b.adj) continue; if((state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::national_bit | province::border::state_bit)) == province::border::state_bit) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -672,24 +757,30 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_state_border]); for(auto b : borders) { + if(!b.adj) continue; if((state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::national_bit)) == province::border::national_bit) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } } + + if(state.map_state.selected_province || (state.local_player_nation && state.current_scene.borders == game_scene::borders_granularity::nation)) { glUniform1f(shader_uniforms[shader_borders][uniform_width], zoom > map::zoom_close ? 0.0004f : 0.00085f); // width glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_state_border]); if(state.local_player_nation && state.current_scene.borders == game_scene::borders_granularity::nation) { for(auto b : borders) { + if(!b.adj) continue; auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0); auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1); if((state.world.province_get_nation_from_province_ownership(p0) == state.local_player_nation || state.world.province_get_nation_from_province_ownership(p1) == state.local_player_nation) && (state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::national_bit)) != 0) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } else if(state.current_scene.borders == game_scene::borders_granularity::state) { @@ -698,21 +789,25 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of auto siid = state.world.province_get_state_membership(state.map_state.selected_province); //per state for(auto b : borders) { + if(!b.adj) continue; auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0); auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1); if((state.world.province_get_state_membership(p0) == siid || state.world.province_get_state_membership(p1) == siid) && (state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::state_bit | province::border::national_bit)) != 0) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } } else if(state.current_scene.borders == game_scene::borders_granularity::province) { for(auto b : borders) { + if(!b.adj) continue; auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0); auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1); if(p0 == state.map_state.selected_province || p1 == state.map_state.selected_province) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -732,33 +827,39 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of if(owner && state.current_scene.borders == game_scene::borders_granularity::nation) { //per nation for(auto b : borders) { + if(!b.adj) continue; auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0); auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1); if((state.world.province_get_nation_from_province_ownership(p0) == owner || state.world.province_get_nation_from_province_ownership(p1) == owner) && (state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::national_bit)) != 0) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } else if(owner && state.current_scene.borders == game_scene::borders_granularity::state) { auto siid = state.world.province_get_state_membership(prov); //per state for(auto b : borders) { + if(!b.adj) continue; auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0); auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1); if((state.world.province_get_state_membership(p0) == siid || state.world.province_get_state_membership(p1) == siid) && (state.world.province_adjacency_get_type(b.adj) & (province::border::non_adjacent_bit | province::border::coastal_bit | province::border::state_bit | province::border::national_bit)) != 0) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } else if(owner && state.current_scene.borders == game_scene::borders_granularity::province) { //per province for(auto b : borders) { + if(!b.adj) continue; auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0); auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1); if(p0 == prov || p1 == prov) { - glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } } } @@ -769,9 +870,19 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glUniform1f(shader_uniforms[shader_borders][uniform_width], 0.0006f); // width glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[texture_coastal_border]); - glBindVertexArray(vao_array[vo_coastal]); - glBindBuffer(GL_ARRAY_BUFFER, vbo_array[vo_coastal]); - glMultiDrawArrays(GL_TRIANGLE_STRIP, coastal_starts.data(), coastal_counts.data(), GLsizei(coastal_starts.size())); + glBindVertexArray(vao_array[vo_border]); + glBindBuffer(GL_ARRAY_BUFFER, vbo_array[vo_border]); + { + for(auto b : borders) { + if(!b.adj) { + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); + } else if((state.world.province_adjacency_get_type(b.adj) & (province::border::coastal_bit)) == province::border::coastal_bit) { + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); + glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); + } + } + } } // trade flow @@ -866,7 +977,7 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of } } - /* + /* else if(state.cheat_data.province_names) { glUniform1f(15, 1.f); glBindVertexArray(vao_array[vo_province_text_line]); @@ -2712,6 +2823,10 @@ void display_data::load_map(sys::state& state) { load_static_meshes(state); create_meshes(); + state.console_log(ogl::opengl_get_error_name(glGetError())); + + + auto assets_dir = simple_fs::open_directory(root, NATIVE("assets")); auto map_dir = simple_fs::open_directory(root, NATIVE("map")); auto map_terrain_dir = simple_fs::open_directory(map_dir, NATIVE("terrain")); diff --git a/src/map/map.hpp b/src/map/map.hpp index 294636127..ec278462a 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -62,6 +62,15 @@ struct textured_line_vertex_b { float distance = 0.f; }; +struct textured_line_vertex_b_enriched_with_province_index { + glm::vec2 position; + glm::vec2 previous_point; + glm::vec2 next_point; + uint16_t province_index; + float texture_coordinate = 0.f; + float distance = 0.f; +}; + struct text_line_vertex { text_line_vertex() { }; text_line_vertex(glm::vec2 position, glm::vec2 normal_direction, glm::vec2 direction, glm::vec3 texture_coord, float thickness) @@ -112,7 +121,7 @@ class display_data { void set_province_text_lines(sys::state& state, std::vector const& data); std::vector borders; - std::vector border_vertices; + std::vector border_vertices; std::vector river_vertices; std::vector river_starts; std::vector river_counts; @@ -240,7 +249,9 @@ class display_data { static constexpr uint32_t shader_map_standing_object = 8; static constexpr uint32_t shader_textured_line_with_variable_width = 9; static constexpr uint32_t shader_trade_flow = 10; - static constexpr uint32_t shader_count = 11; + static constexpr uint32_t shader_provinces = 11; + static constexpr uint32_t shader_borders_provinces = 12; + static constexpr uint32_t shader_count = 13; GLuint shaders[shader_count] = { 0 }; static constexpr uint32_t uniform_offset = 0; @@ -277,7 +288,9 @@ class display_data { static constexpr uint32_t uniform_target_facing = 30; static constexpr uint32_t uniform_target_topview_fixup = 31; static constexpr uint32_t uniform_provinces_sea_mask = 32; - static constexpr uint32_t uniform_count = 33; + static constexpr uint32_t uniform_provinces_real_texture_sampler = 33; + static constexpr uint32_t uniform_screen_size = 34; + static constexpr uint32_t uniform_count = 35; GLuint shader_uniforms[shader_count][uniform_count] = { }; // models: Textures for static meshes diff --git a/src/map/map_borders.cpp b/src/map/map_borders.cpp index e19cfa7f8..2587971e1 100644 --- a/src/map/map_borders.cpp +++ b/src/map/map_borders.cpp @@ -480,66 +480,170 @@ std::vector make_border_section(display_data& dat, sys::state& state, return points; } -void add_border_segment_vertices(display_data& dat, std::vector const& points) { +void add_border_segment_vertices(display_data& dat, std::vector const& points, uint16_t province_A, uint16_t province_B) { if(points.size() < 3) return; - auto first = dat.border_vertices.size(); + { + auto first = dat.border_vertices.size(); - glm::vec2 current_pos = glm::vec2(points.back().x, points.back().y); - glm::vec2 next_pos = put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos, float(dat.size_x)); + glm::vec2 current_pos = glm::vec2(points.back().x, points.back().y); + glm::vec2 next_pos = put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos, float(dat.size_x)); - float distance = 0.0f; - glm::vec2 old_pos; - glm::vec2 raw_dist; - auto norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); + float distance = 0.0f; + glm::vec2 old_pos; + glm::vec2 raw_dist; + auto norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); - { - old_pos = 2.0f * current_pos - next_pos; + { + old_pos = 2.0f * current_pos - next_pos; + + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), + province_A, + 0.0f, distance + }); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), + province_A, + 1.0f, distance + }); + + raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); + raw_dist.x *= 2.0f; + distance += 0.5f * glm::length(raw_dist); + } - dat.border_vertices.emplace_back(textured_line_vertex_b{ norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), 0.0f, distance }); - dat.border_vertices.emplace_back(textured_line_vertex_b{ norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), 1.0f, distance }); + for(auto i = points.size() - 1; i-- > 1; ) { + old_pos = current_pos; + current_pos = glm::vec2(points[i].x, points[i].y); + old_pos = put_in_local(old_pos, current_pos, float(dat.size_x)); + next_pos = put_in_local(glm::vec2(points[i - 1].x, points[i - 1].y), current_pos, float(dat.size_x)); + auto next_direction = glm::normalize(next_pos - current_pos); + + norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); + + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), + province_A, + 0.0f, distance + }); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), + province_A, + 1.0f, distance + }); + + raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); + raw_dist.x *= 2.0f; + distance += 0.5f * glm::length(raw_dist); + } - raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); - raw_dist.x *= 2.0f; - distance += 0.5f * glm::length(raw_dist); - } + // case i == 0 + { + old_pos = current_pos; + current_pos = glm::vec2(points[0].x, points[0].y); - for(auto i = points.size() - 1; i-- > 1; ) { - old_pos = current_pos; - current_pos = glm::vec2(points[i].x, points[i].y); - old_pos = put_in_local(old_pos, current_pos, float(dat.size_x)); - next_pos = put_in_local(glm::vec2(points[i - 1].x, points[i - 1].y), current_pos, float(dat.size_x)); - auto next_direction = glm::normalize(next_pos - current_pos); + next_pos = 2.0f * current_pos - old_pos; - norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); + auto next_direction = glm::normalize(next_pos - current_pos); - dat.border_vertices.emplace_back(textured_line_vertex_b{ norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), 0.0f, distance }); - dat.border_vertices.emplace_back(textured_line_vertex_b{ norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), 1.0f, distance }); + norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); - raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); - raw_dist.x *= 2.0f; - distance += 0.5f * glm::length(raw_dist); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), province_A, 0.0f, distance + }); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), province_A, 1.0f, distance + }); + + raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); + raw_dist.x *= 2.0f; + distance += 0.5f * glm::length(raw_dist); + + } } - // case i == 0 { - old_pos = current_pos; - current_pos = glm::vec2(points[0].x, points[0].y); + auto first = dat.border_vertices.size(); - next_pos = 2.0f * current_pos - old_pos; + glm::vec2 current_pos = glm::vec2(points.back().x, points.back().y); + glm::vec2 next_pos = put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos, float(dat.size_x)); - auto next_direction = glm::normalize(next_pos - current_pos); + float distance = 0.0f; + glm::vec2 old_pos; + glm::vec2 raw_dist; + auto norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); - norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); + { + old_pos = 2.0f * current_pos - next_pos; + + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), + province_B, + 1.0f, distance + }); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), + province_B, + 0.0f, distance + }); + + raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); + raw_dist.x *= 2.0f; + distance += 0.5f * glm::length(raw_dist); + } - dat.border_vertices.emplace_back(textured_line_vertex_b{ norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), 0.0f, distance }); - dat.border_vertices.emplace_back(textured_line_vertex_b{ norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), 1.0f, distance }); + for(auto i = points.size() - 1; i-- > 1; ) { + old_pos = current_pos; + current_pos = glm::vec2(points[i].x, points[i].y); + old_pos = put_in_local(old_pos, current_pos, float(dat.size_x)); + next_pos = put_in_local(glm::vec2(points[i - 1].x, points[i - 1].y), current_pos, float(dat.size_x)); + auto next_direction = glm::normalize(next_pos - current_pos); + + norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); + + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), + province_B, + 1.0f, distance + }); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), + province_B, + 0.0f, distance + }); + + raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); + raw_dist.x *= 2.0f; + distance += 0.5f * glm::length(raw_dist); + } - raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); - raw_dist.x *= 2.0f; - distance += 0.5f * glm::length(raw_dist); + // case i == 0 + { + old_pos = current_pos; + current_pos = glm::vec2(points[0].x, points[0].y); + + next_pos = 2.0f * current_pos - old_pos; + + auto next_direction = glm::normalize(next_pos - current_pos); + + norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), + province_B, 1.0f, distance + }); + dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ + norm_pos, next_pos / glm::vec2(dat.size_x, dat.size_y), old_pos / glm::vec2(dat.size_x, dat.size_y), + province_B, 0.0f, distance + }); + + raw_dist = (current_pos - next_pos) / glm::vec2(dat.size_x, dat.size_y); + raw_dist.x *= 2.0f; + distance += 0.5f * glm::length(raw_dist); + + } } } @@ -559,22 +663,33 @@ void display_data::make_borders(sys::state& state, std::vector& visited) { auto prim = province::from_map_id(safe_get_province(glm::ivec2(i, j))); auto sec = province::from_map_id(safe_get_province(glm::ivec2(i - 1, j))); - if(!was_visited && prim != sec && prim && sec) { - auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec); - assert(adj); - int32_t border_index = adj.index(); - if(borders[border_index].count != 0) { + bool fake_border = false; + if(!prim || !sec) { + fake_border = true; + } + + if(!was_visited && prim != sec) { + int32_t border_index; + if(!fake_border) { + auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec); + assert(adj); + border_index = adj.index(); + if(borders[border_index].count != 0) { + border_index = int32_t(borders.size()); + borders.emplace_back(); + borders.back().adj = adj; + } + + } else { border_index = int32_t(borders.size()); borders.emplace_back(); - borders.back().adj = adj; + borders.back().adj = { }; } - borders[border_index].start_index = int32_t(border_vertices.size()); - + borders[border_index].start_index = int32_t(border_vertices.size()); auto res = make_border_section(*this, state, visited, province::to_map_id(prim), province::to_map_id(sec), i, j * 2); smooth_points(res); - add_border_segment_vertices(*this, res); - + add_border_segment_vertices(*this, res, safe_get_province(glm::ivec2(i, j)), safe_get_province(glm::ivec2(i - 1, j))); borders[border_index].count = int32_t(border_vertices.size() - borders[border_index].start_index); } } @@ -585,22 +700,33 @@ void display_data::make_borders(sys::state& state, std::vector& visited) { auto prim = province::from_map_id(safe_get_province(glm::ivec2(i, j))); auto sec = province::from_map_id(safe_get_province(glm::ivec2(i, j + 1))); + bool fake_border = false; + if(!prim || !sec) { + fake_border = true; + } + if(!was_visited && prim != sec && prim && sec) { - auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec); - assert(adj); - int32_t border_index = adj.index(); - if(borders[border_index].count != 0) { + int32_t border_index; + + if(!fake_border) { + auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec); + assert(adj); + border_index = adj.index(); + if(borders[border_index].count != 0) { + border_index = int32_t(borders.size()); + borders.emplace_back(); + borders.back().adj = adj; + } + } else { border_index = int32_t(borders.size()); borders.emplace_back(); - borders.back().adj = adj; + borders.back().adj = { }; } borders[border_index].start_index = int32_t(border_vertices.size()); - auto res = make_border_section(*this, state, visited, province::to_map_id(prim), province::to_map_id(sec), i, j * 2 + 1); smooth_points(res); - add_border_segment_vertices(*this, res); - + add_border_segment_vertices(*this, res, safe_get_province(glm::ivec2(i, j)), safe_get_province(glm::ivec2(i, j + 1))); borders[border_index].count = int32_t(border_vertices.size() - borders[border_index].start_index); } } diff --git a/src/map/map_state.cpp b/src/map/map_state.cpp index 96889ae87..062e53c02 100644 --- a/src/map/map_state.cpp +++ b/src/map/map_state.cpp @@ -57,7 +57,7 @@ glm::vec2 get_port_location(sys::state& state, dcon::province_id p) { auto id = adj.index(); auto& map_data = state.map_state.map_data; auto& border = map_data.borders[id]; - auto& vertex = map_data.border_vertices[border.start_index + border.count / 2]; + auto& vertex = map_data.border_vertices[border.start_index + border.count / 4]; glm::vec2 map_size = glm::vec2(map_data.size_x, map_data.size_y); return vertex.position * map_size; From abebc509529c30d19fe6e2090ff9c094b439c6f3 Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Wed, 22 Jan 2025 10:22:37 +0300 Subject: [PATCH 3/4] fix the primitive restart bug --- assets/prov_border.dds | Bin 6528 -> 6528 bytes assets/shaders/glsl/textured_line_b_v.glsl | 11 ++++++++--- src/map/map.cpp | 4 ++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/assets/prov_border.dds b/assets/prov_border.dds index 5f486379361a3088b3cb635448dcd01bf62661b0..8f92d3cefa5ad92536e890f9c304e3a43a4132e3 100644 GIT binary patch literal 6528 zcmeI#Nodq?7>4mwYwKQDinvgfQn#WgB6v^>gCcH~0TqiUD;7Mt;He(;ES>~CdJw$n zMFpjx=tWN|2#QuMQWsos-`D3EC*qPBFBy|VKKh%?Bx&-_m;94VE|+iU41%C;SP+b2 z+KNS0yiiV-EM3vsoXh2_g1&`$83 z8b+cX)kvyp+3{%9paYK)mD_nYFc0Q6cid(Fns5Q{5tYM!KEPTGf=9Fuk}6NiI+$TO z?xR%hJ1nz*eov2m+~szs;37VtRF0=C+k$}@4F4~wvTyd!46ER={eq}*^PKr>;JPCa zce&lkIFEAY-xHQ^M*kuviIx2u3bT9Ze27y0d%?0cxbASoU5s!}0qWQQ7V7Vub(0+gQu-=>6k3UcwxIjstVuhGWIvC3){)_k~^zVCu2Y zqZj4+mt(p8bL_-j_F_7Y!TVU$HSiPjFJU3fY?dU;vFJE(+78dZkBB<|?lHdwX7;_YypErM`F+0wm3Z!Bvp>r${vMi%m1xISY{y0{Kt0Txrt)6qGhH*5!Q9)h3wy8= zX0OD3m(BiG)qL`Ig?*ZcrlJW<9k(t|V|h&Nk9~BUntL|9XZU;F?EmYydmegB?UiF% mX?R{C#y=|@&*n9E4g4O?&noLc)`6@8SqHKXWF1IB2fhPeF2X_p literal 6528 zcmeI0U5HLw7=ZT|PLpURb4*S7`J5BUB=U1X5*ke!I>Utggrbm(xgr;Clq4fk>YSu= zaSEfz#YyKBQl}`nP`D5sj=$t5zlHoi&$gF7d-i-YpP!ne@6Ge=wcht#?_Te_*IIjz z`ugVlhA4_EtD@*fu1zo{#}DGAVaBYck@fY>xu{31EB2GeI5lyw9YycLzYiVmQI>KA z{wEda#XS3f+oCqXwmNNJA{7h{v5gtxsxL*{qUl)G=!{)ztlo^Ngc=C>x?|OslCQpw z831FU0X$a3wmNO4#$`y<6U=QejDu+f*jKMzzs^LTzL1CU5Mp_RImfQXGGFWV6HJ7e z5b`x<9r%2IfX*bu8jfQlv_LEDPOz;`n?ByRtIx)K`$HYfhSjjS0Q>5->sPFX-qUq5 z66U}f2(dQNUIo9v2r&1KVud)P@mT=tU>AgZH_~1SlOYeTnPQ^dx;UpTa2U?O#RS{x zwCSU7XEAY!rHbD$&uz5Z;8X$j)tiTY`e#WFWj`1Li(oq(fDr2>?R~Hn=EEqcge+0- zT3rUe!e4M6Lcagd-VbYGI=Jtwd6uZx-U!y`7+izL@GQZ$I&J#sTP!B#SStAa8LW*p zIu2LiK0HdU_SJ_P>hHL;_`HUJwc7zF;6E_dL%0W5;3!zbdEnkm$1=`PSOV7WG~9-# z@Epwf0a(j}U=1fgHDpO2ls=0VI1JY51-yZ`3AWW~(??&&IJTI$huj0};RxIS=lB|o z>D9h^?fU8OxI)R%se!4m0se+tP#EhKeRIDKf5JML1nInu?fJG5dnz_A8p-!7V`Z^|^C#sL)*)tI4!Y()mPaqxJzIyHY>F>D0 zv&(ts!FBu_TmbXSisc;7!cJ(00nh`245DE@euqn7&8=BFU!TVv@L8>eG2q%wOD&2f z*bNt6HLvRybLb`VLeKwvkp0BP|_i(v>U%!6t!SeoXzXrRyf6MQWFMEG@ zCV0j+!WK9N*T8ewvqWsG)25HUj&W=;@!P@k#&drg90$*?`|!PdzmQ6NE)M592dt0Z zD86TXSBPzO+Vs&k>nugxPO8w1hET&c+Tokmt9@&$T|fP^B!{ve_#RvY-R1k4sl@B3 zlB;!bZM8rv_?{Kp>a^*jZ)a-{msouF^@lo`4gS5hxd8j>wd)t&l{DLl_pE{L_V=3; zb#AUH_vKjdozj$GTb(w2x>`G2W3eWlvx8wA`28BNuU>nx+F_1GpYHbm2g%gpi?uNq z-^;ZLw$+tdH->y774$-EV}`iuOA+^SI#xA0W0xAs_27PTU59) 0.5f) || (texture_coord < -0.5f) ) { + if (texture_coord < 0.01f) { + true_width = 0.00001f; + } + + //if((texture_coord > 0.5f) || (texture_coord < -0.5f) ) { vec2 bpt = central_pos.xy; vec2 apt = calc_gl_position(prev_point).xy; vec2 cpt = calc_gl_position(next_point).xy; @@ -122,11 +127,11 @@ void main() { vec2 bnorm = vec2(-bdir.y, bdir.x); vec2 corner_normal = normalize(anorm + bnorm); - corner_shift = corner_normal * zoom * width / (1.0f + max(-0.5f, dot(anorm, bnorm))); + corner_shift = corner_normal * zoom * true_width / (1.0f + max(-0.5f, dot(anorm, bnorm))); // transform result back to screen + depth coordinates corner_shift.x /= aspect_ratio; - } + //} gl_Position = central_pos + vec4(corner_shift.x, corner_shift.y, 0.0f, 0.0f); diff --git a/src/map/map.cpp b/src/map/map.cpp index 5284741e8..87c4ddddc 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -317,6 +317,7 @@ void display_data::create_meshes() { map_indices.push_back(uint16_t(bottom_row_start + 1 + x)); map_indices.push_back(uint16_t(top_row_start + 1 + x)); } + // primitive restart marker map_indices.push_back(std::numeric_limits::max()); } @@ -603,6 +604,9 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of fragment_subroutines = 2; // get_land_political_far/get_water_political() glUniform1ui(shader_uniforms[shader_terrain][uniform_subroutines_index_2], fragment_subroutines); } + + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(std::numeric_limits::max()); glBindVertexArray(vao_array[vo_land]); glDrawElements(GL_TRIANGLE_STRIP, GLsizei(map_indices.size() - 1), GL_UNSIGNED_SHORT, map_indices.data()); From f665bfb20d166311f0b0af89d2c4dee2d130311f Mon Sep 17 00:00:00 2001 From: ineveraskedforthis Date: Wed, 22 Jan 2025 14:11:45 +0300 Subject: [PATCH 4/4] fix wrap around for borders --- src/map/map.cpp | 5 ++- src/map/map_borders.cpp | 90 ++++++++++++++++++++++++++++++++--------- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/map/map.cpp b/src/map/map.cpp index 87c4ddddc..3e2420240 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -527,9 +527,12 @@ void display_data::render(sys::state& state, glm::vec2 screen_size, glm::vec2 of glUniform1i(shader_uniforms[shader_borders_provinces][uniform_provinces_real_texture_sampler], 12); glBindVertexArray(vao_array[vo_border]); glBindBuffer(GL_ARRAY_BUFFER, vbo_array[vo_border]); - glUniform1f(shader_uniforms[shader_borders_provinces][uniform_width], 0.001f); // width for(auto b : borders) { + glUniform1f(shader_uniforms[shader_borders_provinces][uniform_width], 0.001f); // width + if(b.count < 50) { + glUniform1f(shader_uniforms[shader_borders_provinces][uniform_width], 0.0f); // width + } glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count / 2); glDrawArrays(GL_TRIANGLE_STRIP, b.start_index + b.count / 2, b.count / 2); } diff --git a/src/map/map_borders.cpp b/src/map/map_borders.cpp index 2587971e1..d497c933f 100644 --- a/src/map/map_borders.cpp +++ b/src/map/map_borders.cpp @@ -105,25 +105,59 @@ bool extend_if_possible(uint32_t x, int32_t border_id, direction dir, std::vecto void smooth_points(std::vector& vertices) { std::vector vertices_copy = vertices; + bool wrap_around = false; + if(glm::distance(vertices.back(), vertices.front()) < 0.001f) { + wrap_around = true; + } + auto start = int(0); auto end = start + int(vertices.size()); - for(int i = start + 1; i < end - 1; i++) { + + auto start_iteration = start + 1; + auto end_iteration = end - 1; + + if(wrap_around) { + start_iteration = start; + end_iteration = end; + } + + for(int i = start_iteration; i < end_iteration; i++) { glm::vec2 new_position{ 0.f, 0.f }; float count = 0.f; bool smooth = true; for(int shift = -2; shift <= 2; shift++) { - if(i + shift < start) { - continue; - }; - if(i + shift >= end) { - continue; - }; - count += 1.f / (float(std::abs(shift)) + 1.f); - new_position += (vertices_copy[i + shift]) * 1.f / (float(std::abs(shift)) + 1.f); + auto shifted_index = i + shift; + if(wrap_around) { + if(shifted_index < start) { + shifted_index = end + shifted_index - start; + } + if(shifted_index >= end) { + shifted_index = start + shifted_index - end; + } + } else { + if(shifted_index < start) { + continue; + }; + if(shifted_index >= end) { + continue; + }; + } + auto weight = 1.f / (float(std::abs(shift)) + 1.f); + + if(shift == 0) { + weight += 10.f / vertices.size() / vertices.size(); + } + + count += weight; + new_position += (vertices_copy[shifted_index]) * weight; } if((count > 0) && smooth) { vertices[i] = new_position / count; - } + } + } + + if(wrap_around) { + vertices[0] = vertices.back(); } } @@ -484,6 +518,11 @@ void add_border_segment_vertices(display_data& dat, std::vector const if(points.size() < 3) return; + bool wrap_around = false; + if(glm::length(points.back() - points[0]) < 0.1f) { + wrap_around = true; + } + { auto first = dat.border_vertices.size(); @@ -496,7 +535,11 @@ void add_border_segment_vertices(display_data& dat, std::vector const auto norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); { - old_pos = 2.0f * current_pos - next_pos; + if(wrap_around) { + old_pos = put_in_local(glm::vec2(points[1].x, points[1].y), current_pos, float(dat.size_x)); + } else { + old_pos = 2.0f * current_pos - next_pos; + } dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), @@ -539,12 +582,15 @@ void add_border_segment_vertices(display_data& dat, std::vector const distance += 0.5f * glm::length(raw_dist); } - // case i == 0 - { + { // case i == 0 old_pos = current_pos; current_pos = glm::vec2(points[0].x, points[0].y); - next_pos = 2.0f * current_pos - old_pos; + if(wrap_around) { + next_pos = put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos, float(dat.size_x)); + } else { + next_pos = 2.0f * current_pos - old_pos; + } auto next_direction = glm::normalize(next_pos - current_pos); @@ -560,7 +606,6 @@ void add_border_segment_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 += 0.5f * glm::length(raw_dist); - } } @@ -576,7 +621,11 @@ void add_border_segment_vertices(display_data& dat, std::vector const auto norm_pos = current_pos / glm::vec2(dat.size_x, dat.size_y); { - old_pos = 2.0f * current_pos - next_pos; + if(wrap_around) { + old_pos = put_in_local(glm::vec2(points[1].x, points[1].y), current_pos, float(dat.size_x)); + } else { + old_pos = 2.0f * current_pos - next_pos; + } dat.border_vertices.emplace_back(textured_line_vertex_b_enriched_with_province_index{ norm_pos, old_pos / glm::vec2(dat.size_x, dat.size_y), next_pos / glm::vec2(dat.size_x, dat.size_y), @@ -619,12 +668,15 @@ void add_border_segment_vertices(display_data& dat, std::vector const distance += 0.5f * glm::length(raw_dist); } - // case i == 0 - { + { // case i == 0 old_pos = current_pos; current_pos = glm::vec2(points[0].x, points[0].y); - next_pos = 2.0f * current_pos - old_pos; + if(wrap_around) { + next_pos = put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos, float(dat.size_x)); + } else { + next_pos = 2.0f * current_pos - old_pos; + } auto next_direction = glm::normalize(next_pos - current_pos);