Skip to content

Commit

Permalink
Update texture array layers individually
Browse files Browse the repository at this point in the history
  • Loading branch information
Xtarsia authored and TokisanGames committed Sep 25, 2024
1 parent 8827714 commit 6602769
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 6 deletions.
5 changes: 5 additions & 0 deletions src/generated_texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ RID GeneratedTexture::create(const TypedArray<Image> &p_layers) {
return _rid;
}

void GeneratedTexture::update(const Ref<Image> &p_image, const int &p_layer) {
LOG(EXTREME, "RenderingServer updating Texture2DArray at index: ", p_layer);
RS->texture_2d_update(_rid, p_image, p_layer);
}

RID GeneratedTexture::create(const Ref<Image> &p_image) {
LOG(EXTREME, "RenderingServer creating Texture2D");
_image = p_image;
Expand Down
1 change: 1 addition & 0 deletions src/generated_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class GeneratedTexture {
void clear();
bool is_dirty() const { return _dirty; }
RID create(const TypedArray<Image> &p_layers);
void update(const Ref<Image> &p_image, const int &p_layer);
RID create(const Ref<Image> &p_image);
Ref<Image> get_image() const { return _image; }
RID get_rid() const { return _rid; }
Expand Down
28 changes: 27 additions & 1 deletion src/terrain_3d_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ void Terrain3DData::force_update_maps(const MapType p_map_type, const bool p_gen
update_maps();
}

void Terrain3DData::update_maps() {
void Terrain3DData::update_maps(const MapType p_map_type) {
bool any_changed = false;

if (_region_map_dirty) {
Expand Down Expand Up @@ -545,6 +545,32 @@ void Terrain3DData::update_maps() {

if (any_changed) {
emit_signal("maps_changed");
} else {
// If no maps have been rebuilt, it's safe to update individual layers. Regions marked Edited
// have either been recently changed by Terrain3DEditor::_operate_map or were marked by undo / redo.
for (int i = 0; i < _region_locations.size(); i++) {
Vector2i region_loc = _region_locations[i];
Ref<Terrain3DRegion> region = _regions[region_loc];
if (region->is_edited()) {
int region_id = get_region_id(region_loc);
switch (p_map_type) {
case TYPE_HEIGHT:
_generated_height_maps.update(region->get_height_map(), region_id);
break;
case TYPE_CONTROL:
_generated_control_maps.update(region->get_control_map(), region_id);
break;
case TYPE_COLOR:
_generated_color_maps.update(region->get_color_map(), region_id);
break;
default:
_generated_height_maps.update(region->get_height_map(), region_id);
_generated_control_maps.update(region->get_control_map(), region_id);
_generated_color_maps.update(region->get_color_map(), region_id);
break;
}
}
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/terrain_3d_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ class Terrain3DData : public Object {
TypedArray<Image> get_color_maps() const { return _color_maps; }
TypedArray<Image> get_maps(const MapType p_map_type) const;

void force_update_maps(const MapType p_map = TYPE_MAX, const bool p_generate_mipmaps = false);
void update_maps();
void force_update_maps(const MapType p_map_type = TYPE_MAX, const bool p_generate_mipmaps = false);
void update_maps(const MapType p_map_type = TYPE_MAX);

RID get_height_maps_rid() const { return _generated_height_maps.get_rid(); }
RID get_control_maps_rid() const { return _generated_control_maps.get_rid(); }
RID get_color_maps_rid() const { return _generated_color_maps.get_rid(); }
Expand Down
32 changes: 29 additions & 3 deletions src/terrain_3d_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ void Terrain3DEditor::_operate_map(const Vector3 &p_global_position, const real_

// MAP Operations
real_t vertex_spacing = _terrain->get_vertex_spacing();

// save region count before brush pixel loop. Any regions added will have caused an Array
// rebuild at the end of the last _operate() call, but until painting is finished we only
// need to track if _added_removed_locations has changed between now and the end of the loop
int regions_added_removed = _added_removed_locations.size();

for (real_t x = 0.f; x < brush_size; x += vertex_spacing) {
for (real_t y = 0.f; y < brush_size; y += vertex_spacing) {
Vector2 brush_offset = Vector2(x, y) - (Vector2(brush_size, brush_size) / 2.f);
Expand Down Expand Up @@ -459,7 +465,13 @@ void Terrain3DEditor::_operate_map(const Vector3 &p_global_position, const real_
region->get_map(map_type)->generate_mipmaps();
}
}
data->force_update_maps(map_type);
// If no added or removed regions, update only changed texture array layers from the edited regions in the rendering server
if (_added_removed_locations.size() == regions_added_removed) {
data->update_maps(map_type);
} else {
// If region qty was changed, must fully rebuild the maps
data->force_update_maps(map_type);
}
data->add_edited_area(edited_area);
}

Expand Down Expand Up @@ -537,6 +549,8 @@ void Terrain3DEditor::_apply_undo(const Dictionary &p_data) {
Dictionary regions = data->get_regions_all();
regions[region->get_location()] = region;
region->set_modified(true);
// Tell update_maps() this region has layers that can be individually updated
region->set_edited(true);
LOG(DEBUG, "Edited: ", region->get_data());
}
}
Expand Down Expand Up @@ -567,8 +581,20 @@ void Terrain3DEditor::_apply_undo(const Dictionary &p_data) {
Array locations = data->get_region_locations();
LOG(DEBUG, "Locations(", locations.size(), "): ", locations);
}

data->force_update_maps();
// If this undo set modifies the region qty, we must rebuild the arrays. Otherwise we can update individual layers
if (p_data.has("added_regions") || p_data.has("removed_regions")) {
data->force_update_maps();
} else {
data->update_maps();
}
// After TextureArray updates clear edited regions flag.
if (p_data.has("edited_regions")) {
TypedArray<Terrain3DRegion> undo_regions = p_data["edited_regions"];
for (int i = 0; i < undo_regions.size(); i++) {
Ref<Terrain3DRegion> region = undo_regions[i];
region->set_edited(false);
}
}
_terrain->get_instancer()->force_update_mmis();
if (_terrain->get_plugin()->has_method("update_grid")) {
LOG(DEBUG, "Calling GDScript update_grid()");
Expand Down

0 comments on commit 6602769

Please sign in to comment.