summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/Light3D.xml9
-rw-r--r--doc/classes/ProjectSettings.xml14
-rw-r--r--doc/classes/RenderingServer.xml12
-rw-r--r--editor/editor_node.cpp6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp11
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/cpu_particles_3d_editor_plugin.cpp3
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp5
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp2
-rwxr-xr-xmisc/travis/android-tools-linux.sh2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp4
-rw-r--r--modules/bullet/rigid_body_bullet.h2
-rw-r--r--modules/gdscript/gdscript_editor.cpp9
-rw-r--r--modules/upnp/upnp.cpp7
-rw-r--r--modules/upnp/upnp_device.cpp22
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp2
-rw-r--r--platform/android/export/export.cpp9
-rw-r--r--platform/android/java/app/config.gradle2
-rw-r--r--platform/android/java/lib/res/drawable-hdpi/notify_panel_notification_icon_bg.pngbin1116 -> 0 bytes
-rw-r--r--platform/android/java/lib/res/drawable-mdpi/notify_panel_notification_icon_bg.pngbin388 -> 0 bytes
-rw-r--r--platform/android/java/lib/res/drawable-xhdpi/notify_panel_notification_icon_bg.pngbin462 -> 0 bytes
-rw-r--r--platform/android/java/lib/res/drawable-xxhdpi/notify_panel_notification_icon_bg.pngbin1556 -> 0 bytes
-rw-r--r--scene/2d/path_2d.cpp12
-rw-r--r--scene/3d/light_3d.cpp3
-rw-r--r--scene/3d/light_3d.h1
-rw-r--r--scene/3d/path_3d.cpp12
-rw-r--r--scene/gui/rich_text_label.cpp4
-rw-r--r--servers/physics_3d/body_3d_sw.h2
-rw-r--r--servers/physics_server_3d.h2
-rw-r--r--servers/rendering/rasterizer.h3
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp3
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp26
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h18
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp105
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.h32
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl197
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl25
-rw-r--r--servers/rendering/rendering_server_raster.h3
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h3
-rw-r--r--servers/rendering_server.cpp12
-rw-r--r--servers/rendering_server.h16
42 files changed, 404 insertions, 204 deletions
diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml
index 4e48a24951..623b2a2bb0 100644
--- a/doc/classes/Light3D.xml
+++ b/doc/classes/Light3D.xml
@@ -35,6 +35,9 @@
<member name="editor_only" type="bool" setter="set_editor_only" getter="is_editor_only" default="false">
If [code]true[/code], the light only appears in the editor and will not be visible at runtime.
</member>
+ <member name="light_angular_distance" type="float" setter="set_param" getter="get_param" default="0.0">
+ Angular size of the light in degrees. Only available for [DirectionalLight3D]s. For reference, the sun from earth is approximately [code]0.5[/code].
+ </member>
<member name="light_bake_mode" type="int" setter="set_bake_mode" getter="get_bake_mode" enum="Light3D.BakeMode" default="1">
The light's bake mode. See [enum BakeMode].
</member>
@@ -53,12 +56,18 @@
<member name="light_negative" type="bool" setter="set_negative" getter="is_negative" default="false">
If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows.
</member>
+ <member name="light_size" type="float" setter="set_param" getter="get_param" default="0.0">
+ The size of the light in Godot units. Only available for [OmniLight3D]s and [SpotLight3D]s.
+ </member>
<member name="light_specular" type="float" setter="set_param" getter="get_param" default="0.5">
The intensity of the specular blob in objects affected by the light. At [code]0[/code] the light becomes a pure diffuse light.
</member>
<member name="shadow_bias" type="float" setter="set_param" getter="get_param" default="0.15">
Used to adjust shadow appearance. Too small a value results in self-shadowing, while too large a value causes shadows to separate from casters. Adjust as needed.
</member>
+ <member name="shadow_blur" type="float" setter="set_param" getter="get_param" default="1.0">
+ Blurs the edges of the shadow. Can be used to hide pixel artifacts in low resolution shadow maps. A high value can make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible.
+ </member>
<member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color" default="Color( 0, 0, 0, 1 )">
The color of shadows cast by this light.
</member>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 2b3cb6b56c..67a033daca 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -994,6 +994,12 @@
<member name="rendering/quality/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/quality/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
</member>
+ <member name="rendering/quality/directional_shadow/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
+ </member>
+ <member name="rendering/quality/directional_shadow/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
+ Lower-end override for [member rendering/quality/directional_shadow/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
+ </member>
<member name="rendering/quality/driver/driver_name" type="String" setter="" getter="" default="&quot;Vulkan&quot;">
The video driver to use ("GLES2" or "Vulkan").
[b]Note:[/b] The backend in use can be overridden at runtime via the [code]--rendering-driver[/code] command line argument.
@@ -1098,11 +1104,11 @@
<member name="rendering/quality/shadow_atlas/size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/quality/shadow_atlas/size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/shadows/filter_mode" type="int" setter="" getter="" default="1">
- Shadow filter mode. Higher-quality settings result in smoother shadows that flicker less when moving. "Disabled" is the fastest option, but also has the lowest quality. "PCF5" is smoother but is also slower. "PCF13" is the smoothest option, but is also the slowest.
+ <member name="rendering/quality/shadows/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
</member>
- <member name="rendering/quality/shadows/filter_mode.mobile" type="int" setter="" getter="" default="0">
- Lower-end override for [member rendering/quality/shadows/filter_mode] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/quality/shadows/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
+ Lower-end override for [member rendering/quality/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/quality/ssao/half_size" type="bool" setter="" getter="" default="false">
</member>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index aa393877b2..bfdcf1bb79 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -3282,18 +3282,18 @@
<constant name="LIGHT_PARAM_RANGE" value="3" enum="LightParam">
The light's range.
</constant>
- <constant name="LIGHT_PARAM_ATTENUATION" value="4" enum="LightParam">
+ <constant name="LIGHT_PARAM_SIZE" value="4" enum="LightParam">
+ The size of the light when using spot light or omni light. The angular size of the light when using directional light.
+ </constant>
+ <constant name="LIGHT_PARAM_ATTENUATION" value="5" enum="LightParam">
The light's attenuation.
</constant>
- <constant name="LIGHT_PARAM_SPOT_ANGLE" value="5" enum="LightParam">
+ <constant name="LIGHT_PARAM_SPOT_ANGLE" value="6" enum="LightParam">
The spotlight's angle.
</constant>
- <constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="6" enum="LightParam">
+ <constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="7" enum="LightParam">
The spotlight's attenuation.
</constant>
- <constant name="LIGHT_PARAM_CONTACT_SHADOW_SIZE" value="7" enum="LightParam">
- Scales the shadow color.
- </constant>
<constant name="LIGHT_PARAM_SHADOW_MAX_DISTANCE" value="8" enum="LightParam">
Max distance that shadows will be rendered.
</constant>
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index d397c4ff5e..6f6287ccb5 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -374,8 +374,10 @@ void EditorNode::_notification(int p_what) {
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");
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);
+ RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/shadows/soft_shadow_quality")));
+ RS::get_singleton()->shadows_quality_set(shadows_quality);
+ RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/directional_shadow/soft_shadow_quality")));
+ RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality);
}
ResourceImporterTexture::get_singleton()->update_imports();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 2f7747d0ff..43a88a32c8 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1919,6 +1919,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
Point2 offset = drag_to_local - drag_from_local;
Size2 scale = canvas_item->call("get_scale");
+ Size2 original_scale = scale;
float ratio = scale.y / scale.x;
if (drag_type == DRAG_SCALE_BOTH) {
Size2 scale_factor = drag_to_local / drag_from_local;
@@ -1931,6 +1932,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
Size2 scale_factor = Vector2(offset.x, -offset.y) / SCALE_HANDLE_DISTANCE;
Size2 parent_scale = parent_xform.get_scale();
scale_factor *= Vector2(1.0 / parent_scale.x, 1.0 / parent_scale.y);
+
if (drag_type == DRAG_SCALE_X) {
scale.x += scale_factor.x;
if (uniform) {
@@ -1945,8 +1947,13 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
}
if (snap_scale && !is_ctrl) {
- scale.x = roundf(scale.x / snap_scale_step) * snap_scale_step;
- scale.y = roundf(scale.y / snap_scale_step) * snap_scale_step;
+ if (snap_relative) {
+ scale.x = original_scale.x * (roundf((scale.x / original_scale.x) / snap_scale_step) * snap_scale_step);
+ scale.y = original_scale.y * (roundf((scale.y / original_scale.y) / snap_scale_step) * snap_scale_step);
+ } else {
+ scale.x = roundf(scale.x / snap_scale_step) * snap_scale_step;
+ scale.y = roundf(scale.y / snap_scale_step) * snap_scale_step;
+ }
}
canvas_item->call("set_scale", scale);
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index b005519a5e..ef4d7d7646 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -262,9 +262,8 @@ CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin(EditorNode *p_node) {
toolbar->add_child(memnew(VSeparator));
menu = memnew(MenuButton);
- menu->get_popup()->add_item(TTR("Load Emission Mask"), MENU_LOAD_EMISSION_MASK);
- menu->get_popup()->add_separator();
menu->get_popup()->add_item(TTR("Restart"), MENU_RESTART);
+ menu->get_popup()->add_item(TTR("Load Emission Mask"), MENU_LOAD_EMISSION_MASK);
menu->set_text(TTR("CPUParticles2D"));
menu->set_switch_on_hover(true);
toolbar->add_child(menu);
diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.cpp b/editor/plugins/cpu_particles_3d_editor_plugin.cpp
index 0c2fbaf62a..59a353a581 100644
--- a/editor/plugins/cpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_3d_editor_plugin.cpp
@@ -104,9 +104,8 @@ CPUParticles3DEditor::CPUParticles3DEditor() {
particles_editor_hb->hide();
options->set_text(TTR("CPUParticles3D"));
- options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
- options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Restart"), MENU_OPTION_RESTART);
+ options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
options->get_popup()->connect("id_pressed", callable_mp(this, &CPUParticles3DEditor::_menu_option));
}
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 29c47a2b67..5c35285c22 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -371,14 +371,11 @@ GPUParticles2DEditorPlugin::GPUParticles2DEditorPlugin(EditorNode *p_node) {
toolbar->add_child(memnew(VSeparator));
menu = memnew(MenuButton);
+ menu->get_popup()->add_item(TTR("Restart"), MENU_RESTART);
menu->get_popup()->add_item(TTR("Generate Visibility Rect"), MENU_GENERATE_VISIBILITY_RECT);
- menu->get_popup()->add_separator();
menu->get_popup()->add_item(TTR("Load Emission Mask"), MENU_LOAD_EMISSION_MASK);
// menu->get_popup()->add_item(TTR("Clear Emission Mask"), MENU_CLEAR_EMISSION_MASK);
- menu->get_popup()->add_separator();
menu->get_popup()->add_item(TTR("Convert to CPUParticles2D"), MENU_OPTION_CONVERT_TO_CPU_PARTICLES);
- menu->get_popup()->add_separator();
- menu->get_popup()->add_item(TTR("Restart"), MENU_RESTART);
menu->set_text(TTR("GPUParticles2D"));
menu->set_switch_on_hover(true);
toolbar->add_child(menu);
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 534a228098..7f80acc176 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -433,13 +433,10 @@ GPUParticles3DEditor::GPUParticles3DEditor() {
particles_editor_hb->hide();
options->set_text(TTR("GPUParticles3D"));
+ options->get_popup()->add_item(TTR("Restart"), MENU_OPTION_RESTART);
options->get_popup()->add_item(TTR("Generate AABB"), MENU_OPTION_GENERATE_AABB);
- options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
- options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Convert to CPUParticles3D"), MENU_OPTION_CONVERT_TO_CPU_PARTICLES);
- options->get_popup()->add_separator();
- options->get_popup()->add_item(TTR("Restart"), MENU_OPTION_RESTART);
options->get_popup()->connect("id_pressed", callable_mp(this, &GPUParticles3DEditor::_menu_option));
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 960431e655..354c951a7c 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -3849,7 +3849,7 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_
Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
cpu_time_history_index = 0;
- cpu_time_history_index = 0;
+ gpu_time_history_index = 0;
_edit.mode = TRANSFORM_NONE;
_edit.plane = TRANSFORM_VIEW;
diff --git a/misc/travis/android-tools-linux.sh b/misc/travis/android-tools-linux.sh
index 4eeb54412c..6114551861 100755
--- a/misc/travis/android-tools-linux.sh
+++ b/misc/travis/android-tools-linux.sh
@@ -76,7 +76,7 @@ yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager --licenses > /dev/null
echo "Installing: Android Build and Platform Tools ..."
yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'tools' > /dev/null
yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'platform-tools' > /dev/null
-yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'build-tools;28.0.3' > /dev/null
+yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'build-tools;29.0.3' > /dev/null
echo
EXPORT_VAL="export ANDROID_HOME=$ANDROID_SDK_PATH"
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index fc4e1d57de..a4f9affa95 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -138,8 +138,8 @@ void BulletPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impul
body->apply_torque_impulse(p_impulse);
}
-void BulletPhysicsDirectBodyState3D::set_sleep_state(bool p_enable) {
- body->set_activation_state(p_enable);
+void BulletPhysicsDirectBodyState3D::set_sleep_state(bool p_sleep) {
+ body->set_activation_state(!p_sleep);
}
bool BulletPhysicsDirectBodyState3D::is_sleeping() const {
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 95491b1e62..420b5cc443 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -117,7 +117,7 @@ public:
virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse);
virtual void apply_torque_impulse(const Vector3 &p_impulse);
- virtual void set_sleep_state(bool p_enable);
+ virtual void set_sleep_state(bool p_sleep);
virtual bool is_sleeping() const;
virtual int get_contact_count() const;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 1e3cbd661e..2ec3352e70 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2236,6 +2236,8 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
+#define IS_METHOD_SIGNAL(m_method) (m_method == "connect" || m_method == "disconnect" || m_method == "is_connected" || m_method == "emit_signal")
+
while (base_type.has_type) {
switch (base_type.kind) {
case GDScriptParser::DataType::CLASS: {
@@ -2252,7 +2254,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
}
}
- if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
+ if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
option.insert_text = quote_style + option.display + quote_style;
@@ -2265,7 +2267,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
case GDScriptParser::DataType::GDSCRIPT: {
Ref<GDScript> gds = base_type.script_type;
if (gds.is_valid()) {
- if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
+ if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) {
List<MethodInfo> signals;
gds->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
@@ -2327,7 +2329,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
}
}
- if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
+ if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) {
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
@@ -2336,6 +2338,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
r_result.insert(option.display, option);
}
}
+#undef IS_METHOD_SIGNAL
if (ClassDB::is_parent_class(class_name, "Node") && (p_method == "get_node" || p_method == "has_node") && p_argidx == 0) {
// Get autoloads
diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp
index 856f4188aa..988bf3017d 100644
--- a/modules/upnp/upnp.cpp
+++ b/modules/upnp/upnp.cpp
@@ -44,9 +44,8 @@ bool UPNP::is_common_device(const String &dev) const {
}
int UPNP::discover(int timeout, int ttl, const String &device_filter) {
- ERR_FAIL_COND_V(timeout < 0, UPNP_RESULT_INVALID_PARAM);
- ERR_FAIL_COND_V(ttl < 0, UPNP_RESULT_INVALID_PARAM);
- ERR_FAIL_COND_V(ttl > 255, UPNP_RESULT_INVALID_PARAM);
+ ERR_FAIL_COND_V_MSG(timeout < 0, UPNP_RESULT_INVALID_PARAM, "The response's wait time can't be negative.");
+ ERR_FAIL_COND_V_MSG(ttl < 0 || ttl > 255, UPNP_RESULT_INVALID_PARAM, "The time-to-live must be set between 0 and 255 (inclusive).");
devices.clear();
@@ -264,7 +263,7 @@ void UPNP::clear_devices() {
}
Ref<UPNPDevice> UPNP::get_gateway() const {
- ERR_FAIL_COND_V(devices.size() < 1, nullptr);
+ ERR_FAIL_COND_V_MSG(devices.size() < 1, nullptr, "Couldn't find any UPNPDevices.");
for (int i = 0; i < devices.size(); i++) {
Ref<UPNPDevice> dev = get_device(i);
diff --git a/modules/upnp/upnp_device.cpp b/modules/upnp/upnp_device.cpp
index c21826d14d..40eb6106a0 100644
--- a/modules/upnp/upnp_device.cpp
+++ b/modules/upnp/upnp_device.cpp
@@ -35,7 +35,7 @@
#include <miniupnpc/upnpcommands.h>
String UPNPDevice::query_external_address() const {
- ERR_FAIL_COND_V(!is_valid_gateway(), "");
+ ERR_FAIL_COND_V_MSG(!is_valid_gateway(), "", "The Internet Gateway Device must be valid.");
char addr[16];
int i = UPNP_GetExternalIPAddress(
@@ -43,17 +43,17 @@ String UPNPDevice::query_external_address() const {
igd_service_type.utf8().get_data(),
(char *)&addr);
- ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, "");
+ ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, "", "Couldn't get external IP address.");
return String(addr);
}
int UPNPDevice::add_port_mapping(int port, int port_internal, String desc, String proto, int duration) const {
- ERR_FAIL_COND_V(!is_valid_gateway(), UPNP::UPNP_RESULT_INVALID_GATEWAY);
- ERR_FAIL_COND_V(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT);
- ERR_FAIL_COND_V(port_internal < 0 || port_internal > 65535, UPNP::UPNP_RESULT_INVALID_PORT); // Needs to allow 0 because 0 signifies "use external port as internal port"
- ERR_FAIL_COND_V(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL);
- ERR_FAIL_COND_V(duration < 0, UPNP::UPNP_RESULT_INVALID_DURATION);
+ ERR_FAIL_COND_V_MSG(!is_valid_gateway(), UPNP::UPNP_RESULT_INVALID_GATEWAY, "The Internet Gateway Device must be valid.");
+ ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive).");
+ ERR_FAIL_COND_V_MSG(port_internal < 0 || port_internal > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 0 and 65535 (inclusive)."); // Needs to allow 0 because 0 signifies "use external port as internal port"
+ ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP.");
+ ERR_FAIL_COND_V_MSG(duration < 0, UPNP::UPNP_RESULT_INVALID_DURATION, "The port mapping's lease duration can't be negative.");
if (port_internal < 1) {
port_internal = port;
@@ -70,14 +70,14 @@ int UPNPDevice::add_port_mapping(int port, int port_internal, String desc, Strin
nullptr, // Remote host, always nullptr as IGDs don't support it
duration > 0 ? itos(duration).utf8().get_data() : nullptr);
- ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i));
+ ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i), "Couldn't add port mapping.");
return UPNP::UPNP_RESULT_SUCCESS;
}
int UPNPDevice::delete_port_mapping(int port, String proto) const {
- ERR_FAIL_COND_V(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT);
- ERR_FAIL_COND_V(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL);
+ ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive).");
+ ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP.");
int i = UPNP_DeletePortMapping(
igd_control_url.utf8().get_data(),
@@ -87,7 +87,7 @@ int UPNPDevice::delete_port_mapping(int port, String proto) const {
nullptr // Remote host, always nullptr as IGDs don't support it
);
- ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i));
+ ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i), "Couldn't delete port mapping.");
return UPNP::UPNP_RESULT_SUCCESS;
}
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 39d8f7c082..2b5a17c36f 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -508,7 +508,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
} break;
case MATH_POSMOD:
case MATH_ROUND: {
- t = Variant::INT;
+ t = Variant::FLOAT;
} break;
case MATH_ABS: {
t = Variant::NIL;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index b6c30d120c..1eb1ee0d29 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1932,6 +1932,7 @@ public:
ImageLoader::load_image(path, launcher_adaptive_icon_background_image);
}
+ Vector<String> invalid_abis(enabled_abis);
while (ret == UNZ_OK) {
//get filename
@@ -1977,6 +1978,7 @@ public:
bool enabled = false;
for (int i = 0; i < enabled_abis.size(); ++i) {
if (file.begins_with("lib/" + enabled_abis[i] + "/")) {
+ invalid_abis.erase(enabled_abis[i]);
enabled = true;
break;
}
@@ -2016,6 +2018,13 @@ public:
ret = unzGoToNextFile(pkg);
}
+ if (!invalid_abis.empty()) {
+ String unsupported_arch = String(", ").join(invalid_abis);
+ EditorNode::add_io_error("Missing libraries in the export template for the selected architectures: " + unsupported_arch + ".\n" +
+ "Please build a template with all required libraries, or uncheck the missing architectures in the export preset.");
+ CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND);
+ }
+
if (ep.step("Adding files...", 1)) {
CLEANUP_AND_RETURN(ERR_SKIP);
}
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index 96cfd272f2..aa98194a10 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -3,7 +3,7 @@ ext.versions = [
compileSdk : 29,
minSdk : 18,
targetSdk : 29,
- buildTools : '29.0.1',
+ buildTools : '29.0.3',
supportCoreUtils : '28.0.0',
kotlinVersion : '1.3.61',
v4Support : '28.0.0'
diff --git a/platform/android/java/lib/res/drawable-hdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-hdpi/notify_panel_notification_icon_bg.png
deleted file mode 100644
index f849d8e90d..0000000000
--- a/platform/android/java/lib/res/drawable-hdpi/notify_panel_notification_icon_bg.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/java/lib/res/drawable-mdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-mdpi/notify_panel_notification_icon_bg.png
deleted file mode 100644
index 1dfb28b33a..0000000000
--- a/platform/android/java/lib/res/drawable-mdpi/notify_panel_notification_icon_bg.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/java/lib/res/drawable-xhdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-xhdpi/notify_panel_notification_icon_bg.png
deleted file mode 100644
index 372b763ec5..0000000000
--- a/platform/android/java/lib/res/drawable-xhdpi/notify_panel_notification_icon_bg.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/java/lib/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png
deleted file mode 100644
index 302a972049..0000000000
--- a/platform/android/java/lib/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png
+++ /dev/null
Binary files differ
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index d55b21bc24..ed8481db4a 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -321,16 +321,14 @@ void PathFollow2D::set_offset(float p_offset) {
offset = p_offset;
if (path) {
- if (path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
+ if (path->get_curve().is_valid()) {
float path_length = path->get_curve()->get_baked_length();
if (loop) {
- while (offset > path_length)
- offset -= path_length;
-
- while (offset < 0)
- offset += path_length;
-
+ offset = Math::fposmod(offset, path_length);
+ if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) {
+ offset = path_length;
+ }
} else {
offset = CLAMP(offset, 0, path_length);
}
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 2455d46e43..81a5c6f4f3 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -272,6 +272,7 @@ void Light3D::_bind_methods() {
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_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0.1,8,0.01"), "set_param", "get_param", PARAM_SHADOW_BLUR);
ADD_GROUP("Editor", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
ADD_GROUP("", "");
@@ -291,6 +292,7 @@ void Light3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE);
+ BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
BIND_ENUM_CONSTANT(PARAM_MAX);
@@ -335,6 +337,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
set_param(PARAM_SHADOW_FADE_START, 0.8);
set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0);
+ set_param(PARAM_SHADOW_BLUR, 1.0);
set_param(PARAM_SHADOW_BIAS, 0.02);
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 21810e03dd..21e14f0e8b 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -58,6 +58,7 @@ public:
PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+ PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
PARAM_MAX = RS::LIGHT_PARAM_MAX
};
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index f06135f53d..4a425d1e0e 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -316,16 +316,14 @@ void PathFollow3D::set_offset(float p_offset) {
offset = p_offset;
if (path) {
- if (path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
+ if (path->get_curve().is_valid()) {
float path_length = path->get_curve()->get_baked_length();
if (loop) {
- while (offset > path_length)
- offset -= path_length;
-
- while (offset < 0)
- offset += path_length;
-
+ offset = Math::fposmod(offset, path_length);
+ if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) {
+ offset = path_length;
+ }
} else {
offset = CLAMP(offset, 0, path_length);
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 0b314d57c5..9fab9005f9 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -407,7 +407,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
cw = tab_size * font->get_char_size(' ').width;
}
- if (end > 0 && w + cw + begin > p_width) {
+ if (end > 0 && fw + cw + begin > p_width) {
break; //don't allow lines longer than assigned width
}
@@ -416,7 +416,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
end++;
}
CHECK_HEIGHT(fh);
- ENSURE_WIDTH(w);
+ ENSURE_WIDTH(fw);
line_ascent = MAX(line_ascent, ascent);
line_descent = MAX(line_descent, descent);
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h
index a6b18ee33c..2bd335e6c0 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/body_3d_sw.h
@@ -421,7 +421,7 @@ public:
virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { body->apply_impulse(p_pos, p_j); }
virtual void apply_torque_impulse(const Vector3 &p_j) { body->apply_torque_impulse(p_j); }
- virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); }
+ virtual void set_sleep_state(bool p_sleep) { body->set_active(!p_sleep); }
virtual bool is_sleeping() const { return !body->is_active(); }
virtual int get_contact_count() const { return body->contact_count; }
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index a2f08b3ed8..8ea8b22455 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -70,7 +70,7 @@ public:
virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) = 0;
virtual void apply_torque_impulse(const Vector3 &p_j) = 0;
- virtual void set_sleep_state(bool p_enable) = 0;
+ virtual void set_sleep_state(bool p_sleep) = 0;
virtual bool is_sleeping() const = 0;
virtual int get_contact_count() const = 0;
diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h
index 5792b400b9..23b7b509ba 100644
--- a/servers/rendering/rasterizer.h
+++ b/servers/rendering/rasterizer.h
@@ -106,7 +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_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
- virtual void shadow_filter_set(RS::ShadowFilter p_filter) = 0;
+ virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
+ virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
struct InstanceBase;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
index b778bef97a..5dc0e04a94 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -1573,8 +1573,9 @@ RasterizerEffectsRD::~RasterizerEffectsRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
RD::get_singleton()->free(filter.coefficient_buffer);
- copy.shader.version_free(copy.shader_version);
bokeh.shader.version_free(bokeh.shader_version);
+ copy.shader.version_free(copy.shader_version);
+ copy_to_fb.shader.version_free(copy_to_fb.shader_version);
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
filter.shader.version_free(filter.shader_version);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
index d905c60e81..2c23decd1f 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
@@ -92,6 +92,13 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_arra
}
}
+static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
+
+ for (int i = 0; i < 128; i++) {
+ p_array[i] = p_kernel[i];
+ }
+}
+
/* SCENE SHADER */
void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
//compile
@@ -1114,10 +1121,18 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.z_far = p_zfar;
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.shadow_blocker_count = 16;
+
+ store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
+ store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
+ store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
+ store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
+
+ scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get();
+ scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get();
+ scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get();
+ scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get();
scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
@@ -1737,6 +1752,8 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
light_data.fade_to = -light_data.shadow_split_offsets[3];
+ light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+
float softshadow_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
if (softshadow_angle > 0.0) {
// I know tan(0) is 0, but let's not risk it with numerical precision.
@@ -1745,6 +1762,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.softshadow_angle = Math::tan(Math::deg2rad(softshadow_angle));
} else {
light_data.softshadow_angle = 0;
+ light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
}
}
@@ -1855,6 +1873,8 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.atlas_rect[2] = rect.size.width;
light_data.atlas_rect[3] = rect.size.height;
+ light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+
if (type == RS::LIGHT_OMNI) {
light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another
@@ -1867,6 +1887,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.soft_shadow_size = size;
} else {
light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
}
} else if (type == RS::LIGHT_SPOT) {
@@ -1890,6 +1911,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
} else {
light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
}
}
} else {
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
index 5486d92508..bfc21e492a 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
@@ -276,8 +276,9 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float shadow_normal_bias;
float transmittance_bias;
float soft_shadow_size;
+ float soft_shadow_scale;
uint32_t mask;
- uint32_t pad[3];
+ uint32_t pad[2];
};
struct DirectionalLightData {
@@ -289,7 +290,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float specular;
uint32_t mask;
float softshadow_angle;
- uint32_t pad[1];
+ float soft_shadow_scale;
uint32_t blend_splits;
uint32_t shadow_enabled;
float fade_from;
@@ -379,10 +380,17 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float reflection_multiplier;
uint32_t pancake_shadows;
- uint32_t shadow_filter_mode;
+ uint32_t pad;
+
+ float directional_penumbra_shadow_kernel[128]; //32 vec4s
+ float directional_soft_shadow_kernel[128];
+ float penumbra_shadow_kernel[128];
+ float soft_shadow_kernel[128];
- uint32_t shadow_blocker_count;
- uint32_t shadow_pad[3];
+ uint32_t directional_penumbra_shadow_samples;
+ uint32_t directional_soft_shadow_samples;
+ uint32_t penumbra_shadow_samples;
+ uint32_t soft_shadow_samples;
float ambient_light_color_energy[4];
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
index c153e66308..37e2aaad0e 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -36,6 +36,18 @@
uint64_t RasterizerSceneRD::auto_exposure_counter = 2;
+void get_vogel_disk(float *r_kernel, int p_sample_count) {
+ const float golden_angle = 2.4;
+
+ for (int i = 0; i < p_sample_count; i++) {
+ float r = Math::sqrt(float(i) + 0.5) / Math::sqrt(float(p_sample_count));
+ float theta = float(i) * golden_angle;
+
+ r_kernel[i * 4] = Math::cos(theta) * r;
+ r_kernel[i * 4 + 1] = Math::sin(theta) * r;
+ }
+}
+
void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) {
rd.layers.clear();
@@ -3603,8 +3615,86 @@ void RasterizerSceneRD::sub_surface_scattering_set_scale(float p_scale, float p_
sss_depth_scale = p_depth_scale;
}
-void RasterizerSceneRD::shadow_filter_set(RS::ShadowFilter p_filter) {
- shadow_filter = p_filter;
+void RasterizerSceneRD::shadows_quality_set(RS::ShadowQuality p_quality) {
+
+ ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
+
+ if (shadows_quality != p_quality) {
+ shadows_quality = p_quality;
+
+ switch (shadows_quality) {
+ case RS::SHADOW_QUALITY_HARD: {
+ penumbra_shadow_samples = 4;
+ soft_shadow_samples = 1;
+ shadows_quality_radius = 1.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_LOW: {
+ penumbra_shadow_samples = 8;
+ soft_shadow_samples = 4;
+ shadows_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_MEDIUM: {
+ penumbra_shadow_samples = 12;
+ soft_shadow_samples = 8;
+ shadows_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_HIGH: {
+ penumbra_shadow_samples = 24;
+ soft_shadow_samples = 16;
+ shadows_quality_radius = 3.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_ULTRA: {
+ penumbra_shadow_samples = 32;
+ soft_shadow_samples = 32;
+ shadows_quality_radius = 4.0;
+ } break;
+ case RS::SHADOW_QUALITY_MAX:
+ break;
+ }
+ get_vogel_disk(penumbra_shadow_kernel, penumbra_shadow_samples);
+ get_vogel_disk(soft_shadow_kernel, soft_shadow_samples);
+ }
+}
+
+void RasterizerSceneRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) {
+
+ ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
+
+ if (directional_shadow_quality != p_quality) {
+ directional_shadow_quality = p_quality;
+
+ switch (directional_shadow_quality) {
+ case RS::SHADOW_QUALITY_HARD: {
+ directional_penumbra_shadow_samples = 4;
+ directional_soft_shadow_samples = 1;
+ directional_shadow_quality_radius = 1.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_LOW: {
+ directional_penumbra_shadow_samples = 8;
+ directional_soft_shadow_samples = 4;
+ directional_shadow_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_MEDIUM: {
+ directional_penumbra_shadow_samples = 12;
+ directional_soft_shadow_samples = 8;
+ directional_shadow_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_HIGH: {
+ directional_penumbra_shadow_samples = 24;
+ directional_soft_shadow_samples = 16;
+ directional_shadow_quality_radius = 3.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_ULTRA: {
+ directional_penumbra_shadow_samples = 32;
+ directional_soft_shadow_samples = 32;
+ directional_shadow_quality_radius = 4.0;
+ } break;
+ case RS::SHADOW_QUALITY_MAX:
+ break;
+ }
+ get_vogel_disk(directional_penumbra_shadow_kernel, directional_penumbra_shadow_samples);
+ get_vogel_disk(directional_soft_shadow_kernel, directional_soft_shadow_samples);
+ }
}
int RasterizerSceneRD::get_roughness_layers() const {
@@ -4177,7 +4267,12 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
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_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
- shadow_filter = RS::ShadowFilter(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
+ directional_penumbra_shadow_kernel = memnew_arr(float, 128);
+ directional_soft_shadow_kernel = memnew_arr(float, 128);
+ penumbra_shadow_kernel = memnew_arr(float, 128);
+ soft_shadow_kernel = memnew_arr(float, 128);
+ shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/shadows/soft_shadow_quality"))));
+ directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/directional_shadow/soft_shadow_quality"))));
}
RasterizerSceneRD::~RasterizerSceneRD() {
@@ -4206,4 +4301,8 @@ RasterizerSceneRD::~RasterizerSceneRD() {
memdelete_arr(sky_scene_state.last_frame_directional_lights);
storage->free(sky_shader.default_shader);
storage->free(sky_shader.default_material);
+ memdelete_arr(directional_penumbra_shadow_kernel);
+ memdelete_arr(directional_soft_shadow_kernel);
+ memdelete_arr(penumbra_shadow_kernel);
+ memdelete_arr(soft_shadow_kernel);
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
index ac89485764..bb42ce7182 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
@@ -537,7 +537,19 @@ 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);
- RS::ShadowFilter shadow_filter = RS::SHADOW_FILTER_NONE;
+ RS::ShadowQuality shadows_quality = RS::SHADOW_QUALITY_MAX; //So it always updates when first set
+ RS::ShadowQuality directional_shadow_quality = RS::SHADOW_QUALITY_MAX;
+ float shadows_quality_radius = 1.0;
+ float directional_shadow_quality_radius = 1.0;
+
+ float *directional_penumbra_shadow_kernel;
+ float *directional_soft_shadow_kernel;
+ float *penumbra_shadow_kernel;
+ float *soft_shadow_kernel;
+ int directional_penumbra_shadow_samples = 0;
+ int directional_soft_shadow_samples = 0;
+ int penumbra_shadow_samples = 0;
+ int soft_shadow_samples = 0;
/* DIRECTIONAL SHADOW */
@@ -1200,8 +1212,22 @@ public:
RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
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; }
+ virtual void shadows_quality_set(RS::ShadowQuality p_quality);
+ virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality);
+ _FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; }
+ _FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; }
+ _FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; }
+ _FORCE_INLINE_ float directional_shadow_quality_radius_get() const { return directional_shadow_quality_radius; }
+
+ _FORCE_INLINE_ float *directional_penumbra_shadow_kernel_get() { return directional_penumbra_shadow_kernel; }
+ _FORCE_INLINE_ float *directional_soft_shadow_kernel_get() { return directional_soft_shadow_kernel; }
+ _FORCE_INLINE_ float *penumbra_shadow_kernel_get() { return penumbra_shadow_kernel; }
+ _FORCE_INLINE_ float *soft_shadow_kernel_get() { return soft_shadow_kernel; }
+
+ _FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const { return directional_penumbra_shadow_samples; }
+ _FORCE_INLINE_ int directional_soft_shadow_samples_get() const { return directional_soft_shadow_samples; }
+ _FORCE_INLINE_ int penumbra_shadow_samples_get() const { return penumbra_shadow_samples; }
+ _FORCE_INLINE_ int soft_shadow_samples_get() const { return soft_shadow_samples; }
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 53e2f3422c..c6a0e5aaaf 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -678,61 +678,63 @@ LIGHT_SHADER_CODE
#ifndef USE_NO_SHADOWS
-const vec2 shadow_poisson_disk[16] = vec2[](
- vec2(-0.94201624, -0.39906216),
- vec2(0.94558609, -0.76890725),
- vec2(-0.094184101, -0.92938870),
- vec2(0.34495938, 0.29387760),
- vec2(-0.91588581, 0.45771432),
- vec2(-0.81544232, -0.87912464),
- vec2(-0.38277543, 0.27676845),
- vec2(0.97484398, 0.75648379),
- vec2(0.44323325, -0.97511554),
- vec2(0.53742981, -0.47373420),
- vec2(-0.26496911, -0.41893023),
- vec2(0.79197514, 0.19090188),
- vec2(-0.24188840, 0.99706507),
- vec2(-0.81409955, 0.91437590),
- vec2(0.19984126, 0.78641367),
- vec2(0.14383161, -0.14100790));
-
-float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
+// Produces cheap but low-quality white noise, nothing special
+float quick_hash(vec2 pos) {
+ return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237);
+}
+
+float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
vec2 pos = coord.xy;
float depth = coord.z;
- 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);
- };
+ //if only one sample is taken, take it from the center
+ if (scene_data.directional_soft_shadow_samples == 1) {
+ return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
- return 0;
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ float avg = 0.0;
+
+ for (uint i = 0; i < scene_data.directional_soft_shadow_samples; i++) {
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
+ }
+
+ return avg * (1.0 / float(scene_data.directional_soft_shadow_samples));
+}
+
+float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
+
+ vec2 pos = coord.xy;
+ float depth = coord.z;
+
+ //if only one sample is taken, take it from the center
+ if (scene_data.soft_shadow_samples == 1) {
+ return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ }
+
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ float avg = 0.0;
+
+ for (uint i = 0; i < scene_data.soft_shadow_samples; i++) {
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0));
+ }
+
+ return avg * (1.0 / float(scene_data.soft_shadow_samples));
}
float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) {
@@ -741,17 +743,17 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
float blocker_count = 0.0;
float blocker_average = 0.0;
- mat2 poisson_rotate;
-
+ mat2 disk_rotation;
{
- float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
float sr = sin(r);
float cr = cos(r);
- poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * tex_scale;
+ for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < pssm_coord.z) {
blocker_average += d;
@@ -767,12 +769,12 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
tex_scale *= penumbra;
float s = 0.0;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * tex_scale;
+ for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
}
- return s / float(scene_data.shadow_blocker_count);
+ return s / float(scene_data.directional_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -854,13 +856,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float blocker_count = 0.0;
float blocker_average = 0.0;
- mat2 poisson_rotate;
-
+ mat2 disk_rotation;
{
- float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
float sr = sin(r);
float cr = cos(r);
- poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
vec3 normal = normalize(splane.xyz);
@@ -869,12 +870,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
vec3 bitangent = normalize(cross(tangent, normal));
float z_norm = shadow_len * lights.data[idx].inv_radius;
- tangent *= lights.data[idx].soft_shadow_size;
- bitangent *= lights.data[idx].soft_shadow_size;
+ tangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
+ bitangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]);
- vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.y;
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+
+ vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+
+ vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
pos = normalize(pos);
vec4 uv_rect = lights.data[idx].atlas_rect;
@@ -911,10 +914,10 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
z_norm -= lights.data[idx].inv_radius * lights.data[idx].shadow_bias;
shadow = 0.0;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
- vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]);
- vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.y;
+ vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+ vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
pos = normalize(pos);
vec4 uv_rect = lights.data[idx].atlas_rect;
@@ -935,7 +938,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
}
- shadow /= float(scene_data.shadow_blocker_count);
+ shadow /= float(scene_data.penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -962,7 +965,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
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.w = 1.0; //needed? i think it should be 1 already
- shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
+ shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
}
#ifdef LIGHT_TRANSMITTANCE_USED
@@ -1114,18 +1117,18 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float blocker_count = 0.0;
float blocker_average = 0.0;
- mat2 poisson_rotate;
-
+ mat2 disk_rotation;
{
- float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
float sr = sin(r);
float cr = cos(r);
- poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
- float uv_size = lights.data[idx].soft_shadow_size * z_norm;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size;
+ float uv_size = lights.data[idx].soft_shadow_size * z_norm * lights.data[idx].soft_shadow_scale;
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+
+ vec2 suv = splane.xy + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw);
float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < z_norm) {
@@ -1142,13 +1145,13 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
uv_size *= penumbra;
shadow = 0.0;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size;
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ vec2 suv = splane.xy + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw);
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0));
}
- shadow /= float(scene_data.shadow_blocker_count);
+ shadow /= float(scene_data.penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -1158,7 +1161,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
} else {
//hard shadow
splane.z = z_norm;
- shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
+ shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
}
shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
@@ -1951,9 +1954,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.x;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color1.rgb;
@@ -1985,9 +1988,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.y;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color2.rgb;
@@ -2018,9 +2021,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.z;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color3.rgb;
@@ -2052,9 +2055,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.w;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color4.rgb;
@@ -2091,9 +2094,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.y;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
@@ -2109,9 +2112,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.z;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
@@ -2127,9 +2130,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.w;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
index 358b57c46a..329bfe7760 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
@@ -22,10 +22,6 @@ draw_call;
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
#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 = 2) uniform sampler shadow_sampler;
@@ -45,12 +41,18 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
- uint shadow_filter_mode;
+ uint pad;
+
+ //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
+ vec4 directional_penumbra_shadow_kernel[32];
+ vec4 directional_soft_shadow_kernel[32];
+ vec4 penumbra_shadow_kernel[32];
+ vec4 soft_shadow_kernel[32];
- uint shadow_blocker_count;
- uint shadow_pad0;
- uint shadow_pad1;
- uint shadow_pad2;
+ uint directional_penumbra_shadow_samples;
+ uint directional_soft_shadow_samples;
+ uint penumbra_shadow_samples;
+ uint soft_shadow_samples;
vec4 ambient_light_color_energy;
@@ -157,8 +159,9 @@ struct LightData { //this structure needs to be as packed as possible
float shadow_normal_bias;
float transmittance_bias;
float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
+ float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
uint mask;
- uint pad[3];
+ uint pad[2];
};
layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
@@ -191,7 +194,7 @@ struct DirectionalLightData {
float specular;
uint mask;
float softshadow_angle;
- uint pad1;
+ float soft_shadow_scale;
bool blend_splits;
bool shadow_enabled;
float fade_from;
diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h
index e0bb7d0fde..6f7ce7728d 100644
--- a/servers/rendering/rendering_server_raster.h
+++ b/servers/rendering/rendering_server_raster.h
@@ -573,7 +573,8 @@ public:
BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
BIND3(camera_effects_set_custom_exposure, RID, bool, float)
- BIND1(shadow_filter_set, ShadowFilter)
+ BIND1(shadows_quality_set, ShadowQuality);
+ BIND1(directional_shadow_quality_set, ShadowQuality);
/* SCENARIO API */
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
index 6acbd70d5b..79f328cb3b 100644
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ b/servers/rendering/rendering_server_wrap_mt.h
@@ -490,7 +490,8 @@ public:
FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
- FUNC1(shadow_filter_set, ShadowFilter)
+ FUNC1(shadows_quality_set, ShadowQuality);
+ FUNC1(directional_shadow_quality_set, ShadowQuality);
FUNCRID(scenario)
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index f7da0426dd..c288c2986e 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2295,6 +2295,14 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096);
GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
+ GLOBAL_DEF("rendering/quality/directional_shadow/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/quality/directional_shadow/soft_shadow_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard(Fastest), Soft Low (Fast), Soft Medium (Average), Soft High (Slow), Soft Ultra (Slowest)"));
+
+ GLOBAL_DEF("rendering/quality/shadows/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/quality/shadows/soft_shadow_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/quality/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard(Fastest), Soft Low (Fast), Soft Medium (Average), Soft High (Slow), Soft Ultra (Slowest)"));
+
GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096);
GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
@@ -2307,10 +2315,6 @@ RenderingServer::RenderingServer() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- GLOBAL_DEF("rendering/quality/shadows/filter_mode", 1);
- GLOBAL_DEF("rendering/quality/shadows/filter_mode.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/filter_mode", PropertyInfo(Variant::INT, "rendering/quality/shadows/filter_mode", PROPERTY_HINT_ENUM, "Disabled (Fast),PCF5 (Average),PCF13 (Slow)"));
-
GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 8);
GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true);
GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index e090bcb451..43c65d8007 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -394,6 +394,7 @@ public:
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
LIGHT_PARAM_SHADOW_BIAS,
LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+ LIGHT_PARAM_SHADOW_BLUR,
LIGHT_PARAM_TRANSMITTANCE_BIAS,
LIGHT_PARAM_MAX
};
@@ -849,14 +850,17 @@ 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_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
+ enum ShadowQuality {
+ SHADOW_QUALITY_HARD,
+ SHADOW_QUALITY_SOFT_LOW,
+ SHADOW_QUALITY_SOFT_MEDIUM,
+ SHADOW_QUALITY_SOFT_HIGH,
+ SHADOW_QUALITY_SOFT_ULTRA,
+ SHADOW_QUALITY_MAX
};
- virtual void shadow_filter_set(ShadowFilter p_filter) = 0;
+ virtual void shadows_quality_set(ShadowQuality p_quality) = 0;
+ virtual void directional_shadow_quality_set(ShadowQuality p_quality) = 0;
/* SCENARIO API */