Merge pull request #58102 from JFonS/big_lightmap

This commit is contained in:
Rémi Verschelde 2022-02-15 17:47:20 +01:00 committed by GitHub
commit 9343c66815
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 71 deletions

View file

@ -166,15 +166,13 @@ Error LightmapperCPU::_layout_atlas(int p_max_size, Vector2i *r_atlas_size, int
}
float mem_utilization = static_cast<float>(mem_occupied) / mem_used;
if (slices * atlas_size.y <= 16384) { // Maximum Image size
if (mem_used < best_atlas_memory || (mem_used == best_atlas_memory && mem_utilization > best_atlas_mem_utilization)) {
best_atlas_size = atlas_size;
best_atlas_offsets = curr_atlas_offsets;
best_atlas_slices = slices;
best_atlas_memory = mem_used;
best_atlas_mem_utilization = mem_utilization;
best_scaled_sizes = scaled_sizes;
}
if (mem_used < best_atlas_memory || (mem_used == best_atlas_memory && mem_utilization > best_atlas_mem_utilization)) {
best_atlas_size = atlas_size;
best_atlas_offsets = curr_atlas_offsets;
best_atlas_slices = slices;
best_atlas_memory = mem_used;
best_atlas_mem_utilization = mem_utilization;
best_scaled_sizes = scaled_sizes;
}
if (recovery_percent == 0) {
@ -1430,22 +1428,24 @@ LightmapperCPU::BakeError LightmapperCPU::bake(BakeQuality p_quality, bool p_use
parameters.environment_panorama->lock();
}
for (unsigned int i = 0; i < mesh_instances.size(); i++) {
if (!mesh_instances[i].generate_lightmap) {
continue;
}
if (p_step_function) {
float p = float(i) / n_lit_meshes;
bool cancelled = p_step_function(0.4 + p * 0.4, vformat("%s (%d/%d)", TTR("Indirect lighting"), i, mesh_instances.size()), p_bake_userdata, false);
if (cancelled) {
return BAKE_ERROR_USER_ABORTED;
if (parameters.bounces > 0) {
for (unsigned int i = 0; i < mesh_instances.size(); i++) {
if (!mesh_instances[i].generate_lightmap) {
continue;
}
}
if (!scene_lightmaps[i].empty()) {
if (_parallel_run(scene_lightmaps[i].size(), "Computing indirect light", &LightmapperCPU::_compute_indirect_light, scene_lightmaps[i].ptr(), p_substep_function)) {
return BAKE_ERROR_USER_ABORTED;
if (p_step_function) {
float p = float(i) / n_lit_meshes;
bool cancelled = p_step_function(0.4 + p * 0.4, vformat("%s (%d/%d)", TTR("Indirect lighting"), i, mesh_instances.size()), p_bake_userdata, false);
if (cancelled) {
return BAKE_ERROR_USER_ABORTED;
}
}
if (!scene_lightmaps[i].empty()) {
if (_parallel_run(scene_lightmaps[i].size(), "Computing indirect light", &LightmapperCPU::_compute_indirect_light, scene_lightmaps[i].ptr(), p_substep_function)) {
return BAKE_ERROR_USER_ABORTED;
}
}
}
}

View file

@ -954,23 +954,35 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_data_sa
bool use_srgb = use_color && !use_hdr;
if (gen_atlas) {
Ref<Image> large_image;
large_image.instance();
large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format());
for (int i = 0; i < images.size(); i++) {
large_image->blit_rect(images[i], Rect2(0, 0, images[0]->get_width(), images[0]->get_height()), Point2(0, images[0]->get_height() * i));
}
int slice_count = images.size();
int slice_width = images[0]->get_width();
int slice_height = images[0]->get_height();
Ref<TextureLayered> texture;
int slices_per_texture = Image::MAX_HEIGHT / slice_height;
int texture_count = Math::ceil(slice_count / (float)slices_per_texture);
Vector<Ref<TextureLayered>> textures;
textures.resize(texture_count);
String base_path = p_data_save_path.get_basename();
if (ResourceLoader::import) {
_save_image(base_path, large_image, use_srgb);
int last_count = slice_count % slices_per_texture;
for (int i = 0; i < texture_count; i++) {
String texture_path = texture_count > 1 ? base_path + "_" + itos(i) : base_path;
int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture;
Ref<Image> large_image;
large_image.instance();
large_image->create(slice_width, slice_height * texture_slice_count, false, images[0]->get_format());
for (int j = 0; j < texture_slice_count; j++) {
large_image->blit_rect(images[i * slices_per_texture + j], Rect2(0, 0, slice_width, slice_height), Point2(0, slice_height * j));
}
_save_image(texture_path, large_image, use_srgb);
Ref<ConfigFile> config;
config.instance();
if (FileAccess::exists(base_path + ".import")) {
config->load(base_path + ".import");
if (FileAccess::exists(texture_path + ".import")) {
config->load(texture_path + ".import");
} else {
// Set only if settings don't exist, to keep user choice
config->set_value("params", "compress/mode", 0);
@ -983,49 +995,28 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_data_sa
config->set_value("params", "flags/mipmaps", false);
config->set_value("params", "flags/srgb", use_srgb);
config->set_value("params", "slices/horizontal", 1);
config->set_value("params", "slices/vertical", images.size());
config->save(base_path + ".import");
config->set_value("params", "slices/vertical", texture_slice_count);
ResourceLoader::import(base_path);
texture = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus?
} else {
base_path += ".texarr";
Ref<TextureLayered> tex;
bool set_path = true;
if (ResourceCache::has(base_path)) {
tex = Ref<Resource>((Resource *)ResourceCache::get(base_path));
set_path = false;
}
config->save(texture_path + ".import");
if (!tex.is_valid()) {
tex.instance();
}
tex->create(images[0]->get_width(), images[0]->get_height(), images.size(), images[0]->get_format(), Texture::FLAGS_DEFAULT);
for (int i = 0; i < images.size(); i++) {
tex->set_layer_data(images[i], i);
}
ResourceSaver::save(base_path, tex, ResourceSaver::FLAG_CHANGE_PATH);
if (set_path) {
tex->set_path(base_path);
}
texture = tex;
ResourceLoader::import(texture_path);
textures.write[i] = ResourceLoader::load(texture_path); //if already loaded, it will be updated on refocus?
}
for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
if (meshes_found[i].generate_lightmap) {
Dictionary d = lightmapper->get_bake_mesh_userdata(i);
NodePath np = d["path"];
int32_t subindex = -1;
if (d.has("subindex")) {
subindex = d["subindex"];
}
Rect2 uv_rect = lightmapper->get_bake_mesh_uv_scale(i);
int slice_index = lightmapper->get_bake_mesh_texture_slice(i);
data->add_user(np, texture, slice_index, uv_rect, subindex);
if (!meshes_found[i].generate_lightmap) {
continue;
}
Dictionary d = lightmapper->get_bake_mesh_userdata(i);
NodePath np = d["path"];
int32_t subindex = -1;
if (d.has("subindex")) {
subindex = d["subindex"];
}
Rect2 uv_rect = lightmapper->get_bake_mesh_uv_scale(i);
int slice_index = lightmapper->get_bake_mesh_texture_slice(i);
data->add_user(np, textures[slice_index / slices_per_texture], slice_index % slices_per_texture, uv_rect, subindex);
}
} else {
for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {