Browse Source

Merge pull request #100241 from lander-vr/reflection-probe-priority

Add priority-based blending to reflection probes.
Rémi Verschelde 7 months ago
parent
commit
084da581be

+ 11 - 2
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -124,14 +124,23 @@ void RenderForwardMobile::fill_push_constant_instance_indices(SceneState::Instan
 	p_instance_data->reflection_probes[0] = 0xFFFFFFFF;
 	p_instance_data->reflection_probes[0] = 0xFFFFFFFF;
 	p_instance_data->reflection_probes[1] = 0xFFFFFFFF;
 	p_instance_data->reflection_probes[1] = 0xFFFFFFFF;
 
 
+	ForwardIDByMapSort sorted_reflection_probes[MAX_RDL_CULL];
+	for (uint32_t i = 0; i < p_instance->reflection_probe_count; i++) {
+		sorted_reflection_probes[i].forward_id = p_instance->reflection_probes[i];
+		sorted_reflection_probes[i].map = forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]];
+	}
+
+	SortArray<ForwardIDByMapSort> sort_array;
+	sort_array.sort(sorted_reflection_probes, p_instance->reflection_probe_count);
+
 	idx = 0;
 	idx = 0;
 	for (uint32_t i = 0; i < p_instance->reflection_probe_count; i++) {
 	for (uint32_t i = 0; i < p_instance->reflection_probe_count; i++) {
 		uint32_t ofs = idx < 4 ? 0 : 1;
 		uint32_t ofs = idx < 4 ? 0 : 1;
 		uint32_t shift = (idx & 0x3) << 3;
 		uint32_t shift = (idx & 0x3) << 3;
 		uint32_t mask = ~(0xFF << shift);
 		uint32_t mask = ~(0xFF << shift);
-		if (forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].last_pass[p_instance->reflection_probes[i]] == current_frame) {
+		if (forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].last_pass[sorted_reflection_probes[i].forward_id] == current_frame) {
 			p_instance_data->reflection_probes[ofs] &= mask;
 			p_instance_data->reflection_probes[ofs] &= mask;
-			p_instance_data->reflection_probes[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift;
+			p_instance_data->reflection_probes[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[sorted_reflection_probes[i].forward_id]) << shift;
 			idx++;
 			idx++;
 		}
 		}
 	}
 	}

+ 8 - 0
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h

@@ -527,6 +527,14 @@ protected:
 		return forward_id_storage_mobile;
 		return forward_id_storage_mobile;
 	}
 	}
 
 
+	struct ForwardIDByMapSort {
+		uint8_t map;
+		RendererRD::ForwardID forward_id;
+		bool operator<(const ForwardIDByMapSort &p_sort) const {
+			return map > p_sort.map;
+		}
+	};
+
 public:
 public:
 	static RenderForwardMobile *get_singleton() { return singleton; }
 	static RenderForwardMobile *get_singleton() { return singleton; }
 
 

+ 14 - 2
servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl

@@ -1928,17 +1928,29 @@ void fragment_shader(in SceneData scene_data) {
 					continue; //not masked
 					continue; //not masked
 				}
 				}
 
 
+				if (reflection_accum.a >= 1.0 && ambient_accum.a >= 1.0) {
+					break;
+				}
+
 				reflection_process(reflection_index, vertex, ref_vec, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
 				reflection_process(reflection_index, vertex, ref_vec, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
 			}
 			}
 		}
 		}
 
 
