Skip to content

Commit 8954125

Browse files
committed
Merge pull request #105437 from Ansraer/teleport_spatial_nodes
Allow moving meshes without motion vectors
2 parents 7f7dd0d + a4a5f4e commit 8954125

13 files changed

+55
-7
lines changed

doc/classes/RenderingServer.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,13 @@
20462046
Sets whether an instance is drawn or not. Equivalent to [member Node3D.visible].
20472047
</description>
20482048
</method>
2049+
<method name="instance_teleport">
2050+
<return type="void" />
2051+
<param index="0" name="instance" type="RID" />
2052+
<description>
2053+
Resets motion vectors and other interpolated values. Use this [i]after[/i] teleporting a mesh from one position to another to avoid ghosting artifacts.
2054+
</description>
2055+
</method>
20492056
<method name="instances_cull_aabb" qualifiers="const">
20502057
<return type="PackedInt64Array" />
20512058
<param index="0" name="aabb" type="AABB" />

scene/3d/visual_instance_3d.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ void VisualInstance3D::_notification(int p_what) {
110110
if (!_is_using_identity_transform()) {
111111
RenderingServer::get_singleton()->instance_set_transform(instance, get_global_transform());
112112
}
113+
RenderingServer::get_singleton()->instance_teleport(instance);
113114

114115
RenderingServer::get_singleton()->instance_reset_physics_interpolation(instance);
115116
}

servers/rendering/dummy/rasterizer_scene_dummy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class RasterizerSceneDummy : public RendererSceneRender {
4949
virtual void set_surface_materials(const Vector<RID> &p_materials) override {}
5050
virtual void set_mesh_instance(RID p_mesh_instance) override {}
5151
virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override {}
52+
virtual void reset_motion_vectors() override {}
5253
virtual void set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) override {}
5354
virtual void set_lod_bias(float p_lod_bias) override {}
5455
virtual void set_layer_mask(uint32_t p_layer_mask) override {}

servers/rendering/renderer_geometry_instance.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ void RenderGeometryInstanceBase::set_cast_double_sided_shadows(bool p_enable) {
134134
_mark_dirty();
135135
}
136136

137+
void RenderGeometryInstanceBase::reset_motion_vectors() {
138+
}
139+
137140
Transform3D RenderGeometryInstanceBase::get_transform() {
138141
return transform;
139142
}

servers/rendering/renderer_geometry_instance.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class RenderGeometryInstance {
6161
virtual void set_instance_shader_uniforms_offset(int32_t p_offset) = 0;
6262
virtual void set_cast_double_sided_shadows(bool p_enable) = 0;
6363

64+
virtual void reset_motion_vectors() = 0;
65+
6466
virtual Transform3D get_transform() = 0;
6567
virtual AABB get_aabb() = 0;
6668

@@ -145,6 +147,8 @@ class RenderGeometryInstanceBase : public RenderGeometryInstance {
145147
virtual void set_instance_shader_uniforms_offset(int32_t p_offset) override;
146148
virtual void set_cast_double_sided_shadows(bool p_enable) override;
147149

150+
virtual void reset_motion_vectors() override;
151+
148152
virtual Transform3D get_transform() override;
149153
virtual AABB get_aabb() override;
150154
};

servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
10151015
}
10161016
}
10171017
if (p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI || p_pass_mode == PASS_MODE_COLOR) {
1018-
bool transform_changed = inst->prev_transform_change_frame == frame;
1018+
bool transform_changed = inst->transform_status == GeometryInstanceForwardClustered::TransformStatus::MOVED;
10191019
bool has_mesh_instance = inst->mesh_instance.is_valid();
10201020
bool uses_particles = inst->base_flags & INSTANCE_DATA_FLAG_PARTICLES;
10211021
bool is_multimesh_with_motion = !uses_particles && (inst->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) && mesh_storage->_multimesh_uses_motion_vectors_offsets(inst->data->base);
@@ -1044,9 +1044,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
10441044
lod_distance = surface_distance.length();
10451045
}
10461046

