diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2022-12-23 09:47:24 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2022-12-23 09:47:24 +0100 |
commit | 1cab6c91e97b6371247afaf4de016ef6b83efcb0 (patch) | |
tree | 819f6ab8ebf5b1d323202475074574d4edfbfa2b | |
parent | ae4c025da9598f3d9efbda8008d4ac7fb5b3ba63 (diff) | |
parent | 6f4f38db07c901a8b7dc74ad871af98030336031 (diff) |
Merge pull request #69998 from BastiaanOlij/sorting-pivot-4
Added options for sorting transparent objects (port of PR #63040)
-rw-r--r-- | doc/classes/RenderingServer.xml | 9 | ||||
-rw-r--r-- | doc/classes/VisualInstance3D.xml | 7 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 13 | ||||
-rw-r--r-- | scene/3d/visual_instance_3d.cpp | 26 | ||||
-rw-r--r-- | scene/3d/visual_instance_3d.h | 8 | ||||
-rw-r--r-- | servers/rendering/dummy/rasterizer_scene_dummy.h | 1 | ||||
-rw-r--r-- | servers/rendering/renderer_geometry_instance.cpp | 5 | ||||
-rw-r--r-- | servers/rendering/renderer_geometry_instance.h | 8 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp | 14 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp | 14 | ||||
-rw-r--r-- | servers/rendering/renderer_scene_cull.cpp | 15 | ||||
-rw-r--r-- | servers/rendering/renderer_scene_cull.h | 5 | ||||
-rw-r--r-- | servers/rendering/rendering_method.h | 1 | ||||
-rw-r--r-- | servers/rendering/rendering_server_default.h | 1 | ||||
-rw-r--r-- | servers/rendering_server.cpp | 1 | ||||
-rw-r--r-- | servers/rendering_server.h | 1 |
16 files changed, 119 insertions, 10 deletions
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 1cc52e6837..87e569ba20 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1586,6 +1586,15 @@ Sets the render layers that this instance will be drawn to. Equivalent to [member VisualInstance3D.layers]. </description> </method> + <method name="instance_set_pivot_data"> + <return type="void" /> + <param index="0" name="instance" type="RID" /> + <param index="1" name="sorting_offset" type="float" /> + <param index="2" name="use_aabb_center" type="bool" /> + <description> + Sets the sorting offset and switches between using the bounding box or instance origin for depth sorting. + </description> + </method> <method name="instance_set_scenario"> <return type="void" /> <param index="0" name="instance" type="RID" /> diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml index 31811f817b..e069642e50 100644 --- a/doc/classes/VisualInstance3D.xml +++ b/doc/classes/VisualInstance3D.xml @@ -61,5 +61,12 @@ This object will only be visible for [Camera3D]s whose cull mask includes the render object this [VisualInstance3D] is set to. For [Light3D]s, this can be used to control which [VisualInstance3D]s are affected by a specific light. For [GPUParticles3D], this can be used to control which particles are effected by a specific attractor. For [Decal]s, this can be used to control which [VisualInstance3D]s are affected by a specific decal. </member> + <member name="sorting_offset" type="float" setter="set_sorting_offset" getter="get_sorting_offset" default="0.0"> + The sorting offset used by this [VisualInstance3D]. Adjusting it to a higher value will make the [VisualInstance3D] reliably draw on top of other [VisualInstance3D]s that are otherwise positioned at the same spot. + </member> + <member name="sorting_use_aabb_center" type="bool" setter="set_sorting_use_aabb_center" getter="is_sorting_use_aabb_center" default="true"> + If [code]true[/code], the object is sorted based on the [AABB] center. The object will be sorted based on the global position otherwise. + The [AABB] center based sorting is generally more accurate for 3D models. The position based sorting instead allows to better control the drawing order when working with [GPUParticles3D] and [CPUParticles3D]. + </member> </members> </class> diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 2b44043faf..1faecfd4d0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1170,12 +1170,17 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const for (int i = 0; i < (int)p_render_data->instances->size(); i++) { GeometryInstanceGLES3 *inst = static_cast<GeometryInstanceGLES3 *>((*p_render_data->instances)[i]); + Vector3 center = inst->transform.origin; if (p_render_data->cam_orthogonal) { - Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); - inst->depth = near_plane.distance_to(support_min); + if (inst->use_aabb_center) { + center = inst->transformed_aabb.get_support(-near_plane.normal); + } + inst->depth = near_plane.distance_to(center) - inst->sorting_offset; } else { - Vector3 aabb_center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5); - inst->depth = p_render_data->cam_transform.origin.distance_to(aabb_center); + if (inst->use_aabb_center) { + center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5); + } + inst->depth = p_render_data->cam_transform.origin.distance_to(center) - inst->sorting_offset; } uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index c027e33ad3..3b21f5c03a 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -102,6 +102,24 @@ bool VisualInstance3D::get_layer_mask_value(int p_layer_number) const { return layers & (1 << (p_layer_number - 1)); } +void VisualInstance3D::set_sorting_offset(float p_offset) { + sorting_offset = p_offset; + RenderingServer::get_singleton()->instance_set_pivot_data(instance, sorting_offset, sorting_use_aabb_center); +} + +float VisualInstance3D::get_sorting_offset() const { + return sorting_offset; +} + +void VisualInstance3D::set_sorting_use_aabb_center(bool p_enabled) { + sorting_use_aabb_center = p_enabled; + RenderingServer::get_singleton()->instance_set_pivot_data(instance, sorting_offset, sorting_use_aabb_center); +} + +bool VisualInstance3D::is_sorting_use_aabb_center() const { + return sorting_use_aabb_center; +} + void VisualInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance3D::set_base); ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance3D::get_base); @@ -110,9 +128,17 @@ void VisualInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_layer_mask"), &VisualInstance3D::get_layer_mask); ClassDB::bind_method(D_METHOD("set_layer_mask_value", "layer_number", "value"), &VisualInstance3D::set_layer_mask_value); ClassDB::bind_method(D_METHOD("get_layer_mask_value", "layer_number"), &VisualInstance3D::get_layer_mask_value); + ClassDB::bind_method(D_METHOD("set_sorting_offset", "offset"), &VisualInstance3D::set_sorting_offset); + ClassDB::bind_method(D_METHOD("get_sorting_offset"), &VisualInstance3D::get_sorting_offset); + ClassDB::bind_method(D_METHOD("set_sorting_use_aabb_center", "enabled"), &VisualInstance3D::set_sorting_use_aabb_center); + ClassDB::bind_method(D_METHOD("is_sorting_use_aabb_center"), &VisualInstance3D::is_sorting_use_aabb_center); GDVIRTUAL_BIND(_get_aabb); ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask"); + + ADD_GROUP("Sorting", "sorting_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sorting_offset"), "set_sorting_offset", "get_sorting_offset"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sorting_use_aabb_center"), "set_sorting_use_aabb_center", "is_sorting_use_aabb_center"); } void VisualInstance3D::set_base(const RID &p_base) { diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index c741ef710d..2d107f61d2 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -39,6 +39,8 @@ class VisualInstance3D : public Node3D { RID base; RID instance; uint32_t layers = 1; + float sorting_offset = 0.0; + bool sorting_use_aabb_center = true; protected: void _update_visibility(); @@ -67,6 +69,12 @@ public: void set_layer_mask_value(int p_layer_number, bool p_enable); bool get_layer_mask_value(int p_layer_number) const; + void set_sorting_offset(float p_offset); + float get_sorting_offset() const; + + void set_sorting_use_aabb_center(bool p_enabled); + bool is_sorting_use_aabb_center() const; + VisualInstance3D(); ~VisualInstance3D(); }; diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index 3937362920..918f5c1fb7 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -49,6 +49,7 @@ public: virtual void set_surface_materials(const Vector<RID> &p_materials) override {} virtual void set_mesh_instance(RID p_mesh_instance) override {} virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override {} + virtual void set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) override {} virtual void set_lod_bias(float p_lod_bias) override {} virtual void set_layer_mask(uint32_t p_layer_mask) override {} virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp index 675659f4c8..f4681916f4 100644 --- a/servers/rendering/renderer_geometry_instance.cpp +++ b/servers/rendering/renderer_geometry_instance.cpp @@ -80,6 +80,11 @@ void RenderGeometryInstanceBase::set_transform(const Transform3D &p_transform, c lod_model_scale = max_scale; } +void RenderGeometryInstanceBase::set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) { + sorting_offset = p_sorting_offset; + use_aabb_center = p_use_aabb_center; +} + void RenderGeometryInstanceBase::set_lod_bias(float p_lod_bias) { lod_bias = p_lod_bias; } diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h index fecb9878c2..37fde9e1f6 100644 --- a/servers/rendering/renderer_geometry_instance.h +++ b/servers/rendering/renderer_geometry_instance.h @@ -50,6 +50,7 @@ public: virtual void set_surface_materials(const Vector<RID> &p_materials) = 0; virtual void set_mesh_instance(RID p_mesh_instance) = 0; virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) = 0; + virtual void set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) = 0; virtual void set_lod_bias(float p_lod_bias) = 0; virtual void set_layer_mask(uint32_t p_layer_mask) = 0; virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0; @@ -86,11 +87,13 @@ public: RID mesh_instance; Transform3D transform; - bool mirror = false; // move into data? - AABB transformed_aabb; //needed for LOD + bool mirror = false; + AABB transformed_aabb; bool non_uniform_scale = false; float lod_model_scale = 1.0; float lod_bias = 0.0; + float sorting_offset = 0.0; + bool use_aabb_center = true; uint32_t layer_mask = 1; @@ -133,6 +136,7 @@ public: virtual void set_surface_materials(const Vector<RID> &p_materials) override; virtual void set_mesh_instance(RID p_mesh_instance) override; virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; + virtual void set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) override; virtual void set_lod_bias(float p_lod_bias) override; virtual void set_layer_mask(uint32_t p_layer_mask) override; virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override; 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 0cfe639480..608f7ff958 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -831,8 +831,18 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con for (int i = 0; i < (int)p_render_data->instances->size(); i++) { GeometryInstanceForwardClustered *inst = static_cast<GeometryInstanceForwardClustered *>((*p_render_data->instances)[i]); - Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); - inst->depth = near_plane.distance_to(support_min); + Vector3 center = inst->transform.origin; + if (p_render_data->scene_data->cam_orthogonal) { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.get_support(-near_plane.normal); + } + inst->depth = near_plane.distance_to(center) - inst->sorting_offset; + } else { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5); + } + inst->depth = p_render_data->scene_data->cam_transform.origin.distance_to(center) - inst->sorting_offset; + } uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); uint32_t flags = inst->base_flags; //fill flags if appropriate 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 c792914246..e47ca8dd73 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1757,8 +1757,18 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const for (int i = 0; i < (int)p_render_data->instances->size(); i++) { GeometryInstanceForwardMobile *inst = static_cast<GeometryInstanceForwardMobile *>((*p_render_data->instances)[i]); - Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); - inst->depth = near_plane.distance_to(support_min); + Vector3 center = inst->transform.origin; + if (p_render_data->scene_data->cam_orthogonal) { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.get_support(-near_plane.normal); + } + inst->depth = near_plane.distance_to(center) - inst->sorting_offset; + } else { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5); + } + inst->depth = p_render_data->scene_data->cam_transform.origin.distance_to(center) - inst->sorting_offset; + } uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); uint32_t flags = inst->base_flags; //fill flags if appropriate diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index cfc25fc577..a378c3fde8 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -646,6 +646,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { geom->geometry_instance->set_surface_materials(instance->materials); geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb); geom->geometry_instance->set_layer_mask(instance->layer_mask); + geom->geometry_instance->set_pivot_data(instance->sorting_offset, instance->use_aabb_center); geom->geometry_instance->set_lod_bias(instance->lod_bias); geom->geometry_instance->set_transparency(instance->transparency); geom->geometry_instance->set_use_baked_light(instance->baked_light); @@ -844,6 +845,20 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) } } +void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) { + Instance *instance = instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!instance); + + instance->sorting_offset = p_sorting_offset; + instance->use_aabb_center = p_use_aabb_center; + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + ERR_FAIL_NULL(geom->geometry_instance); + geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center); + } +} + void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float p_transparency) { Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 51f800381b..106871edfd 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -459,6 +459,10 @@ public: float extra_margin; ObjectID object_id; + // sorting + float sorting_offset = 0.0; + bool use_aabb_center = true; + Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior uint64_t last_frame_pass; @@ -933,6 +937,7 @@ public: virtual void instance_set_base(RID p_instance, RID p_base); virtual void instance_set_scenario(RID p_instance, RID p_scenario); virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); + virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center); virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform); virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h index 51b9cb2bcf..e3f29b51d5 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -72,6 +72,7 @@ public: virtual void instance_set_base(RID p_instance, RID p_base) = 0; virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0; + virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) = 0; virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0; virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 3de5083a8b..3f5b135d2a 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -762,6 +762,7 @@ public: FUNC2(instance_set_base, RID, RID) FUNC2(instance_set_scenario, RID, RID) FUNC2(instance_set_layer_mask, RID, uint32_t) + FUNC3(instance_set_pivot_data, RID, float, bool) FUNC2(instance_set_transform, RID, const Transform3D &) FUNC2(instance_attach_object_instance_id, RID, ObjectID) FUNC3(instance_set_blend_shape_weight, RID, int, float) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 49af56830a..de3bd8d3e0 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2480,6 +2480,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("instance_set_base", "instance", "base"), &RenderingServer::instance_set_base); ClassDB::bind_method(D_METHOD("instance_set_scenario", "instance", "scenario"), &RenderingServer::instance_set_scenario); ClassDB::bind_method(D_METHOD("instance_set_layer_mask", "instance", "mask"), &RenderingServer::instance_set_layer_mask); + ClassDB::bind_method(D_METHOD("instance_set_pivot_data", "instance", "sorting_offset", "use_aabb_center"), &RenderingServer::instance_set_pivot_data); ClassDB::bind_method(D_METHOD("instance_set_transform", "instance", "transform"), &RenderingServer::instance_set_transform); ClassDB::bind_method(D_METHOD("instance_attach_object_instance_id", "instance", "id"), &RenderingServer::instance_attach_object_instance_id); ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 5bdbf33c28..f3d95e07cb 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1209,6 +1209,7 @@ public: virtual void instance_set_base(RID p_instance, RID p_base) = 0; virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0; + virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) = 0; virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0; virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; |