aboutsummaryrefslogtreecommitdiff
path: root/game/src/Game/GameSession/TerrainMap.gdshader
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-04-22 21:15:25 +0200
committer hop311 <hop3114@gmail.com>2024-04-22 21:15:25 +0200
commit4af4638e3ecdde7b0dd91f5d8e7a86e34238184c (patch)
treebd2b6c9f953ea022ff083b0cd82fc81e0e6ded9f /game/src/Game/GameSession/TerrainMap.gdshader
parent747ccf4491512763559bf524cbceafe640188b89 (diff)
Smooth province edges and zoom tweaksprovince-edge-blending
Diffstat (limited to 'game/src/Game/GameSession/TerrainMap.gdshader')
-rw-r--r--game/src/Game/GameSession/TerrainMap.gdshader119
1 files changed, 80 insertions, 39 deletions
diff --git a/game/src/Game/GameSession/TerrainMap.gdshader b/game/src/Game/GameSession/TerrainMap.gdshader
index 98f9efd..467e277 100644
--- a/game/src/Game/GameSession/TerrainMap.gdshader
+++ b/game/src/Game/GameSession/TerrainMap.gdshader
@@ -34,37 +34,87 @@ uniform sampler2D colormap_water_tex: repeat_enable, filter_linear;
// Overlay map tint
uniform sampler2D colormap_overlay_tex: repeat_enable, filter_linear;
-struct terrain_args_t {
- vec2 uv, half_pixel_size; // Components for calculating terrain sampling UV
+struct corner_args_t {
+ vec2 uv, half_pixel_size; // Components for calculating a corner's sampling UV
vec2 terrain_uv; // UV coordinates scaled for terrain texture tiling
vec3 land_tint_colour, water_tint_colour; // Colours for tinting the terrain
+ float stripe_mask; // Weight for mixing base and stripe province colours
+};
+
+struct corner_ret_t {
+ vec3 terrain_colour;
+ vec4 province_colour;
+ float highlight_mix_val;
};
// Calculate terrain colour at the specified corner of the current pixel
-vec3 get_terrain_colour(const terrain_args_t terrain_args, const vec2 corner) {
+corner_ret_t get_corner_colour(const corner_args_t corner_args, const vec2 corner) {
+ corner_ret_t ret;
+
+ uvec3 province_data = read_uvec3(fma(corner, corner_args.half_pixel_size, corner_args.uv));
+
// Find the terrain index at the specified corner of the current pixel
- uint terrain_index = read_uvec3(fma(corner, terrain_args.half_pixel_size, terrain_args.uv)).z;
+ uint terrain_index = province_data.z;
// Get the tinted land colour at the current position
- vec3 land_colour = texture(terrain_tex, vec3(terrain_args.terrain_uv, float(terrain_index))).rgb;
- land_colour = mix(land_colour, terrain_args.land_tint_colour, 0.3);
+ vec3 land_colour = texture(terrain_tex, vec3(corner_args.terrain_uv, float(terrain_index))).rgb;
+ land_colour = mix(land_colour, corner_args.land_tint_colour, 0.3);
// TODO - proper water texture
- vec3 water_colour = terrain_args.water_tint_colour;
+ vec3 water_colour = corner_args.water_tint_colour;
// Select land or water colour based on the terrain index (0 is water, otherwise land)
- vec3 terrain_colour = mix(land_colour, water_colour, float(terrain_index == 0u));
+ ret.terrain_colour = mix(land_colour, water_colour, float(terrain_index == 0u));
+
+ uint province_index = uvec2_to_uint(province_data.xy);
+
+ // Get base and stripe colours for province at the current position
+ province_data.x *= 2u; // Double "x coordinate" as colours come in (base, stripe) pairs
+ vec4 province_base_colour = texelFetch(province_colour_tex, ivec2(province_data.xy), 0);
+
+ province_data.x += 1u; // Add 1 to "x coordinate" to move from base to strip colour
+ vec4 province_stripe_colour = texelFetch(province_colour_tex, ivec2(province_data.xy), 0);
+
+ // Blend the base and stripe colours according to the current position's stripe mask value
+ ret.province_colour = mix(province_base_colour, province_stripe_colour, corner_args.stripe_mask);
+
+ ret.province_colour = mix(ret.province_colour, vec4(corner_args.water_tint_colour, 0.0), float(terrain_index == 0u));
+
+ ret.highlight_mix_val = 0.4 * (
+ float(province_index == hover_index) + float(province_index == selected_index)
+ ) * float(province_index != 0u);
- return terrain_colour;
+ return ret;
}
// Blend together terrain colours from the four corners of the current pixel
-vec3 mix_terrain_colour(const terrain_args_t terrain_args, const vec2 pixel_offset) {
- return mix(
- mix(get_terrain_colour(terrain_args, vec2(-1, -1)), get_terrain_colour(terrain_args, vec2(+1, -1)), pixel_offset.x),
- mix(get_terrain_colour(terrain_args, vec2(-1, +1)), get_terrain_colour(terrain_args, vec2(+1, +1)), pixel_offset.x),
+corner_ret_t mix_terrain_colour(const corner_args_t corner_args, const vec2 pixel_offset) {
+ corner_ret_t mm = get_corner_colour(corner_args, vec2(-1, -1));
+ corner_ret_t pm = get_corner_colour(corner_args, vec2(+1, -1));
+ corner_ret_t mp = get_corner_colour(corner_args, vec2(-1, +1));
+ corner_ret_t pp = get_corner_colour(corner_args, vec2(+1, +1));
+
+ corner_ret_t ret;
+
+ ret.terrain_colour = mix(
+ mix(mm.terrain_colour, pm.terrain_colour, pixel_offset.x),
+ mix(mp.terrain_colour, pp.terrain_colour, pixel_offset.x),
+ pixel_offset.y
+ );
+
+ ret.province_colour = mix(
+ mix(mm.province_colour, pm.province_colour, pixel_offset.x),
+ mix(mp.province_colour, pp.province_colour, pixel_offset.x),
+ pixel_offset.y
+ );
+
+ ret.highlight_mix_val = mix(
+ mix(mm.highlight_mix_val, pm.highlight_mix_val, pixel_offset.x),
+ mix(mp.highlight_mix_val, pp.highlight_mix_val, pixel_offset.x),
pixel_offset.y
);
+
+ return ret;
}
// Mix overlay and base colours, used for the parchment map
@@ -84,41 +134,33 @@ vec3 get_map_colour(vec2 uv) {
// Offset of uv_map_pixels from the top left corner of the current pixel
vec2 pixel_offset = fract(uv_map_pixels);
- terrain_args_t terrain_args;
- terrain_args.uv = uv;
- terrain_args.half_pixel_size = 0.49 / map_size;
+ corner_args_t corner_args;
+ corner_args.uv = uv;
+ corner_args.half_pixel_size = 0.49 / map_size;
// Terrain texture tiling UV
- terrain_args.terrain_uv = 0.5 - uv_map_pixels * terrain_tile_factor;
+ corner_args.terrain_uv = 0.5 - uv_map_pixels * terrain_tile_factor;
+
+ vec2 stripe_uv = uv_map_pixels * stripe_tile_factor;
+ // Stripe mask value - between 0 (base) and 1 (stripe)
+ corner_args.stripe_mask = texture(stripe_tex, stripe_uv).b;
vec2 colormap_uv = vec2(uv.x, 1.0 - uv.y);
// Terrain tinting colours
- terrain_args.land_tint_colour = texture(colormap_land_tex, colormap_uv).rgb;
- terrain_args.water_tint_colour = texture(colormap_water_tex, colormap_uv).rgb;
+ corner_args.land_tint_colour = texture(colormap_land_tex, colormap_uv).rgb;
+ corner_args.water_tint_colour = texture(colormap_water_tex, colormap_uv).rgb;
// Parchment tint colour
vec3 overlay_tint_colour = texture(colormap_overlay_tex, colormap_uv).rgb;
- // Blended terrain colour (average of four corners of current pixel)
- vec3 terrain_colour = mix_terrain_colour(terrain_args, pixel_offset);
+ corner_ret_t colours = mix_terrain_colour(corner_args, pixel_offset);
- vec2 stripe_uv = uv_map_pixels * stripe_tile_factor;
- // Stripe mask value - between 0 (base) and 1 (stripe)
- float stripe_mask = texture(stripe_tex, stripe_uv).b;
+ // Blended terrain colour (average of four corners of current pixel)
+ vec3 terrain_colour = colours.terrain_colour;
vec2 overlay_uv = vec2(uv_map_pixels.x, map_size.y - uv_map_pixels.y) * overlay_tile_factor;
// Parchment overlay colour
vec3 overlay_colour = texture(overlay_tex, overlay_uv).rgb;
- // Current province index as a pair of byte coordinates and as a combined 16 bit value
- uvec2 province_data = read_uvec3(uv).xy;
- uint province_index = uvec2_to_uint(province_data);
-
- // Get base and stripe colours for province at the current position
- province_data.x *= 2u; // Double "x coordinate" as colours come in (base, stripe) pairs
- vec4 province_base_colour = texelFetch(province_colour_tex, ivec2(province_data), 0);
- province_data.x += 1u; // Add 1 to "x coordinate" to move from base to strip colour
- vec4 province_stripe_colour = texelFetch(province_colour_tex, ivec2(province_data), 0);
- // Blend the base and stripe colours according to the current position's stripe mask value
- vec4 province_colour = mix(province_base_colour, province_stripe_colour, stripe_mask);
+ vec4 province_colour = colours.province_colour;
// Darken the province colour
province_colour.rgb -= 0.7;
@@ -129,22 +171,21 @@ vec3 get_map_colour(vec2 uv) {
// Near colour is either the terrain's luma component tinted with the province colour and brightened,
// or the normal terrain colour
vec3 near_province_colour = mix(vec3(terrain_luma), province_colour.rgb, 0.3) * 1.5;
- vec3 near_colour = mix(near_province_colour, terrain_colour, float(province_colour.a == 0.0));
+ vec3 near_colour = mix(terrain_colour, near_province_colour, province_colour.a);
// Far colour is either the province colour mixed with the overlay texture, tinted with the overlay colormap and brightened,
// or the normal terrain colour mixed with the overlay texture (primarily for water)
vec3 far_province_colour = mix_overlay(overlay_colour, province_colour.rgb);
far_province_colour = mix(overlay_tint_colour, far_province_colour, 0.3) * 1.5;
vec3 far_terrain_colour = mix_overlay(overlay_colour, terrain_colour);
- vec3 far_colour = mix(far_province_colour, far_terrain_colour, float(province_colour.a == 0.0));
+ vec3 far_colour = mix(far_terrain_colour, far_province_colour, province_colour.a);
// Blend the near (detailed terrain) and far (parchment) colours according to the parchment mix factor (0 for near, 1 for far)
vec3 final_colour = mix(near_colour, far_colour, parchment_mix);
// Significantly brighted the colour if it is hovered over and/or selected, but not if it has province index 0 (all invalid pixels)
const vec3 highlight_colour = vec3(1.0);
- float highlight_mix_val = 0.4 * (float(province_index == hover_index) + float(province_index == selected_index)) * float(province_index != 0u);
- vec3 highlighted_colour = mix(final_colour, highlight_colour, highlight_mix_val);
+ vec3 highlighted_colour = mix(final_colour, highlight_colour, colours.highlight_mix_val);
return highlighted_colour;
}