Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort decals and lights based on camera origin #71709

Merged
merged 1 commit into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/classes/VisualInstance3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
<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">
<member name="sorting_use_aabb_center" type="bool" setter="set_sorting_use_aabb_center" getter="is_sorting_use_aabb_center">
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>
Expand Down
3 changes: 1 addition & 2 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
LightData &light_data = (i < r_omni_light_count) ? scene_state.omni_lights[index] : scene_state.spot_lights[index];
RS::LightType type = (i < r_omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
GLES3::LightInstance *li = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].instance : scene_state.spot_light_sort[index].instance;
real_t distance = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].depth : scene_state.spot_light_sort[index].depth;
RID base = li->light;

Transform3D light_transform = li->transform;
Expand Down Expand Up @@ -1612,13 +1613,11 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
// Reuse fade begin, fade length and distance for shadow LOD determination later.
float fade_begin = 0.0;
float fade_length = 0.0;
real_t distance = 0.0;

float fade = 1.0;
if (light_storage->light_is_distance_fade_enabled(li->light)) {
fade_begin = light_storage->light_get_distance_fade_begin(li->light);
fade_length = light_storage->light_get_distance_fade_length(li->light);
distance = p_render_data->cam_transform.origin.distance_to(li->transform.origin);

if (distance > fade_begin) {
// Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
Expand Down
12 changes: 0 additions & 12 deletions drivers/gles3/storage/texture_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,18 +1534,6 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
return AABB();
}

/* DECAL INSTANCE API */

RID TextureStorage::decal_instance_create(RID p_decal) {
return RID();
}

void TextureStorage::decal_instance_free(RID p_decal_instance) {
}

void TextureStorage::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
}

/* RENDER TARGET API */

GLuint TextureStorage::system_fbo = 0;
Expand Down
7 changes: 4 additions & 3 deletions drivers/gles3/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,9 +561,10 @@ class TextureStorage : public RendererTextureStorage {

/* DECAL INSTANCE */

virtual RID decal_instance_create(RID p_decal) override;
virtual void decal_instance_free(RID p_decal_instance) override;
virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
virtual RID decal_instance_create(RID p_decal) override { return RID(); }
virtual void decal_instance_free(RID p_decal_instance) override {}
virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override {}

/* RENDER TARGET API */

Expand Down
4 changes: 4 additions & 0 deletions scene/3d/decal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ void Decal::_validate_property(PropertyInfo &p_property) const {
if (!distance_fade_enabled && (p_property.name == "distance_fade_begin" || p_property.name == "distance_fade_length")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}

if (p_property.name == "sorting_offset") {
p_property.usage = PROPERTY_USAGE_DEFAULT;
}
}

PackedStringArray Decal::get_configuration_warnings() const {
Expand Down
12 changes: 12 additions & 0 deletions scene/3d/visual_instance_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ bool VisualInstance3D::is_sorting_use_aabb_center() const {
return sorting_use_aabb_center;
}

void VisualInstance3D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "sorting_offset" || p_property.name == "sorting_use_aabb_center") {
p_property.usage = PROPERTY_USAGE_NONE;
}
}

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);
Expand Down Expand Up @@ -437,6 +443,12 @@ PackedStringArray GeometryInstance3D::get_configuration_warnings() const {
return warnings;
}

void GeometryInstance3D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "sorting_offset" || p_property.name == "sorting_use_aabb_center") {
p_property.usage = PROPERTY_USAGE_DEFAULT;
}
}

void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance3D::set_material_override);
ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance3D::get_material_override);
Expand Down
2 changes: 2 additions & 0 deletions scene/3d/visual_instance_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class VisualInstance3D : public Node3D {

void _notification(int p_what);
static void _bind_methods();
void _validate_property(PropertyInfo &p_property) const;

GDVIRTUAL0RC(AABB, _get_aabb)
public:
Expand Down Expand Up @@ -140,6 +141,7 @@ class GeometryInstance3D : public VisualInstance3D {
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
void _validate_property(PropertyInfo &p_property) const;

static void _bind_methods();

Expand Down
1 change: 1 addition & 0 deletions servers/rendering/dummy/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class TextureStorage : public RendererTextureStorage {
virtual RID decal_instance_create(RID p_decal) override { return RID(); }
virtual void decal_instance_free(RID p_decal_instance) override {}
virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override {}

/* RENDER TARGET */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1480,7 +1480,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse());
texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform);

p_render_data->directional_light_count = directional_light_count;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse());
texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform);

p_render_data->directional_light_count = directional_light_count;
}
Expand Down
9 changes: 3 additions & 6 deletions servers/rendering/renderer_rd/storage_rd/light_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
r_directional_light_count = 0;
r_positional_light_count = 0;

Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);

omni_light_count = 0;
spot_light_count = 0;

Expand Down Expand Up @@ -720,7 +718,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
}

Transform3D light_transform = light_instance->transform;
const real_t distance = camera_plane.distance_to(light_transform.origin);
const real_t distance = p_camera_transform.origin.distance_to(light_transform.origin);

if (light->distance_fade) {
const float fade_begin = light->distance_fade_begin;
Expand All @@ -745,7 +743,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
}

Transform3D light_transform = light_instance->transform;
const real_t distance = camera_plane.distance_to(light_transform.origin);
const real_t distance = p_camera_transform.origin.distance_to(light_transform.origin);