1047-
if (unlikely(inst->prev_transform_dirty && frame > inst->prev_transform_change_frame + 1 && inst->prev_transform_change_frame)) {
1047+
if (unlikely(inst->transform_status != GeometryInstanceForwardClustered::TransformStatus::NONE && frame > inst->prev_transform_change_frame + 1 && inst->prev_transform_change_frame)) {
10481048
inst->prev_transform = inst->transform;
1049-
inst->prev_transform_dirty = false;
1049+
inst->transform_status = GeometryInstanceForwardClustered::TransformStatus::NONE;
10501050
}
10511051

10521052
while (surf) {
@@ -4694,12 +4694,19 @@ void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(con
46944694
if (frame != prev_transform_change_frame) {
46954695
prev_transform = transform;
46964696
prev_transform_change_frame = frame;
4697-
prev_transform_dirty = true;
4697+
transform_status = TransformStatus::MOVED;
4698+
} else if (unlikely(transform_status == TransformStatus::TELEPORTED)) {
4699+
prev_transform = transform;
46984700
}
46994701

47004702
RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabb);
47014703
}
47024704

4705+
void RenderForwardClustered::GeometryInstanceForwardClustered::reset_motion_vectors() {
4706+
prev_transform = transform;
4707+
transform_status = TransformStatus::TELEPORTED;
4708+
}
4709+
47034710
void RenderForwardClustered::GeometryInstanceForwardClustered::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
47044711
lightmap_instance = p_lightmap_instance;
47054712
lightmap_uv_scale = p_lightmap_uv_scale;

servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
544544

545545
//used during setup
546546
uint64_t prev_transform_change_frame = 0xFFFFFFFF;
547-
bool prev_transform_dirty = true;
547+
enum TransformStatus {
548+
NONE,
549+
MOVED,
550+
TELEPORTED,
551+
} transform_status = TransformStatus::MOVED;
548552
Transform3D prev_transform;
549553
RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE];
550554
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
@@ -556,6 +560,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
556560
virtual void _mark_dirty() override;
557561

558562
virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
563+
virtual void reset_motion_vectors() override;
559564
virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
560565
virtual void set_lightmap_capture(const Color *p_sh9) override;
561566

servers/rendering/renderer_scene_cull.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,8 @@ void RendererSceneCull::instance_reset_physics_interpolation(RID p_instance) {
10441044
Instance *instance = instance_owner.get_or_null(p_instance);
10451045
ERR_FAIL_NULL(instance);
10461046

1047+
instance->teleported = true;
1048+
10471049
if (_interpolation_data.interpolation_enabled && instance->interpolated) {
10481050
instance->transform_prev = instance->transform_curr;
10491051
instance->transform_checksum_prev = instance->transform_checksum_curr;
@@ -1156,8 +1158,10 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
11561158
}
11571159
}
11581160

1159-
inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
1160-
return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES;
1161+
void RendererSceneCull::instance_teleport(RID p_instance) {
1162+
Instance *instance = instance_owner.get_or_null(p_instance);
1163+
ERR_FAIL_NULL(instance);
1164+
instance->teleported = true;
11611165
}
11621166

11631167
void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
@@ -1790,7 +1794,11 @@ void RendererSceneCull::_update_instance(Instance *p_instance) const {
17901794
}
17911795

17921796
ERR_FAIL_NULL(geom->geometry_instance);
1797+
17931798
geom->geometry_instance->set_transform(*instance_xform, p_instance->aabb, p_instance->transformed_aabb);
1799+
if (p_instance->teleported) {
1800+
geom->geometry_instance->reset_motion_vectors();
1801+
}
17941802
}
17951803

17961804
// note: we had to remove is equal approx check here, it meant that det == 0.000004 won't work, which is the case for some of our scenes.
@@ -4204,6 +4212,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) const {
42044212

42054213
_update_instance(p_instance);
42064214

4215+
p_instance->teleported = false;
42074216
p_instance->update_aabb = false;
42084217
p_instance->update_dependencies = false;
42094218
}

servers/rendering/renderer_scene_cull.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ class RendererSceneCull : public RenderingMethod {
412412
// This will either be the interpolated transform (when using fixed timestep interpolation)
413413
// or the ONLY transform (when not using FTI).
414414
Transform3D transform;
415+
bool teleported = false;
415416

416417
// For interpolation we store the current transform (this physics tick)
417418
// and the transform in the previous tick.
@@ -1054,6 +1055,8 @@ class RendererSceneCull : public RenderingMethod {
10541055
virtual void instance_set_visible(RID p_instance, bool p_visible);
10551056
virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency);
10561057

1058+
virtual void instance_teleport(RID p_instance);
1059+
10571060
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
10581061

10591062
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton);

servers/rendering/rendering_method.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class RenderingMethod {
9090
virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
9191
virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0;
9292

93+
virtual void instance_teleport(RID p_instance) = 0;
94+
9395
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0;
9496

9597
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;

0 commit comments

Comments
 (0)