Browse Source

Fixed a SDFGI reflections bug in Radeon

-Code was using too many conditionals.
-Rewrote it to use less and it now works fine.
reduz 4 years ago
parent
commit
c4daf1c4ba
1 changed files with 45 additions and 40 deletions
  1. 45 40
      servers/rendering/renderer_rd/shaders/gi.glsl

+ 45 - 40
servers/rendering/renderer_rd/shaders/gi.glsl

@@ -363,57 +363,62 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o
 				ray_pos += (ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) + cam_normal * 1.4) * bias / sdfgi.cascades[cascade].to_cell;
 				ray_pos += (ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) + cam_normal * 1.4) * bias / sdfgi.cascades[cascade].to_cell;
 			}
 			}
 			float softness = 0.2 + min(1.0, roughness * 5.0) * 4.0; //approximation to roughness so it does not seem like a hard fade
 			float softness = 0.2 + min(1.0, roughness * 5.0) * 4.0; //approximation to roughness so it does not seem like a hard fade
-			while (length(ray_pos) < max_distance) {
-				for (uint i = 0; i < sdfgi.max_cascades; i++) {
-					if (i >= cascade && length(ray_pos) < radius_sizes[i]) {
-						cascade = max(i, cascade); //never go down
-
-						vec3 pos = ray_pos - sdfgi.cascades[i].position;
-						pos *= sdfgi.cascades[i].to_cell * pos_to_uvw;
-
-						float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), pos).r * 255.0 - 1.1;
-
-						vec4 hit_light = vec4(0.0);
-						if (distance < softness) {
-							hit_light.rgb = texture(sampler3D(light_cascades[i], linear_sampler), pos).rgb;
-							hit_light.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
-							hit_light.a = clamp(1.0 - (distance / softness), 0.0, 1.0);
-							hit_light.rgb *= hit_light.a;
-						}
+			uint i = 0;
+			bool found = false;
+			while (true) {
+				if (length(ray_pos) >= max_distance || light_accum.a > 0.99) {
+					break;
+				}
+				if (!found && i >= cascade && length(ray_pos) < radius_sizes[i]) {
+					uint next_i = min(i + 1, sdfgi.max_cascades - 1);
+					cascade = max(i, cascade); //never go down
 
 
-						distance /= sdfgi.cascades[i].to_cell;
+					vec3 pos = ray_pos - sdfgi.cascades[i].position;
+					pos *= sdfgi.cascades[i].to_cell * pos_to_uvw;
 
 
-						if (i < (sdfgi.max_cascades - 1)) {
-							pos = ray_pos - sdfgi.cascades[i + 1].position;
-							pos *= sdfgi.cascades[i + 1].to_cell * pos_to_uvw;
+					float fdistance = textureLod(sampler3D(sdf_cascades[i], linear_sampler), pos, 0.0).r * 255.0 - 1.1;
 
 
-							float distance2 = texture(sampler3D(sdf_cascades[i + 1], linear_sampler), pos).r * 255.0 - 1.1;
+					vec4 hit_light = vec4(0.0);
+					if (fdistance < softness) {
+						hit_light.rgb = textureLod(sampler3D(light_cascades[i], linear_sampler), pos, 0.0).rgb;
+						hit_light.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
+						hit_light.a = clamp(1.0 - (fdistance / softness), 0.0, 1.0);
+						hit_light.rgb *= hit_light.a;
+					}
 
 
-							vec4 hit_light2 = vec4(0.0);
-							if (distance2 < softness) {
-								hit_light2.rgb = texture(sampler3D(light_cascades[i + 1], linear_sampler), pos).rgb;
-								hit_light2.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
-								hit_light2.a = clamp(1.0 - (distance2 / softness), 0.0, 1.0);
-								hit_light2.rgb *= hit_light2.a;
-							}
+					fdistance /= sdfgi.cascades[i].to_cell;
 
 
-							float prev_radius = i == 0 ? 0.0 : radius_sizes[i - 1];
-							float blend = clamp((length(ray_pos) - prev_radius) / (radius_sizes[i] - prev_radius), 0.0, 1.0);
+					if (i < (sdfgi.max_cascades - 1)) {
+						pos = ray_pos - sdfgi.cascades[next_i].position;
+						pos *= sdfgi.cascades[next_i].to_cell * pos_to_uvw;
 
 
-							distance2 /= sdfgi.cascades[i + 1].to_cell;
+						float fdistance2 = textureLod(sampler3D(sdf_cascades[next_i], linear_sampler), pos, 0.0).r * 255.0 - 1.1;
 
 
-							hit_light = mix(hit_light, hit_light2, blend);
-							distance = mix(distance, distance2, blend);
+						vec4 hit_light2 = vec4(0.0);
+						if (fdistance2 < softness) {
+							hit_light2.rgb = textureLod(sampler3D(light_cascades[next_i], linear_sampler), pos, 0.0).rgb;
+							hit_light2.rgb *= 0.5; //approximation given value read is actually meant for anisotropy
+							hit_light2.a = clamp(1.0 - (fdistance2 / softness), 0.0, 1.0);
+							hit_light2.rgb *= hit_light2.a;
 						}
 						}
 
 
-						light_accum += hit_light;
-						ray_pos += ray_dir * distance;
-						break;
+						float prev_radius = i == 0 ? 0.0 : radius_sizes[max(0, i - 1)];
+						float blend = clamp((length(ray_pos) - prev_radius) / (radius_sizes[i] - prev_radius), 0.0, 1.0);
+
+						fdistance2 /= sdfgi.cascades[next_i].to_cell;
+
+						hit_light = mix(hit_light, hit_light2, blend);
+						fdistance = mix(fdistance, fdistance2, blend);
 					}
 					}
-				}
 
 
-				if (light_accum.a > 0.99) {
-					break;
+					light_accum += hit_light;
+					ray_pos += ray_dir * fdistance;
+					found = true;
+				}
+				i++;
+				if (i == sdfgi.max_cascades) {
+					i = 0;
+					found = false;
 				}
 				}
 			}
 			}