Procházet zdrojové kódy

Refactored shadowmapping.

- Made shadow bias size independent, so it will remain when changing light or camera size.
- Implemented normal offset bias, which greatly enhances quality.
- Added transmission to subsurface scattering
- Reimplemented shadow filter modes

Closes #17260
Juan Linietsky před 5 roky
rodič
revize
4ffc0d6b3f
34 změnil soubory, kde provedl 1032 přidání a 291 odebrání
  1. 9 0
      core/class_db.cpp
  2. 1 0
      core/class_db.h
  3. 2 4
      core/object.h
  4. 31 3
      editor/editor_inspector.cpp
  5. 2 0
      editor/editor_node.cpp
  6. 5 0
      editor/plugins/node_3d_editor_plugin.cpp
  7. 1 0
      editor/plugins/node_3d_editor_plugin.h
  8. 10 16
      scene/3d/light_3d.cpp
  9. 2 2
      scene/3d/light_3d.h
  10. 2 0
      scene/main/viewport.cpp
  11. 2 1
      scene/main/viewport.h
  12. 133 36
      scene/resources/material.cpp
  13. 41 10
      scene/resources/material.h
  14. 3 1
      servers/rendering/rasterizer.h
  15. 7 9
      servers/rendering/rasterizer_rd/light_cluster_builder.h
  16. 20 0
      servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
  17. 2 0
      servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
  18. 84 27
      servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
  19. 19 6
      servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
  20. 24 7
      servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
  21. 57 6
      servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
  22. 5 3
      servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
  23. 8 0
      servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
  24. 7 0
      servers/rendering/rasterizer_rd/shaders/blur.glsl
  25. 2 1
      servers/rendering/rasterizer_rd/shaders/copy.glsl
  26. 365 90
      servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
  27. 26 9
      servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
  28. 2 0
      servers/rendering/rendering_server_raster.h
  29. 137 52
      servers/rendering/rendering_server_scene.cpp
  30. 2 2
      servers/rendering/rendering_server_scene.h
  31. 2 0
      servers/rendering/rendering_server_wrap_mt.h
  32. 6 2
      servers/rendering/shader_types.cpp
  33. 1 2
      servers/rendering_server.cpp
  34. 12 2
      servers/rendering_server.h

+ 9 - 0
core/class_db.cpp

@@ -930,6 +930,15 @@ void ClassDB::add_property_group(StringName p_class, const String &p_name, const
 	type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_GROUP));
 	type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_GROUP));
 }
 }
 
 
+void ClassDB::add_property_subgroup(StringName p_class, const String &p_name, const String &p_prefix) {
+
+	OBJTYPE_WLOCK;
+	ClassInfo *type = classes.getptr(p_class);
+	ERR_FAIL_COND(!type);
+
+	type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_SUBGROUP));
+}
+
 void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
 void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
 
 
 	lock->read_lock();
 	lock->read_lock();

+ 1 - 0
core/class_db.h

@@ -349,6 +349,7 @@ public:
 	static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
 	static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
 
 
 	static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
 	static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
+	static void add_property_subgroup(StringName p_class, const String &p_name, const String &p_prefix = "");
 	static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
 	static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
 	static void set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default);
 	static void set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default);
 	static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);
 	static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);

+ 2 - 4
core/object.h

