浏览代码

Directional lights and shadow mapping are functional.

Juan Linietsky 6 年之前
父节点
当前提交
88a7debbbc

+ 5 - 0
scene/3d/light.cpp

@@ -281,6 +281,7 @@ void Light::_bind_methods() {
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET);
+	BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
@@ -325,8 +326,10 @@ Light::Light(VisualServer::LightType p_type) {
 	set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
 	set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
 	set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
+	set_param(PARAM_SHADOW_FADE_START, 0.8);
 	set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0);
 	set_param(PARAM_SHADOW_BIAS, 0.15);
+	set_param(PARAM_SHADOW_FADE_START, 1);
 	set_disable_scale(true);
 }
 
@@ -393,6 +396,7 @@ void DirectionalLight::_bind_methods() {
 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
+	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
@@ -413,6 +417,7 @@ DirectionalLight::DirectionalLight() :
 	set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8);
 	set_param(PARAM_SHADOW_BIAS, 0.1);
 	set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
+	set_param(PARAM_SHADOW_FADE_START, 0.8);
 	set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25);
 	set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
 	set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);

+ 1 - 0
scene/3d/light.h

@@ -54,6 +54,7 @@ public:
 		PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
 		PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
+		PARAM_SHADOW_FADE_START = VS::LIGHT_PARAM_SHADOW_FADE_START,
 		PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
 		PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS,
 		PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,

+ 71 - 2
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp

@@ -1377,6 +1377,66 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
 				if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
 					continue;
 				}
+
+				DirectionalLightData &light_data = scene_state.directional_lights[scene_state.ubo.directional_light_count];
+
+				Transform light_transform = light_instance_get_base_transform(li);
+
+				Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
+
+				light_data.direction[0] = direction.x;
+				light_data.direction[1] = direction.y;
+				light_data.direction[2] = direction.z;
+
+				float sign = storage->light_is_negative(base) ? -1 : 1;
+
+				light_data.energy = sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI;
+
+				Color linear_col = storage->light_get_color(base).to_linear();
+				light_data.color[0] = linear_col.r;
+				light_data.color[1] = linear_col.g;
+				light_data.color[2] = linear_col.b;
+
+				light_data.specular = storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR);
+				light_data.mask = storage->light_get_cull_mask(base);
+
+				Color shadow_col = storage->light_get_shadow_color(base).to_linear();
+
+				light_data.shadow_color[0] = shadow_col.r;
+				light_data.shadow_color[1] = shadow_col.g;
+				light_data.shadow_color[2] = shadow_col.b;
+
+				light_data.shadow_enabled = storage->light_has_shadow(base);
+
+				if (light_data.shadow_enabled) {
+
+					VS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
+
+					int limit = smode == VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
+					light_data.blend_splits = storage->light_directional_get_blend_splits(base);
+					for (int j = 0; j < 4; j++) {
+						Rect2 atlas_rect = light_instance_get_directional_shadow_atlas_rect(li, j);
+						CameraMatrix matrix = light_instance_get_shadow_camera(li, j);
+						float split = light_instance_get_directional_shadow_split(li, MIN(limit, j));
+
+						CameraMatrix bias;
+						bias.set_light_bias();
+						CameraMatrix rectm;
+						rectm.set_light_atlas_rect(atlas_rect);
+
+						Transform modelview = (p_camera_inverse_transform * light_instance_get_shadow_transform(li, j)).inverse();
+
+						CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
+						light_data.shadow_split_offsets[j] = split;
+						store_camera(shadow_mtx, light_data.shadow_matrices[j]);
+					}
+
+					float fade_start = storage->light_get_param(base, VS::LIGHT_PARAM_SHADOW_FADE_START);
+					light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999);
+					light_data.fade_to = -light_data.shadow_split_offsets[3];
+				}
+
+				scene_state.ubo.directional_light_count++;
 			} break;
 			case VS::LIGHT_SPOT:
 			case VS::LIGHT_OMNI: {
@@ -1476,7 +1536,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
 	}
 
 	if (scene_state.ubo.directional_light_count) {
-		RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * light_count, scene_state.directional_lights, true);
+		RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * scene_state.ubo.directional_light_count, scene_state.directional_lights, true);
 	}
 }
 
@@ -2092,7 +2152,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 
 	storage->render_target_disable_clear_request(render_buffer->render_target);
 