+		if (ambient_accum.a < 1.0) {
+			ambient_accum.rgb = mix(ambient_light, ambient_accum.rgb, ambient_accum.a);
+		}
+
+		if (reflection_accum.a < 1.0) {
+			reflection_accum.rgb = mix(specular_light, reflection_accum.rgb, reflection_accum.a);
+		}
+
 		if (reflection_accum.a > 0.0) {
 		if (reflection_accum.a > 0.0) {
-			specular_light = reflection_accum.rgb / reflection_accum.a;
+			specular_light = reflection_accum.rgb;
 		}
 		}
 
 
 #if !defined(USE_LIGHTMAP)
 #if !defined(USE_LIGHTMAP)
 		if (ambient_accum.a > 0.0) {
 		if (ambient_accum.a > 0.0) {
-			ambient_light = ambient_accum.rgb / ambient_accum.a;
+			ambient_light = ambient_accum.rgb;
 		}
 		}
 #endif
 #endif
 	}
 	}

+ 16 - 3
servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl

@@ -1396,16 +1396,29 @@ void main() {
 		uvec2 reflection_indices = instances.data[draw_call.instance_index].reflection_probes;
 		uvec2 reflection_indices = instances.data[draw_call.instance_index].reflection_probes;
 		for (uint i = 0; i < sc_reflection_probes(); i++) {
 		for (uint i = 0; i < sc_reflection_probes(); i++) {
 			uint reflection_index = (i > 3) ? ((reflection_indices.y >> ((i - 4) * 8)) & 0xFF) : ((reflection_indices.x >> (i * 8)) & 0xFF);
 			uint reflection_index = (i > 3) ? ((reflection_indices.y >> ((i - 4) * 8)) & 0xFF) : ((reflection_indices.x >> (i * 8)) & 0xFF);
-			reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+
+			if (reflection_accum.a >= 1.0 && ambient_accum.a >= 1.0) {
+				break;
+			}
+
+			reflection_process(reflection_index, vertex, ref_vec, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+		}
+
+		if (ambient_accum.a < 1.0) {
+			ambient_accum.rgb = mix(ambient_light, ambient_accum.rgb, ambient_accum.a);
+		}
+
+		if (reflection_accum.a < 1.0) {
+			reflection_accum.rgb = mix(specular_light, reflection_accum.rgb, reflection_accum.a);
 		}
 		}
 
 
 		if (reflection_accum.a > 0.0) {
 		if (reflection_accum.a > 0.0) {
-			specular_light = reflection_accum.rgb / reflection_accum.a;
+			specular_light = reflection_accum.rgb;
 		}
 		}
 
 
 #if !defined(USE_LIGHTMAP)
 #if !defined(USE_LIGHTMAP)
 		if (ambient_accum.a > 0.0) {
 		if (ambient_accum.a > 0.0) {
-			ambient_light = ambient_accum.rgb / ambient_accum.a;
+			ambient_light = ambient_accum.rgb;
 		}
 		}
 #endif
 #endif
 	} //Reflection probes
 	} //Reflection probes

+ 13 - 17
servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl

@@ -885,7 +885,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
 		blend = pow(blend_axes.x * blend_axes.y * blend_axes.z, 2.0);
 		blend = pow(blend_axes.x * blend_axes.y * blend_axes.z, 2.0);
 	}
 	}
 
 
-	if (reflections.data[ref_index].intensity > 0.0) { // compute reflection
+	if (reflections.data[ref_index].intensity > 0.0 && reflection_accum.a < 1.0) { // compute reflection
 
 
 		vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
 		vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
 
 
@@ -903,47 +903,43 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
 		}
 		}
 
 
 		vec4 reflection;
 		vec4 reflection;
+		float reflection_blend = max(0.0, blend - reflection_accum.a);
 
 
 		reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier();
 		reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier();
 		reflection.rgb *= reflections.data[ref_index].exposure_normalization;
 		reflection.rgb *= reflections.data[ref_index].exposure_normalization;
-		if (reflections.data[ref_index].exterior) {
-			reflection.rgb = mix(specular_light, reflection.rgb, blend);
-		}
+		reflection.a = reflection_blend;
 
 
-		reflection.rgb *= reflections.data[ref_index].intensity; //intensity
-		reflection.a = blend;
+		reflection.rgb *= reflections.data[ref_index].intensity;
 		reflection.rgb *= reflection.a;
 		reflection.rgb *= reflection.a;
 
 
 		reflection_accum += reflection;
 		reflection_accum += reflection;
 	}
 	}
 
 