@@ -107,10 +107,7 @@ enum PropertyUsageFlags {
 	PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings
 	PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings
 	PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor
 	PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor
 	PROPERTY_USAGE_CATEGORY = 256,
 	PROPERTY_USAGE_CATEGORY = 256,
-	// FIXME: Drop in 4.0, possibly reorder other flags?
-	// Those below are deprecated thanks to ClassDB's now class value cache
-	//PROPERTY_USAGE_STORE_IF_NONZERO = 512, //only store if nonzero
-	//PROPERTY_USAGE_STORE_IF_NONONE = 1024, //only store if false
+	PROPERTY_USAGE_SUBGROUP = 512,
 	PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
 	PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
 	PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
 	PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
 	PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
 	PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
@@ -138,6 +135,7 @@ enum PropertyUsageFlags {
 #define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
 #define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
 #define ADD_PROPERTY_DEFAULT(m_property, m_default) ClassDB::set_property_default_value(get_class_static(), m_property, m_default)
 #define ADD_PROPERTY_DEFAULT(m_property, m_default) ClassDB::set_property_default_value(get_class_static(), m_property, m_default)
 #define ADD_GROUP(m_name, m_prefix) ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
 #define ADD_GROUP(m_name, m_prefix) ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
+#define ADD_SUBGROUP(m_name, m_prefix) ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
 
 
 struct PropertyInfo {
 struct PropertyInfo {
 
 

+ 31 - 3
editor/editor_inspector.cpp

@@ -1478,6 +1478,8 @@ void EditorInspector::update_tree() {
 	String filter = search_box ? search_box->get_text() : "";
 	String filter = search_box ? search_box->get_text() : "";
 	String group;
 	String group;
 	String group_base;
 	String group_base;
+	String subgroup;
+	String subgroup_base;
 	VBoxContainer *category_vbox = nullptr;
 	VBoxContainer *category_vbox = nullptr;
 
 
 	List<PropertyInfo>
 	List<PropertyInfo>
@@ -1503,10 +1505,19 @@ void EditorInspector::update_tree() {
 
 
 		//make sure the property can be edited
 		//make sure the property can be edited
 
 
-		if (p.usage & PROPERTY_USAGE_GROUP) {
+		if (p.usage & PROPERTY_USAGE_SUBGROUP) {
+
+			subgroup = p.name;
+			subgroup_base = p.hint_string;
+
+			continue;
+
+		} else if (p.usage & PROPERTY_USAGE_GROUP) {
 
 
 			group = p.name;
 			group = p.name;
 			group_base = p.hint_string;
 			group_base = p.hint_string;
+			subgroup = "";
+			subgroup_base = "";
 
 
 			continue;
 			continue;
 
 
@@ -1514,6 +1525,8 @@ void EditorInspector::update_tree() {
 
 
 			group = "";
 			group = "";
 			group_base = "";
 			group_base = "";
+			subgroup = "";
+			subgroup_base = "";
 
 
 			if (!show_categories)
 			if (!show_categories)
 				continue;
 				continue;
@@ -1577,18 +1590,33 @@ void EditorInspector::update_tree() {
 		}
 		}
 
 
 		String basename = p.name;
 		String basename = p.name;
+
+		if (subgroup != "") {
+			if (subgroup_base != "") {
+				if (basename.begins_with(subgroup_base)) {
+					basename = basename.replace_first(subgroup_base, "");
+				} else if (subgroup_base.begins_with(basename)) {
+					//keep it, this is used pretty often
+				} else {
+					subgroup = ""; //no longer using subgroup base, clear
+				}
+			}
+		}
 		if (group != "") {
 		if (group != "") {
-			if (group_base != "") {
+			if (group_base != "" && subgroup == "") {
 				if (basename.begins_with(group_base)) {
 				if (basename.begins_with(group_base)) {
 					basename = basename.replace_first(group_base, "");
 					basename = basename.replace_first(group_base, "");
 				} else if (group_base.begins_with(basename)) {
 				} else if (group_base.begins_with(basename)) {
 					//keep it, this is used pretty often
 					//keep it, this is used pretty often
 				} else {
 				} else {
 					group = ""; //no longer using group base, clear
 					group = ""; //no longer using group base, clear
+					subgroup = "";
 				}
 				}
 			}
 			}
 		}
 		}
-
+		if (subgroup != "") {
+			basename = subgroup + "/" + basename;
+		}
 		if (group != "") {
 		if (group != "") {
 			basename = group + "/" + basename;
 			basename = group + "/" + basename;
 		}
 		}

+ 2 - 0
editor/editor_node.cpp

@@ -374,6 +374,8 @@ void EditorNode::_notification(int p_what) {
 				float sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
 				float sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
 				float sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
 				float sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
 				RS::get_singleton()->sub_surface_scattering_set_scale(sss_scale, sss_depth_scale);
 				RS::get_singleton()->sub_surface_scattering_set_scale(sss_scale, sss_depth_scale);
+				RS::ShadowFilter shadow_filter = RS::ShadowFilter(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
+				RS::get_singleton()->shadow_filter_set(shadow_filter);
 			}
 			}
 
 
 			ResourceImporterTexture::get_singleton()->update_imports();
 			ResourceImporterTexture::get_singleton()->update_imports();

+ 5 - 0
editor/plugins/node_3d_editor_plugin.cpp

@@ -3000,6 +3000,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
 		case VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION:
 		case VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION:
 		case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE:
 		case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE:
 		case VIEW_DISPLAY_DEBUG_SSAO:
 		case VIEW_DISPLAY_DEBUG_SSAO:
+		case VIEW_DISPLAY_DEBUG_PSSM_SPLITS:
 		case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: {
 		case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: {
 
 
 			static const int display_options[] = {
 			static const int display_options[] = {
@@ -3018,6 +3019,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
 				VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
 				VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
 				VIEW_DISPLAY_DEBUG_SSAO,
 				VIEW_DISPLAY_DEBUG_SSAO,
 				VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
 				VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
+				VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
 				VIEW_MAX
 				VIEW_MAX
 			};
 			};
 			static const Viewport::DebugDraw debug_draw_modes[] = {
 			static const Viewport::DebugDraw debug_draw_modes[] = {
@@ -3036,6 +3038,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
 				Viewport::DEBUG_DRAW_SCENE_LUMINANCE,
 				Viewport::DEBUG_DRAW_SCENE_LUMINANCE,
 				Viewport::DEBUG_DRAW_SSAO,
 				Viewport::DEBUG_DRAW_SSAO,
 				Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER,
 				Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER,
+				Viewport::DEBUG_DRAW_PSSM_SPLITS,
 			};
 			};
 
 
 			int idx = 0;
 			int idx = 0;
@@ -3887,6 +3890,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
 	view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_lighting", TTR("Display Lighting")), VIEW_DISPLAY_LIGHTING);
 	view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_lighting", TTR("Display Lighting")), VIEW_DISPLAY_LIGHTING);
 	view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_unshaded", TTR("Display Unshaded")), VIEW_DISPLAY_SHADELESS);
 	view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_unshaded", TTR("Display Unshaded")), VIEW_DISPLAY_SHADELESS);
 	view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), true);
 	view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), true);
+	display_submenu->add_radio_check_item(TTR("Directional Shadow Splits"), VIEW_DISPLAY_DEBUG_PSSM_SPLITS);
+	display_submenu->add_separator();
 	display_submenu->add_radio_check_item(TTR("Normal Buffer"), VIEW_DISPLAY_NORMAL_BUFFER);
 	display_submenu->add_radio_check_item(TTR("Normal Buffer"), VIEW_DISPLAY_NORMAL_BUFFER);
 	display_submenu->add_separator();
 	display_submenu->add_separator();
 	display_submenu->add_radio_check_item(TTR("Shadow Atlas"), VIEW_DISPLAY_DEBUG_SHADOW_ATLAS);
 	display_submenu->add_radio_check_item(TTR("Shadow Atlas"), VIEW_DISPLAY_DEBUG_SHADOW_ATLAS);

+ 1 - 0
editor/plugins/node_3d_editor_plugin.h

@@ -218,6 +218,7 @@ class Node3DEditorViewport : public Control {
 		VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
 		VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
 		VIEW_DISPLAY_DEBUG_SSAO,
 		VIEW_DISPLAY_DEBUG_SSAO,
 		VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
 		VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER,
+		VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
 		VIEW_LOCK_ROTATION,
 		VIEW_LOCK_ROTATION,
 		VIEW_CINEMATIC_PREVIEW,
 		VIEW_CINEMATIC_PREVIEW,
 		VIEW_AUTO_ORTHOGONAL,
 		VIEW_AUTO_ORTHOGONAL,

+ 10 - 16
scene/3d/light_3d.cpp

@@ -216,10 +216,6 @@ bool Light3D::is_editor_only() const {
 }
 }
 
 
 void Light3D::_validate_property(PropertyInfo &property) const {
 void Light3D::_validate_property(PropertyInfo &property) const {
-
-	if (RenderingServer::get_singleton()->is_low_end() && property.name == "shadow_contact") {
-		property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
-	}
 }
 }
 
 
 void Light3D::_bind_methods() {
 void Light3D::_bind_methods() {
@@ -262,9 +258,10 @@ void Light3D::_bind_methods() {
 	ADD_GROUP("Shadow", "shadow_");
 	ADD_GROUP("Shadow", "shadow_");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color");
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color");
-	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS);
-	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_contact", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE);
+	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS);
+	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
+	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
 	ADD_GROUP("Editor", "");
 	ADD_GROUP("Editor", "");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
 	ADD_GROUP("", "");
 	ADD_GROUP("", "");
@@ -276,7 +273,6 @@ void Light3D::_bind_methods() {
 	BIND_ENUM_CONSTANT(PARAM_ATTENUATION);
 	BIND_ENUM_CONSTANT(PARAM_ATTENUATION);
 	BIND_ENUM_CONSTANT(PARAM_SPOT_ANGLE);
 	BIND_ENUM_CONSTANT(PARAM_SPOT_ANGLE);
 	BIND_ENUM_CONSTANT(PARAM_SPOT_ATTENUATION);
 	BIND_ENUM_CONSTANT(PARAM_SPOT_ATTENUATION);
-	BIND_ENUM_CONSTANT(PARAM_CONTACT_SHADOW_SIZE);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_MAX_DISTANCE);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_MAX_DISTANCE);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
@@ -284,7 +280,8 @@ void Light3D::_bind_methods() {
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
 	BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
-	BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
+	BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE);
+	BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
 	BIND_ENUM_CONSTANT(PARAM_MAX);
 	BIND_ENUM_CONSTANT(PARAM_MAX);
 
 
 	BIND_ENUM_CONSTANT(BAKE_DISABLED);
 	BIND_ENUM_CONSTANT(BAKE_DISABLED);
@@ -321,14 +318,15 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
 	set_param(PARAM_ATTENUATION, 1);
 	set_param(PARAM_ATTENUATION, 1);
 	set_param(PARAM_SPOT_ANGLE, 45);
 	set_param(PARAM_SPOT_ANGLE, 45);
 	set_param(PARAM_SPOT_ATTENUATION, 1);
 	set_param(PARAM_SPOT_ATTENUATION, 1);
-	set_param(PARAM_CONTACT_SHADOW_SIZE, 0);
 	set_param(PARAM_SHADOW_MAX_DISTANCE, 0);
 	set_param(PARAM_SHADOW_MAX_DISTANCE, 0);
 	set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
 	set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
 	set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
 	set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
 	set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
 	set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
 	set_param(PARAM_SHADOW_FADE_START, 0.8);
 	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_PANCAKE_SIZE, 20.0);
+	set_param(PARAM_SHADOW_BIAS, 0.02);
+	set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
+	set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
 	set_param(PARAM_SHADOW_FADE_START, 1);
 	set_param(PARAM_SHADOW_FADE_START, 1);
 	set_disable_scale(true);
 	set_disable_scale(true);
 }
 }
@@ -398,10 +396,9 @@ void DirectionalLight3D::_bind_methods() {
 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "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_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
-	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
-	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range");
 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
+	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_EXP_RANGE, "0,1024,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE);
 
 
 	BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL);
 	BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL);
 	BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
 	BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
@@ -414,11 +411,8 @@ void DirectionalLight3D::_bind_methods() {
 DirectionalLight3D::DirectionalLight3D() :
 DirectionalLight3D::DirectionalLight3D() :
 		Light3D(RenderingServer::LIGHT_DIRECTIONAL) {
 		Light3D(RenderingServer::LIGHT_DIRECTIONAL) {
 
 
-	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_MAX_DISTANCE, 100);
 	set_param(PARAM_SHADOW_FADE_START, 0.8);
 	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_mode(SHADOW_PARALLEL_4_SPLITS);
 	set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
 	set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
 
 

+ 2 - 2
scene/3d/light_3d.h

@@ -49,7 +49,6 @@ public:
 		PARAM_ATTENUATION = RS::LIGHT_PARAM_ATTENUATION,
 		PARAM_ATTENUATION = RS::LIGHT_PARAM_ATTENUATION,
 		PARAM_SPOT_ANGLE = RS::LIGHT_PARAM_SPOT_ANGLE,
 		PARAM_SPOT_ANGLE = RS::LIGHT_PARAM_SPOT_ANGLE,
 		PARAM_SPOT_ATTENUATION = RS::LIGHT_PARAM_SPOT_ATTENUATION,
 		PARAM_SPOT_ATTENUATION = RS::LIGHT_PARAM_SPOT_ATTENUATION,
-		PARAM_CONTACT_SHADOW_SIZE = RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE,
 		PARAM_SHADOW_MAX_DISTANCE = RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE,
 		PARAM_SHADOW_MAX_DISTANCE = RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE,
 		PARAM_SHADOW_SPLIT_1_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		PARAM_SHADOW_SPLIT_1_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		PARAM_SHADOW_SPLIT_2_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
 		PARAM_SHADOW_SPLIT_2_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
@@ -57,7 +56,8 @@ public:
 		PARAM_SHADOW_FADE_START = RS::LIGHT_PARAM_SHADOW_FADE_START,
 		PARAM_SHADOW_FADE_START = RS::LIGHT_PARAM_SHADOW_FADE_START,
 		PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
 		PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
 		PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
 		PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
-		PARAM_SHADOW_BIAS_SPLIT_SCALE = RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
+		PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+		PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
 		PARAM_MAX = RS::LIGHT_PARAM_MAX
 		PARAM_MAX = RS::LIGHT_PARAM_MAX
 	};
 	};
 
 

+ 2 - 0
scene/main/viewport.cpp

@@ -3498,6 +3498,8 @@ void Viewport::_bind_methods() {
 	BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
 	BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
 	BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE);
 	BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE);
 	BIND_ENUM_CONSTANT(DEBUG_DRAW_SSAO);
 	BIND_ENUM_CONSTANT(DEBUG_DRAW_SSAO);
+	BIND_ENUM_CONSTANT(DEBUG_DRAW_ROUGHNESS_LIMITER);
+	BIND_ENUM_CONSTANT(DEBUG_DRAW_PSSM_SPLITS);
 
 
 	BIND_ENUM_CONSTANT(MSAA_DISABLED);
 	BIND_ENUM_CONSTANT(MSAA_DISABLED);
 	BIND_ENUM_CONSTANT(MSAA_2X);
 	BIND_ENUM_CONSTANT(MSAA_2X);

+ 2 - 1
scene/main/viewport.h

@@ -133,7 +133,8 @@ public:
 		DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
 		DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
 		DEBUG_DRAW_SCENE_LUMINANCE,
 		DEBUG_DRAW_SCENE_LUMINANCE,
 		DEBUG_DRAW_SSAO,
 		DEBUG_DRAW_SSAO,
-		DEBUG_DRAW_ROUGHNESS_LIMITER
+		DEBUG_DRAW_ROUGHNESS_LIMITER,
+		DEBUG_DRAW_PSSM_SPLITS
 	};
 	};
 
 
 	enum DefaultCanvasItemTextureFilter {
 	enum DefaultCanvasItemTextureFilter {

+ 133 - 36
scene/resources/material.cpp

@@ -314,7 +314,7 @@ void BaseMaterial3D::init_shaders() {
 	shader_names->anisotropy = "anisotropy_ratio";
 	shader_names->anisotropy = "anisotropy_ratio";
 	shader_names->heightmap_scale = "heightmap_scale";
 	shader_names->heightmap_scale = "heightmap_scale";
 	shader_names->subsurface_scattering_strength = "subsurface_scattering_strength";
 	shader_names->subsurface_scattering_strength = "subsurface_scattering_strength";
-	shader_names->transmission = "transmission";
+	shader_names->backlight = "backlight";
 	shader_names->refraction = "refraction";
 	shader_names->refraction = "refraction";
 	shader_names->point_size = "point_size";
 	shader_names->point_size = "point_size";
 	shader_names->uv1_scale = "uv1_scale";
 	shader_names->uv1_scale = "uv1_scale";
@@ -347,6 +347,11 @@ void BaseMaterial3D::init_shaders() {
 	shader_names->refraction_texture_channel = "refraction_texture_channel";
 	shader_names->refraction_texture_channel = "refraction_texture_channel";
 	shader_names->alpha_scissor_threshold = "alpha_scissor_threshold";
 	shader_names->alpha_scissor_threshold = "alpha_scissor_threshold";
 
 
+	shader_names->transmittance_color = "transmittance_color";
+	shader_names->transmittance_curve = "transmittance_curve";
+	shader_names->transmittance_depth = "transmittance_depth";
+	shader_names->transmittance_boost = "transmittance_boost";
+
 	shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo";
 	shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo";
 	shader_names->texture_names[TEXTURE_METALLIC] = "texture_metallic";
 	shader_names->texture_names[TEXTURE_METALLIC] = "texture_metallic";
 	shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness";
 	shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness";
@@ -358,7 +363,8 @@ void BaseMaterial3D::init_shaders() {
 	shader_names->texture_names[TEXTURE_AMBIENT_OCCLUSION] = "texture_ambient_occlusion";
 	shader_names->texture_names[TEXTURE_AMBIENT_OCCLUSION] = "texture_ambient_occlusion";
 	shader_names->texture_names[TEXTURE_HEIGHTMAP] = "texture_heightmap";
 	shader_names->texture_names[TEXTURE_HEIGHTMAP] = "texture_heightmap";
 	shader_names->texture_names[TEXTURE_SUBSURFACE_SCATTERING] = "texture_subsurface_scattering";
 	shader_names->texture_names[TEXTURE_SUBSURFACE_SCATTERING] = "texture_subsurface_scattering";
-	shader_names->texture_names[TEXTURE_TRANSMISSION] = "texture_transmission";
+	shader_names->texture_names[TEXTURE_SUBSURFACE_TRANSMITTANCE] = "texture_subsurface_transmittance";
+	shader_names->texture_names[TEXTURE_BACKLIGHT] = "texture_backlight";
 	shader_names->texture_names[TEXTURE_REFRACTION] = "texture_refraction";
 	shader_names->texture_names[TEXTURE_REFRACTION] = "texture_refraction";
 	shader_names->texture_names[TEXTURE_DETAIL_MASK] = "texture_detail_mask";
 	shader_names->texture_names[TEXTURE_DETAIL_MASK] = "texture_detail_mask";
 	shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo";
 	shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo";
@@ -385,7 +391,7 @@ void BaseMaterial3D::_update_shader() {
 	dirty_materials->remove(&element);
 	dirty_materials->remove(&element);
 
 
 	MaterialKey mk = _compute_key();
 	MaterialKey mk = _compute_key();
-	if (mk.key == current_key.key)
+	if (mk == current_key)
 		return; //no update required in the end
 		return; //no update required in the end
 
 
 	if (shader_map.has(current_key)) {
 	if (shader_map.has(current_key)) {
@@ -444,9 +450,6 @@ void BaseMaterial3D::_update_shader() {
 		case DEPTH_DRAW_DISABLED: code += ",depth_draw_never"; break;
 		case DEPTH_DRAW_DISABLED: code += ",depth_draw_never"; break;
 	}
 	}
 
 
-	if (features[FEATURE_SUBSURACE_SCATTERING] && flags[FLAG_SUBSURFACE_MODE_SKIN]) {
-		code += ",sss_mode_skin";
-	}
 	if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
 	if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
 		code += ",depth_prepass_alpha";
 		code += ",depth_prepass_alpha";
 	}
 	}
@@ -470,6 +473,9 @@ void BaseMaterial3D::_update_shader() {
 		case SPECULAR_TOON: code += ",specular_toon"; break;
 		case SPECULAR_TOON: code += ",specular_toon"; break;
 		case SPECULAR_DISABLED: code += ",specular_disabled"; break;
 		case SPECULAR_DISABLED: code += ",specular_disabled"; break;
 	}
 	}
+	if (features[FEATURE_SUBSURFACE_SCATTERING] && flags[FLAG_SUBSURFACE_MODE_SKIN]) {
+		code += ",sss_mode_skin";
+	}
 
 
 	if (shading_mode == SHADING_MODE_UNSHADED) {
 	if (shading_mode == SHADING_MODE_UNSHADED) {
 		code += ",unshaded";
 		code += ",unshaded";
@@ -589,16 +595,25 @@ void BaseMaterial3D::_update_shader() {
 		code += "uniform sampler2D texture_detail_mask : hint_white," + texfilter_str + ";\n";
 		code += "uniform sampler2D texture_detail_mask : hint_white," + texfilter_str + ";\n";
 	}
 	}
 
 
-	if (features[FEATURE_SUBSURACE_SCATTERING]) {
+	if (features[FEATURE_SUBSURFACE_SCATTERING]) {
 
 
 		code += "uniform float subsurface_scattering_strength : hint_range(0,1);\n";
 		code += "uniform float subsurface_scattering_strength : hint_range(0,1);\n";
 		code += "uniform sampler2D texture_subsurface_scattering : hint_white," + texfilter_str + ";\n";
 		code += "uniform sampler2D texture_subsurface_scattering : hint_white," + texfilter_str + ";\n";
 	}
 	}
 
 
-	if (features[FEATURE_TRANSMISSION]) {
+	if (features[FEATURE_SUBSURFACE_TRANSMITTANCE]) {
 
 
-		code += "uniform vec4 transmission : hint_color;\n";
-		code += "uniform sampler2D texture_transmission : hint_black," + texfilter_str + ";\n";
+		code += "uniform vec4 transmittance_color : hint_color;\n";
+		code += "uniform float transmittance_depth;\n";
+		code += "uniform sampler2D texture_subsurface_transmittance : hint_white," + texfilter_str + ";\n";
+		code += "uniform float transmittance_curve;\n";
+		code += "uniform float transmittance_boost;\n";
+	}
+
+	if (features[FEATURE_BACKLIGHT]) {
+
+		code += "uniform vec4 backlight : hint_color;\n";
+		code += "uniform sampler2D texture_backlight : hint_black," + texfilter_str + ";\n";
 	}
 	}
 
 
 	if (features[FEATURE_HEIGHT_MAPPING]) {
 	if (features[FEATURE_HEIGHT_MAPPING]) {
@@ -1051,7 +1066,7 @@ void BaseMaterial3D::_update_shader() {
 		code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n";
 		code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n";
 	}
 	}
 
 
-	if (features[FEATURE_SUBSURACE_SCATTERING]) {
+	if (features[FEATURE_SUBSURFACE_SCATTERING]) {
 
 
 		if (flags[FLAG_UV1_USE_TRIPLANAR]) {
 		if (flags[FLAG_UV1_USE_TRIPLANAR]) {
 			code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n";
 			code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n";
@@ -1061,13 +1076,27 @@ void BaseMaterial3D::_update_shader() {
 		code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n";
 		code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n";
 	}
 	}
 
 
-	if (features[FEATURE_TRANSMISSION]) {
+	if (features[FEATURE_SUBSURFACE_TRANSMITTANCE]) {
+
+		if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+			code += "\tvec4 trans_color_tex = triplanar_texture(texture_subsurface_transmittance,uv1_power_normal,uv1_triplanar_pos);\n";
+		} else {
+			code += "\tvec4 trans_color_tex = texture(texture_subsurface_transmittance,base_uv);\n";
+		}
+		code += "\tSSS_TRANSMITTANCE_COLOR=transmittance_color*trans_color_tex;\n";
+
+		code += "\tSSS_TRANSMITTANCE_DEPTH=transmittance_depth;\n";
+		code += "\tSSS_TRANSMITTANCE_CURVE=transmittance_curve;\n";
+		code += "\tSSS_TRANSMITTANCE_BOOST=transmittance_boost;\n";
+	}
+
+	if (features[FEATURE_BACKLIGHT]) {
 		if (flags[FLAG_UV1_USE_TRIPLANAR]) {
 		if (flags[FLAG_UV1_USE_TRIPLANAR]) {
-			code += "\tvec3 transmission_tex = triplanar_texture(texture_transmission,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
+			code += "\tvec3 backlight_tex = triplanar_texture(texture_backlight,uv1_power_normal,uv1_triplanar_pos).rgb;\n";
 		} else {
 		} else {
-			code += "\tvec3 transmission_tex = texture(texture_transmission,base_uv).rgb;\n";
+			code += "\tvec3 backlight_tex = texture(texture_backlight,base_uv).rgb;\n";
 		}
 		}
-		code += "\tTRANSMISSION = (transmission.rgb+transmission_tex);\n";
+		code += "\tBACKLIGHT = (backlight.rgb+backlight_tex);\n";
 	}
 	}
 
 
 	if (features[FEATURE_DETAIL]) {
 	if (features[FEATURE_DETAIL]) {
@@ -1309,15 +1338,48 @@ float BaseMaterial3D::get_subsurface_scattering_strength() const {
 	return subsurface_scattering_strength;
 	return subsurface_scattering_strength;
 }
 }
 
 
-void BaseMaterial3D::set_transmission(const Color &p_transmission) {
+void BaseMaterial3D::set_transmittance_color(const Color &p_color) {
+	transmittance_color = p_color;
+	RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_color, p_color);
+}
 
 
-	transmission = p_transmission;
-	RS::get_singleton()->material_set_param(_get_material(), shader_names->transmission, transmission);
+Color BaseMaterial3D::get_transmittance_color() const {
+	return transmittance_color;
 }
 }
 
 
-Color BaseMaterial3D::get_transmission() const {
+void BaseMaterial3D::set_transmittance_depth(float p_depth) {
+	transmittance_depth = p_depth;
+	RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_depth, p_depth);
+}
+float BaseMaterial3D::get_transmittance_depth() const {
+	return transmittance_depth;
+}
 
 
-	return transmission;
+void BaseMaterial3D::set_transmittance_curve(float p_curve) {
+	transmittance_curve = p_curve;
+	RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_curve, p_curve);
+}
+float BaseMaterial3D::get_transmittance_curve() const {
+	return transmittance_curve;
+}
+
+void BaseMaterial3D::set_transmittance_boost(float p_boost) {
+	transmittance_boost = p_boost;
+	RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_boost, p_boost);
+}
+float BaseMaterial3D::get_transmittance_boost() const {
+	return transmittance_boost;
+}
+
+void BaseMaterial3D::set_backlight(const Color &p_backlight) {
+
+	backlight = p_backlight;
+	RS::get_singleton()->material_set_param(_get_material(), shader_names->backlight, backlight);
+}
+
+Color BaseMaterial3D::get_backlight() const {
+
+	return backlight;
 }
 }
 
 
 void BaseMaterial3D::set_refraction(float p_refraction) {
 void BaseMaterial3D::set_refraction(float p_refraction) {
@@ -1457,7 +1519,7 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) {
 		return;
 		return;
 
 
 	flags[p_flag] = p_enabled;
 	flags[p_flag] = p_enabled;
-	if ((p_flag == FLAG_USE_SHADOW_TO_OPACITY) || (p_flag == FLAG_USE_TEXTURE_REPEAT)) {
+	if (p_flag == FLAG_USE_SHADOW_TO_OPACITY || p_flag == FLAG_USE_TEXTURE_REPEAT || p_flag == FLAG_SUBSURFACE_MODE_SKIN) {
 		_change_notify();
 		_change_notify();
 	}
 	}
 	_queue_shader_change();
 	_queue_shader_change();
@@ -1540,8 +1602,8 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
 	_validate_feature("anisotropy", FEATURE_ANISOTROPY, property);
 	_validate_feature("anisotropy", FEATURE_ANISOTROPY, property);
 	_validate_feature("ao", FEATURE_AMBIENT_OCCLUSION, property);
 	_validate_feature("ao", FEATURE_AMBIENT_OCCLUSION, property);
 	_validate_feature("heightmap", FEATURE_HEIGHT_MAPPING, property);
 	_validate_feature("heightmap", FEATURE_HEIGHT_MAPPING, property);
-	_validate_feature("subsurf_scatter", FEATURE_SUBSURACE_SCATTERING, property);
-	_validate_feature("transmission", FEATURE_TRANSMISSION, property);
+	_validate_feature("subsurf_scatter", FEATURE_SUBSURFACE_SCATTERING, property);
+	_validate_feature("backlight", FEATURE_BACKLIGHT, property);
 	_validate_feature("refraction", FEATURE_REFRACTION, property);
 	_validate_feature("refraction", FEATURE_REFRACTION, property);
 	_validate_feature("detail", FEATURE_DETAIL, property);
 	_validate_feature("detail", FEATURE_DETAIL, property);
 
 
@@ -1575,6 +1637,10 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
 		property.usage = 0;
 		property.usage = 0;
 	}
 	}
 
 
+	if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (property.name == "subsurf_scatter_transmittance_color" || property.name == "subsurf_scatter_transmittance_texture" || property.name == "subsurf_scatter_transmittance_curve")) {
+		property.usage = 0;
+	}
+
 	if (orm) {
 	if (orm) {
 
 
 		if (property.name == "shading_mode") {
 		if (property.name == "shading_mode") {
@@ -1631,7 +1697,11 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
 			property.usage = 0;
 			property.usage = 0;
 		}
 		}
 
 
-		if (property.name.begins_with("transmission")) {
+		if (property.name.begins_with("backlight")) {
+			property.usage = 0;
+		}
+
+		if (property.name.begins_with("transmittance")) {
 			property.usage = 0;
 			property.usage = 0;
 		}
 		}
 	}
 	}
@@ -2070,8 +2140,20 @@ void BaseMaterial3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &BaseMaterial3D::set_subsurface_scattering_strength);
 	ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &BaseMaterial3D::set_subsurface_scattering_strength);
 	ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &BaseMaterial3D::get_subsurface_scattering_strength);
 	ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &BaseMaterial3D::get_subsurface_scattering_strength);
 
 