-	if (true) {
+	if (false) {
 		if (p_shadow_atlas.is_valid()) {
 			RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
 			Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
@@ -2101,6 +2161,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 		}
 	}
 
+	if (true) {
+		if (directional_shadow_get_texture().is_valid()) {
+			RID shadow_atlas_texture = directional_shadow_get_texture();
+			Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
+
+			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
+		}
+	}
+
 #if 0
 	_post_process(env, p_cam_projection);
 	// Needed only for debugging

+ 5 - 7
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h

@@ -235,16 +235,14 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 		float energy;
 		float color[3];
 		float specular;
-		uint32_t mask;
-		uint32_t pad[3];
 		float shadow_color[3];
+		uint32_t mask;
+		uint32_t blend_splits;
 		uint32_t shadow_enabled;
-		float shadow_atlas_rect[4];
+		float fade_from;
+		float fade_to;
 		float shadow_split_offsets[4];
-		float shadow_matrix1[16];
-		float shadow_matrix2[16];
-		float shadow_matrix3[16];
-		float shadow_matrix4[16];
+		float shadow_matrices[4][16];
 	};
 
 	struct InstanceData {

+ 36 - 30
servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp

@@ -898,6 +898,8 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
 		return;
 	}
 
+	directional_shadow.size = p_size;
+
 	if (directional_shadow.depth.is_valid()) {
 		RD::get_singleton()->free(directional_shadow.depth);
 		directional_shadow.depth = RID();
@@ -925,17 +927,34 @@ void RasterizerSceneRD::set_directional_shadow_count(int p_count) {
 	directional_shadow.current_light = 0;
 }
 
+static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) {
+
+	int split_h = 1;
+	int split_v = 1;
+
+	while (split_h * split_v < p_shadow_count) {
+		if (split_h == split_v) {
+			split_h <<= 1;
+		} else {
+			split_v <<= 1;
+		}
+	}
+
+	Rect2i rect(0, 0, p_size, p_size);
+	rect.size.width /= split_h;
+	rect.size.height /= split_v;
+
+	rect.position.x = rect.size.width * (p_shadow_index % split_h);
+	rect.position.y = rect.size.height * (p_shadow_index / split_h);
+
+	return rect;
+}
+
 int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
 
 	ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
 
-	int shadow_size;
-
-	if (directional_shadow.light_count == 1) {
-		shadow_size = directional_shadow.size;
-	} else {
-		shadow_size = directional_shadow.size / 2; //more than 4 not supported anyway
-	}
+	Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);
 
 	LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
 	ERR_FAIL_COND_V(!light_instance, 0);
@@ -943,11 +962,11 @@ int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
 	switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
 		case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
 			break; //none
-		case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
-		case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break;
+		case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: r.size.height /= 2; break;
+		case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: r.size /= 2; break;
 	}
 
-	return shadow_size;
+	return MAX(r.size.width, r.size.height);
 }
 
 //////////////////////////////////////////////////
@@ -1112,27 +1131,9 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 	if (storage->light_get_type(light_instance->light) == VS::LIGHT_DIRECTIONAL) {
 		//set pssm stuff
 		if (light_instance->last_scene_shadow_pass != scene_pass) {
-			//assign rect if unassigned
-			light_instance->light_directional_index = directional_shadow.current_light;
-			light_instance->last_scene_shadow_pass = scene_pass;
+			light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
 			directional_shadow.current_light++;
-
-			if (directional_shadow.light_count == 1) {
-				light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size);
-			} else if (directional_shadow.light_count == 2) {
-				light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size / 2);
-				if (light_instance->light_directional_index == 1) {
-					light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
-				}
-			} else { //3 and 4
-				light_instance->directional_rect = Rect2(0, 0, directional_shadow.size / 2, directional_shadow.size / 2);
-				if (light_instance->light_directional_index & 1) {
-					light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
-				}
-				if (light_instance->light_directional_index / 2) {
-					light_instance->directional_rect.position.y += light_instance->directional_rect.size.y;
-				}
-			}
+			light_instance->last_scene_shadow_pass = scene_pass;
 		}
 
 		light_projection = light_instance->shadow_transform[p_pass].camera;
@@ -1168,6 +1169,11 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 			}
 		}
 
+		light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect;
+
+		light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
+		light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
+
 		float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
 		zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE);
 		bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;

+ 19 - 0
servers/visual/rasterizer_rd/rasterizer_scene_rd.h

@@ -180,6 +180,7 @@ private:
 			float farplane;
 			float split;
 			float bias_scale;
+			Rect2 atlas_rect;
 		};
 
 		VS::LightType light_type;
@@ -409,6 +410,24 @@ public:
 		return li->shadow_transform[p_index].camera;
 	}
 
