Repository: godotengine/godot
File: servers/rendering/renderer_scene_cull.cpp (C++)

Code before:
											RSG::light_storage->light_get_param(E->base, RS::LightParam::LIGHT_PARAM_RANGE) *
											RSG::light_storage->light_get_param(E->base, RS::LightParam::LIGHT_PARAM_ENERGY);
									float light_inst_score = mesh_center.distance_to(light_center) / MAX(0.01f, light_range_energy);
									//	Keep the best per-light-type
									switch (light_type) {
										case RS::LIGHT_OMNI: {
											if (omni_count < max_per_mesh_total.first) {
												//	We have room to just add it, and track the score and where it goes
												omni_score_idx.push_back(Pair(light_inst_score, omni_count));
												geom->geometry_instance->pair_light_instance(light->instance, light_type, omni_count++);
											} else {
												if (omni_needs_heap) {
													//	We need to make this a heap one time
													heapify.make_heap(0, omni_count, &omni_score_idx[0]);
													omni_needs_heap = false;
												}
												if (light_inst_score < omni_score_idx[0].first) {
													uint32_t replace_index = omni_score_idx[0].second;
													geom->geometry_instance->pair_light_instance(light->instance, light_type, replace_index);
													heapify.adjust_heap(0, 0, omni_count, Pair(light_inst_score, replace_index), &omni_score_idx[0]);
												}
											}
										} break;
										case RS::LIGHT_SPOT: {
											if (spot_count < max_per_mesh_total.first) {
												//	We have room to just add it, and track the score and where it goes
												spot_score_idx.push_back(Pair(light_inst_score, spot_count));
												geom->geometry_instance->pair_light_instance(light->instance, light_type, spot_count++);
											} else {
												if (spot_needs_heap) {
													//	We need to make this a heap one time
													heapify.make_heap(0, spot_count, &spot_score_idx[0]);
													spot_needs_heap = false;
												}
												if (light_inst_score < spot_score_idx[0].first) {
													uint32_t replace_index = spot_score_idx[0].second;
													geom->geometry_instance->pair_light_instance(light->instance, light_type, replace_index);
													heapify.adjust_heap(0, 0, spot_count, Pair(light_inst_score, replace_index), &spot_score_idx[0]);
												}
											}
										} break;
										default:
											break;
									}
								}
							}
						}
						idata.flags &= ~InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
					}

					if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {

Review comment (suggestion):
```suggestion
												// We have room to just add it, and track the score and where it goes.
```

Code after:
									if (!(RSG::light_storage->light_get_cull_mask(E->base) & idata.layer_mask)) {
										continue;
									}
									if ((RSG::light_storage->light_get_bake_mode(E->base) == RS::LIGHT_BAKE_STATIC) && idata.instance->lightmap) {
										continue;
									}

									InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);
									// Large scores are worse, so linear with distance, inverse with energy and range.
									Vector3 light_center = E->transformed_aabb.get_center();
									float light_range_energy =
											RSG::light_storage->light_get_param(E->base, RS::LightParam::LIGHT_PARAM_RANGE) *
											RSG::light_storage->light_get_param(E->base, RS::LightParam::LIGHT_PARAM_ENERGY);
									float light_inst_score = mesh_center.distance_to(light_center) / MAX(0.01f, light_range_energy);
									// Of the N lights (on a per-light-type basis, Omni or Spot) keep only the M "best" lights.
									// If N <= M, we can simply store the lights, but once we exceed M, we need check each new
									// light and see if it's score is better than the worst light stored to date.  If the new
									// light is better, we can replace the current worst light with the new one.  In order to
									// efficiently track our currently worst light we use a "max heap".  This loosely orders
									// the elements in an array as a binary-tree structure, and has the properties that finding
									// the worst score element is O(1) (it will always be stored in element [0]), and removing
									// the old max and inserting a new value is O(log M).
#define VERIFY_RELEVANT_LIGHT_HEAP 0
#if VERIFY_RELEVANT_LIGHT_HEAP
									WARN_PRINT_ONCE("VERIFY_RELEVANT_LIGHT_HEAP is True");
#endif
									switch (light_type) {
										case RS::LIGHT_OMNI: {
											if (omni_count < max_lights_per_mesh) {
												// We have room to just add it, and track the score and where it goes.
												omni_score_idx.push_back(Pair(light_inst_score, omni_count));
												geom->geometry_instance->pair_light_instance(light->instance, light_type, omni_count++);
											} else {
												if (omni_needs_heap) {
													// We need to make this a heap one time.
													heapify.make_heap(0, omni_count, &omni_score_idx[0]);
													omni_needs_heap = false;
												}
												if (light_inst_score < omni_score_idx[0].first) {
#if VERIFY_RELEVANT_LIGHT_HEAP
													// The [0] element should have the max score.
													for (uint32_t vi = 1; vi < max_lights_per_mesh; ++vi) {
														if (omni_score_idx[vi].first > omni_score_idx[0].first) {
															ERR_PRINT_ONCE("Relevant Omni Light Heap Error");
														}
													}
#endif
													uint32_t replace_index = omni_score_idx[0].second;
													geom->geometry_instance->pair_light_instance(light->instance, light_type, replace_index);
													heapify.adjust_heap(0, 0, omni_count, Pair(light_inst_score, replace_index), &omni_score_idx[0]);
												}