-	ClassDB::bind_method(D_METHOD("set_transmission", "transmission"), &BaseMaterial3D::set_transmission);
-	ClassDB::bind_method(D_METHOD("get_transmission"), &BaseMaterial3D::get_transmission);
+	ClassDB::bind_method(D_METHOD("set_transmittance_color", "color"), &BaseMaterial3D::set_transmittance_color);
+	ClassDB::bind_method(D_METHOD("get_transmittance_color"), &BaseMaterial3D::get_transmittance_color);
+
+	ClassDB::bind_method(D_METHOD("set_transmittance_depth", "depth"), &BaseMaterial3D::set_transmittance_depth);
+	ClassDB::bind_method(D_METHOD("get_transmittance_depth"), &BaseMaterial3D::get_transmittance_depth);
+
+	ClassDB::bind_method(D_METHOD("set_transmittance_curve", "curve"), &BaseMaterial3D::set_transmittance_curve);
+	ClassDB::bind_method(D_METHOD("get_transmittance_curve"), &BaseMaterial3D::get_transmittance_curve);
+
+	ClassDB::bind_method(D_METHOD("set_transmittance_boost", "boost"), &BaseMaterial3D::set_transmittance_boost);
+	ClassDB::bind_method(D_METHOD("get_transmittance_boost"), &BaseMaterial3D::get_transmittance_boost);
+
+	ClassDB::bind_method(D_METHOD("set_backlight", "backlight"), &BaseMaterial3D::set_backlight);
+	ClassDB::bind_method(D_METHOD("get_backlight"), &BaseMaterial3D::get_backlight);
 
 
 	ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &BaseMaterial3D::set_refraction);
 	ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &BaseMaterial3D::set_refraction);
 	ClassDB::bind_method(D_METHOD("get_refraction"), &BaseMaterial3D::get_refraction);
 	ClassDB::bind_method(D_METHOD("get_refraction"), &BaseMaterial3D::get_refraction);
@@ -2285,15 +2367,23 @@ void BaseMaterial3D::_bind_methods() {
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "heightmap_flip_texture"), "set_flag", "get_flag", FLAG_INVERT_HEIGHTMAP);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "heightmap_flip_texture"), "set_flag", "get_flag", FLAG_INVERT_HEIGHTMAP);
 
 
 	ADD_GROUP("Subsurf Scatter", "subsurf_scatter_");
 	ADD_GROUP("Subsurf Scatter", "subsurf_scatter_");
-	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURACE_SCATTERING);
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURFACE_SCATTERING);
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength");
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_skin_mode"), "set_flag", "get_flag", FLAG_SUBSURFACE_MODE_SKIN);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_skin_mode"), "set_flag", "get_flag", FLAG_SUBSURFACE_MODE_SKIN);
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_SCATTERING);
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_SCATTERING);
 
 
-	ADD_GROUP("Transmission", "transmission_");
-	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transmission_enabled"), "set_feature", "get_feature", FEATURE_TRANSMISSION);
-	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "transmission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_transmission", "get_transmission");
-	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "transmission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_TRANSMISSION);
+	ADD_SUBGROUP("Transmittance", "subsurf_scatter_transmittance_");
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_transmittance_enabled"), "set_feature", "get_feature", FEATURE_SUBSURFACE_TRANSMITTANCE);
+	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "subsurf_scatter_transmittance_color"), "set_transmittance_color", "get_transmittance_color");
+	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_transmittance_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_TRANSMITTANCE);
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_depth", PROPERTY_HINT_RANGE, "0.001,8,0.001,or_greater"), "set_transmittance_depth", "get_transmittance_depth");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_curve", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_transmittance_curve", "get_transmittance_curve");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_boost", PROPERTY_HINT_RANGE, "0.00,1.0,0.01"), "set_transmittance_boost", "get_transmittance_boost");
+
+	ADD_GROUP("Back Lighting", "backlight_");
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "backlight_enabled"), "set_feature", "get_feature", FEATURE_BACKLIGHT);
+	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "backlight", PROPERTY_HINT_COLOR_NO_ALPHA), "set_backlight", "get_backlight");
+	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "backlight_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_BACKLIGHT);
 
 
 	ADD_GROUP("Refraction", "refraction_");
 	ADD_GROUP("Refraction", "refraction_");
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "refraction_enabled"), "set_feature", "get_feature", FEATURE_REFRACTION);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "refraction_enabled"), "set_feature", "get_feature", FEATURE_REFRACTION);
@@ -2366,7 +2456,8 @@ void BaseMaterial3D::_bind_methods() {
 	BIND_ENUM_CONSTANT(TEXTURE_AMBIENT_OCCLUSION);
 	BIND_ENUM_CONSTANT(TEXTURE_AMBIENT_OCCLUSION);
 	BIND_ENUM_CONSTANT(TEXTURE_HEIGHTMAP);
 	BIND_ENUM_CONSTANT(TEXTURE_HEIGHTMAP);
 	BIND_ENUM_CONSTANT(TEXTURE_SUBSURFACE_SCATTERING);
 	BIND_ENUM_CONSTANT(TEXTURE_SUBSURFACE_SCATTERING);
-	BIND_ENUM_CONSTANT(TEXTURE_TRANSMISSION);
+	BIND_ENUM_CONSTANT(TEXTURE_SUBSURFACE_TRANSMITTANCE);
+	BIND_ENUM_CONSTANT(TEXTURE_BACKLIGHT);
 	BIND_ENUM_CONSTANT(TEXTURE_REFRACTION);
 	BIND_ENUM_CONSTANT(TEXTURE_REFRACTION);
 	BIND_ENUM_CONSTANT(TEXTURE_DETAIL_MASK);
 	BIND_ENUM_CONSTANT(TEXTURE_DETAIL_MASK);
 	BIND_ENUM_CONSTANT(TEXTURE_DETAIL_ALBEDO);
 	BIND_ENUM_CONSTANT(TEXTURE_DETAIL_ALBEDO);
@@ -2403,8 +2494,9 @@ void BaseMaterial3D::_bind_methods() {
 	BIND_ENUM_CONSTANT(FEATURE_ANISOTROPY);
 	BIND_ENUM_CONSTANT(FEATURE_ANISOTROPY);
 	BIND_ENUM_CONSTANT(FEATURE_AMBIENT_OCCLUSION);
 	BIND_ENUM_CONSTANT(FEATURE_AMBIENT_OCCLUSION);
 	BIND_ENUM_CONSTANT(FEATURE_HEIGHT_MAPPING);
 	BIND_ENUM_CONSTANT(FEATURE_HEIGHT_MAPPING);
-	BIND_ENUM_CONSTANT(FEATURE_SUBSURACE_SCATTERING);
-	BIND_ENUM_CONSTANT(FEATURE_TRANSMISSION);
+	BIND_ENUM_CONSTANT(FEATURE_SUBSURFACE_SCATTERING);
+	BIND_ENUM_CONSTANT(FEATURE_SUBSURFACE_TRANSMITTANCE);
+	BIND_ENUM_CONSTANT(FEATURE_BACKLIGHT);
 	BIND_ENUM_CONSTANT(FEATURE_REFRACTION);
 	BIND_ENUM_CONSTANT(FEATURE_REFRACTION);
 	BIND_ENUM_CONSTANT(FEATURE_DETAIL);
 	BIND_ENUM_CONSTANT(FEATURE_DETAIL);
 	BIND_ENUM_CONSTANT(FEATURE_MAX);
 	BIND_ENUM_CONSTANT(FEATURE_MAX);
@@ -2496,7 +2588,11 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
 	set_anisotropy(0);
 	set_anisotropy(0);
 	set_heightmap_scale(0.05);
 	set_heightmap_scale(0.05);
 	set_subsurface_scattering_strength(0);
 	set_subsurface_scattering_strength(0);
-	set_transmission(Color(0, 0, 0));
+	set_backlight(Color(0, 0, 0));
+	set_transmittance_color(Color(1, 1, 1, 1));
+	set_transmittance_depth(0.1);
+	set_transmittance_curve(1.0);
+	set_transmittance_boost(0.0);
 	set_refraction(0.05);
 	set_refraction(0.05);
 	set_point_size(1);
 	set_point_size(1);
 	set_uv1_offset(Vector3(0, 0, 0));
 	set_uv1_offset(Vector3(0, 0, 0));
@@ -2552,7 +2648,8 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
 		features[i] = false;
 		features[i] = false;
 	}
 	}
 
 
-	current_key.key = 0;
+	current_key.key0 = 0;
+	current_key.key1 = 0;
 	current_key.invalid_key = 1;
 	current_key.invalid_key = 1;
 	texture_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
 	texture_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
 	_queue_shader_change();
 	_queue_shader_change();

+ 41 - 10
scene/resources/material.h

@@ -125,7 +125,8 @@ public:
 		TEXTURE_AMBIENT_OCCLUSION,
 		TEXTURE_AMBIENT_OCCLUSION,
 		TEXTURE_HEIGHTMAP,
 		TEXTURE_HEIGHTMAP,
 		TEXTURE_SUBSURFACE_SCATTERING,
 		TEXTURE_SUBSURFACE_SCATTERING,
-		TEXTURE_TRANSMISSION,
+		TEXTURE_SUBSURFACE_TRANSMITTANCE,
+		TEXTURE_BACKLIGHT,
 		TEXTURE_REFRACTION,
 		TEXTURE_REFRACTION,
 		TEXTURE_DETAIL_MASK,
 		TEXTURE_DETAIL_MASK,
 		TEXTURE_DETAIL_ALBEDO,
 		TEXTURE_DETAIL_ALBEDO,
@@ -173,8 +174,9 @@ public:
 		FEATURE_ANISOTROPY,
 		FEATURE_ANISOTROPY,
 		FEATURE_AMBIENT_OCCLUSION,
 		FEATURE_AMBIENT_OCCLUSION,
 		FEATURE_HEIGHT_MAPPING,
 		FEATURE_HEIGHT_MAPPING,
-		FEATURE_SUBSURACE_SCATTERING,
-		FEATURE_TRANSMISSION,
+		FEATURE_SUBSURFACE_SCATTERING,
+		FEATURE_SUBSURFACE_TRANSMITTANCE,
+		FEATURE_BACKLIGHT,
 		FEATURE_REFRACTION,
 		FEATURE_REFRACTION,
 		FEATURE_DETAIL,
 		FEATURE_DETAIL,
 		FEATURE_MAX
 		FEATURE_MAX
@@ -291,10 +293,16 @@ private:
 			uint64_t roughness_channel : 3;
 			uint64_t roughness_channel : 3;
 		};
 		};
 
 
-		uint64_t key;
+		struct {
+			uint64_t key0;
+			uint64_t key1;
+		};
 
 
+		bool operator==(const MaterialKey &p_key) const {
+			return (key0 == p_key.key0) && (key1 == p_key.key1);
+		}
 		bool operator<(const MaterialKey &p_key) const {
 		bool operator<(const MaterialKey &p_key) const {
-			return key < p_key.key;
+			return (key0 == p_key.key0) ? (key1 < p_key.key1) : (key0 < p_key.key0);
 		}
 		}
 	};
 	};
 
 
