aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hop311 <hop3114@gmail.com>2023-04-26 00:51:44 +0200
committer Hop311 <hop3114@gmail.com>2023-04-26 00:51:44 +0200
commit563834e7e6f9ce565bbfd553a0d9ff80a98c677d (patch)
treefcf86e6fac31430ba537a0d056e97f901ad76dd7
parent50327abf33078c44fef85c62ce3d90e23056fb34 (diff)
Divide map texture to fit in 16384 GPU dim limit
-rw-r--r--extension/src/GameSingleton.cpp40
-rw-r--r--extension/src/GameSingleton.hpp5
-rw-r--r--extension/src/openvic2/Types.hpp3
-rw-r--r--game/src/GameSession/MapView.gd12
-rw-r--r--game/src/GameSession/TerrainMap.gdshader23
5 files changed, 49 insertions, 34 deletions
diff --git a/extension/src/GameSingleton.cpp b/extension/src/GameSingleton.cpp
index 32d940c..3811dea 100644
--- a/extension/src/GameSingleton.cpp
+++ b/extension/src/GameSingleton.cpp
@@ -24,7 +24,7 @@ void GameSingleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_province_info_from_index", "index"), &GameSingleton::get_province_info_from_index);
ClassDB::bind_method(D_METHOD("get_width"), &GameSingleton::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &GameSingleton::get_height);
- ClassDB::bind_method(D_METHOD("get_province_index_image"), &GameSingleton::get_province_index_image);
+ ClassDB::bind_method(D_METHOD("get_province_index_images"), &GameSingleton::get_province_index_images);
ClassDB::bind_method(D_METHOD("get_province_colour_image"), &GameSingleton::get_province_colour_image);
ClassDB::bind_method(D_METHOD("update_colour_image"), &GameSingleton::update_colour_image);
@@ -231,7 +231,7 @@ Error GameSingleton::load_region_file(String const& file_path) {
}
Error GameSingleton::load_province_shape_file(String const& file_path) {
- if (province_index_image.is_valid()) {
+ if (province_index_image[0].is_valid()) {
UtilityFunctions::push_error("Province shape file has already been loaded, cannot load: ", file_path);
return FAILED;
}
@@ -242,12 +242,16 @@ Error GameSingleton::load_province_shape_file(String const& file_path) {
UtilityFunctions::push_error("Failed to load province shape file: ", file_path);
return err;
}
- int32_t width = province_shape_image->get_width();
- int32_t height = province_shape_image->get_height();
+ const int32_t width = province_shape_image->get_width();
+ const int32_t height = province_shape_image->get_height();
if (width < 1 || height < 1) {
UtilityFunctions::push_error("Invalid dimensions (", width, "x", height, ") for province shape file: ", file_path);
err = FAILED;
}
+ if (width % image_width_divide != 0) {
+ UtilityFunctions::push_error("Invalid width ", width, " (must be divisible by ", image_width_divide, ") for province shape file: ", file_path);
+ err = FAILED;
+ }
static constexpr Image::Format expected_format = Image::FORMAT_RGB8;
const Image::Format format = province_shape_image->get_format();
if (format != expected_format) {
@@ -257,15 +261,20 @@ Error GameSingleton::load_province_shape_file(String const& file_path) {
if (err != OK) return err;
err = ERR(game_manager.map.generate_province_index_image(width, height, province_shape_image->get_data().ptr()));
- PackedByteArray index_data_array;
- index_data_array.resize(width * height * sizeof(Province::index_t));
std::vector<Province::index_t> const& province_index_data = game_manager.map.get_province_index_image();
- memcpy(index_data_array.ptrw(), province_index_data.data(), province_index_data.size());
-
- province_index_image = Image::create_from_data(width, height, false, Image::FORMAT_RG8, index_data_array);
- if (province_index_image.is_null()) {
- UtilityFunctions::push_error("Failed to create province ID image");
- err = FAILED;
+ const int32_t divided_width = width / image_width_divide;
+ for (int32_t i = 0; i < image_width_divide; ++i) {
+ PackedByteArray index_data_array;
+ index_data_array.resize(divided_width * height * sizeof(Province::index_t));
+ for (int32_t y = 0; y < height; ++y)
+ memcpy(index_data_array.ptrw() + y * divided_width * sizeof(Province::index_t),
+ province_index_data.data() + y * width + i * divided_width,
+ divided_width * sizeof(Province::index_t));
+ province_index_image[i] = Image::create_from_data(divided_width, height, false, Image::FORMAT_RG8, index_data_array);
+ if (province_index_image[i].is_null()) {
+ UtilityFunctions::push_error("Failed to create province ID image #", i);
+ err = FAILED;
+ }
}
if (update_colour_image() != OK) err = FAILED;
@@ -357,8 +366,11 @@ int32_t GameSingleton::get_height() const {
return game_manager.map.get_height();
}
-Ref<Image> GameSingleton::get_province_index_image() const {
- return province_index_image;
+Array GameSingleton::get_province_index_images() const {
+ Array ret;
+ for (int i = 0; i < image_width_divide; ++i)
+ ret.append(province_index_image[i]);
+ return ret;
}
Ref<Image> GameSingleton::get_province_colour_image() const {
diff --git a/extension/src/GameSingleton.hpp b/extension/src/GameSingleton.hpp
index 815c92f..d9879ef 100644
--- a/extension/src/GameSingleton.hpp
+++ b/extension/src/GameSingleton.hpp
@@ -14,7 +14,8 @@ namespace OpenVic2 {
GameManager game_manager;
- godot::Ref<godot::Image> province_index_image, province_colour_image;
+ static constexpr int image_width_divide = 2;
+ godot::Ref<godot::Image> province_index_image[image_width_divide], province_colour_image;
Mapmode::index_t mapmode_index = 0;
godot::Error _parse_province_identifier_entry(godot::String const& identifier, godot::Variant const& entry);
@@ -39,7 +40,7 @@ namespace OpenVic2 {
godot::Dictionary get_province_info_from_index(int32_t index) const;
int32_t get_width() const;
int32_t get_height() const;
- godot::Ref<godot::Image> get_province_index_image() const;
+ godot::Array get_province_index_images() const;
godot::Ref<godot::Image> get_province_colour_image() const;
godot::Error update_colour_image();
diff --git a/extension/src/openvic2/Types.hpp b/extension/src/openvic2/Types.hpp
index f53f842..98e92ce 100644
--- a/extension/src/openvic2/Types.hpp
+++ b/extension/src/openvic2/Types.hpp
@@ -22,6 +22,9 @@ namespace OpenVic2 {
public:
HasIdentifier(HasIdentifier const&) = delete;
HasIdentifier(HasIdentifier&&) = default;
+ HasIdentifier& operator=(HasIdentifier const&) = delete;
+ HasIdentifier& operator=(HasIdentifier&&) = delete;
+
std::string const& get_identifier() const;
};
diff --git a/game/src/GameSession/MapView.gd b/game/src/GameSession/MapView.gd
index 510d70a..e74ea59 100644
--- a/game/src/GameSession/MapView.gd
+++ b/game/src/GameSession/MapView.gd
@@ -41,7 +41,6 @@ var _mouse_over_viewport : bool = true
var _map_mesh : MapMesh
var _map_shader_material : ShaderMaterial
var _map_image_size : Vector2
-var _map_province_index_image : Image
var _map_province_colour_image : Image
var _map_province_colour_texture : ImageTexture
var _map_mesh_corner : Vector2
@@ -77,12 +76,15 @@ func _ready():
return
_map_shader_material = map_material
- # Province index texture
- _map_province_index_image = GameSingleton.get_province_index_image()
- if _map_province_index_image == null:
+ # Province index textures
+ var map_province_index_images := GameSingleton.get_province_index_images()
+ if map_province_index_images == null or map_province_index_images.is_empty():
push_error("Failed to get province index image!")
return
- var province_index_texture := ImageTexture.create_from_image(_map_province_index_image)
+ var province_index_texture := Texture2DArray.new()
+ if province_index_texture.create_from_images(map_province_index_images) != OK:
+ push_error("Failed to generate province index texture array!")
+ return
_map_shader_material.set_shader_parameter(_shader_param_province_index, province_index_texture)
# Province colour texture
diff --git a/game/src/GameSession/TerrainMap.gdshader b/game/src/GameSession/TerrainMap.gdshader
index 9ce1a24..305a34b 100644
--- a/game/src/GameSession/TerrainMap.gdshader
+++ b/game/src/GameSession/TerrainMap.gdshader
@@ -5,7 +5,7 @@ render_mode unshaded;
// Cosmetic farmlands terrain texture
uniform sampler2D farmlands_tex: source_color, repeat_enable, filter_linear;
// Province index texture
-uniform sampler2D province_index_tex : source_color, repeat_enable, filter_nearest;
+uniform sampler2DArray province_index_tex : source_color, repeat_enable, filter_nearest;
// Province colour texture
uniform sampler2D province_colour_tex: source_color, repeat_enable, filter_nearest;
// Index of the mouse over the map mesh
@@ -18,23 +18,20 @@ uniform float terrain_tile_factor;
uvec2 vec2_to_uvec2(vec2 v) {
return uvec2(v * 255.0);
}
-
+uvec2 read_uvec2(vec2 uv) {
+ float width_divisions = float(textureSize(province_index_tex, 0).z);
+ uv.x *= width_divisions;
+ float idx = mod(floor(uv.x), width_divisions);
+ return vec2_to_uvec2(texture(province_index_tex, vec3(uv, idx)).rg);
+}
uint uvec2_to_uint(uvec2 v) {
return (v.y << 8u) | v.x;
}
-uvec2 read_uvec2(sampler2D tex, vec2 uv) {
- return vec2_to_uvec2(texture(tex, uv).rg);
-}
-
-uint read_uint16(sampler2D tex, vec2 uv) {
- return uvec2_to_uint(read_uvec2(tex, uv));
-}
-
const vec3 water_colour = vec3(0, 0, 1);
vec3 get_terrain_colour(vec2 uv, vec2 corner, vec2 half_pixel_size, vec2 terrain_uv) {
- uvec2 index_split = read_uvec2(province_index_tex, fma(corner, half_pixel_size, uv));
+ uvec2 index_split = read_uvec2(fma(corner, half_pixel_size, uv));
uint index = uvec2_to_uint(index_split);
vec4 province_data = texelFetch(province_colour_tex, ivec2(index_split), 0);
vec3 province_colour = province_data.rgb;
@@ -47,8 +44,8 @@ vec3 get_terrain_colour(vec2 uv, vec2 corner, vec2 half_pixel_size, vec2 terrain
}
vec3 mix_terrain_colour(vec2 uv) {
- vec2 map_size = vec2(textureSize(province_index_tex, 0));
- vec2 pixel_offset = mod(fma(uv, map_size, vec2(0.5)), 1.0);
+ vec2 map_size = vec2(textureSize(province_index_tex, 0).xy);
+ vec2 pixel_offset = fract(fma(uv, map_size, vec2(0.5)));
vec2 half_pixel_size = 0.49 / map_size;
vec2 terrain_uv = uv;