diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 20f8ef02c07..6db2a5b19c6 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/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[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 sort_array; + sort_array.sort(sorted_reflection_probes, p_instance->reflection_probe_count); + idx = 0; for (uint32_t i = 0; i < p_instance->reflection_probe_count; i++) { uint32_t ofs = idx < 4 ? 0 : 1; uint32_t shift = (idx & 0x3) << 3; 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] |= 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++; } } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 0969dd0b508..1661d1f415c 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -529,6 +529,14 @@ protected: 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: static RenderForwardMobile *get_singleton() { return singleton; } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index c14ea34c8f0..1a09261a326 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -1897,17 +1897,29 @@ void fragment_shader(in SceneData scene_data) { 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); } } + 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) { - specular_light = reflection_accum.rgb / reflection_accum.a; + specular_light = reflection_accum.rgb; } #if !defined(USE_LIGHTMAP) if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; + ambient_light = ambient_accum.rgb; } #endif } diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index a3c264b8236..cc98b64d480 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -1364,16 +1364,29 @@ void main() { uvec2 reflection_indices = instances.data[draw_call.instance_index].reflection_probes; 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); - 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) { - specular_light = reflection_accum.rgb / reflection_accum.a; + specular_light = reflection_accum.rgb; } #if !defined(USE_LIGHTMAP) if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; + ambient_light = ambient_accum.rgb; } #endif } //Reflection probes diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 5ea24bff715..fc26848784f 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/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); } - 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; @@ -903,47 +903,43 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, } 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 *= 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_accum += reflection; } + if (ambient_accum.a >= 1.0) { + return; + } + switch (reflections.data[ref_index].ambient_mode) { case REFLECTION_AMBIENT_DISABLED: { //do nothing } break; case REFLECTION_AMBIENT_ENVIRONMENT: { - //do nothing vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz; - 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 *= 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_accum += ambient_out; } break; case REFLECTION_AMBIENT_COLOR: { 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; - 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_accum += ambient_out; } break; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index abf673a1fa5..b291749e79f 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/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) { 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].depth = -p_camera_inverse_transform.xform(transform.origin).z; + reflection_sort[reflection_count].size = -probe_size; reflection_count++; } diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index b71c1d36fdd..73543ce6447 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -316,10 +316,10 @@ private: }; struct ReflectionProbeInstanceSort { - float depth; + float size; ReflectionProbeInstance *probe_instance; bool operator<(const ReflectionProbeInstanceSort &p_sort) const { - return depth < p_sort.depth; + return size < p_sort.size; } };