@@ -310,7 +318,8 @@ private:
 	_FORCE_INLINE_ MaterialKey _compute_key() const {
 	_FORCE_INLINE_ MaterialKey _compute_key() const {
 
 
 		MaterialKey mk;
 		MaterialKey mk;
-		mk.key = 0;
+		mk.key0 = 0;
+		mk.key1 = 0;
 		for (int i = 0; i < FEATURE_MAX; i++) {
 		for (int i = 0; i < FEATURE_MAX; i++) {
 			if (features[i]) {
 			if (features[i]) {
 				mk.feature_mask |= ((uint64_t)1 << i);
 				mk.feature_mask |= ((uint64_t)1 << i);
@@ -357,7 +366,11 @@ private:
 		StringName anisotropy;
 		StringName anisotropy;
 		StringName heightmap_scale;
 		StringName heightmap_scale;
 		StringName subsurface_scattering_strength;
 		StringName subsurface_scattering_strength;
-		StringName transmission;
+		StringName transmittance_color;
+		StringName transmittance_curve;
+		StringName transmittance_depth;
+		StringName transmittance_boost;
+		StringName backlight;
 		StringName refraction;
 		StringName refraction;
 		StringName point_size;
 		StringName point_size;
 		StringName uv1_scale;
 		StringName uv1_scale;
@@ -415,7 +428,13 @@ private:
 	float anisotropy;
 	float anisotropy;
 	float heightmap_scale;
 	float heightmap_scale;
 	float subsurface_scattering_strength;
 	float subsurface_scattering_strength;
-	Color transmission;
+	float transmittance_amount;
+	Color transmittance_color;
+	float transmittance_depth;
+	float transmittance_curve;
+	float transmittance_boost;
+
+	Color backlight;
 	float refraction;
 	float refraction;
 	float point_size;
 	float point_size;
 	float alpha_scissor_threshold;
 	float alpha_scissor_threshold;
@@ -546,8 +565,20 @@ public:
 	void set_subsurface_scattering_strength(float p_subsurface_scattering_strength);
 	void set_subsurface_scattering_strength(float p_subsurface_scattering_strength);
 	float get_subsurface_scattering_strength() const;
 	float get_subsurface_scattering_strength() const;
 
 
-	void set_transmission(const Color &p_transmission);
-	Color get_transmission() const;
+	void set_transmittance_color(const Color &p_color);
+	Color get_transmittance_color() const;
+
+	void set_transmittance_depth(float p_depth);
+	float get_transmittance_depth() const;
+
+	void set_transmittance_curve(float p_curve);
+	float get_transmittance_curve() const;
+
+	void set_transmittance_boost(float p_boost);
+	float get_transmittance_boost() const;
+
+	void set_backlight(const Color &p_backlight);
+	Color get_backlight() const;
 
 
 	void set_refraction(float p_refraction);
 	void set_refraction(float p_refraction);
 	float get_refraction() const;
 	float get_refraction() const;

+ 3 - 1
servers/rendering/rasterizer.h

@@ -106,6 +106,8 @@ public:
 	virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
 	virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
 	virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
 	virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
 
 
+	virtual void shadow_filter_set(RS::ShadowFilter p_filter) = 0;
+
 	struct InstanceBase;
 	struct InstanceBase;
 
 
 	struct InstanceDependency {
 	struct InstanceDependency {
@@ -229,7 +231,7 @@ public:
 
 
 	virtual RID light_instance_create(RID p_light) = 0;
 	virtual RID light_instance_create(RID p_light) = 0;
 	virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
 	virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
-	virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) = 0;
+	virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0) = 0;
 	virtual void light_instance_mark_visible(RID p_light_instance) = 0;
 	virtual void light_instance_mark_visible(RID p_light_instance) = 0;
 	virtual bool light_instances_can_render_shadow_cube() const {
 	virtual bool light_instances_can_render_shadow_cube() const {
 		return true;
 		return true;

+ 7 - 9
servers/rendering/rasterizer_rd/light_cluster_builder.h

@@ -170,17 +170,15 @@ public:
 				_add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count);
 				_add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count);
 			} break;
 			} break;
 			case LIGHT_TYPE_SPOT: {
 			case LIGHT_TYPE_SPOT: {
-				Vector3 v(0, 0, -1);
-				v.rotated(Vector3(0, 1, 0), Math::deg2rad(ld.spot_aperture)); //rotate in x-z
-				v.normalize();
-				v *= ld.radius;
-				v.y = v.x;
+
+				float r = ld.radius;
+				real_t len = Math::tan(Math::deg2rad(ld.spot_aperture)) * r;
 
 
 				aabb.position = xform.origin;
 				aabb.position = xform.origin;
-				aabb.expand_to(xform.xform(v));
-				aabb.expand_to(xform.xform(Vector3(-v.x, v.y, v.z)));
-				aabb.expand_to(xform.xform(Vector3(-v.x, -v.y, v.z)));
-				aabb.expand_to(xform.xform(Vector3(v.x, -v.y, v.z)));
+				aabb.expand_to(xform.xform(Vector3(len, len, -r)));
+				aabb.expand_to(xform.xform(Vector3(-len, len, -r)));
+				aabb.expand_to(xform.xform(Vector3(-len, -len, -r)));
+				aabb.expand_to(xform.xform(Vector3(len, -len, -r)));
 				_add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count);
 				_add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count);
 			} break;
 			} break;
 		}
 		}

+ 20 - 0
servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp

@@ -204,6 +204,25 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1
 	return uniform_set;
 	return uniform_set;
 }
 }
 
 
+void RasterizerEffectsRD::copy_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
+
+	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+	if (p_flip_y) {
+		blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
+	}
+
+	blur.push_constant.camera_z_near = p_z_near;
+	blur.push_constant.camera_z_far = p_z_far;
+
+	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_LINEARIZE_DEPTH].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+	RD::get_singleton()->draw_list_draw(draw_list, true);
+	RD::get_singleton()->draw_list_end();
+}
+
 void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) {
 void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) {
 
 
 	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
 	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -1127,6 +1146,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
 		blur_modes.push_back("\n#define MODE_SSAO_MERGE\n");
 		blur_modes.push_back("\n#define MODE_SSAO_MERGE\n");
 		blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
 		blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
 		blur_modes.push_back("\n#define MODE_MIPMAP\n");
 		blur_modes.push_back("\n#define MODE_MIPMAP\n");
+		blur_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
 
 
 		blur.shader.initialize(blur_modes);
 		blur.shader.initialize(blur_modes);
 		zeromem(&blur.push_constant, sizeof(BlurPushConstant));
 		zeromem(&blur.push_constant, sizeof(BlurPushConstant));

+ 2 - 0
servers/rendering/rasterizer_rd/rasterizer_effects_rd.h

@@ -71,6 +71,7 @@ class RasterizerEffectsRD {
 		BLUR_MODE_SSAO_MERGE,
 		BLUR_MODE_SSAO_MERGE,
 		BLUR_MODE_SIMPLY_COPY,
 		BLUR_MODE_SIMPLY_COPY,
 		BLUR_MODE_MIPMAP,
 		BLUR_MODE_MIPMAP,
+		BLUR_MODE_LINEARIZE_DEPTH,
 		BLUR_MODE_MAX,
 		BLUR_MODE_MAX,
 
 
 	};
 	};
@@ -540,6 +541,7 @@ public:
 
 
 	void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
 	void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
 	void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
 	void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
+	void copy_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
 	void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
 	void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
 	void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
 	void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
 
 

+ 84 - 27
servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp

@@ -109,6 +109,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
 	unshaded = false;
 	unshaded = false;
 	uses_vertex = false;
 	uses_vertex = false;
 	uses_sss = false;
 	uses_sss = false;
+	uses_transmittance = false;
 	uses_screen_texture = false;
 	uses_screen_texture = false;
 	uses_depth_texture = false;
 	uses_depth_texture = false;
 	uses_normal_texture = false;
 	uses_normal_texture = false;
@@ -142,6 +143,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
 	actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
 	actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
 
 
 	actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
 	actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
+	actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
 
 
 	actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
 	actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
 	actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
 	actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
@@ -944,7 +946,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
 	}
 	}
 }
 }
 
 
-void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers) {
+void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {
 
 
 	//CameraMatrix projection = p_cam_projection;
 	//CameraMatrix projection = p_cam_projection;
 	//projection.flip_y(); // Vulkan and modern APIs use Y-Down
 	//projection.flip_y(); // Vulkan and modern APIs use Y-Down
@@ -960,6 +962,9 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
 
 
 	scene_state.ubo.z_far = p_zfar;
 	scene_state.ubo.z_far = p_zfar;
 	scene_state.ubo.z_near = p_znear;
 	scene_state.ubo.z_near = p_znear;
+	scene_state.ubo.shadow_filter_mode = shadow_filter_get();
+
+	scene_state.ubo.pancake_shadows = p_pancake_shadows;
 
 
 	scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
 	scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
 	scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
 	scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
@@ -1481,9 +1486,43 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
 
 
 				Color shadow_col = storage->light_get_shadow_color(base).to_linear();
 				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;
+				if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
+					light_data.shadow_color1[0] = 1.0;
+					light_data.shadow_color1[1] = 0.0;
+					light_data.shadow_color1[2] = 0.0;
+					light_data.shadow_color1[3] = 1.0;
+					light_data.shadow_color2[0] = 0.0;
+					light_data.shadow_color2[1] = 1.0;
+					light_data.shadow_color2[2] = 0.0;
+					light_data.shadow_color2[3] = 1.0;
+					light_data.shadow_color3[0] = 0.0;
+					light_data.shadow_color3[1] = 0.0;
+					light_data.shadow_color3[2] = 1.0;
+					light_data.shadow_color3[3] = 1.0;
+					light_data.shadow_color4[0] = 1.0;
+					light_data.shadow_color4[1] = 1.0;
+					light_data.shadow_color4[2] = 0.0;
+					light_data.shadow_color4[3] = 1.0;
+
+				} else {
+
+					light_data.shadow_color1[0] = shadow_col.r;
+					light_data.shadow_color1[1] = shadow_col.g;
+					light_data.shadow_color1[2] = shadow_col.b;
+					light_data.shadow_color1[3] = 1.0;
+					light_data.shadow_color2[0] = shadow_col.r;
+					light_data.shadow_color2[1] = shadow_col.g;
+					light_data.shadow_color2[2] = shadow_col.b;
+					light_data.shadow_color2[3] = 1.0;
+					light_data.shadow_color3[0] = shadow_col.r;
+					light_data.shadow_color3[1] = shadow_col.g;
+					light_data.shadow_color3[2] = shadow_col.b;
+					light_data.shadow_color3[3] = 1.0;
+					light_data.shadow_color4[0] = shadow_col.r;
+					light_data.shadow_color4[1] = shadow_col.g;
+					light_data.shadow_color4[2] = shadow_col.b;
+					light_data.shadow_color4[3] = 1.0;
+				}
 
 
 				light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
 				light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
 
 
@@ -1507,6 +1546,11 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
 
 
 						CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
 						CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
 						light_data.shadow_split_offsets[j] = split;
 						light_data.shadow_split_offsets[j] = split;
+						float bias_scale = light_instance_get_shadow_bias_scale(li, j);
+						light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_scale;
+						light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * light_instance_get_directional_shadow_texel_size(li, j);
+						light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
+						light_data.shadow_transmittance_z_scale[j] = light_instance_get_shadow_range(li, j);
 						store_camera(shadow_mtx, light_data.shadow_matrices[j]);
 						store_camera(shadow_mtx, light_data.shadow_matrices[j]);
 					}
 					}
 
 
@@ -1581,14 +1625,6 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
 
 
 				light_data.mask = storage->light_get_cull_mask(base);
 				light_data.mask = storage->light_get_cull_mask(base);
 
 
-				Color shadow_color = storage->light_get_shadow_color(base);
-
-				bool has_shadow = p_using_shadows && storage->light_has_shadow(base);
-				light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
-				light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
-				light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
-				light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0;
-
 				light_data.atlas_rect[0] = 0;
 				light_data.atlas_rect[0] = 0;
 				light_data.atlas_rect[1] = 0;
 				light_data.atlas_rect[1] = 0;
 				light_data.atlas_rect[2] = 0;
 				light_data.atlas_rect[2] = 0;
@@ -1597,6 +1633,27 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
 				if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
 				if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
 					// fill in the shadow information
 					// fill in the shadow information
 
 
+					Color shadow_color = storage->light_get_shadow_color(base);
+
+					light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
+					light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
+					light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
+					light_data.shadow_color_enabled[3] = 255;
+
+					if (type == RS::LIGHT_SPOT) {
+						light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0);
+						float shadow_texel_size = Math::tan(Math::deg2rad(spot_angle)) * radius * 2.0;
+						shadow_texel_size *= light_instance_get_shadow_texel_size(li, p_shadow_atlas);
+
+						light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size;
+					} else { //omni
+						light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0;
+						float shadow_texel_size = light_instance_get_shadow_texel_size(li, p_shadow_atlas);
+						light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space
+					}
+
+					light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
+
 					Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
 					Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
 
 
 					if (type == RS::LIGHT_OMNI) {
 					if (type == RS::LIGHT_OMNI) {
@@ -1620,6 +1677,8 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
 						CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview;
 						CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview;
 						store_camera(shadow_mtx, light_data.shadow_matrix);
 						store_camera(shadow_mtx, light_data.shadow_matrix);
 					}
 					}
+				} else {
+					light_data.shadow_color_enabled[3] = 0;
 				}
 				}
 
 
 				light_instance_set_index(li, light_count);
 				light_instance_set_index(li, light_count);
@@ -1698,9 +1757,6 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
 
 
 	//scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
 	//scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
 
 
-	scene_state.ubo.shadow_z_offset = 0;
-	scene_state.ubo.shadow_z_slope_scale = 0;
-
 	Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
 	Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
 	scene_state.ubo.viewport_size[0] = vp_he.x;
 	scene_state.ubo.viewport_size[0] = vp_he.x;
 	scene_state.ubo.viewport_size[1] = vp_he.y;
 	scene_state.ubo.viewport_size[1] = vp_he.y;
@@ -2063,7 +2119,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
 	//disable all stuff
 	//disable all stuff
 #endif
 #endif
 }
 }
-void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip) {
+void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake) {
 
 
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 
 
@@ -2071,11 +2127,9 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **
 
 
 	render_pass++;
 	render_pass++;
 
 
-	scene_state.ubo.shadow_z_offset = p_bias;
-	scene_state.ubo.shadow_z_slope_scale = p_normal_bias;
 	scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
 	scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
 
 
-	_setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar);
+	_setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake);
 
 
 	render_list.clear();
 	render_list.clear();
 
 
@@ -2106,8 +2160,6 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform
 
 
 	render_pass++;
 	render_pass++;
 
 
-	scene_state.ubo.shadow_z_offset = 0;
-	scene_state.ubo.shadow_z_slope_scale = 0;
 	scene_state.ubo.dual_paraboloid_side = 0;
 	scene_state.ubo.dual_paraboloid_side = 0;
 
 
 	_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
 	_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
@@ -2204,7 +2256,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
 			u.binding = 5;
 			u.binding = 5;
-			u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+			u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.ids.push_back(scene_state.light_buffer);
 			u.ids.push_back(scene_state.light_buffer);
 			uniforms.push_back(u);
 			uniforms.push_back(u);
 		}
 		}
@@ -2463,11 +2515,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
 		}
 		}
 
 
 		{ //lights
 		{ //lights
-			scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData);
+			scene_state.max_lights = MIN(1024 * 1024, uniform_max_size) / sizeof(LightData); //1mb of lights
 			uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData);
 			uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData);
 			scene_state.lights = memnew_arr(LightData, scene_state.max_lights);
 			scene_state.lights = memnew_arr(LightData, scene_state.max_lights);
-			scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size);
-			defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
+			scene_state.light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
+			//defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
 
 
 			scene_state.max_directional_lights = 8;
 			scene_state.max_directional_lights = 8;
 			uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData);
 			uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData);
@@ -2569,7 +2621,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
 		actions.renames["ANISOTROPY"] = "anisotropy";
 		actions.renames["ANISOTROPY"] = "anisotropy";
 		actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
 		actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
 		actions.renames["SSS_STRENGTH"] = "sss_strength";
 		actions.renames["SSS_STRENGTH"] = "sss_strength";
-		actions.renames["TRANSMISSION"] = "transmission";
+		actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
+		actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
+		actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve";
+		actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
+		actions.renames["BACKLIGHT"] = "backlight";
 		actions.renames["AO"] = "ao";
 		actions.renames["AO"] = "ao";
 		actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
 		actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
 		actions.renames["EMISSION"] = "emission";
 		actions.renames["EMISSION"] = "emission";