+	if (ambient_accum.a >= 1.0) {
+		return;
+	}
+
 	switch (reflections.data[ref_index].ambient_mode) {
 	switch (reflections.data[ref_index].ambient_mode) {
 		case REFLECTION_AMBIENT_DISABLED: {
 		case REFLECTION_AMBIENT_DISABLED: {
 			//do nothing
 			//do nothing
 		} break;
 		} break;
 		case REFLECTION_AMBIENT_ENVIRONMENT: {
 		case REFLECTION_AMBIENT_ENVIRONMENT: {
-			//do nothing
 			vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
 			vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
-
 			vec4 ambient_out;
 			vec4 ambient_out;
+			float ambient_blend = max(0.0, blend - ambient_accum.a);
 
 
 			ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
 			ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
 			ambient_out.rgb *= reflections.data[ref_index].exposure_normalization;
 			ambient_out.rgb *= reflections.data[ref_index].exposure_normalization;
-			ambient_out.a = blend;
-			if (reflections.data[ref_index].exterior) {
-				ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
-			}
-
+			ambient_out.a = ambient_blend;
 			ambient_out.rgb *= ambient_out.a;
 			ambient_out.rgb *= ambient_out.a;
 			ambient_accum += ambient_out;
 			ambient_accum += ambient_out;
 		} break;
 		} break;
 		case REFLECTION_AMBIENT_COLOR: {
 		case REFLECTION_AMBIENT_COLOR: {
 			vec4 ambient_out;
 			vec4 ambient_out;
-			ambient_out.a = blend;
+			float ambient_blend = max(0.0, blend - ambient_accum.a);
+
 			ambient_out.rgb = reflections.data[ref_index].ambient;
 			ambient_out.rgb = reflections.data[ref_index].ambient;
-			if (reflections.data[ref_index].exterior) {
-				ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
-			}
+			ambient_out.a = ambient_blend;
 			ambient_out.rgb *= ambient_out.a;
 			ambient_out.rgb *= ambient_out.a;
 			ambient_accum += ambient_out;
 			ambient_accum += ambient_out;
 		} break;
 		} break;

+ 4 - 3
servers/rendering/renderer_rd/storage_rd/light_storage.cpp

@@ -1732,11 +1732,12 @@ void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, c
 		if (!rpi) {
 		if (!rpi) {
 			continue;
 			continue;
 		}
 		}
-
-		Transform3D transform = rpi->transform;
+		ReflectionProbe *probe = reflection_probe_owner.get_or_null(rpi->probe);
+		Vector3 extents = probe->size / 2;
+		float probe_size = extents.length();
 
 
 		reflection_sort[reflection_count].probe_instance = rpi;
 		reflection_sort[reflection_count].probe_instance = rpi;
-		reflection_sort[reflection_count].depth = -p_camera_inverse_transform.xform(transform.origin).z;
+		reflection_sort[reflection_count].size = -probe_size;
 		reflection_count++;
 		reflection_count++;
 	}
 	}
 
 

+ 2 - 2
servers/rendering/renderer_rd/storage_rd/light_storage.h

@@ -316,10 +316,10 @@ private:
 	};
 	};
 
 
 	struct ReflectionProbeInstanceSort {
 	struct ReflectionProbeInstanceSort {
-		float depth;
+		float size;
 		ReflectionProbeInstance *probe_instance;
 		ReflectionProbeInstance *probe_instance;
 		bool operator<(const ReflectionProbeInstanceSort &p_sort) const {
 		bool operator<(const ReflectionProbeInstanceSort &p_sort) const {
-			return depth < p_sort.depth;
+			return size < p_sort.size;
 		}
 		}
 	};
 	};