+	_FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
+
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->shadow_transform[p_index].transform;
+	}
+
+	_FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
+
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->shadow_transform[p_index].atlas_rect;
+	}
+
+	_FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) {
+
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->shadow_transform[p_index].split;
+	}
+
 	_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
 		LightInstance *li = light_instance_owner.getornull(p_light_instance);
 		li->last_pass = p_pass;

+ 1 - 0
servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp

@@ -2104,6 +2104,7 @@ RID RasterizerStorageRD::light_create(VS::LightType p_type) {
 	light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
 	light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
 	light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
+	light.param[VS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
 	light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
 	light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
 

+ 88 - 8
servers/visual/rasterizer_rd/shaders/scene_forward.glsl

@@ -584,7 +584,11 @@ LIGHT_SHADER_CODE
 
 #ifndef USE_NO_SHADOWS
 
-float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec2 pos, float depth) {
+float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
+
+	//todo optimize
+	vec2 pos = coord.xy;
+	float depth = coord.z;
 
 #ifdef SHADOW_MODE_PCF_13
 
@@ -657,7 +661,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 	if (shadow_color_enabled.w > 0.5) {
 		// there is a shadowmap
 
-		vec3 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
+		vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
 		float shadow_len = length(splane);
 		splane = normalize(splane);
 		vec4 clamp_rect = lights.data[idx].atlas_rect;
@@ -677,9 +681,9 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 		splane.xy /= splane.z;
 		splane.xy = splane.xy * 0.5 + 0.5;
 		splane.z = shadow_len * lights.data[idx].inv_radius;
-
 		splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
-		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+		splane.w = 1.0; //needed? i think it should be 1 already
+		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
 
 		light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
 	}
@@ -750,9 +754,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 	if (shadow_color_enabled.w > 0.5) {
 		//there is a shadowmap
 		vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
-		splane.xyz /= splane.w;
-
-		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+		splane /= splane.w;
+		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
 
 		light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
 	}
@@ -1132,7 +1135,84 @@ FRAGMENT_SHADER_CODE
 #endif
 	}
 
-	//directional light
+	{ //directional light
+
+		for (uint i = 0; i < scene_data.directional_light_count; i++) {
+
+			if (!bool(directional_lights.data[i].mask&instances.data[instance_index].layer_mask)) {
+				continue; //not masked
+			}
+
+			vec3 light_attenuation = vec3(1.0);
+
+			if (directional_lights.data[i].shadow_enabled) {
+				float depth_z = -vertex.z;
+
+				vec4 pssm_coord;
+
+				if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+					pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
+				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+					pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+					pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+				} else {
+					pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
+				}
+
+				pssm_coord/=pssm_coord.w;
+
+				float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+
+				if (directional_lights.data[i].blend_splits) {
+
+					float pssm_blend;
+
+					if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+						pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+						pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+					} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+						pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+						pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+					} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+						pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
+						pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+					} else {
+						pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
+					}
+
+					pssm_coord/=pssm_coord.w;
+
+					float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+					shadow = mix(shadow,shadow2,pssm_blend);
+
+				}
+
+				shadow = mix(shadow,1.0,smoothstep(directional_lights.data[i].fade_from,directional_lights.data[i].fade_to,vertex.z)); //done with negative values for performance
+
+				light_attenuation = vec3(shadow); //mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
+			}
+
+
+			light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, light_attenuation, albedo, roughness, metallic, specular,directional_lights.data[i].specular * specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+				transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+				rim * omni_attenuation, rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+				clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+				binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+				alpha
+#endif
+				diffuse_light, specular_light);
+		}
+	}
 
 	{ //omni lights
 		uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;

+ 4 - 3
servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl

@@ -184,11 +184,12 @@ struct DirectionalLightData {
 	float energy;
 	vec3 color;
 	float specular;
-	uint mask;
-	uint pad0,pad1,pad2;
 	vec3 shadow_color;
+	uint mask;
+	bool blend_splits;
 	bool shadow_enabled;
-	vec4 shadow_atlas_rect;
+	float fade_from;
+	float fade_to;
 	vec4 shadow_split_offsets;
 	mat4 shadow_matrix1;
 	mat4 shadow_matrix2;

+ 1 - 0
servers/visual_server.cpp

@@ -2047,6 +2047,7 @@ void VisualServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
+	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE);

+ 1 - 0
servers/visual_server.h

@@ -404,6 +404,7 @@ public:
 		LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
 		LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
+		LIGHT_PARAM_SHADOW_FADE_START,
 		LIGHT_PARAM_SHADOW_NORMAL_BIAS,
 		LIGHT_PARAM_SHADOW_BIAS,
 		LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,