@@ -2609,7 +2665,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
 		actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
 		actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
 
 
 		actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
 		actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
-		actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n";
+		actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
+		actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
 		actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
 		actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
 		actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
 		actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
 
 

+ 19 - 6
servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h

@@ -138,6 +138,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
 		bool unshaded;
 		bool unshaded;
 		bool uses_vertex;
 		bool uses_vertex;
 		bool uses_sss;
 		bool uses_sss;
+		bool uses_transmittance;
 		bool uses_screen_texture;
 		bool uses_screen_texture;
 		bool uses_depth_texture;
 		bool uses_depth_texture;
 		bool uses_normal_texture;
 		bool uses_normal_texture;
@@ -260,6 +261,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
 		uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
 		uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
 		float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
 		float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
 		float shadow_matrix[16];
 		float shadow_matrix[16];
+		float shadow_bias;
+		float shadow_normal_bias;
+		float transmittance_bias;
+		uint32_t pad;
 	};
 	};
 
 
 	struct DirectionalLightData {
 	struct DirectionalLightData {
@@ -268,14 +273,22 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
 		float energy;
 		float energy;
 		float color[3];
 		float color[3];
 		float specular;
 		float specular;
-		float shadow_color[3];
 		uint32_t mask;
 		uint32_t mask;
+		uint32_t pad[3];
 		uint32_t blend_splits;
 		uint32_t blend_splits;
 		uint32_t shadow_enabled;
 		uint32_t shadow_enabled;
 		float fade_from;
 		float fade_from;
 		float fade_to;
 		float fade_to;
+		float shadow_bias[4];
+		float shadow_normal_bias[4];
+		float shadow_transmittance_bias[4];
+		float shadow_transmittance_z_scale[4];
 		float shadow_split_offsets[4];
 		float shadow_split_offsets[4];
 		float shadow_matrices[4][16];
 		float shadow_matrices[4][16];
+		float shadow_color1[4];
+		float shadow_color2[4];
+		float shadow_color3[4];
+		float shadow_color4[4];
 	};
 	};
 
 
 	struct GIProbeData {
 	struct GIProbeData {
@@ -324,12 +337,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
 			float viewport_size[2];
 			float viewport_size[2];
 			float screen_pixel_size[2];
 			float screen_pixel_size[2];
 
 
-			float shadow_z_offset;
-			float shadow_z_slope_scale;
-
 			float time;
 			float time;
 			float reflection_multiplier;
 			float reflection_multiplier;
 
 
+			uint32_t pancake_shadows;
+			uint32_t shadow_filter_mode;
+
 			float ambient_light_color_energy[4];
 			float ambient_light_color_energy[4];
 
 
 			float ambient_color_sky_mix;
 			float ambient_color_sky_mix;
@@ -558,7 +571,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
 		PASS_MODE_DEPTH_MATERIAL,
 		PASS_MODE_DEPTH_MATERIAL,
 	};
 	};
 
 
-	void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false);
+	void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
 	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
 	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
 	void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
 	void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
 	void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
 	void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
@@ -572,7 +585,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
 
 
 protected:
 protected:
 	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
 	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
-	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
+	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake);
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
 
 
 public:
 public:

+ 24 - 7
servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp

@@ -2032,7 +2032,7 @@ void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const
 	light_instance->transform = p_transform;
 	light_instance->transform = p_transform;
 }
 }
 
 
-void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) {
+void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale) {
 
 
 	LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
 	LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
 	ERR_FAIL_COND(!light_instance);
 	ERR_FAIL_COND(!light_instance);
@@ -2048,6 +2048,7 @@ void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance
 	light_instance->shadow_transform[p_pass].farplane = p_far;
 	light_instance->shadow_transform[p_pass].farplane = p_far;
 	light_instance->shadow_transform[p_pass].split = p_split;
 	light_instance->shadow_transform[p_pass].split = p_split;
 	light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
 	light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
+	light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size;
 }
 }
 
 
 void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) {
 void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) {
@@ -3580,6 +3581,10 @@ void RasterizerSceneRD::sub_surface_scattering_set_scale(float p_scale, float p_
 	sss_depth_scale = p_depth_scale;
 	sss_depth_scale = p_depth_scale;
 }
 }
 
 
+void RasterizerSceneRD::shadow_filter_set(RS::ShadowFilter p_filter) {
+	shadow_filter = p_filter;
+}
+
 int RasterizerSceneRD::get_roughness_layers() const {
 int RasterizerSceneRD::get_roughness_layers() const {
 	return roughness_layers;
 	return roughness_layers;
 }
 }
@@ -3625,12 +3630,15 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 
 
 	bool using_dual_paraboloid = false;
 	bool using_dual_paraboloid = false;
 	bool using_dual_paraboloid_flip = false;
 	bool using_dual_paraboloid_flip = false;
+	float znear = 0;
 	float zfar = 0;
 	float zfar = 0;
 	RID render_fb;
 	RID render_fb;
 	RID render_texture;
 	RID render_texture;
 	float bias = 0;
 	float bias = 0;
 	float normal_bias = 0;
 	float normal_bias = 0;
 
 
+	bool use_pancake = false;
+	bool use_linear_depth = false;
 	bool render_cubemap = false;
 	bool render_cubemap = false;
 	bool finalize_cubemap = false;
 	bool finalize_cubemap = false;
 
 
@@ -3645,6 +3653,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 			light_instance->last_scene_shadow_pass = scene_pass;
 			light_instance->last_scene_shadow_pass = scene_pass;
 		}
 		}
 
 
+		use_pancake = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
 		light_projection = light_instance->shadow_transform[p_pass].camera;
 		light_projection = light_instance->shadow_transform[p_pass].camera;
 		light_transform = light_instance->shadow_transform[p_pass].transform;
 		light_transform = light_instance->shadow_transform[p_pass].transform;
 
 
@@ -3683,7 +3692,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 		light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
 		light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
 		light_instance->shadow_transform[p_pass].atlas_rect.size /= 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, RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
+		float bias_mult = light_instance->shadow_transform[p_pass].bias_scale;
 		zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
 		zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
 		bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
 		bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
 		normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult;
 		normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult;
@@ -3762,26 +3771,33 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 			ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
 			ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
 			render_fb = shadow_map->fb;
 			render_fb = shadow_map->fb;
 			render_texture = shadow_map->depth;
 			render_texture = shadow_map->depth;
+
+			znear = light_instance->shadow_transform[0].camera.get_z_near();
+			use_linear_depth = true;
 		}
 		}
 	}
 	}
 
 
 	if (render_cubemap) {
 	if (render_cubemap) {
 		//rendering to cubemap
 		//rendering to cubemap
-		_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false);
+		_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake);
 		if (finalize_cubemap) {
 		if (finalize_cubemap) {
 			//reblit
 			//reblit
 			atlas_rect.size.height /= 2;
 			atlas_rect.size.height /= 2;
-			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, false);
+			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, false);
 			atlas_rect.position.y += atlas_rect.size.height;
 			atlas_rect.position.y += atlas_rect.size.height;
-			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, true);
+			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, true);
 		}
 		}
 	} else {
 	} else {
 		//render shadow
 		//render shadow
 
 
-		_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip);
+		_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake);
 
 
 		//copy to atlas
 		//copy to atlas
-		storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true);
+		if (use_linear_depth) {
+			storage->get_effects()->copy_to_rect_and_linearize(render_texture, atlas_fb, atlas_rect, true, znear, zfar);
+		} else {
+			storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true);
+		}
 
 
 		//does not work from depth to color
 		//does not work from depth to color
 		//RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true);
 		//RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true);
@@ -4137,6 +4153,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
 	sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality")));
 	sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality")));
 	sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
 	sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
 	sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
 	sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
+	shadow_filter = RS::ShadowFilter(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
 }
 }
 
 
 RasterizerSceneRD::~RasterizerSceneRD() {
 RasterizerSceneRD::~RasterizerSceneRD() {

+ 57 - 6
servers/rendering/rasterizer_rd/rasterizer_scene_rd.h

@@ -79,7 +79,7 @@ protected:
 	virtual RenderBufferData *_create_render_buffer_data() = 0;
 	virtual RenderBufferData *_create_render_buffer_data() = 0;
 
 
 	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
 	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
-	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
+	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0;
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
 
 
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
@@ -527,6 +527,8 @@ private:
 
 
 	bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
 	bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
 
 
+	RS::ShadowFilter shadow_filter = RS::SHADOW_FILTER_NONE;
+
 	/* DIRECTIONAL SHADOW */
 	/* DIRECTIONAL SHADOW */
 
 
 	struct DirectionalShadow {
 	struct DirectionalShadow {
@@ -570,6 +572,7 @@ private:
 			float farplane;
 			float farplane;
 			float split;
 			float split;
 			float bias_scale;
 			float bias_scale;
+			float shadow_texel_size;
 			Rect2 atlas_rect;
 			Rect2 atlas_rect;
 		};
 		};
 
 
@@ -880,7 +883,7 @@ public:
 
 
 	RID light_instance_create(RID p_light);
 	RID light_instance_create(RID p_light);
 	void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
 	void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
-	void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
+	void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0);
 	void light_instance_mark_visible(RID p_light_instance);
 	void light_instance_mark_visible(RID p_light_instance);
 
 
 	_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
 	_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
@@ -926,11 +929,44 @@ public:
 		return li->shadow_transform[p_index].camera;
 		return li->shadow_transform[p_index].camera;
 	}
 	}
 
 
-	_FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
+	_FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) {
+
+#ifdef DEBUG_ENABLED
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0);
+#endif
+		ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+		ERR_FAIL_COND_V(!shadow_atlas, 0);
+#ifdef DEBUG_ENABLED
+		ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0);
+#endif
+		uint32_t key = shadow_atlas->shadow_owners[p_light_instance];
+
+		uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+
+		uint32_t quadrant_size = shadow_atlas->size >> 1;
+
+		uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+
+		return float(1.0) / shadow_size;
+	}
+
+	_FORCE_INLINE_ Transform
+	light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
 
 
 		LightInstance *li = light_instance_owner.getornull(p_light_instance);
 		LightInstance *li = light_instance_owner.getornull(p_light_instance);
 		return li->shadow_transform[p_index].transform;
 		return li->shadow_transform[p_index].transform;
 	}
 	}
+	_FORCE_INLINE_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) {
+
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->shadow_transform[p_index].bias_scale;
+	}
+	_FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) {
+
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->shadow_transform[p_index].farplane;
+	}
 
 
 	_FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
 	_FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
 
 
@@ -944,6 +980,12 @@ public:
 		return li->shadow_transform[p_index].split;
 		return li->shadow_transform[p_index].split;
 	}
 	}
 
 
+	_FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) {
+
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->shadow_transform[p_index].shadow_texel_size;
+	}
+
 	_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
 	_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);
 		LightInstance *li = light_instance_owner.getornull(p_light_instance);
 		li->last_pass = p_pass;
 		li->last_pass = p_pass;
@@ -1107,8 +1149,12 @@ public:
 
 
 	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
 	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
 
 
-	virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; }
-	_FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; }
+	virtual void set_scene_pass(uint64_t p_pass) {
+		scene_pass = p_pass;
+	}
+	_FORCE_INLINE_ uint64_t get_scene_pass() {
+		return scene_pass;
+	}
 
 
 	virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve);
 	virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve);
 	virtual bool screen_space_roughness_limiter_is_active() const;
 	virtual bool screen_space_roughness_limiter_is_active() const;
@@ -1118,6 +1164,9 @@ public:
 	RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
 	RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
 	virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale);
 	virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale);
 
 
+	virtual void shadow_filter_set(RS::ShadowFilter p_filter);
+	_FORCE_INLINE_ RS::ShadowFilter shadow_filter_get() const { return shadow_filter; }
+
 	int get_roughness_layers() const;
 	int get_roughness_layers() const;
 	bool is_using_radiance_cubemap_array() const;
 	bool is_using_radiance_cubemap_array() const;
 
 
@@ -1126,7 +1175,9 @@ public:
 	virtual void update();
 	virtual void update();
 
 
 	virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw);
 	virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw);
-	_FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const { return debug_draw; }
+	_FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const {
+		return debug_draw;
+	}
 
 
 	virtual void set_time(double p_time, double p_step);
 	virtual void set_time(double p_time, double p_step);
 
 

+ 5 - 3
servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp

@@ -3105,14 +3105,15 @@ RID RasterizerStorageRD::light_create(RS::LightType p_type) {
 	light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
 	light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
 	light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
 	light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
 	light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
 	light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
-	light.param[RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45;
 	light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
 	light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
 	light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
 	light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
-	light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
-	light.param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
+	light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+	light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+	light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
+	light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
 
 
 	return light_owner.make_rid(light);
 	return light_owner.make_rid(light);
 }
 }
@@ -3138,6 +3139,7 @@ void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, f
 		case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
 		case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
 		case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
 		case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
 		case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
 		case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+		case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
 		case RS::LIGHT_PARAM_SHADOW_BIAS: {
 		case RS::LIGHT_PARAM_SHADOW_BIAS: {
 
 
 			light->version++;
 			light->version++;

+ 8 - 0
servers/rendering/rasterizer_rd/rasterizer_storage_rd.h

@@ -926,6 +926,14 @@ public:
 		return light->negative;
 		return light->negative;
 	}
 	}
 
 
+	_FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
+
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, 0.0);
+
+		return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
+	}
+
 	bool light_get_use_gi(RID p_light);
 	bool light_get_use_gi(RID p_light);
 	uint64_t light_get_version(RID p_light) const;
 	uint64_t light_get_version(RID p_light) const;
 
 

+ 7 - 0
servers/rendering/rasterizer_rd/shaders/blur.glsl

@@ -285,6 +285,13 @@ void main() {
 	frag_color = color;
 	frag_color = color;
 #endif
 #endif
 
 
+#ifdef MODE_LINEARIZE_DEPTH_COPY
+	float depth = texture(source_color, uv_interp, 0.0).r;
+	depth = depth * 2.0 - 1.0;
+	depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
+	frag_color = vec4(depth / blur.camera_z_far);
+#endif
+
 #ifdef MODE_SSAO_MERGE
 #ifdef MODE_SSAO_MERGE
 	vec4 color = texture(source_color, uv_interp, 0.0);
 	vec4 color = texture(source_color, uv_interp, 0.0);
 	float ssao = texture(source_ssao, uv_interp, 0.0).r;
 	float ssao = texture(source_ssao, uv_interp, 0.0).r;

+ 2 - 1
servers/rendering/rasterizer_rd/shaders/copy.glsl

@@ -57,6 +57,7 @@ void main() {
 	}
 	}
 
 
 	float depth = texture(source_cube, normal).r;
 	float depth = texture(source_cube, normal).r;
+	depth_buffer = depth;
 
 
 	// absolute values for direction cosines, bigger value equals closer to basis axis
 	// absolute values for direction cosines, bigger value equals closer to basis axis
 	vec3 unorm = abs(normal);
 	vec3 unorm = abs(normal);
@@ -80,7 +81,7 @@ void main() {
 
 
 	depth = 2.0 * depth - 1.0;
 	depth = 2.0 * depth - 1.0;
 	float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
 	float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
-	depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
+	depth_buffer = (linear_depth * depth_fix) / params.z_far;
 
 
 #endif
 #endif
 }
 }

+ 365 - 90
servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl

