Explorar o código

Merge pull request #58102 from JFonS/big_lightmap

Rémi Verschelde %!s(int64=3) %!d(string=hai) anos
pai
achega
9343c66815
Modificáronse 2 ficheiros con 61 adicións e 70 borrados
  1. 22 22
      modules/lightmapper_cpu/lightmapper_cpu.cpp
  2. 39 48
      scene/3d/baked_lightmap.cpp

+ 22 - 22
modules/lightmapper_cpu/lightmapper_cpu.cpp

@@ -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 (parameters.bounces > 0) {
+		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 (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;
+			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;
+				}
 			}
 		}
 	}

+ 39 - 48
scene/3d/baked_lightmap.cpp

@@ -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();
+
+		int slices_per_texture = Image::MAX_HEIGHT / slice_height;
+		int texture_count = Math::ceil(slice_count / (float)slices_per_texture);
 
-		Ref<TextureLayered> 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");
-
-			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;
-			}
-
-			if (!tex.is_valid()) {
-				tex.instance();
-			}
+			config->set_value("params", "slices/vertical", texture_slice_count);
 
-			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);
-			}
+			config->save(texture_path + ".import");
 
-			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++) {