Jelajahi Sumber

Merge pull request #107145 from BlueCube3310/light-shadowmask-sort

LightmapGI: Search for shadowmask light index only after sorting the lights
Rémi Verschelde 3 bulan lalu
induk
melakukan
a54286197e

+ 44 - 21
modules/lightmapper_rd/lightmapper_rd.cpp

@@ -79,7 +79,11 @@ void LightmapperRD::add_directional_light(const String &p_name, bool p_static, c
 	l.size = Math::tan(Math::deg_to_rad(p_angular_distance));
 	l.shadow_blur = p_shadow_blur;
 	lights.push_back(l);
-	light_names.push_back(p_name);
+
+	LightMetadata md;
+	md.name = p_name;
+	md.type = LIGHT_TYPE_DIRECTIONAL;
+	light_metadata.push_back(md);
 }
 
 void LightmapperRD::add_omni_light(const String &p_name, bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) {
@@ -99,7 +103,11 @@ void LightmapperRD::add_omni_light(const String &p_name, bool p_static, const Ve
 	l.size = p_size;
 	l.shadow_blur = p_shadow_blur;
 	lights.push_back(l);
-	light_names.push_back(p_name);
+
+	LightMetadata md;
+	md.name = p_name;
+	md.type = LIGHT_TYPE_OMNI;
+	light_metadata.push_back(md);
 }
 
 void LightmapperRD::add_spot_light(const String &p_name, bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) {
@@ -124,7 +132,11 @@ void LightmapperRD::add_spot_light(const String &p_name, bool p_static, const Ve
 	l.size = p_size;
 	l.shadow_blur = p_shadow_blur;
 	lights.push_back(l);
-	light_names.push_back(p_name);
+
+	LightMetadata md;
+	md.name = p_name;
+	md.type = LIGHT_TYPE_SPOT;
+	light_metadata.push_back(md);
 }
 
 void LightmapperRD::add_probe(const Vector3 &p_position) {
@@ -620,6 +632,7 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i
 	/*****************************/
 
 	lights.sort();
+	light_metadata.sort();
 
 	Vector<Vector2i> seam_buffer_vec;
 	seam_buffer_vec.resize(seams.size() * 2);
@@ -1083,32 +1096,19 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 		return bake_error;
 	}
 
-	// The index of the directional light used for shadowmasking.
-	int shadowmask_light_idx = -1;
-
-	// If there are no valid directional lights for shadowmasking, the entire
-	// scene would be shadowed and this saves baking time.
+	// Find any directional light suitable for shadowmasking.
 	if (p_bake_shadowmask) {
-		int shadowmask_lights_count = 0;
-
+		bool found = false;
 		for (int i = 0; i < lights.size(); i++) {
 			if (lights[i].type == LightType::LIGHT_TYPE_DIRECTIONAL && !lights[i].static_bake) {
-				if (shadowmask_light_idx < 0) {
-					shadowmask_light_idx = i;
-				}
-
-				shadowmask_lights_count += 1;
+				found = true;
+				break;
 			}
 		}
 
-		if (shadowmask_light_idx < 0) {
+		if (!found) {
 			p_bake_shadowmask = false;
 			WARN_PRINT("Shadowmask disabled: no directional light with their bake mode set to dynamic exists.");
-
-		} else if (shadowmask_lights_count > 1) {
-			WARN_PRINT(
-					vformat("%d directional lights detected for shadowmask baking. Only %s will be used.",
-							shadowmask_lights_count, light_names[shadowmask_light_idx]));
 		}
 	}
 
@@ -1300,6 +1300,29 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 	const uint32_t cluster_size = 16;
 	_create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, cluster_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, lights_buffer, triangle_indices_buffer, cluster_indices_buffer, cluster_aabbs_buffer, probe_positions_buffer, grid_texture, seams_buffer, p_step_function, p_bake_userdata);
 
+	// The index of the directional light used for shadowmasking.
+	int shadowmask_light_idx = -1;
+
+	// Find the directional light index in the sorted lights array.
+	if (p_bake_shadowmask) {
+		int shadowmask_lights_count = 0;
+
+		for (int i = 0; i < lights.size(); i++) {
+			if (lights[i].type == LightType::LIGHT_TYPE_DIRECTIONAL && !lights[i].static_bake) {
+				if (shadowmask_light_idx < 0) {
+					shadowmask_light_idx = i;
+				}
+				shadowmask_lights_count += 1;
+			}
+		}
+
+		if (shadowmask_lights_count > 1) {
+			WARN_PRINT(
+					vformat("%d directional lights detected for shadowmask baking. Only %s will be used.",
+							shadowmask_lights_count, light_metadata[shadowmask_light_idx].name));
+		}
+	}
+
 	// Create global bake parameters buffer.
 	BakeParameters bake_parameters;
 	bake_parameters.world_size[0] = bounds.size.x;

+ 10 - 1
modules/lightmapper_rd/lightmapper_rd.h

@@ -88,6 +88,15 @@ class LightmapperRD : public Lightmapper {
 		}
 	};
 
+	struct LightMetadata {
+		String name;
+		uint32_t type = LIGHT_TYPE_DIRECTIONAL;
+
+		bool operator<(const LightMetadata &p_light) const {
+			return type < p_light.type;
+		}
+	};
+
 	struct Vertex {
 		float position[3] = {};
 		float normal_z = 0.0;
@@ -203,7 +212,7 @@ class LightmapperRD : public Lightmapper {
 	Vector<MeshInstance> mesh_instances;
 
 	Vector<Light> lights;
-	Vector<String> light_names;
+	Vector<LightMetadata> light_metadata;
 
 	struct TriangleSort {
 		uint32_t cell_index = 0;