Browse Source

Merge pull request #45752 from JFonS/cpu_lightmapper_fixes

Assorted CPU lightmapper fixes
Rémi Verschelde 4 years ago
parent
commit
f36c529ad0

+ 27 - 8
modules/lightmapper_cpu/lightmapper_cpu.cpp

@@ -393,11 +393,11 @@ Vector3 LightmapperCPU::_fix_sample_position(const Vector3 &p_position, const Ve
 			Vector3 target = p_texel_center + rotated_offset;
 			Vector3 target = p_texel_center + rotated_offset;
 			Vector3 ray_vector = target - corrected;
 			Vector3 ray_vector = target - corrected;
 
 
-			Vector3 ray_back_offset = -ray_vector.normalized() * parameters.bias;
+			Vector3 ray_back_offset = -ray_vector.normalized() * parameters.bias / 2.0;
 			Vector3 ray_origin = corrected + ray_back_offset;
 			Vector3 ray_origin = corrected + ray_back_offset;
 			ray_vector = target - ray_origin;
 			ray_vector = target - ray_origin;
 			float ray_length = ray_vector.length();
 			float ray_length = ray_vector.length();
-			LightmapRaycaster::Ray ray(ray_origin + p_normal * parameters.bias, ray_vector.normalized(), 0.0f, ray_length + parameters.bias);
+			LightmapRaycaster::Ray ray(ray_origin + p_normal * parameters.bias, ray_vector.normalized(), 0.0f, ray_length + parameters.bias / 2.0);
 
 
 			bool hit = raycaster->intersect(ray);
 			bool hit = raycaster->intersect(ray);
 			if (hit) {
 			if (hit) {
@@ -476,8 +476,10 @@ void LightmapperCPU::_plot_triangle(const Vector2 *p_vertices, const Vector3 *p_
 		Vector2 p = centroid;
 		Vector2 p = centroid;
 		p[i] += 1;
 		p[i] += 1;
 		Vector3 bary = Geometry::barycentric_coordinates_2d(p, v0, v1, v2);
 		Vector3 bary = Geometry::barycentric_coordinates_2d(p, v0, v1, v2);
-		Vector3 pos = p0 * bary[0] + p1 * bary[1] + p2 * bary[2];
-		texel_size[i] = centroid_pos.distance_to(pos);
+		if (bary.length() <= 1.0) {
+			Vector3 pos = p0 * bary[0] + p1 * bary[1] + p2 * bary[2];
+			texel_size[i] = centroid_pos.distance_to(pos);
+		}
 	}
 	}
 
 
 	Vector<Vector2> pixel_polygon;
 	Vector<Vector2> pixel_polygon;
@@ -676,7 +678,7 @@ void LightmapperCPU::_plot_triangle(const Vector2 *p_vertices, const Vector3 *p_
 			Vector2 texel_center = Vector2(i, j) + Vector2(0.5f, 0.5f);
 			Vector2 texel_center = Vector2(i, j) + Vector2(0.5f, 0.5f);
 			Vector3 texel_center_bary = Geometry::barycentric_coordinates_2d(texel_center, v0, v1, v2);
 			Vector3 texel_center_bary = Geometry::barycentric_coordinates_2d(texel_center, v0, v1, v2);
 
 
-			if (!Math::is_nan(texel_center_bary.x) && !Math::is_nan(texel_center_bary.y) && !Math::is_nan(texel_center_bary.z) && !Math::is_inf(texel_center_bary.x) && !Math::is_inf(texel_center_bary.y) && !Math::is_inf(texel_center_bary.z)) {
+			if (texel_center_bary.length_squared() <= 1.3 && !Math::is_nan(texel_center_bary.x) && !Math::is_nan(texel_center_bary.y) && !Math::is_nan(texel_center_bary.z) && !Math::is_inf(texel_center_bary.x) && !Math::is_inf(texel_center_bary.y) && !Math::is_inf(texel_center_bary.z)) {
 				Vector3 texel_center_pos = p0 * texel_center_bary[0] + p1 * texel_center_bary[1] + p2 * texel_center_bary[2];
 				Vector3 texel_center_pos = p0 * texel_center_bary[0] + p1 * texel_center_bary[1] + p2 * texel_center_bary[2];
 				pos = _fix_sample_position(pos, texel_center_pos, normal, tangent, bitangent, texel_size);
 				pos = _fix_sample_position(pos, texel_center_pos, normal, tangent, bitangent, texel_size);
 			}
 			}
@@ -855,8 +857,8 @@ void LightmapperCPU::_compute_indirect_light(uint32_t p_idx, void *r_lightmap) {
 			unsigned int hit_mesh_id = ray.geomID;
 			unsigned int hit_mesh_id = ray.geomID;
 			const Vector2i &size = mesh_instances[hit_mesh_id].size;
 			const Vector2i &size = mesh_instances[hit_mesh_id].size;
 
 
-			int x = ray.u * size.x;
-			int y = ray.v * size.y;
+			int x = CLAMP(ray.u * size.x, 0, size.x - 1);
+			int y = CLAMP(ray.v * size.y, 0, size.y - 1);
 
 
 			const int idx = scene_lightmap_indices[hit_mesh_id][y * size.x + x];
 			const int idx = scene_lightmap_indices[hit_mesh_id][y * size.x + x];
 
 
@@ -988,7 +990,7 @@ void LightmapperCPU::_post_process(uint32_t p_idx, void *r_output) {
 void LightmapperCPU::_compute_seams(const MeshInstance &p_mesh, LocalVector<UVSeam> &r_seams) {
 void LightmapperCPU::_compute_seams(const MeshInstance &p_mesh, LocalVector<UVSeam> &r_seams) {
 	float max_uv_distance = 1.0f / MAX(p_mesh.size.x, p_mesh.size.y);
 	float max_uv_distance = 1.0f / MAX(p_mesh.size.x, p_mesh.size.y);
 	max_uv_distance *= max_uv_distance; // We use distance_to_squared(), so wee need to square the max distance as well
 	max_uv_distance *= max_uv_distance; // We use distance_to_squared(), so wee need to square the max distance as well
-	float max_pos_distance = 0.0005f;
+	float max_pos_distance = 0.00025f;
 	float max_normal_distance = 0.05f;
 	float max_normal_distance = 0.05f;
 
 
 	const Vector<Vector3> &points = p_mesh.data.points;
 	const Vector<Vector3> &points = p_mesh.data.points;
@@ -1026,9 +1028,26 @@ void LightmapperCPU::_compute_seams(const MeshInstance &p_mesh, LocalVector<UVSe
 
 
 	for (unsigned int j = 0; j < edges.size(); j++) {
 	for (unsigned int j = 0; j < edges.size(); j++) {
 		const SeamEdge &edge0 = edges[j];
 		const SeamEdge &edge0 = edges[j];
+
+		if (edge0.uv[0].distance_squared_to(edge0.uv[1]) < 0.001) {
+			continue;
+		}
+
+		if (edge0.pos[0].distance_squared_to(edge0.pos[1]) < 0.001) {
+			continue;
+		}
+
 		for (unsigned int k = j + 1; k < edges.size() && edges[k].pos[0].x < (edge0.pos[0].x + max_pos_distance * 1.1f); k++) {
 		for (unsigned int k = j + 1; k < edges.size() && edges[k].pos[0].x < (edge0.pos[0].x + max_pos_distance * 1.1f); k++) {
 			const SeamEdge &edge1 = edges[k];
 			const SeamEdge &edge1 = edges[k];
 
 
+			if (edge1.uv[0].distance_squared_to(edge1.uv[1]) < 0.001) {
+				continue;
+			}
+
+			if (edge1.pos[0].distance_squared_to(edge1.pos[1]) < 0.001) {
+				continue;
+			}
+
 			if (edge0.uv[0].distance_squared_to(edge1.uv[0]) < max_uv_distance && edge0.uv[1].distance_squared_to(edge1.uv[1]) < max_uv_distance) {
 			if (edge0.uv[0].distance_squared_to(edge1.uv[0]) < max_uv_distance && edge0.uv[1].distance_squared_to(edge1.uv[1]) < max_uv_distance) {
 				continue;
 				continue;
 			}
 			}

+ 46 - 21
scene/3d/baked_lightmap.cpp

@@ -147,6 +147,14 @@ void BakedLightmapData::clear_users() {
 	users.clear();
 	users.clear();
 }
 }
 
 
+void BakedLightmapData::clear_data() {
+	clear_users();
+	if (baked_light.is_valid()) {
+		VS::get_singleton()->free(baked_light);
+	}
+	baked_light = VS::get_singleton()->lightmap_capture_create();
+}
+
 void BakedLightmapData::_set_user_data(const Array &p_data) {
 void BakedLightmapData::_set_user_data(const Array &p_data) {
 
 
 	// Detect old lightmapper format
 	// Detect old lightmapper format
@@ -226,6 +234,7 @@ void BakedLightmapData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path);
 	ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path);
 	ClassDB::bind_method(D_METHOD("get_user_lightmap", "user_idx"), &BakedLightmapData::get_user_lightmap);
 	ClassDB::bind_method(D_METHOD("get_user_lightmap", "user_idx"), &BakedLightmapData::get_user_lightmap);
 	ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users);
 	ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users);
+	ClassDB::bind_method(D_METHOD("clear_data"), &BakedLightmapData::clear_data);
 
 
 	ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
 	ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "cell_space_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_space_transform", "get_cell_space_transform");
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "cell_space_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_space_transform", "get_cell_space_transform");
@@ -317,6 +326,9 @@ Size2i BakedLightmap::_compute_lightmap_size(const MeshesFound &p_mesh) {
 }
 }
 
 
 void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights) {
 void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights) {
+
+	AABB bounds = AABB(-extents, extents * 2.0);
+
 	MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
 	MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
 	if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) {
 	if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) {
 		Ref<Mesh> mesh = mi->get_mesh();
 		Ref<Mesh> mesh = mi->get_mesh();
@@ -339,27 +351,34 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound>
 			}
 			}
 
 
 			if (surfaces_found && all_have_uv2_and_normal) {
 			if (surfaces_found && all_have_uv2_and_normal) {
-				MeshesFound mf;
-				mf.cast_shadows = mi->get_cast_shadows_setting() != GeometryInstance::SHADOW_CASTING_SETTING_OFF;
-				mf.generate_lightmap = mi->get_generate_lightmap();
-				mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform();
-				mf.node_path = get_path_to(mi);
-				mf.subindex = -1;
-				mf.mesh = mesh;
 
 
-				static const int lightmap_scale[4] = { 1, 2, 4, 8 }; //GeometryInstance3D::LIGHTMAP_SCALE_MAX = { 1, 2, 4, 8 };
-				mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()];
+				Transform mesh_xform = get_global_transform().affine_inverse() * mi->get_global_transform();
 
 
-				Ref<Material> all_override = mi->get_material_override();
-				for (int i = 0; i < mesh->get_surface_count(); i++) {
-					if (all_override.is_valid()) {
-						mf.overrides.push_back(all_override);
-					} else {
-						mf.overrides.push_back(mi->get_surface_material(i));
+				AABB aabb = mesh_xform.xform(mesh->get_aabb());
+
+				if (bounds.intersects(aabb)) {
+					MeshesFound mf;
+					mf.cast_shadows = mi->get_cast_shadows_setting() != GeometryInstance::SHADOW_CASTING_SETTING_OFF;
+					mf.generate_lightmap = mi->get_generate_lightmap();
+					mf.xform = mesh_xform;
+					mf.node_path = get_path_to(mi);
+					mf.subindex = -1;
+					mf.mesh = mesh;
+
+					static const int lightmap_scale[4] = { 1, 2, 4, 8 }; //GeometryInstance3D::LIGHTMAP_SCALE_MAX = { 1, 2, 4, 8 };
+					mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()];
+
+					Ref<Material> all_override = mi->get_material_override();
+					for (int i = 0; i < mesh->get_surface_count(); i++) {
+						if (all_override.is_valid()) {
+							mf.overrides.push_back(all_override);
+						} else {
+							mf.overrides.push_back(mi->get_surface_material(i));
+						}
 					}
 					}
-				}
 
 
-				meshes.push_back(mf);
+					meshes.push_back(mf);
+				}
 			}
 			}
 		}
 		}
 	}
 	}
