diff options
Diffstat (limited to 'servers/rendering/renderer_rd/shaders')
6 files changed, 104 insertions, 86 deletions
| diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl index 35522103df..92a5682572 100644 --- a/servers/rendering/renderer_rd/shaders/gi.glsl +++ b/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;  			}  			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;  				}  			} diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl index 4f4753d147..b931461b31 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe.glsl @@ -51,10 +51,10 @@ struct Light {  	float attenuation;  	vec3 color; -	float spot_angle_radians; +	float cos_spot_angle;  	vec3 position; -	float spot_attenuation; +	float inv_spot_attenuation;  	vec3 direction;  	bool has_shadow; @@ -233,13 +233,15 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3  		if (lights.data[light].type == LIGHT_TYPE_SPOT) {  			vec3 rel = normalize(pos - light_pos); -			float angle = acos(dot(rel, lights.data[light].direction)); -			if (angle > lights.data[light].spot_angle_radians) { +			float cos_spot_angle = lights.data[light].cos_spot_angle; +			float cos_angle = dot(rel, lights.data[light].direction); +			if (cos_angle < cos_spot_angle) {  				return false;  			} -			float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1); -			attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation); +			float scos = max(cos_angle, cos_spot_angle); +			float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle)); +			attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation);  		}  	} diff --git a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl index 9c794f1bcc..56b3b7ccb4 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl @@ -43,10 +43,10 @@ struct Light {  	float attenuation;  	vec3 color; -	float spot_angle_radians; +	float cos_spot_angle;  	vec3 position; -	float spot_attenuation; +	float inv_spot_attenuation;  	vec3 direction;  	bool has_shadow; @@ -146,13 +146,15 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation  		if (lights.data[light].type == LIGHT_TYPE_SPOT) {  			vec3 rel = normalize(pos - light_pos); -			float angle = acos(dot(rel, lights.data[light].direction)); -			if (angle > lights.data[light].spot_angle_radians) { +			float cos_spot_angle = lights.data[light].cos_spot_angle; +			float cos_angle = dot(rel, lights.data[light].direction); +			if (cos_angle < cos_spot_angle) {  				return false;  			} -			float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1); -			attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation); +			float scos = max(cos_angle, cos_spot_angle); +			float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle)); +			attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation);  		}  	} diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl index bcdfe8cc85..5e8934adb4 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl @@ -67,8 +67,8 @@ struct Light {  	float attenuation;  	uint type; -	float spot_angle; -	float spot_attenuation; +	float cos_spot_angle; +	float inv_spot_attenuation;  	float radius;  	vec4 shadow_color; @@ -266,13 +266,16 @@ void main() {  				rel_vec.y /= params.y_mult;  				attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation); -				float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction)); -				if (angle > lights.data[i].spot_angle) { -					attenuation = 0.0; -				} else { -					float d = clamp(angle / lights.data[i].spot_angle, 0, 1); -					attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation); +				float cos_spot_angle = lights.data[i].cos_spot_angle; +				float cos_angle = dot(-direction, lights.data[i].direction); + +				if (cos_angle < cos_spot_angle) { +					continue;  				} + +				float scos = max(cos_angle, cos_spot_angle); +				float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle)); +				attenuation *= 1.0 - pow(spot_rim, lights.data[i].inv_spot_attenuation);  			} break;  		} diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl index e4f6f4b7ea..007e4c113a 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl @@ -244,20 +244,26 @@ void main() {  		vec4 light;  		if (hit) { -			const float EPSILON = 0.001; -			vec3 hit_normal = normalize(vec3( -					texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r, -					texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r, -					texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r)); - -			vec3 hit_light = texture(sampler3D(light_cascades[hit_cascade], linear_sampler), uvw).rgb; -			vec4 aniso0 = texture(sampler3D(aniso0_cascades[hit_cascade], linear_sampler), uvw); -			vec3 hit_aniso0 = aniso0.rgb; -			vec3 hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[hit_cascade], linear_sampler), uvw).rg); - -			//one liner magic -			light.rgb = hit_light * (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0))); -			light.a = 1.0; +			//avoid reading different texture from different threads +			for (uint j = params.cascade; j < params.max_cascades; j++) { +				if (j == hit_cascade) { +					const float EPSILON = 0.001; +					vec3 hit_normal = normalize(vec3( +							texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r, +							texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r, +							texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r)); + +					vec3 hit_light = texture(sampler3D(light_cascades[hit_cascade], linear_sampler), uvw).rgb; +					vec4 aniso0 = texture(sampler3D(aniso0_cascades[hit_cascade], linear_sampler), uvw); +					vec3 hit_aniso0 = aniso0.rgb; +					vec3 hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[hit_cascade], linear_sampler), uvw).rg); + +					//one liner magic +					light.rgb = hit_light * (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0))); +					light.a = 1.0; +				} +			} +  		} else if (params.sky_mode == SKY_MODE_SKY) {  #ifdef USE_CUBEMAP_ARRAY  			light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index 4cbea055fa..e7ba8feb80 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -497,31 +497,31 @@ void main() {  				uint light_index = 32 * i + bit; -				vec3 light_pos = omni_lights.data[light_index].position; -				vec3 light_rel_vec = omni_lights.data[light_index].position - view_pos; +				vec3 light_pos = spot_lights.data[light_index].position; +				vec3 light_rel_vec = spot_lights.data[light_index].position - view_pos;  				float d = length(light_rel_vec);  				float shadow_attenuation = 1.0; -				if (d * omni_lights.data[light_index].inv_radius < 1.0) { -					float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation); +				if (d * spot_lights.data[light_index].inv_radius < 1.0) { +					float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation); -					vec3 spot_dir = omni_lights.data[light_index].direction; -					float scos = max(dot(-normalize(light_rel_vec), spot_dir), omni_lights.data[light_index].cone_angle); -					float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - omni_lights.data[light_index].cone_angle)); -					attenuation *= 1.0 - pow(spot_rim, omni_lights.data[light_index].cone_attenuation); +					vec3 spot_dir = spot_lights.data[light_index].direction; +					float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[light_index].cone_angle); +					float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[light_index].cone_angle)); +					attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation); -					vec3 light = omni_lights.data[light_index].color / M_PI; +					vec3 light = spot_lights.data[light_index].color / M_PI; -					if (omni_lights.data[light_index].shadow_enabled) { +					if (spot_lights.data[light_index].shadow_enabled) {  						//has shadow  						vec4 v = vec4(view_pos, 1.0); -						vec4 splane = (omni_lights.data[light_index].shadow_matrix * v); +						vec4 splane = (spot_lights.data[light_index].shadow_matrix * v);  						splane /= splane.w;  						float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r; -						shadow_attenuation = exp(min(0.0, (depth - splane.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade); +						shadow_attenuation = exp(min(0.0, (depth - splane.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);  					}  					total_light += light * attenuation * shadow_attenuation; |