if (light->distance_fade) {
const float fade_begin = light->distance_fade_begin;
Expand Down Expand Up @@ -787,6 +785,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
RS::LightType type = (i < omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
LightInstance *light_instance = (i < omni_light_count) ? omni_light_sort[index].light_instance : spot_light_sort[index].light_instance;
Light *light = (i < omni_light_count) ? omni_light_sort[index].light : spot_light_sort[index].light;
real_t distance = (i < omni_light_count) ? omni_light_sort[index].depth : spot_light_sort[index].depth;

if (using_forward_ids) {
forward_id_storage->map_forward_id(type == RS::LIGHT_OMNI ? RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT : RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id, index);
Expand All @@ -803,15 +802,13 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
float fade_begin = 0.0;
float fade_shadow = 0.0;
float fade_length = 0.0;
real_t distance = 0.0;

float fade = 1.0;
float shadow_opacity_fade = 1.0;
if (light->distance_fade) {
fade_begin = light->distance_fade_begin;
fade_shadow = light->distance_fade_shadow;
fade_length = light->distance_fade_length;
distance = camera_plane.distance_to(light_transform.origin);

// Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
if (distance > fade_begin) {
Expand Down
26 changes: 18 additions & 8 deletions servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2206,6 +2206,12 @@ void TextureStorage::decal_instance_set_transform(RID p_decal_instance, const Tr
di->transform = p_transform;
}

void TextureStorage::decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
ERR_FAIL_COND(!di);
di->sorting_offset = p_sorting_offset;
}

/* DECAL DATA API */

void TextureStorage::free_decal_data() {
Expand Down Expand Up @@ -2233,7 +2239,7 @@ void TextureStorage::set_max_decals(const uint32_t p_max_decals) {
decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
}

void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform) {
ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton();

Transform3D uv_xform;
Expand All @@ -2257,7 +2263,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const

Transform3D xform = decal_instance->transform;

real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
real_t distance = p_camera_xform.origin.distance_to(xform.origin);

if (decal->distance_fade) {
float fade_begin = decal->distance_fade_begin;
Expand All @@ -2272,7 +2278,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const

decal_sort[decal_count].decal_instance = decal_instance;
decal_sort[decal_count].decal = decal;
decal_sort[decal_count].depth = distance;
decal_sort[decal_count].depth = distance - decal_instance->sorting_offset;
decal_count++;
}

Expand All @@ -2292,11 +2298,10 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const

decal_instance->cull_mask = decal->cull_mask;

Transform3D xform = decal_instance->transform;
float fade = 1.0;

if (decal->distance_fade) {
const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
const real_t distance = decal_sort[i].depth + decal_instance->sorting_offset;
const float fade_begin = decal->distance_fade_begin;
const float fade_length = decal->distance_fade_length;

Expand All @@ -2312,11 +2317,16 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const

Transform3D scale_xform;
scale_xform.basis.scale(decal_extents);
Transform3D to_decal_xform = (p_camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse();

Transform3D xform = decal_instance->transform;

Transform3D camera_inverse_xform = p_camera_xform.affine_inverse();

Transform3D to_decal_xform = (camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse();
MaterialStorage::store_transform(to_decal_xform, dd.xform);

Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized();
normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
normal = camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine

dd.normal[0] = normal.x;
dd.normal[1] = normal.y;
Expand Down Expand Up @@ -2350,7 +2360,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
dd.normal_rect[2] = rect.size.x;
dd.normal_rect[3] = rect.size.y;

Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
Basis normal_xform = camera_inverse_xform.basis * xform.basis.orthonormalized();
MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform);
} else {
dd.normal_rect[0] = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class TextureStorage : public RendererTextureStorage {
struct DecalInstance {
RID decal;
Transform3D transform;
float sorting_offset = 0.0;
uint32_t cull_mask = 0;
RendererRD::ForwardID forward_id = -1;
};
Expand Down Expand Up @@ -646,6 +647,7 @@ class TextureStorage : public RendererTextureStorage {
virtual RID decal_instance_create(RID p_decal) override;
virtual void decal_instance_free(RID p_decal_instance) override;
virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) override;
virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override;

_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal_instance) const {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
Expand Down Expand Up @@ -677,7 +679,7 @@ class TextureStorage : public RendererTextureStorage {
void free_decal_data();
void set_max_decals(const uint32_t p_max_decals);
RID get_decal_buffer() { return decal_buffer; }
void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform);

/* RENDER TARGET API */

Expand Down
4 changes: 4 additions & 0 deletions servers/rendering/renderer_scene_cull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base_data = decal;

decal->instance = RSG::texture_storage->decal_instance_create(p_base);
RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);
} break;
case RS::INSTANCE_LIGHTMAP: {
InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
Expand Down Expand Up @@ -871,6 +872,9 @@ void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_
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);
} else if (instance->base_type == RS::INSTANCE_DECAL && instance->base_data) {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);
RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);
}
}

Expand Down
1 change: 1 addition & 0 deletions servers/rendering/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class RendererTextureStorage {
virtual RID decal_instance_create(RID p_decal) = 0;
virtual void decal_instance_free(RID p_decal_instance) = 0;
virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) = 0;
virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) = 0;

/* RENDER TARGET */

Expand Down