@@ -383,10 +402,16 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound>
 					continue;
 					continue;
 				}
 				}
 
 
-				MeshesFound mf;
+				Transform mesh_xform = xf * bmeshes[i + 1];
 
 
-				Transform mesh_xf = bmeshes[i + 1];
-				mf.xform = xf * mesh_xf;
+				AABB aabb = mesh_xform.xform(mesh->get_aabb());
+
+				if (!bounds.intersects(aabb)) {
+					continue;
+				}
+
+				MeshesFound mf;
+				mf.xform = mesh_xform;
 				mf.node_path = get_path_to(s);
 				mf.node_path = get_path_to(s);
 				mf.subindex = i / 2;
 				mf.subindex = i / 2;
 				mf.lightmap_scale = 1;
 				mf.lightmap_scale = 1;
@@ -770,7 +795,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_data_sa
 	if (get_light_data().is_valid()) {
 	if (get_light_data().is_valid()) {
 		data = get_light_data();
 		data = get_light_data();
 		set_light_data(Ref<BakedLightmapData>()); //clear
 		set_light_data(Ref<BakedLightmapData>()); //clear
-		data->clear_users();
+		data->clear_data();
 	} else {
 	} else {
 		data.instance();
 		data.instance();
 	}
 	}

+ 1 - 0
scene/3d/baked_lightmap.h

@@ -91,6 +91,7 @@ public:
 	Rect2 get_user_lightmap_uv_rect(int p_user) const;
 	Rect2 get_user_lightmap_uv_rect(int p_user) const;
 	int get_user_instance(int p_user) const;
 	int get_user_instance(int p_user) const;
 	void clear_users();
 	void clear_users();
+	void clear_data();
 
 
 	virtual RID get_rid() const;
 	virtual RID get_rid() const;
 	BakedLightmapData();
 	BakedLightmapData();