@@ -244,19 +244,13 @@ VERTEX_SHADER_CODE
 
 
 	//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
 	//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
 
 
-	vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
+	vec3 vtx = vertex_interp;
 	float distance = length(vtx);
 	float distance = length(vtx);
 	vtx = normalize(vtx);
 	vtx = normalize(vtx);
 	vtx.xy /= 1.0 - vtx.z;
 	vtx.xy /= 1.0 - vtx.z;
 	vtx.z = (distance / scene_data.z_far);
 	vtx.z = (distance / scene_data.z_far);
 	vtx.z = vtx.z * 2.0 - 1.0;
 	vtx.z = vtx.z * 2.0 - 1.0;
-
 	vertex_interp = vtx;
 	vertex_interp = vtx;
-#else
-
-	float z_ofs = scene_data.z_offset;
-	z_ofs += max(0.0, 1.0 - abs(normalize(normal_interp).z)) * scene_data.z_slope_scale;
-	vertex_interp.z -= z_ofs;
 
 
 #endif
 #endif
 
 
@@ -267,6 +261,14 @@ VERTEX_SHADER_CODE
 #else
 #else
 	gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
 	gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
 #endif
 #endif
+
+#ifdef MODE_RENDER_DEPTH
+	if (scene_data.pancake_shadows) {
+		if (gl_Position.z <= 0.00001) {
+			gl_Position.z = 0.00001;
+		}
+	}
+#endif
 }
 }
 
 
 /* clang-format off */
 /* clang-format off */
@@ -315,6 +317,11 @@ layout(location = 8) in float dp_clip;
 #define world_normal_matrix instances.data[instance_index].normal_transform
 #define world_normal_matrix instances.data[instance_index].normal_transform
 #define projection_matrix scene_data.projection_matrix
 #define projection_matrix scene_data.projection_matrix
 
 
+#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
+//both required for transmittance to be enabled
+#define LIGHT_TRANSMITTANCE_USED
+#endif
+
 #ifdef USE_MATERIAL_UNIFORMS
 #ifdef USE_MATERIAL_UNIFORMS
 layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
 layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
 	/* clang-format off */
 	/* clang-format off */
@@ -434,9 +441,16 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
 	return mix(vec3(dielectric), albedo, vec3(metallic));
 	return mix(vec3(dielectric), albedo, vec3(metallic));
 }
 }
 
 
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
-		vec3 transmission,
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, vec3 shadow_attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+		vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+		vec4 transmittance_color,
+		float transmittance_depth,
+		float transmittance_curve,
+		float transmittance_boost,
+		float transmittance_z,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 		float rim, float rim_tint,
 		float rim, float rim_tint,
@@ -538,16 +552,48 @@ LIGHT_SHADER_CODE
 		diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
 		diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
 #endif
 #endif
 
 
-		diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
+		diffuse_light += light_color * diffuse_color * shadow_attenuation * diffuse_brdf_NL * attenuation;
 
 
-#if defined(LIGHT_TRANSMISSION_USED)
-		diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
+#if defined(LIGHT_BACKLIGHT_USED)
+		diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
 #endif
 #endif
 
 
 #if defined(LIGHT_RIM_USED)
 #if defined(LIGHT_RIM_USED)
 		float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
 		float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
 		diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
 		diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
 #endif
 #endif
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+
+#ifdef SSS_MODE_SKIN
+
+		{
+			float scale = 8.25 / transmittance_depth;
+			float d = scale * abs(transmittance_z);
+			float dd = -d * d;
+			vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
+						   vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
+						   vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
+						   vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
+						   vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
+						   vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
+
+			diffuse_light += profile * transmittance_color.a * diffuse_color * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI) * attenuation;
+		}
+#else
+
+		if (transmittance_depth > 0.0) {
+			float fade = clamp(abs(transmittance_z / transmittance_depth), 0.0, 1.0);
+
+			fade = pow(max(0.0, 1.0 - fade), transmittance_curve);
+			fade *= clamp(transmittance_boost - NdotL, 0.0, 1.0);
+
+			diffuse_light += diffuse_color * transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade * attenuation;
+		}
+
+#endif //SSS_MODE_SKIN
+
+#endif //LIGHT_TRANSMITTANCE_USED
 	}
 	}
 
 
 	if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
 	if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
@@ -562,7 +608,7 @@ LIGHT_SHADER_CODE
 		blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
 		blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
 		float intensity = blinn;
 		float intensity = blinn;
 
 
-		specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+		specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
 
 
 #elif defined(SPECULAR_PHONG)
 #elif defined(SPECULAR_PHONG)
 
 
@@ -573,7 +619,7 @@ LIGHT_SHADER_CODE
 		phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
 		phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
 		float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
 		float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
 
 
-		specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+		specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
 
 
 #elif defined(SPECULAR_TOON)
 #elif defined(SPECULAR_TOON)
 
 
@@ -582,7 +628,7 @@ LIGHT_SHADER_CODE
 		float mid = 1.0 - roughness;
 		float mid = 1.0 - roughness;
 		mid *= mid;
 		mid *= mid;
 		float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
 		float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
-		diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
+		diffuse_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
 
 
 #elif defined(SPECULAR_DISABLED)
 #elif defined(SPECULAR_DISABLED)
 		// none..
 		// none..
@@ -613,7 +659,7 @@ LIGHT_SHADER_CODE
 
 
 		vec3 specular_brdf_NL = cNdotL * D * F * G;
 		vec3 specular_brdf_NL = cNdotL * D * F * G;
 
 
-		specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+		specular_light += specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
 #endif
 #endif
 
 
 #if defined(LIGHT_CLEARCOAT_USED)
 #if defined(LIGHT_CLEARCOAT_USED)
@@ -627,12 +673,12 @@ LIGHT_SHADER_CODE
 
 
 		float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
 		float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
 
 
-		specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+		specular_light += clearcoat_specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
 #endif
 #endif
 	}
 	}
 
 
 #ifdef USE_SHADOW_TO_OPACITY
 #ifdef USE_SHADOW_TO_OPACITY
-	alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0));
+	alpha = min(alpha, clamp(1.0 - length(shadow_attenuation * attenuation), 0.0, 1.0));
 #endif
 #endif
 
 
 #endif //defined(USE_LIGHT_SHADER_CODE)
 #endif //defined(USE_LIGHT_SHADER_CODE)
@@ -642,51 +688,54 @@ LIGHT_SHADER_CODE
 
 
 float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
 float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
 
 
-	//todo optimize
 	vec2 pos = coord.xy;
 	vec2 pos = coord.xy;
 	float depth = coord.z;
 	float depth = coord.z;
 
 
-#ifdef SHADOW_MODE_PCF_13
-
-	float avg = textureProj(shadow, vec4(pos, depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
-	return avg * (1.0 / 13.0);
-#endif
-
-#ifdef SHADOW_MODE_PCF_5
-
-	float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
-	avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
-	return avg * (1.0 / 5.0);
-
-#endif
-
-#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
-
-	return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+	switch (scene_data.shadow_filter_mode) {
+		case SHADOW_MODE_NO_FILTER: {
+			return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+		};
+		case SHADOW_MODE_PCF5: {
+			float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+			return avg * (1.0 / 5.0);
+		};
+		case SHADOW_MODE_PCF13: {
+
+			float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
+			avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
+			return avg * (1.0 / 13.0);
+		};
+	}
 
 
-#endif
+	return 0;
 }
 }
 
 
 #endif //USE_NO_SHADOWS
 #endif //USE_NO_SHADOWS
 
 
 void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
 void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
-		vec3 transmission,
+#ifdef LIGHT_BACKLIGHT_USED
+		vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+		vec4 transmittance_color,
+		float transmittance_depth,
+		float transmittance_curve,
+		float transmittance_boost,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 		float rim, float rim_tint,
 		float rim, float rim_tint,
@@ -707,18 +756,33 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 	float normalized_distance = light_length * lights.data[idx].inv_radius;
 	float normalized_distance = light_length * lights.data[idx].inv_radius;
 	vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
 	vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
 	float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
 	float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
-	vec3 light_attenuation = vec3(omni_attenuation);
+	float light_attenuation = omni_attenuation;
+	vec3 shadow_attenuation = vec3(1.0);
 	vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
 	vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
 	color_specular.rgb *= attenuation_energy.y;
 	color_specular.rgb *= attenuation_energy.y;
 
 
+#ifdef LIGHT_TRANSMITTANCE_USED
+	float transmittance_z = transmittance_depth; //no transmittance by default
+#endif
+
 #ifndef USE_NO_SHADOWS
 #ifndef USE_NO_SHADOWS
 	vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
 	vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
 	if (shadow_color_enabled.w > 0.5) {
 	if (shadow_color_enabled.w > 0.5) {
 		// there is a shadowmap
 		// there is a shadowmap
 
 
-		vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
-		float shadow_len = length(splane);
-		splane = normalize(splane);
+		vec4 v = vec4(vertex, 1.0);
+
+		vec4 splane = (lights.data[idx].shadow_matrix * v);
+		float shadow_len = length(splane.xyz);
+
+		{
+			vec3 nofs = normal_interp * lights.data[idx].shadow_normal_bias / lights.data[idx].inv_radius;
+			nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp))));
+			v.xyz += nofs;
+			splane = (lights.data[idx].shadow_matrix * v);
+		}
+
+		splane.xyz = normalize(splane.xyz);
 		vec4 clamp_rect = lights.data[idx].atlas_rect;
 		vec4 clamp_rect = lights.data[idx].atlas_rect;
 
 
 		if (splane.z >= 0.0) {
 		if (splane.z >= 0.0) {
@@ -728,24 +792,60 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 			clamp_rect.y += clamp_rect.w;
 			clamp_rect.y += clamp_rect.w;
 
 
 		} else {
 		} else {
-
 			splane.z = 1.0 - splane.z;
 			splane.z = 1.0 - splane.z;
 		}
 		}
 
 
 		splane.xy /= splane.z;
 		splane.xy /= splane.z;
+
 		splane.xy = splane.xy * 0.5 + 0.5;
 		splane.xy = splane.xy * 0.5 + 0.5;
-		splane.z = shadow_len * lights.data[idx].inv_radius;
+		splane.z = (shadow_len - lights.data[idx].shadow_bias) * lights.data[idx].inv_radius;
 		splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
 		splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
 		splane.w = 1.0; //needed? i think it should be 1 already
 		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);
 		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
 
 
-		light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+#ifdef LIGHT_TRANSMITTANCE_USED
+		{
+
+			//redo shadowmapping, but shrink the model a bit to avoid arctifacts
+			splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
+
+			shadow_len = length(splane);
+			splane = normalize(splane);
+
+			if (splane.z >= 0.0) {
+
+				splane.z += 1.0;
+
+			} else {
+
+				splane.z = 1.0 - splane.z;
+			}
+
+			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;
+			splane.w = 1.0; //needed? i think it should be 1 already
+
+			float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
+			transmittance_z = (splane.z - shadow_z) / lights.data[idx].inv_radius;
+		}
+#endif
+
+		shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
 	}
 	}
 #endif //USE_NO_SHADOWS
 #endif //USE_NO_SHADOWS
 
 
-	light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
-			transmission,
+	light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+			backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+			transmittance_color,
+			transmittance_depth,
+			transmittance_curve,
+			transmittance_boost,
+			transmittance_z,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 			rim * omni_attenuation, rim_tint,
 			rim * omni_attenuation, rim_tint,
@@ -764,8 +864,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 }
 }
 
 
 void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
 void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
-		vec3 transmission,
+#ifdef LIGHT_BACKLIGHT_USED
+		vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+		vec4 transmittance_color,
+		float transmittance_depth,
+		float transmittance_curve,
+		float transmittance_boost,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 		float rim, float rim_tint,
 		float rim, float rim_tint,
@@ -792,7 +898,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 	float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
 	float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
 	float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
 	float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
 	spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
 	spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
-	vec3 light_attenuation = vec3(spot_attenuation);
+	float light_attenuation = spot_attenuation;
+	vec3 shadow_attenuation = vec3(1.0);
 	vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
 	vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
 	color_specular.rgb *= attenuation_energy.y;
 	color_specular.rgb *= attenuation_energy.y;
 
 
@@ -801,22 +908,58 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
 		//use projector texture
 		//use projector texture
 	}
 	}
 	*/
 	*/
+#ifdef LIGHT_TRANSMITTANCE_USED
+	float transmittance_z = transmittance_depth;
+#endif
+
 #ifndef USE_NO_SHADOWS
 #ifndef USE_NO_SHADOWS
 	vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
 	vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
 	if (shadow_color_enabled.w > 0.5) {
 	if (shadow_color_enabled.w > 0.5) {
 		//there is a shadowmap
 		//there is a shadowmap
-		vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+		vec4 v = vec4(vertex, 1.0);
+
+		v.xyz -= spot_dir * lights.data[idx].shadow_bias;
+
+		float depth_bias_scale = 1.0 / (max(0.0001, dot(spot_dir, -light_rel_vec) * lights.data[idx].inv_radius)); //the closer to the light origin, the more you have to offset to reach 1px in the map
+		vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * lights.data[idx].shadow_normal_bias * depth_bias_scale;
+		normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z
+		v.xyz += normal_bias;
+
+		vec4 splane = (lights.data[idx].shadow_matrix * v);
 		splane /= splane.w;
 		splane /= splane.w;
+		splane.z = dot(spot_dir, v.xyz - lights.data[idx].position) * lights.data[idx].inv_radius;
 		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
 		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
 
 
-		light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+		shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+		{
+
+			splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
+			splane /= splane.w;
+
+			float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
+			//reconstruct depth
+			shadow_z / lights.data[idx].inv_radius;
+			//distance to light plane
+			float z = dot(spot_dir, -light_rel_vec);
+			transmittance_z = z - shadow_z;
+		}
+#endif //LIGHT_TRANSMITTANCE_USED
 	}
 	}
 
 
 #endif //USE_NO_SHADOWS
 #endif //USE_NO_SHADOWS
 
 
-	light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
-			transmission,
+	light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+			backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+			transmittance_color,
+			transmittance_depth,
+			transmittance_curve,
+			transmittance_boost,
+			transmittance_z,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 			rim * spot_attenuation, rim_tint,
 			rim * spot_attenuation, rim_tint,
@@ -1185,7 +1328,11 @@ void main() {
 	vec3 vertex = vertex_interp;
 	vec3 vertex = vertex_interp;
 	vec3 view = -normalize(vertex_interp);
 	vec3 view = -normalize(vertex_interp);
 	vec3 albedo = vec3(1.0);
 	vec3 albedo = vec3(1.0);
-	vec3 transmission = vec3(0.0);
+	vec3 backlight = vec3(0.0);
+	vec4 transmittance_color = vec4(0.0);
+	float transmittance_depth = 0.0;
+	float transmittance_curve = 1.0;
+	float transmittance_boost = 0.0;
 	float metallic = 0.0;
 	float metallic = 0.0;
 	float specular = 0.5;
 	float specular = 0.5;
 	vec3 emission = vec3(0.0);
 	vec3 emission = vec3(0.0);
@@ -1254,6 +1401,14 @@ FRAGMENT_SHADER_CODE
 		/* clang-format on */
 		/* clang-format on */
 	}
 	}
 
 
