summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/extension/gdextension_interface.cpp4
-rw-r--r--core/extension/gdextension_interface.h4
-rw-r--r--doc/classes/LightOccluder2D.xml1
-rw-r--r--doc/classes/RenderingDevice.xml2
-rw-r--r--drivers/egl/egl_manager.cpp19
-rw-r--r--drivers/gles3/environment/gi.cpp3
-rw-r--r--drivers/gles3/environment/gi.h2
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/filesystem_dock.cpp4
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp4
-rw-r--r--editor/property_selector.cpp2
-rw-r--r--editor/scene_tree_dock.cpp22
-rw-r--r--modules/navigation/nav_mesh_generator_2d.cpp29
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp2
-rw-r--r--scene/2d/tile_map.cpp39
-rw-r--r--scene/3d/reflection_probe.cpp5
-rw-r--r--scene/gui/base_button.cpp2
-rw-r--r--scene/gui/graph_edit.cpp12
-rw-r--r--scene/gui/graph_node.cpp4
-rw-r--r--scene/gui/menu_bar.cpp5
-rw-r--r--scene/gui/popup_menu.cpp1
-rw-r--r--scene/gui/text_edit.cpp8
-rw-r--r--scene/resources/particle_process_material.cpp20
-rw-r--r--scene/resources/tile_set.cpp27
-rw-r--r--servers/rendering/dummy/environment/gi.h2
-rw-r--r--servers/rendering/environment/renderer_gi.h2
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp5
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h4
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp8
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp16
-rw-r--r--servers/rendering/renderer_scene_cull.cpp2
-rw-r--r--servers/rendering/renderer_viewport.cpp60
-rw-r--r--servers/rendering/rendering_server_default.h2
-rw-r--r--servers/rendering/shader_language.cpp4
-rw-r--r--servers/rendering_server.h2
36 files changed, 226 insertions, 108 deletions
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp
index d1b4e6a30f..e02e7aa701 100644
--- a/core/extension/gdextension_interface.cpp
+++ b/core/extension/gdextension_interface.cpp
@@ -159,9 +159,7 @@ public:
userdata = p_info->callable_userdata;
token = p_info->token;
- if (p_info->object != nullptr) {
- object = ((Object *)p_info->object)->get_instance_id();
- }
+ object = p_info->object_id;
call_func = p_info->call_func;
is_valid_func = p_info->is_valid_func;
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index 240da6e073..d58f0226d8 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -392,7 +392,7 @@ typedef GDExtensionBool (*GDExtensionCallableCustomLessThan)(void *callable_user
typedef void (*GDExtensionCallableCustomToString)(void *callable_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
typedef struct {
- /* Only `call_func` and `token` are strictly required, however, `object` should be passed if its not a static method.
+ /* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method.
*
* `token` should point to an address that uniquely identifies the GDExtension (for example, the
* `GDExtensionClassLibraryPtr` passed to the entry symbol function.
@@ -409,7 +409,7 @@ typedef struct {
void *callable_userdata;
void *token;
- GDExtensionObjectPtr object;
+ GDObjectInstanceID object_id;
GDExtensionCallableCustomCall call_func;
GDExtensionCallableCustomIsValid is_valid_func;
diff --git a/doc/classes/LightOccluder2D.xml b/doc/classes/LightOccluder2D.xml
index 533e87bce9..e42ecd1c49 100644
--- a/doc/classes/LightOccluder2D.xml
+++ b/doc/classes/LightOccluder2D.xml
@@ -17,6 +17,7 @@
The LightOccluder2D's occluder light mask. The LightOccluder2D will cast shadows only from Light2D(s) that have the same light mask(s).
</member>
<member name="sdf_collision" type="bool" setter="set_as_sdf_collision" getter="is_set_as_sdf_collision" default="true">
+ If enabled, the occluder will be part of a real-time generated signed distance field that can be used in custom shaders.
</member>
</members>
</class>
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index b35eb89d19..20faa70226 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -706,7 +706,7 @@
<param index="5" name="layer_count" type="int" />
<param index="6" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" />
<description>
- Clears the specified [param texture] by replacing all of its pixels with the specified [param color]. [param base_mipmap] and [param mipmap_count] determine which mipmaps of the texture are affected by this clear operation, while [param base_layer] and [param layer_count] determine which layers of a 3D texture (or texture array) are affected by this clear operation. For 2D textures (which only have one layer by design), [param base_layer] and [param layer_count] must both be [code]0[/code].
+ Clears the specified [param texture] by replacing all of its pixels with the specified [param color]. [param base_mipmap] and [param mipmap_count] determine which mipmaps of the texture are affected by this clear operation, while [param base_layer] and [param layer_count] determine which layers of a 3D texture (or texture array) are affected by this clear operation. For 2D textures (which only have one layer by design), [param base_layer] must be [code]0[/code] and [param layer_count] must be [code]1[/code].
[b]Note:[/b] [param texture] can't be cleared while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to [constant FINAL_ACTION_CONTINUE]) to clear this texture.
</description>
</method>
diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp
index 0faae8cf6f..4c9d610935 100644
--- a/drivers/egl/egl_manager.cpp
+++ b/drivers/egl/egl_manager.cpp
@@ -52,9 +52,13 @@ int EGLManager::_get_gldisplay_id(void *p_display) {
GLDisplay new_gldisplay;
new_gldisplay.display = p_display;
- Vector<EGLAttrib> attribs = _get_platform_display_attributes();
-
- new_gldisplay.egl_display = eglGetPlatformDisplay(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
+ if (GLAD_EGL_VERSION_1_5) {
+ Vector<EGLAttrib> attribs = _get_platform_display_attributes();
+ new_gldisplay.egl_display = eglGetPlatformDisplay(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
+ } else {
+ NativeDisplayType *native_display_type = (NativeDisplayType *)new_gldisplay.display;
+ new_gldisplay.egl_display = eglGetDisplay(*native_display_type);
+ }
ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, -1);
ERR_FAIL_COND_V_MSG(new_gldisplay.egl_display == EGL_NO_DISPLAY, -1, "Can't create an EGL display.");
@@ -198,7 +202,12 @@ Error EGLManager::window_create(DisplayServer::WindowID p_window_id, void *p_dis
GLWindow &glwindow = windows[p_window_id];
glwindow.gldisplay_id = gldisplay_id;
- glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, nullptr);
+ if (GLAD_EGL_VERSION_1_5) {
+ glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, nullptr);
+ } else {
+ EGLNativeWindowType *native_window_type = (EGLNativeWindowType *)p_native_window;
+ glwindow.egl_surface = eglCreateWindowSurface(gldisplay.egl_display, gldisplay.egl_config, *native_window_type, nullptr);
+ }
if (glwindow.egl_surface == EGL_NO_SURFACE) {
return ERR_CANT_CREATE;
@@ -345,7 +354,7 @@ Error EGLManager::initialize() {
ERR_FAIL_COND_V_MSG(!version, ERR_UNAVAILABLE, "Can't load EGL.");
print_verbose(vformat("Loaded EGL %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)));
- ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_5, ERR_UNAVAILABLE, "EGL version is too old!");
+ ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, "EGL version is too old!");
eglTerminate(tmp_display);
#endif
diff --git a/drivers/gles3/environment/gi.cpp b/drivers/gles3/environment/gi.cpp
index 8beee25c64..6b33e0aa22 100644
--- a/drivers/gles3/environment/gi.cpp
+++ b/drivers/gles3/environment/gi.cpp
@@ -137,4 +137,7 @@ uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const {
return 0;
}
+void GI::sdfgi_reset() {
+}
+
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/environment/gi.h b/drivers/gles3/environment/gi.h
index 41958e43e6..3eaa687f4f 100644
--- a/drivers/gles3/environment/gi.h
+++ b/drivers/gles3/environment/gi.h
@@ -85,6 +85,8 @@ public:
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override;
virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override;
+
+ virtual void sdfgi_reset() override;
};
}; // namespace GLES3
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 7b0bea81d7..8c3637663d 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -68,6 +68,7 @@
#include "servers/display_server.h"
#include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h"
+#include "servers/rendering_server.h"
#include "editor/audio_stream_preview.h"
#include "editor/debugger/editor_debugger_node.h"
@@ -3577,6 +3578,9 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
ScriptEditor::get_singleton()->set_scene_root_script(editor_data.get_scene_root_script(editor_data.get_edited_scene()));
editor_data.notify_edited_scene_changed();
emit_signal(SNAME("scene_changed"));
+
+ // Reset SDFGI after everything else so that any last-second scene modifications will be processed.
+ RenderingServer::get_singleton()->sdfgi_reset();
}
bool EditorNode::is_changing_scene() const {
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index a491a9b214..afefd38b20 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1554,7 +1554,9 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
void FileSystemDock::_update_resource_paths_after_move(const HashMap<String, String> &p_renames, const HashMap<String, ResourceUID::ID> &p_uids) const {
// Update the paths in ResourceUID, so that UIDs remain valid.
for (const KeyValue<String, ResourceUID::ID> &pair : p_uids) {
- ResourceUID::get_singleton()->set_id(pair.value, p_renames[pair.key]);
+ if (p_renames.has(pair.key)) {
+ ResourceUID::get_singleton()->set_id(pair.value, p_renames[pair.key]);
+ }
}
// Rename all resources loaded, be it subresources or actual resources.
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 20b91d8bfd..eeefd1c90d 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -871,7 +871,9 @@ void Skeleton3DEditor::_notification(int p_what) {
skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties));
skeleton->set_transform_gizmo_visible(true);
#endif
- handles_mesh_instance->get_parent()->remove_child(handles_mesh_instance);
+ if (handles_mesh_instance->get_parent()) {
+ handles_mesh_instance->get_parent()->remove_child(handles_mesh_instance);
+ }
}
edit_mode_toggled(false);
} break;
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index 8c0a5b999a..87dbbd599d 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -569,5 +569,7 @@ PropertySelector::PropertySelector() {
help_bit = memnew(EditorHelpBit);
vbc->add_margin_child(TTR("Description:"), help_bit);
+ help_bit->get_rich_text()->set_fit_content(false);
+ help_bit->get_rich_text()->set_custom_minimum_size(Size2(help_bit->get_rich_text()->get_minimum_size().x, 135 * EDSCALE));
help_bit->connect("request_hide", callable_mp(this, &PropertySelector::_hide_requested));
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 0d106bf842..9722f656f7 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -681,10 +681,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
}
- if (!_validate_no_foreign()) {
- break;
- }
-
List<Node *> selection = editor_selection->get_selected_node_list();
if (selection.size() == 0) {
break;
@@ -704,7 +700,15 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Node *parent = node->get_parent();
List<Node *> owned;
- node->get_owned_by(node->get_owner(), &owned);
+ Node *owner = node;
+ while (owner) {
+ List<Node *> cur_owned;
+ node->get_owned_by(owner, &cur_owned);
+ owner = owner->get_owner();
+ for (Node *F : cur_owned) {
+ owned.push_back(F);
+ }
+ }
HashMap<const Node *, Node *> duplimap;
Node *dup = node->duplicate_from_editor(duplimap);
@@ -724,9 +728,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
continue;
}
Node *d = duplimap[F];
- undo_redo->add_do_method(d, "set_owner", node->get_owner());
+ undo_redo->add_do_method(d, "set_owner", edited_scene);
}
undo_redo->add_do_method(editor_selection, "add_node", dup);
+ undo_redo->add_do_method(dup, "set_owner", edited_scene);
undo_redo->add_undo_method(parent, "remove_child", dup);
undo_redo->add_do_reference(dup);
@@ -2162,8 +2167,13 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
}
undo_redo->commit_action();
+ // Avoid changing the currently edited object.
+ Object *edited_object = InspectorDock::get_inspector_singleton()->get_edited_object();
+
_push_item(p_script.ptr());
_update_script_button();
+
+ InspectorDock::get_inspector_singleton()->edit(edited_object);
}
void SceneTreeDock::_shader_created(Ref<Shader> p_shader) {
diff --git a/modules/navigation/nav_mesh_generator_2d.cpp b/modules/navigation/nav_mesh_generator_2d.cpp
index 089744c8bd..f8c12935b4 100644
--- a/modules/navigation/nav_mesh_generator_2d.cpp
+++ b/modules/navigation/nav_mesh_generator_2d.cpp
@@ -587,6 +587,9 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo
const Vector2i &cell = used_cells[used_cell_index];
const TileData *tile_data = tilemap->get_cell_tile_data(tilemap_layer, cell, false);
+ if (tile_data == nullptr) {
+ continue;
+ }
Transform2D tile_transform;
tile_transform.set_origin(tilemap->map_to_local(cell));
@@ -597,10 +600,19 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(tilemap_layer);
if (navigation_polygon.is_valid()) {
for (int outline_index = 0; outline_index < navigation_polygon->get_outline_count(); outline_index++) {
- Vector<Vector2> traversable_outline = navigation_polygon->get_outline(outline_index);
+ const Vector<Vector2> &navigation_polygon_outline = navigation_polygon->get_outline(outline_index);
+ if (navigation_polygon_outline.size() == 0) {
+ continue;
+ }
+
+ Vector<Vector2> traversable_outline;
+ traversable_outline.resize(navigation_polygon_outline.size());
+
+ const Vector2 *navigation_polygon_outline_ptr = navigation_polygon_outline.ptr();
+ Vector2 *traversable_outline_ptrw = traversable_outline.ptrw();
for (int traversable_outline_index = 0; traversable_outline_index < traversable_outline.size(); traversable_outline_index++) {
- traversable_outline.write[traversable_outline_index] = tile_transform_offset.xform(traversable_outline[traversable_outline_index]);
+ traversable_outline_ptrw[traversable_outline_index] = tile_transform_offset.xform(navigation_polygon_outline_ptr[traversable_outline_index]);
}
p_source_geometry_data->_add_traversable_outline(traversable_outline);
@@ -610,10 +622,19 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo
if (physics_layers_count > 0 && (parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH) && (tile_set->get_physics_layer_collision_layer(tilemap_layer) & parsed_collision_mask)) {
for (int collision_polygon_index = 0; collision_polygon_index < tile_data->get_collision_polygons_count(tilemap_layer); collision_polygon_index++) {
- Vector<Vector2> obstruction_outline = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index);
+ const Vector<Vector2> &collision_polygon_points = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index);
+ if (collision_polygon_points.size() == 0) {
+ continue;
+ }
+
+ Vector<Vector2> obstruction_outline;
+ obstruction_outline.resize(collision_polygon_points.size());
+
+ const Vector2 *collision_polygon_points_ptr = collision_polygon_points.ptr();
+ Vector2 *obstruction_outline_ptrw = obstruction_outline.ptrw();
for (int obstruction_outline_index = 0; obstruction_outline_index < obstruction_outline.size(); obstruction_outline_index++) {
- obstruction_outline.write[obstruction_outline_index] = tile_transform_offset.xform(obstruction_outline[obstruction_outline_index]);
+ obstruction_outline_ptrw[obstruction_outline_index] = tile_transform_offset.xform(collision_polygon_points_ptr[obstruction_outline_index]);
}
p_source_geometry_data->_add_obstruction_outline(obstruction_outline);
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 1660101598..a1a844cb05 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -1571,7 +1571,7 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
//Use xrandr to get screen refresh rate.
if (xrandr_ext_ok) {
- XRRScreenResources *screen_info = XRRGetScreenResources(x11_display, windows[MAIN_WINDOW_ID].x11_window);
+ XRRScreenResources *screen_info = XRRGetScreenResourcesCurrent(x11_display, windows[MAIN_WINDOW_ID].x11_window);
if (screen_info) {
RRMode current_mode = 0;
xrr_monitor_info *monitors = nullptr;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index b6da4d5082..6eca32fbb6 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -2294,11 +2294,12 @@ void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_ter
TypedArray<Vector2i> TileMapLayer::get_used_cells() const {
// Returns the cells used in the tilemap.
TypedArray<Vector2i> a;
- a.resize(tile_map.size());
- int i = 0;
for (const KeyValue<Vector2i, CellData> &E : tile_map) {
- Vector2i p(E.key.x, E.key.y);
- a[i++] = p;
+ const TileMapCell &c = E.value.cell;
+ if (c.source_id == TileSet::INVALID_SOURCE) {
+ continue;
+ }
+ a.push_back(E.key);
}
return a;
@@ -2308,9 +2309,13 @@ TypedArray<Vector2i> TileMapLayer::get_used_cells_by_id(int p_source_id, const V
// Returns the cells used in the tilemap.
TypedArray<Vector2i> a;
for (const KeyValue<Vector2i, CellData> &E : tile_map) {
- if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == E.value.cell.source_id) &&
- (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == E.value.cell.get_atlas_coords()) &&
- (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == E.value.cell.alternative_tile)) {
+ const TileMapCell &c = E.value.cell;
+ if (c.source_id == TileSet::INVALID_SOURCE) {
+ continue;
+ }
+ if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == c.source_id) &&
+ (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == c.get_atlas_coords()) &&
+ (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == c.alternative_tile)) {
a.push_back(E.key);
}
}
@@ -2323,13 +2328,23 @@ Rect2i TileMapLayer::get_used_rect() const {
if (used_rect_cache_dirty) {
used_rect_cache = Rect2i();
- if (tile_map.size() > 0) {
- used_rect_cache = Rect2i(tile_map.begin()->key.x, tile_map.begin()->key.y, 0, 0);
-
- for (const KeyValue<Vector2i, CellData> &E : tile_map) {
+ bool first = true;
+ for (const KeyValue<Vector2i, CellData> &E : tile_map) {
+ const TileMapCell &c = E.value.cell;
+ if (c.source_id == TileSet::INVALID_SOURCE) {
+ continue;
+ }
+ if (first) {
+ used_rect_cache = Rect2i(E.key.x, E.key.y, 0, 0);
+ first = false;
+ } else {
used_rect_cache.expand_to(E.key);
}
- used_rect_cache.size += Vector2i(1, 1); // The cache expands to top-left coordinate, so we add one full tile.
+ }
+ if (!first) {
+ // Only if we have at least one cell.
+ // The cache expands to top-left coordinate, so we add one full tile.
+ used_rect_cache.size += Vector2i(1, 1);
}
used_rect_cache_dirty = false;
}
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index e533f08861..2e34f6aad0 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -68,8 +68,9 @@ Color ReflectionProbe::get_ambient_color() const {
}
void ReflectionProbe::set_max_distance(float p_distance) {
- max_distance = p_distance;
- RS::get_singleton()->reflection_probe_set_max_distance(probe, p_distance);
+ max_distance = CLAMP(p_distance, 0.0, 262'144.0);
+ // Reflection rendering breaks if distance exceeds 262,144 units (due to floating-point precision with the near plane being 0.01).
+ RS::get_singleton()->reflection_probe_set_max_distance(probe, max_distance);
}
float ReflectionProbe::get_max_distance() const {
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index f57afb66b3..66b14dc967 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -380,7 +380,7 @@ void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) {
queue_redraw();
accept_event();
- if (shortcut_feedback) {
+ if (shortcut_feedback && is_inside_tree()) {
if (shortcut_feedback_timer == nullptr) {
shortcut_feedback_timer = memnew(Timer);
shortcut_feedback_timer->set_one_shot(true);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 1fc501e980..8dddbf78cf 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -598,7 +598,7 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
// Determine slot height.
int slot_index = graph_node->get_input_port_slot(j);
- Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index));
+ Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false));
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
@@ -612,7 +612,7 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
// Determine slot height.
int slot_index = graph_node->get_output_port_slot(j);
- Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index));
+ Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false));
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
if (is_in_output_hotzone(graph_node, j, p_point / zoom, port_size)) {
@@ -643,7 +643,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
// Determine slot height.
int slot_index = graph_node->get_output_port_slot(j);
- Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index));
+ Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false));
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
if (is_in_output_hotzone(graph_node, j, click_pos, port_size)) {
@@ -700,7 +700,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
// Determine slot height.
int slot_index = graph_node->get_input_port_slot(j);
- Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index));
+ Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false));
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
if (is_in_input_hotzone(graph_node, j, click_pos, port_size)) {
@@ -777,7 +777,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
// Determine slot height.
int slot_index = graph_node->get_output_port_slot(j);
- Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index));
+ Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false));
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
int type = graph_node->get_output_port_type(j);
@@ -801,7 +801,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
// Determine slot height.
int slot_index = graph_node->get_input_port_slot(j);
- Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index));
+ Control *child = Object::cast_to<Control>(graph_node->get_child(slot_index, false));
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
int type = graph_node->get_input_port_type(j);
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index fdebca3d28..3b1c1a153f 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -620,7 +620,7 @@ void GraphNode::_port_pos_update() {
port_cache.pos = Point2i(edgeofs, vertical_ofs + size.height / 2);
port_cache.type = slot_table[i].type_left;
port_cache.color = slot_table[i].color_left;
- port_cache.slot_index = child->get_index(); // Index with internal nodes included.
+ port_cache.slot_index = child->get_index(false);
left_port_cache.push_back(port_cache);
}
if (slot_table[i].enable_right) {
@@ -628,7 +628,7 @@ void GraphNode::_port_pos_update() {
port_cache.pos = Point2i(get_size().width - edgeofs, vertical_ofs + size.height / 2);
port_cache.type = slot_table[i].type_right;
port_cache.color = slot_table[i].color_right;
- port_cache.slot_index = child->get_index(); // Index with internal nodes included.
+ port_cache.slot_index = child->get_index(false);
right_port_cache.push_back(port_cache);
}
}
diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp
index 371d6c69af..7418ba7333 100644
--- a/scene/gui/menu_bar.cpp
+++ b/scene/gui/menu_bar.cpp
@@ -561,6 +561,7 @@ void MenuBar::add_child_notify(Node *p_child) {
int index = DisplayServer::get_singleton()->global_menu_add_submenu_item("_main", atr(menu.name), submenu_name, _find_global_start_index() + menu_cache.size() - 1);
DisplayServer::get_singleton()->global_menu_set_item_tag("_main", index, global_menu_name + "#" + itos(menu_cache.size() - 1));
}
+ update_minimum_size();
}
void MenuBar::move_child_notify(Node *p_child) {
@@ -621,6 +622,8 @@ void MenuBar::remove_child_notify(Node *p_child) {
p_child->disconnect("renamed", callable_mp(this, &MenuBar::_refresh_menu_names));
p_child->disconnect("about_to_popup", callable_mp(this, &MenuBar::_popup_visibility_changed));
p_child->disconnect("popup_hide", callable_mp(this, &MenuBar::_popup_visibility_changed));
+
+ update_minimum_size();
}
void MenuBar::_bind_methods() {
@@ -808,6 +811,7 @@ void MenuBar::set_menu_title(int p_menu, const String &p_title) {
if (!global_menu_name.is_empty()) {
DisplayServer::get_singleton()->global_menu_set_item_text("_main", _find_global_start_index() + p_menu, atr(menu_cache[p_menu].name));
}
+ update_minimum_size();
}
String MenuBar::get_menu_title(int p_menu) const {
@@ -849,6 +853,7 @@ void MenuBar::set_menu_hidden(int p_menu, bool p_hidden) {
if (!global_menu_name.is_empty()) {
DisplayServer::get_singleton()->global_menu_set_item_hidden("_main", _find_global_start_index() + p_menu, p_hidden);
}
+ update_minimum_size();
}
bool MenuBar::is_menu_hidden(int p_menu) const {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index dfaf7d88b7..ec9e2cacb4 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -2186,6 +2186,7 @@ void PopupMenu::scroll_to_item(int p_idx) {
}
bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only) {
+ ERR_FAIL_COND_V(p_event.is_null(), false);
Key code = Key::NONE;
Ref<InputEventKey> k = p_event;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 479480011c..86e726d9da 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -2948,6 +2948,8 @@ void TextEdit::_update_placeholder() {
return; // Not in tree?
}
+ const String placeholder_translated = atr(placeholder_text);
+
// Placeholder is generally smaller then text documents, and updates less so this should be fast enough for now.
placeholder_data_buf->clear();
placeholder_data_buf->set_width(text.get_width());
@@ -2958,9 +2960,9 @@ void TextEdit::_update_placeholder() {
placeholder_data_buf->set_direction((TextServer::Direction)text_direction);
}
placeholder_data_buf->set_preserve_control(draw_control_chars);
- placeholder_data_buf->add_string(placeholder_text, theme_cache.font, theme_cache.font_size, language);
+ placeholder_data_buf->add_string(placeholder_translated, theme_cache.font, theme_cache.font_size, language);
- placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text);
+ placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_translated);
if (placeholder_bidi_override.is_empty()) {
TS->shaped_text_set_bidi_override(placeholder_data_buf->get_rid(), placeholder_bidi_override);
}
@@ -2985,7 +2987,7 @@ void TextEdit::_update_placeholder() {
placeholder_wraped_rows.clear();
for (int i = 0; i <= wrap_amount; i++) {
Vector2i line_range = placeholder_data_buf->get_line_range(i);
- placeholder_wraped_rows.push_back(placeholder_text.substr(line_range.x, line_range.y - line_range.x));
+ placeholder_wraped_rows.push_back(placeholder_translated.substr(line_range.x, line_range.y - line_range.x));
}
}
diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp
index 9ceddbc7b1..6075db4ffb 100644
--- a/scene/resources/particle_process_material.cpp
+++ b/scene/resources/particle_process_material.cpp
@@ -985,10 +985,6 @@ void ParticleProcessMaterial::_update_shader() {
code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n";
code += " } else {\n";
code += " VELOCITY = vec3(0.0);\n";
- // If turbulence is enabled, set the noise direction to up so the turbulence color is "neutral"
- if (turbulence_enabled) {
- code += " noise_direction = vec3(1.0, 0.0, 0.0);\n";
- }
code += " }\n";
code += " }\n";
} else if (collision_mode == COLLISION_HIDE_ON_CONTACT) {
@@ -1007,14 +1003,16 @@ void ParticleProcessMaterial::_update_shader() {
}
code += " \n";
code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz);\n";
- // The following snippet causes massive performance hit. We don't need it as long as collision is disabled.
- // Refer to GH-83744 for more info.
- if (collision_mode != COLLISION_DISABLED) {
+
+ // Godot detects when the COLLIDED keyword is used. If it's used anywhere in the shader then Godot will generate the screen space SDF for collisions.
+ // We don't need it as long as collision is disabled. Refer to GH-83744 for more info.
+ if (collision_mode == COLLISION_RIGID) {
code += " if (!COLLIDED) {\n";
- code += " \n";
- code += " float vel_mag = length(final_velocity);\n";
- code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0,1.0);\n";
- code += " final_velocity = mix(final_velocity, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n";
+ }
+ code += " float vel_mag = length(final_velocity);\n";
+ code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0,1.0);\n";
+ code += " final_velocity = mix(final_velocity, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n";
+ if (collision_mode == COLLISION_RIGID) {
code += " }\n";
}
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 121d29b728..7b4080517f 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -4787,15 +4787,17 @@ Ref<ImageTexture> TileSetAtlasSource::_create_padded_image_texture(const Ref<Tex
image->blit_rect(*src_image, src_rect, base_pos);
+ // Sides
image->blit_rect(*src_image, top_src_rect, base_pos + Vector2i(0, -1));
image->blit_rect(*src_image, bottom_src_rect, base_pos + Vector2i(0, src_rect.size.y));
image->blit_rect(*src_image, left_src_rect, base_pos + Vector2i(-1, 0));
image->blit_rect(*src_image, right_src_rect, base_pos + Vector2i(src_rect.size.x, 0));
- image->set_pixelv(base_pos + Vector2i(-1, -1), src_image->get_pixelv(src_rect.position));
- image->set_pixelv(base_pos + Vector2i(src_rect.size.x, -1), src_image->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, 0)));
- image->set_pixelv(base_pos + Vector2i(-1, src_rect.size.y), src_image->get_pixelv(src_rect.position + Vector2i(0, src_rect.size.y - 1)));
- image->set_pixelv(base_pos + Vector2i(src_rect.size.x, src_rect.size.y), src_image->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1)));
+ // Corners
+ image->blit_rect(*src_image, Rect2i(src_rect.position, Vector2i(1, 1)), base_pos + Vector2i(-1, -1));
+ image->blit_rect(*src_image, Rect2i(src_rect.position + Vector2i(src_rect.size.x - 1, 0), Vector2i(1, 1)), base_pos + Vector2i(src_rect.size.x, -1));
+ image->blit_rect(*src_image, Rect2i(src_rect.position + Vector2i(0, src_rect.size.y - 1), Vector2i(1, 1)), base_pos + Vector2i(-1, src_rect.size.y));
+ image->blit_rect(*src_image, Rect2i(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1), Vector2i(1, 1)), base_pos + Vector2i(src_rect.size.x, src_rect.size.y));
}
}
@@ -4831,31 +4833,20 @@ void TileSetAtlasSource::_update_padded_texture() {
Ref<Texture2D> src = src_canvas_texture->get_diffuse_texture();
Ref<ImageTexture> image_texture;
if (src.is_valid()) {
- image_texture = _create_padded_image_texture(src);
- } else {
- image_texture.instantiate();
+ padded_texture->set_diffuse_texture(_create_padded_image_texture(src));
}
- padded_texture->set_diffuse_texture(image_texture);
// Normal
src = src_canvas_texture->get_normal_texture();
- image_texture.instantiate();
if (src.is_valid()) {
- image_texture = _create_padded_image_texture(src);
- } else {
- image_texture.instantiate();
+ padded_texture->set_normal_texture(_create_padded_image_texture(src));
}
- padded_texture->set_normal_texture(image_texture);
// Specular
src = src_canvas_texture->get_specular_texture();
- image_texture.instantiate();
if (src.is_valid()) {
- image_texture = _create_padded_image_texture(src);
- } else {
- image_texture.instantiate();
+ padded_texture->set_specular_texture(_create_padded_image_texture(src));
}
- padded_texture->set_specular_texture(image_texture);
// Other properties.
padded_texture->set_specular_color(src_canvas_texture->get_specular_color());
diff --git a/servers/rendering/dummy/environment/gi.h b/servers/rendering/dummy/environment/gi.h
index a26938c740..5d0e84ae43 100644
--- a/servers/rendering/dummy/environment/gi.h
+++ b/servers/rendering/dummy/environment/gi.h
@@ -78,6 +78,8 @@ public:
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override { return 0; }
+
+ virtual void sdfgi_reset() override {}
};
} // namespace RendererDummy
diff --git a/servers/rendering/environment/renderer_gi.h b/servers/rendering/environment/renderer_gi.h
index 6eff319882..94e2c1afda 100644
--- a/servers/rendering/environment/renderer_gi.h
+++ b/servers/rendering/environment/renderer_gi.h
@@ -79,6 +79,8 @@ public:
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
virtual uint32_t voxel_gi_get_version(RID p_probe) const = 0;
+
+ virtual void sdfgi_reset() = 0;
};
#endif // RENDERER_GI_H
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 0667ae87e5..dce8fadb63 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -392,6 +392,10 @@ Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const {
return &voxel_gi->dependency;
}
+void GI::sdfgi_reset() {
+ sdfgi_current_version++;
+}
+
////////////////////////////////////////////////////////////////////////////////
// SDFGI
@@ -416,6 +420,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
y_scale_mode = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_y_scale(p_env);
static const float y_scale[3] = { 2.0, 1.5, 1.0 };
y_mult = y_scale[y_scale_mode];
+ version = gi->sdfgi_current_version;
cascades.resize(num_cascades);
probe_axis_count = SDFGI::PROBE_DIVISOR + 1;
solid_cell_ratio = gi->sdfgi_solid_cell_ratio;
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index 9a45919a2f..c46d4cbd25 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -667,6 +667,7 @@ public:
float y_mult = 1.0;
+ uint32_t version = 0;
uint32_t render_pass = 0;
int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
@@ -701,11 +702,14 @@ public:
Vector3 sdfgi_debug_probe_dir;
bool sdfgi_debug_probe_enabled = false;
Vector3i sdfgi_debug_probe_index;
+ uint32_t sdfgi_current_version = 0;
/* SDFGI UPDATE */
int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
+ virtual void sdfgi_reset() override;
+
struct SDFGIData {
float grid_size[3];
uint32_t max_cascades;
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index dce97808b1..768701329b 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -3486,14 +3486,18 @@ void RenderForwardClustered::sdfgi_update(const Ref<RenderSceneBuffers> &p_rende
}
bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment);
+ bool needs_reset = sdfgi.is_valid() ? sdfgi->version != gi.sdfgi_current_version : false;
- if (!needs_sdfgi) {
+ if (!needs_sdfgi || needs_reset) {
if (sdfgi.is_valid()) {
// delete it
sdfgi.unref();
rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
}
- return;
+
+ if (!needs_sdfgi) {
+ return;
+ }
}
// Ensure advanced shaders are available if SDFGI is used.
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 9e8d654b4e..a6a32d9e86 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -264,7 +264,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
RID render_target = render_buffers->get_render_target();
ERR_FAIL_COND_V(render_target.is_null(), RID());
RID target_buffer;
- if (texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) {
+ if (view_count > 1 || texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) {
target_buffer = texture_storage->render_target_get_rd_texture(render_target);
} else {
target_buffer = texture_storage->render_target_get_rd_texture_msaa(render_target);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index d10443d6ad..1a33f1d6e0 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -365,6 +365,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RID color_texture = use_upscaled_texture ? rb->get_upscaled_texture() : rb->get_internal_texture();
Size2i color_size = use_upscaled_texture ? target_size : rb->get_internal_size();
+ bool dest_is_msaa_2d = rb->get_view_count() == 1 && texture_storage->render_target_get_msaa(render_target) != RS::VIEWPORT_MSAA_DISABLED;
+
if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Depth of Field");
RD::get_singleton()->draw_command_begin_label("DOF");
@@ -581,7 +583,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// If we do a bilinear upscale we just render into our render target and our shader will upscale automatically.
// Target size in this case is lying as we never get our real target size communicated.
// Bit nasty but...
- dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
+
+ if (dest_is_msaa_2d) {
+ dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
+ } else {
+ dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
+ }
}
tone_mapper->tonemapper(color_texture, dest_fb, tonemap);
@@ -599,6 +606,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
fsr->fsr_upscale(rb, source_texture, dest_texture);
}
+ if (dest_is_msaa_2d) {
+ // We can't upscale directly into our MSAA buffer so we need to do a copy
+ RID source_texture = texture_storage->render_target_get_rd_texture(render_target);
+ RID dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
+ copy_effects->copy_to_fb_rect(source_texture, dest_fb, Rect2i(Point2i(), rb->get_target_size()));
+ }
+
RD::get_singleton()->draw_command_end_label();
}
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 1c5cbe9612..73aacf311f 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -2239,7 +2239,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
// 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.
- const real_t unit = (radius + soft_shadow_expand) * 2.0 / texture_size;
+ const real_t unit = (radius + soft_shadow_expand) * 4.0 / texture_size;
x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);
x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);
y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 34d6a93e36..6b47c29382 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -116,19 +116,30 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
p_viewport->render_buffers.unref();
} else {
+ const float EPSILON = 0.0001;
float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
+ bool upscaler_available = p_viewport->fsr_enabled;
+
+ if ((!upscaler_available || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_BILINEAR || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && scaling_3d_scale >= (1.0 - EPSILON) && scaling_3d_scale <= (1.0 + EPSILON)) {
+ // No 3D scaling on bilinear or FSR? Ignore scaling mode, this just introduces overhead.
+ // - Mobile can't perform optimal path
+ // - FSR does an extra pass (or 2 extra passes if 2D-MSAA is enabled)
+ // Scaling = 1.0 on FSR2 has benefits
+ scaling_3d_scale = 1.0;
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
+ }
+
bool scaling_3d_is_fsr = (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) || (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2);
bool use_taa = p_viewport->use_taa;
- if (scaling_3d_is_fsr && (scaling_3d_scale > 1.0)) {
+ if (scaling_3d_is_fsr && (scaling_3d_scale >= (1.0 + EPSILON))) {
// FSR is not designed for downsampling.
// Fall back to bilinear scaling.
WARN_PRINT_ONCE("FSR 3D resolution scaling is not designed for downsampling. Falling back to bilinear 3D resolution scaling.");
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
}
- bool upscaler_available = p_viewport->fsr_enabled;
if (scaling_3d_is_fsr && !upscaler_available) {
// FSR is not actually available.
// Fall back to bilinear scaling.
@@ -143,8 +154,8 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
use_taa = false;
}
- int width;
- int height;
+ int target_width;
+ int target_height;
int render_width;
int render_height;
@@ -152,40 +163,40 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR:
// Clamp 3D rendering resolution to reasonable values supported on most hardware.
// This prevents freezing the engine or outright crashing on lower-end GPUs.
- width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
- height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);
- render_width = width;
- render_height = height;
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = CLAMP(target_width * scaling_3d_scale, 1, 16384);
+ render_height = CLAMP(target_height * scaling_3d_scale, 1, 16384);
break;
case RS::VIEWPORT_SCALING_3D_MODE_FSR:
case RS::VIEWPORT_SCALING_3D_MODE_FSR2:
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling)
- render_height = MAX(height * scaling_3d_scale, 1.0);
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = MAX(target_width * scaling_3d_scale, 1.0); // target_width / (target_width * scaling)
+ render_height = MAX(target_height * scaling_3d_scale, 1.0);
break;
case RS::VIEWPORT_SCALING_3D_MODE_OFF:
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = width;
- render_height = height;
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = target_width;
+ render_height = target_height;
break;
default:
// This is an unknown mode.
WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
scaling_3d_scale = 1.0;
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = width;
- render_height = height;
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = target_width;
+ render_height = target_height;
break;
}
uint32_t jitter_phase_count = 0;
if (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2) {
// Implementation has been copied from ffxFsr2GetJitterPhaseCount.
- jitter_phase_count = uint32_t(8.0f * pow(float(width) / render_width, 2.0f));
+ jitter_phase_count = uint32_t(8.0f * pow(float(target_width) / render_width, 2.0f));
} else if (use_taa) {
// Default jitter count for TAA.
jitter_phase_count = 16;
@@ -201,7 +212,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RenderSceneBuffersConfiguration rb_config;
rb_config.set_render_target(p_viewport->render_target);
rb_config.set_internal_size(Size2i(render_width, render_height));
- rb_config.set_target_size(Size2(width, height));
+ rb_config.set_target_size(Size2(target_width, target_height));
rb_config.set_view_count(p_viewport->view_count);
rb_config.set_scaling_3d_mode(scaling_3d_mode);
rb_config.set_msaa_3d(p_viewport->msaa_3d);
@@ -259,6 +270,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
/* Camera should always be BEFORE any other 3D */
+ bool can_draw_2d = !p_viewport->disable_2d && p_viewport->view_count == 1; // Stereo rendering does not support 2D, no depth data
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
int scenario_canvas_max_layer = 0;
bool force_clear_render_target = false;
@@ -272,7 +284,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (RSG::scene->is_scenario(p_viewport->scenario)) {
RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
if (RSG::scene->is_environment(environment)) {
- if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport)) {
+ if (can_draw_2d && !viewport_is_environment_disabled(p_viewport)) {
scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS;
scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment);
} else if (RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS) {
@@ -307,7 +319,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_draw_3d(p_viewport);
}
- if (!p_viewport->disable_2d) {
+ if (can_draw_2d) {
RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 3d75ced3e3..cd5904f175 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -476,6 +476,8 @@ public:
FUNC2(voxel_gi_set_interior, RID, bool)
FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
+ FUNC0(sdfgi_reset)
+
/* PARTICLES */
#undef ServerName
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 41f2fbb03f..a2da26eb65 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -4639,6 +4639,10 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
+ if (shader->varyings.has(var->name)) {
+ return _validate_varying_assign(shader->varyings[var->name], r_message);
+ }
+
if (!(p_function_info.built_ins.has(var->name) && p_function_info.built_ins[var->name].constant)) {
return true;
}
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index fb658aaee8..d23e0fb48d 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -633,6 +633,8 @@ public:
virtual void voxel_gi_set_quality(VoxelGIQuality) = 0;
+ virtual void sdfgi_reset() = 0;
+
/* LIGHTMAP */
virtual RID lightmap_create() = 0;