+#if defined(LIGHT_TRANSMITTANCE_USED)
+#ifdef SSS_MODE_SKIN
+	transmittance_color.a = sss_strength;
+#else
+	transmittance_color.a *= sss_strength;
+#endif
+#endif
+
 #if !defined(USE_SHADOW_TO_OPACITY)
 #if !defined(USE_SHADOW_TO_OPACITY)
 
 
 #if defined(ALPHA_SCISSOR_USED)
 #if defined(ALPHA_SCISSOR_USED)
@@ -1462,21 +1617,109 @@ FRAGMENT_SHADER_CODE
 				continue; //not masked
 				continue; //not masked
 			}
 			}
 
 
-			vec3 light_attenuation = vec3(1.0);
+			vec3 shadow_attenuation = vec3(1.0);
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+			float transmittance_z = transmittance_depth;
+#endif
 
 
 			if (directional_lights.data[i].shadow_enabled) {
 			if (directional_lights.data[i].shadow_enabled) {
 				float depth_z = -vertex.z;
 				float depth_z = -vertex.z;
 
 
 				vec4 pssm_coord;
 				vec4 pssm_coord;
+				vec3 shadow_color = vec3(0.0);
+				vec3 light_dir = directional_lights.data[i].direction;
+
+#define BIAS_FUNC(m_var, m_idx)                                                                                                                                       \
+	m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx];                                                                                           \
+	vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \
+	normal_bias -= light_dir * dot(light_dir, normal_bias);                                                                                                           \
+	m_var.xyz += normal_bias;
 
 
 				if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
 				if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
-					pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
+					vec4 v = vec4(vertex, 1.0);
+
+					BIAS_FUNC(v, 0)
+
+					pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+					shadow_color = directional_lights.data[i].shadow_color1.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+					{
+						vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
+						vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
+						trans_coord /= trans_coord.w;
+
+						float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+						shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
+						float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
+
+						transmittance_z = z - shadow_z;
+					}
+#endif
 				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
 				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
-					pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+
+					vec4 v = vec4(vertex, 1.0);
+
+					BIAS_FUNC(v, 1)
+
+					pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+					shadow_color = directional_lights.data[i].shadow_color2.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+					{
+						vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
+						vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
+						trans_coord /= trans_coord.w;
+
+						float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+						shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
+						float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
+
+						transmittance_z = z - shadow_z;
+					}
+#endif
 				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
 				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
-					pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+
+					vec4 v = vec4(vertex, 1.0);
+
+					BIAS_FUNC(v, 2)
+
+					pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+					shadow_color = directional_lights.data[i].shadow_color3.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+					{
+						vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
+						vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
+						trans_coord /= trans_coord.w;
+
+						float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+						shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
+						float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
+
+						transmittance_z = z - shadow_z;
+					}
+#endif
+
 				} else {
 				} else {
-					pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
+
+					vec4 v = vec4(vertex, 1.0);
+
+					BIAS_FUNC(v, 3)
+
+					pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+					shadow_color = directional_lights.data[i].shadow_color4.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+					{
+						vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
+						vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
+						trans_coord /= trans_coord.w;
+
+						float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+						shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
+						float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
+
+						transmittance_z = z - shadow_z;
+					}
+#endif
 				}
 				}
 
 
 				pssm_coord /= pssm_coord.w;
 				pssm_coord /= pssm_coord.w;
@@ -1485,17 +1728,27 @@ FRAGMENT_SHADER_CODE
 
 
 				if (directional_lights.data[i].blend_splits) {
 				if (directional_lights.data[i].blend_splits) {
 
 
+					vec3 shadow_color_blend = vec3(0.0);
 					float pssm_blend;
 					float pssm_blend;
 
 
 					if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
 					if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
-						pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+						vec4 v = vec4(vertex, 1.0);
+						BIAS_FUNC(v, 1)
+						pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
 						pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
 						pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+						shadow_color_blend = directional_lights.data[i].shadow_color2.rgb;
 					} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
 					} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
-						pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+						vec4 v = vec4(vertex, 1.0);
+						BIAS_FUNC(v, 2)
+						pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
 						pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
 						pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+						shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
 					} else if (depth_z < directional_lights.data[i].shadow_split_offsets.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));
+						vec4 v = vec4(vertex, 1.0);
+						BIAS_FUNC(v, 3)
+						pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
 						pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
 						pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+						shadow_color_blend = directional_lights.data[i].shadow_color4.rgb;
 					} else {
 					} 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_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
 					}
 					}
@@ -1504,16 +1757,26 @@ FRAGMENT_SHADER_CODE
 
 
 					float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
 					float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
 					shadow = mix(shadow, shadow2, pssm_blend);
 					shadow = mix(shadow, shadow2, pssm_blend);
+					shadow_color = mix(shadow_color, shadow_color_blend, 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
 				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 = mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
+				shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
+
+#undef BIAS_FUNC
 			}
 			}
 
 
-			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,
+			light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, 1.0, shadow_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+					backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+					transmittance_color,
+					transmittance_depth,
+					transmittance_curve,
+					transmittance_boost,
+					transmittance_z,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 					rim, rim_tint,
 					rim, rim_tint,
@@ -1546,8 +1809,14 @@ FRAGMENT_SHADER_CODE
 			}
 			}
 
 
 			light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
 			light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
-					transmission,
+#ifdef LIGHT_BACKLIGHT_USED
+					backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+					transmittance_color,
+					transmittance_depth,
+					transmittance_curve,
+					transmittance_boost,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 					rim,
 					rim,
@@ -1579,8 +1848,14 @@ FRAGMENT_SHADER_CODE
 			}
 			}
 
 
 			light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
 			light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
-					transmission,
+#ifdef LIGHT_BACKLIGHT_USED
+					backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+					transmittance_color,
+					transmittance_depth,
+					transmittance_curve,
+					transmittance_boost,
 #endif
 #endif
 #ifdef LIGHT_RIM_USED
 #ifdef LIGHT_RIM_USED
 					rim,
 					rim,

+ 26 - 9
servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl

@@ -22,6 +22,10 @@ draw_call;
 #define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
 #define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
 #define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
 #define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
 
 
+#define SHADOW_MODE_NO_FILTER 0
+#define SHADOW_MODE_PCF5 1
+#define SHADOW_MODE_PCF13 2
+
 layout(set = 0, binding = 1) uniform sampler material_samplers[12];
 layout(set = 0, binding = 1) uniform sampler material_samplers[12];
 
 
 layout(set = 0, binding = 2) uniform sampler shadow_sampler;
 layout(set = 0, binding = 2) uniform sampler shadow_sampler;
@@ -37,13 +41,12 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
 	vec2 viewport_size;
 	vec2 viewport_size;
 	vec2 screen_pixel_size;
 	vec2 screen_pixel_size;
 
 
-	//used for shadow mapping only
-	float z_offset;
-	float z_slope_scale;
-
 	float time;
 	float time;
 	float reflection_multiplier; // one normally, zero when rendering reflections
 	float reflection_multiplier; // one normally, zero when rendering reflections
 
 
+	bool pancake_shadows;
+	uint shadow_filter_mode;
+
 	vec4 ambient_light_color_energy;
 	vec4 ambient_light_color_energy;
 
 
 	float ambient_color_sky_mix;
 	float ambient_color_sky_mix;
@@ -134,7 +137,7 @@ layout(set = 0, binding = 4, std430) buffer Instances {
 }
 }
 instances;
 instances;
 
 
-struct LightData { //this structure needs to be 128 bits
+struct LightData { //this structure needs to be as packed as possible
 	vec3 position;
 	vec3 position;
 	float inv_radius;
 	float inv_radius;
 	vec3 direction;
 	vec3 direction;
@@ -143,12 +146,16 @@ struct LightData { //this structure needs to be 128 bits
 	uint cone_attenuation_angle; // attenuation and angle, (16bit float)
 	uint cone_attenuation_angle; // attenuation and angle, (16bit float)
 	uint mask;
 	uint mask;
 	uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
 	uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
-	vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
+	vec4 atlas_rect; // used for spot
 	mat4 shadow_matrix;
 	mat4 shadow_matrix;
+	float shadow_bias;
+	float shadow_normal_bias;
+	float transmittance_bias;
+	uint pad;
 };
 };
 
 
-layout(set = 0, binding = 5, std140) uniform Lights {
-	LightData data[MAX_LIGHT_DATA_STRUCTS];
+layout(set = 0, binding = 5, std430) buffer Lights {
+	LightData data[];
 }
 }
 lights;
 lights;
 
 
@@ -174,17 +181,27 @@ struct DirectionalLightData {
 	float energy;
 	float energy;
 	vec3 color;
 	vec3 color;
 	float specular;
 	float specular;
-	vec3 shadow_color;
 	uint mask;
 	uint mask;
+	uint pad0;
+	uint pad1;
+	uint pad2;
 	bool blend_splits;
 	bool blend_splits;
 	bool shadow_enabled;
 	bool shadow_enabled;
 	float fade_from;
 	float fade_from;
 	float fade_to;
 	float fade_to;
+	vec4 shadow_bias;
+	vec4 shadow_normal_bias;
+	vec4 shadow_transmittance_bias;
+	vec4 shadow_transmittance_z_scale;
 	vec4 shadow_split_offsets;
 	vec4 shadow_split_offsets;
 	mat4 shadow_matrix1;
 	mat4 shadow_matrix1;
 	mat4 shadow_matrix2;
 	mat4 shadow_matrix2;
 	mat4 shadow_matrix3;
 	mat4 shadow_matrix3;
 	mat4 shadow_matrix4;
 	mat4 shadow_matrix4;
+	vec4 shadow_color1;
+	vec4 shadow_color2;
+	vec4 shadow_color3;
+	vec4 shadow_color4;
 };
 };
 
 
 layout(set = 0, binding = 7, std140) uniform DirectionalLights {
 layout(set = 0, binding = 7, std140) uniform DirectionalLights {

+ 2 - 0
servers/rendering/rendering_server_raster.h

@@ -554,6 +554,8 @@ public:
 	BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
 	BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
 	BIND3(camera_effects_set_custom_exposure, RID, bool, float)
 	BIND3(camera_effects_set_custom_exposure, RID, bool, float)
 
 
+	BIND1(shadow_filter_set, ShadowFilter)
+
 	/* SCENARIO API */
 	/* SCENARIO API */
 
 
 #undef BINDBASE
 #undef BINDBASE

+ 137 - 52
servers/rendering/rendering_server_scene.cpp

@@ -1334,7 +1334,7 @@ void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instan
 	}
 	}
 }
 }
 
 
-bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
+bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario) {
 
 
 	InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
 	InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
 
 
@@ -1347,16 +1347,18 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 
 
 		case RS::LIGHT_DIRECTIONAL: {
 		case RS::LIGHT_DIRECTIONAL: {
 
 
-			float max_distance = p_cam_projection.get_z_far();
-			float shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+			real_t max_distance = p_cam_projection.get_z_far();
+			real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
 			if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
 			if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
 				max_distance = MIN(shadow_max, max_distance);
 				max_distance = MIN(shadow_max, max_distance);
 			}
 			}
 			max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
 			max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
-			float min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
+			real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
 
 
 			RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
 			RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
 
 
+			real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+
 			if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
 			if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
 				//optimize min/max
 				//optimize min/max
 				Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
 				Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
@@ -1365,8 +1367,8 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 				//check distance max and min
 				//check distance max and min
 
 
 				bool found_items = false;
 				bool found_items = false;
-				float z_max = -1e20;
-				float z_min = 1e20;
+				real_t z_max = -1e20;
+				real_t z_min = 1e20;
 
 
 				for (int i = 0; i < cull_count; i++) {
 				for (int i = 0; i < cull_count; i++) {
 
 
@@ -1379,7 +1381,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 						animated_material_found = true;
 						animated_material_found = true;
 					}
 					}
 
 
-					float max, min;
+					real_t max, min;
 					instance->transformed_aabb.project_range_in_plane(base, min, max);
 					instance->transformed_aabb.project_range_in_plane(base, min, max);
 
 
 					if (max > z_max) {
 					if (max > z_max) {
@@ -1399,7 +1401,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 				}
 				}
 			}
 			}
 
 
-			float range = max_distance - min_distance;
+			real_t range = max_distance - min_distance;
 
 
 			int splits = 0;
 			int splits = 0;
 			switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
 			switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
@@ -1408,7 +1410,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 				case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits = 4; break;
 				case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits = 4; break;
 			}
 			}
 
 
-			float distances[5];
+			real_t distances[5];
 
 
 			distances[0] = min_distance;
 			distances[0] = min_distance;
 			for (int i = 0; i < splits; i++) {
 			for (int i = 0; i < splits; i++) {
@@ -1417,11 +1419,13 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 
 
 			distances[splits] = max_distance;
 			distances[splits] = max_distance;
 
 
-			float texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance);
+			real_t texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance);
 
 
 			bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
 			bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
 
 
-			float first_radius = 0.0;
+			real_t first_radius = 0.0;
+
+			real_t min_distance_bias_scale = pancake_size > 0 ? distances[1] / 10.0 : 0;
 
 
 			for (int i = 0; i < splits; i++) {
 			for (int i = 0; i < splits; i++) {
 
 
@@ -1430,7 +1434,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 				// setup a camera matrix for that range!
 				// setup a camera matrix for that range!
 				CameraMatrix camera_matrix;
 				CameraMatrix camera_matrix;
 
 
-				float aspect = p_cam_projection.get_aspect();
+				real_t aspect = p_cam_projection.get_aspect();
 
 
 				if (p_cam_orthogonal) {
 				if (p_cam_orthogonal) {
 
 
@@ -1439,8 +1443,8 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 					camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
 					camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
 				} else {
 				} else {
 
 
-					float fov = p_cam_projection.get_fov();
-					camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+					real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it
+					camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
 				}
 				}
 
 
 				//obtain the frustum endpoints
 				//obtain the frustum endpoints
@@ -1458,26 +1462,27 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 				Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized();
 				Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized();
 				//z_vec points agsint the camera, like in default opengl
 				//z_vec points agsint the camera, like in default opengl
 
 
-				float x_min = 0.f, x_max = 0.f;
-				float y_min = 0.f, y_max = 0.f;
-				float z_min = 0.f, z_max = 0.f;
+				real_t x_min = 0.f, x_max = 0.f;
+				real_t y_min = 0.f, y_max = 0.f;
+				real_t z_min = 0.f, z_max = 0.f;
 
 
 				// FIXME: z_max_cam is defined, computed, but not used below when setting up
 				// FIXME: z_max_cam is defined, computed, but not used below when setting up
 				// ortho_camera. Commented out for now to fix warnings but should be investigated.
 				// ortho_camera. Commented out for now to fix warnings but should be investigated.
-				float x_min_cam = 0.f, x_max_cam = 0.f;
-				float y_min_cam = 0.f, y_max_cam = 0.f;
-				float z_min_cam = 0.f;
-				//float z_max_cam = 0.f;
+				real_t x_min_cam = 0.f, x_max_cam = 0.f;
+				real_t y_min_cam = 0.f, y_max_cam = 0.f;
+				real_t z_min_cam = 0.f;
+				//real_t z_max_cam = 0.f;
 
 
-				float bias_scale = 1.0;
+				real_t bias_scale = 1.0;
+				real_t aspect_bias_scale = 1.0;
 
 
 				//used for culling
 				//used for culling
 
 
 				for (int j = 0; j < 8; j++) {
 				for (int j = 0; j < 8; j++) {
 
 
-					float d_x = x_vec.dot(endpoints[j]);
-					float d_y = y_vec.dot(endpoints[j]);
-					float d_z = z_vec.dot(endpoints[j]);
+					real_t d_x = x_vec.dot(endpoints[j]);
+					real_t d_y = y_vec.dot(endpoints[j]);
+					real_t d_z = z_vec.dot(endpoints[j]);
 
 
 					if (j == 0 || d_x < x_min)
 					if (j == 0 || d_x < x_min)
 						x_min = d_x;
 						x_min = d_x;
@@ -1494,12 +1499,12 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 					if (j == 0 || d_z > z_max)
 					if (j == 0 || d_z > z_max)
 						z_max = d_z;
 						z_max = d_z;
 				}
 				}
+				real_t radius = 0;
+				Vector3 center;
 
 
 				{
 				{
 					//camera viewport stuff
 					//camera viewport stuff
 
 
-					Vector3 center;
-
 					for (int j = 0; j < 8; j++) {
 					for (int j = 0; j < 8; j++) {
 
 
 						center += endpoints[j];
 						center += endpoints[j];
@@ -1508,11 +1513,9 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 
 
 					//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
 					//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
 
 
-					float radius = 0;
-
 					for (int j = 0; j < 8; j++) {
 					for (int j = 0; j < 8; j++) {
 
 
-						float d = center.distance_to(endpoints[j]);
+						real_t d = center.distance_to(endpoints[j]);
 						if (d > radius)
 						if (d > radius)
 							radius = d;
 							radius = d;
 					}
 					}
@@ -1529,14 +1532,13 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 					x_min_cam = x_vec.dot(center) - radius;
 					x_min_cam = x_vec.dot(center) - radius;
 					y_max_cam = y_vec.dot(center) + radius;
 					y_max_cam = y_vec.dot(center) + radius;
 					y_min_cam = y_vec.dot(center) - radius;
 					y_min_cam = y_vec.dot(center) - radius;
-					//z_max_cam = z_vec.dot(center) + radius;
 					z_min_cam = z_vec.dot(center) - radius;
 					z_min_cam = z_vec.dot(center) - radius;
 
 
 					if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
 					if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
 						//this trick here is what stabilizes the shadow (make potential jaggies to not move)
 						//this trick here is what stabilizes the shadow (make potential jaggies to not move)
 						//at the cost of some wasted resolution. Still the quality increase is very well worth it
 						//at the cost of some wasted resolution. Still the quality increase is very well worth it
 
 
-						float unit = radius * 2.0 / texture_size;
+						real_t unit = radius * 2.0 / texture_size;
 
 
 						x_max_cam = Math::stepify(x_max_cam, unit);
 						x_max_cam = Math::stepify(x_max_cam, unit);
 						x_min_cam = Math::stepify(x_min_cam, unit);
 						x_min_cam = Math::stepify(x_min_cam, unit);
@@ -1566,9 +1568,10 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 
 
 				Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
 				Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
 
 
+				real_t cull_max = 0;
 				for (int j = 0; j < cull_count; j++) {
 				for (int j = 0; j < cull_count; j++) {
 
 
-					float min, max;
+					real_t min, max;
 					Instance *instance = instance_shadow_cull_result[j];
 					Instance *instance = instance_shadow_cull_result[j];
 					if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
 					if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
 						cull_count--;
 						cull_count--;
@@ -1580,8 +1583,90 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 					instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max);
 					instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max);
 					instance->depth = near_plane.distance_to(instance->transform.origin);
 					instance->depth = near_plane.distance_to(instance->transform.origin);
 					instance->depth_layer = 0;
 					instance->depth_layer = 0;
-					if (max > z_max)
-						z_max = max;
+					if (j == 0 || max > cull_max) {
+						cull_max = max;
+					}
+				}
+
+				if (cull_max > z_max)
+					z_max = cull_max;
+
+				if (pancake_size > 0) {
+					z_max = z_vec.dot(center) + radius + pancake_size;
+				}
+
+				if (aspect != 1.0) {
+
+					// if the aspect is different, then the radius will become larger.
+					// if this happens, then bias needs to be adjusted too, as depth will increase
+					// to do this, compare the depth of one that would have resulted from a square frustum
+
+					CameraMatrix camera_matrix_square;
+					if (p_cam_orthogonal) {
+
+						Vector2 vp_he = camera_matrix.get_viewport_half_extents();
+						if (p_cam_vaspect) {
+							camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
+						} else {
+							camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+						}
+					} else {
+						Vector2 vp_he = camera_matrix.get_viewport_half_extents();
+						if (p_cam_vaspect) {
+							camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
+						} else {
+							camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+						}
+
+						if (i == 0) {
+							//print_line("prev he: " + vp_he + " new he: " + camera_matrix_square.get_viewport_half_extents());
+						}
+					}
+
+					Vector3 endpoints_square[8]; // frustum plane endpoints
+					res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square);
+					ERR_CONTINUE(!res);
+					Vector3 center_square;
+					real_t z_max_square = 0;
+
+					for (int j = 0; j < 8; j++) {
+
+						center_square += endpoints_square[j];
+
+						real_t d_z = z_vec.dot(endpoints_square[j]);
+
+						if (j == 0 || d_z > z_max_square)
+							z_max_square = d_z;
+					}
+
+					if (cull_max > z_max_square) {
+						z_max_square = cull_max;
+					}
+
+					center_square /= 8.0;
+
+					real_t radius_square = 0;
+
+					for (int j = 0; j < 8; j++) {
+
+						real_t d = center_square.distance_to(endpoints_square[j]);
+						if (d > radius_square)
+							radius_square = d;
+					}
+
+					radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side
+
+					if (pancake_size > 0) {
+						z_max_square = z_vec.dot(center_square) + radius_square + pancake_size;
+					}
+
+					real_t z_min_cam_square = z_vec.dot(center_square) - radius_square;
+
+					aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square);
+
+					// this is not entirely perfect, because the cull-adjusted z-max may be different
+					// but at least it's warranted that it results in a greater bias, so no acne should be present either way.
+					// pancaking also helps with this.
 				}
 				}
 
 
 				{
 				{
@@ -1596,7 +1681,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 					ortho_transform.basis = transform.basis;
 					ortho_transform.basis = transform.basis;
 					ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;
 					ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;
 
 
-					RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, 0, distances[i + 1], i, bias_scale);
+					RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, z_max - z_min_cam, distances[i + 1], i, radius * 2.0 / texture_size, bias_scale * aspect_bias_scale * min_distance_bias_scale);
 				}
 				}
 
 
 				RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 				RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
@@ -1614,9 +1699,9 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 					//using this one ensures that raster deferred will have it
 					//using this one ensures that raster deferred will have it
 					RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i));
 					RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i));
 
 
-					float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+					real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
 
 
-					float z = i == 0 ? -1 : 1;
+					real_t z = i == 0 ? -1 : 1;
 					Vector<Plane> planes;
 					Vector<Plane> planes;
 					planes.resize(5);
 					planes.resize(5);
 					planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
 					planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
@@ -1645,12 +1730,12 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 						}
 						}
 					}
 					}
 
 
-					RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
+					RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
 					RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 					RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 				}
 				}
 			} else { //shadow cube
 			} else { //shadow cube
 
 
-				float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+				real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
 				CameraMatrix cm;
 				CameraMatrix cm;
 				cm.set_perspective(90, 1, 0.01, radius);
 				cm.set_perspective(90, 1, 0.01, radius);
 
 
@@ -1699,12 +1784,12 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 						}
 						}
 					}
 					}
 
 
-					RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
+					RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
 					RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 					RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 				}
 				}
 
 
 				//restore the regular DP matrix
 				//restore the regular DP matrix
-				RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
+				RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
 			}
 			}
 
 
 		} break;
 		} break;
@@ -1712,8 +1797,8 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 
 
 			RENDER_TIMESTAMP("Culling Spot Light");
 			RENDER_TIMESTAMP("Culling Spot Light");
 
 
-			float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
-			float angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+			real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+			real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
 
 
 			CameraMatrix cm;
 			CameraMatrix cm;
 			cm.set_perspective(angle * 2.0, 1.0, 0.01, radius);
 			cm.set_perspective(angle * 2.0, 1.0, 0.01, radius);
@@ -1738,7 +1823,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
 				}
 				}
 			}
 			}
 
 
-			RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0);
+			RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
 			RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 			RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 
 
 		} break;
 		} break;
@@ -1793,7 +1878,7 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID
 		} break;
 		} break;
 	}
 	}
 
 
-	_prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+	_prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
 	_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
 	_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
 #endif
 #endif
 }
 }
@@ -1872,17 +1957,17 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<ARVRInterface
 		mono_transform *= apply_z_shift;
 		mono_transform *= apply_z_shift;
 
 
 		// now prepare our scene with our adjusted transform projection matrix
 		// now prepare our scene with our adjusted transform projection matrix
-		_prepare_scene(mono_transform, combined_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+		_prepare_scene(mono_transform, combined_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
 	} else if (p_eye == ARVRInterface::EYE_MONO) {
 	} else if (p_eye == ARVRInterface::EYE_MONO) {
 		// For mono render, prepare as per usual
 		// For mono render, prepare as per usual
-		_prepare_scene(cam_transform, camera_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+		_prepare_scene(cam_transform, camera_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
 	}
 	}
 
 
 	// And render our scene...
 	// And render our scene...
 	_render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
 	_render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
 };
 };
 
 
-void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
+void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
 	// Note, in stereo rendering:
 	// Note, in stereo rendering:
 	// - p_cam_transform will be a transform in the middle of our two eyes
 	// - p_cam_transform will be a transform in the middle of our two eyes
 	// - p_cam_projection is a wider frustrum that encompasses both eyes
 	// - p_cam_projection is a wider frustrum that encompasses both eyes
@@ -2112,7 +2197,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
 
 
 			RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
 			RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
 
 
-			_light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
+			_light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
 
 
 			RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
 			RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
 		}
 		}
@@ -2214,7 +2299,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
 			if (redraw) {
 			if (redraw) {
 				//must redraw!
 				//must redraw!
 				RENDER_TIMESTAMP(">Rendering Light " + itos(i));
 				RENDER_TIMESTAMP(">Rendering Light " + itos(i));
-				light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
+				light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
 				RENDER_TIMESTAMP("<Rendering Light " + itos(i));
 				RENDER_TIMESTAMP("<Rendering Light " + itos(i));
 			}
 			}
 		}
 		}
@@ -2324,7 +2409,7 @@ bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, i
 		}
 		}
 
 
 		RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
 		RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
-		_prepare_scene(xform, cm, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
+		_prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
 		_render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
 		_render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
 
 
 	} else {
 	} else {

+ 2 - 2
servers/rendering/rendering_server_scene.h

@@ -418,10 +418,10 @@ public:
 	_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
 	_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
 	_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
 	_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
 
 
-	_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
+	_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario);
 
 
 	bool _render_reflection_probe_step(Instance *p_instance, int p_step);
 	bool _render_reflection_probe_step(Instance *p_instance, int p_step);
-	void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
+	void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
 	void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
 	void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
 	void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
 	void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
 
 

+ 2 - 0
servers/rendering/rendering_server_wrap_mt.h

@@ -467,6 +467,8 @@ public:
 	FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
 	FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
 	FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
 	FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
 
 
+	FUNC1(shadow_filter_set, ShadowFilter)
+
 	FUNCRID(scenario)
 	FUNCRID(scenario)
 
 
 	FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
 	FUNC2(scenario_set_debug, RID, ScenarioDebugMode)

+ 6 - 2
servers/rendering/shader_types.cpp

@@ -108,7 +108,11 @@ ShaderTypes::ShaderTypes() {
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT;
-	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3;
+	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_COLOR"] = ShaderLanguage::TYPE_VEC4;
+	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
+	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_CURVE"] = ShaderLanguage::TYPE_FLOAT;
+	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_BOOST"] = ShaderLanguage::TYPE_FLOAT;
+	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["BACKLIGHT"] = ShaderLanguage::TYPE_VEC3;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
 	shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
@@ -145,7 +149,7 @@ ShaderTypes::ShaderTypes() {
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3);
-	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = constt(ShaderLanguage::TYPE_VEC3);
+	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["BACKLIGHT"] = constt(ShaderLanguage::TYPE_VEC3);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT);
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;
 	shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;

+ 1 - 2
servers/rendering_server.cpp

@@ -2030,7 +2030,6 @@ void RenderingServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION);
-	BIND_ENUM_CONSTANT(LIGHT_PARAM_CONTACT_SHADOW_SIZE);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
 	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_2_OFFSET);
@@ -2038,7 +2037,6 @@ void RenderingServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
-	BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
 	BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
 
 
 	BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID);
 	BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID);
@@ -2098,6 +2096,7 @@ void RenderingServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE);
 	BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE);
 	BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSAO);
 	BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSAO);
 	BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER);
 	BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER);
+	BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_PSSM_SPLITS);
 
 
 	BIND_ENUM_CONSTANT(SKY_MODE_QUALITY);
 	BIND_ENUM_CONSTANT(SKY_MODE_QUALITY);
 	BIND_ENUM_CONSTANT(SKY_MODE_REALTIME);
 	BIND_ENUM_CONSTANT(SKY_MODE_REALTIME);

+ 12 - 2
servers/rendering_server.h

@@ -385,7 +385,6 @@ public:
 		LIGHT_PARAM_ATTENUATION,
 		LIGHT_PARAM_ATTENUATION,
 		LIGHT_PARAM_SPOT_ANGLE,
 		LIGHT_PARAM_SPOT_ANGLE,
 		LIGHT_PARAM_SPOT_ATTENUATION,
 		LIGHT_PARAM_SPOT_ATTENUATION,
-		LIGHT_PARAM_CONTACT_SHADOW_SIZE,
 		LIGHT_PARAM_SHADOW_MAX_DISTANCE,
 		LIGHT_PARAM_SHADOW_MAX_DISTANCE,
 		LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
 		LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
@@ -393,7 +392,8 @@ public:
 		LIGHT_PARAM_SHADOW_FADE_START,
 		LIGHT_PARAM_SHADOW_FADE_START,
 		LIGHT_PARAM_SHADOW_NORMAL_BIAS,
 		LIGHT_PARAM_SHADOW_NORMAL_BIAS,
 		LIGHT_PARAM_SHADOW_BIAS,
 		LIGHT_PARAM_SHADOW_BIAS,
-		LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
+		LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+		LIGHT_PARAM_TRANSMITTANCE_BIAS,
 		LIGHT_PARAM_MAX
 		LIGHT_PARAM_MAX
 	};
 	};
 
 
@@ -666,6 +666,7 @@ public:
 		VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE,
 		VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE,
 		VIEWPORT_DEBUG_DRAW_SSAO,
 		VIEWPORT_DEBUG_DRAW_SSAO,
 		VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER,
 		VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER,
+		VIEWPORT_DEBUG_DRAW_PSSM_SPLITS,
 
 
 	};
 	};
 
 
@@ -816,6 +817,15 @@ public:
 	virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
 	virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
 	virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
 	virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
 
 
+	enum ShadowFilter {
+		SHADOW_FILTER_NONE,
+		SHADOW_FILTER_PCF5,
+		SHADOW_FILTER_PCF13,
+		SHADOW_FILTER_MAX
+	};
+
+	virtual void shadow_filter_set(ShadowFilter p_filter) = 0;
+
 	/* SCENARIO API */
 	/* SCENARIO API */
 
 
 	virtual RID scenario_create() = 0;
 	virtual RID scenario_create() = 0;