Skip to content

Commit

Permalink
Add shadow_caster_mask to Light3D
Browse files Browse the repository at this point in the history
  • Loading branch information
EMBYRDEV authored and eswartz committed Jul 11, 2024
1 parent 6b9193e commit 5f02cb2
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 5 deletions.
3 changes: 3 additions & 0 deletions doc/classes/Light3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@
<member name="shadow_blur" type="float" setter="set_param" getter="get_param" default="1.0">
Blurs the edges of the shadow. Can be used to hide pixel artifacts in low-resolution shadow maps. A high value can impact performance, make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible.
</member>
<member name="shadow_caster_mask" type="int" setter="set_shadow_caster_mask" getter="get_shadow_caster_mask" default="4294967295">
The light will only cast shadows using objects in the selected layers.
</member>
<member name="shadow_enabled" type="bool" setter="set_shadow" getter="has_shadow" default="false">
If [code]true[/code], the light will cast real-time shadows. This has a significant performance cost. Only enable shadow rendering when it makes a noticeable difference in the scene's appearance, and consider using [member distance_fade_enabled] to hide the light when far away from the [Camera3D].
</member>
Expand Down
15 changes: 15 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2012,6 +2012,13 @@
If [code]true[/code], this light will not be used for anything except sky shaders. Use this for lights that impact your sky shader that you may want to hide from affecting the rest of the scene. For example, you may want to enable this when the sun in your sky shader falls below the horizon.
</description>
</method>
<method name="light_get_shadow_caster_mask" qualifiers="const">
<return type="int" />
<param index="0" name="light" type="RID" />
<description>
Gets the shadow caster mask for this 3D light. Shadows will only be cast using objects in the selected layers. Equivalent to [member Light3D.shadow_caster_mask].
</description>
</method>
<method name="light_omni_set_shadow_mode">
<return type="void" />
<param index="0" name="light" type="RID" />
Expand Down Expand Up @@ -2111,6 +2118,14 @@
If [code]true[/code], light will cast shadows. Equivalent to [member Light3D.shadow_enabled].
</description>
</method>
<method name="light_set_shadow_caster_mask">
<return type="void" />
<param index="0" name="light" type="RID" />
<param index="1" name="mask" type="int" />
<description>
Sets the shadow caster mask for this 3D light. Shadows will only be cast using objects in the selected layers. Equivalent to [member Light3D.shadow_caster_mask].
</description>
</method>
<method name="lightmap_create">
<return type="RID" />
<description>
Expand Down
17 changes: 17 additions & 0 deletions drivers/gles3/storage/light_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,23 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}

void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);

light->shadow_caster_mask = p_caster_mask;

light->version++;
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}

uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL_V(light, 0);

return light->shadow_caster_mask;
}

void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct Light {
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
uint32_t max_sdfgi_cascade = 2;
uint32_t cull_mask = 0xFFFFFFFF;
uint32_t shadow_caster_mask = 0xFFFFFFFF;
bool distance_fade = false;
real_t distance_fade_begin = 40.0;
real_t distance_fade_shadow = 50.0;
Expand Down Expand Up @@ -326,6 +327,8 @@ class LightStorage : public RendererLightStorage {
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}

Expand Down
15 changes: 14 additions & 1 deletion scene/3d/light_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ bool Light3D::get_shadow_reverse_cull_face() const {
return reverse_cull;
}

void Light3D::set_shadow_caster_mask(uint32_t p_caster_mask) {
shadow_caster_mask = p_caster_mask;
RS::get_singleton()->light_set_shadow_caster_mask(light, shadow_caster_mask);
}

uint32_t Light3D::get_shadow_caster_mask() const {
return shadow_caster_mask;
}

AABB Light3D::get_aabb() const {
if (type == RenderingServer::LIGHT_DIRECTIONAL) {
return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
Expand Down Expand Up @@ -300,7 +309,7 @@ bool Light3D::is_editor_only() const {
}

void Light3D::_validate_property(PropertyInfo &p_property) const {
if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow")) {
if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow" || p_property.name == "shadow_caster_mask")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}

Expand Down Expand Up @@ -354,6 +363,9 @@ void Light3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_reverse_cull_face", "enable"), &Light3D::set_shadow_reverse_cull_face);
ClassDB::bind_method(D_METHOD("get_shadow_reverse_cull_face"), &Light3D::get_shadow_reverse_cull_face);

ClassDB::bind_method(D_METHOD("set_shadow_caster_mask", "enable"), &Light3D::set_shadow_caster_mask);
ClassDB::bind_method(D_METHOD("get_shadow_caster_mask"), &Light3D::get_shadow_caster_mask);

ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &Light3D::set_bake_mode);
ClassDB::bind_method(D_METHOD("get_bake_mode"), &Light3D::get_bake_mode);

Expand Down Expand Up @@ -388,6 +400,7 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_OPACITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_caster_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_shadow_caster_mask", "get_shadow_caster_mask");

ADD_GROUP("Distance Fade", "distance_fade_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled");
Expand Down
4 changes: 4 additions & 0 deletions scene/3d/light_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Light3D : public VisualInstance3D {
bool negative = false;
bool reverse_cull = false;
uint32_t cull_mask = 0;
uint32_t shadow_caster_mask = 0xFFFFFFFF;
bool distance_fade_enabled = false;
real_t distance_fade_begin = 40.0;
real_t distance_fade_shadow = 50.0;
Expand Down Expand Up @@ -136,6 +137,9 @@ class Light3D : public VisualInstance3D {
void set_shadow_reverse_cull_face(bool p_enable);
bool get_shadow_reverse_cull_face() const;

void set_shadow_caster_mask(uint32_t p_caster_mask);
uint32_t get_shadow_caster_mask() const;

void set_bake_mode(BakeMode p_mode);
BakeMode get_bake_mode() const;

Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/dummy/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class LightStorage : public RendererLightStorage {
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override {}
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override { return 0xFFFFFFFF; }
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}

Expand Down
17 changes: 17 additions & 0 deletions servers/rendering/renderer_rd/storage_rd/light_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,23 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled)
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}

void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);

light->shadow_caster_mask = p_caster_mask;

light->version++;
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}

uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL_V(light, 0);

return light->shadow_caster_mask;
}

void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);
Expand Down
3 changes: 3 additions & 0 deletions servers/rendering/renderer_rd/storage_rd/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class LightStorage : public RendererLightStorage {
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
uint32_t max_sdfgi_cascade = 2;
uint32_t cull_mask = 0xFFFFFFFF;
uint32_t shadow_caster_mask = 0xFFFFFFFF;
bool distance_fade = false;
real_t distance_fade_begin = 40.0;
real_t distance_fade_shadow = 50.0;
Expand Down Expand Up @@ -474,6 +475,8 @@ class LightStorage : public RendererLightStorage {
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;

Expand Down
9 changes: 5 additions & 4 deletions servers/rendering/renderer_scene_cull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2139,6 +2139,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
cull.shadow_count = p_shadow_index + 1;
cull.shadows[p_shadow_index].cascade_count = splits;
cull.shadows[p_shadow_index].light_instance = light->instance;
cull.shadows[p_shadow_index].caster_mask = RSG::light_storage->light_get_shadow_caster_mask(p_instance->base);

for (int i = 0; i < splits; i++) {
RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
Expand Down Expand Up @@ -2369,7 +2370,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons

for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
Expand Down Expand Up @@ -2451,7 +2452,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons

for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
Expand Down Expand Up @@ -2518,7 +2519,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons

for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
Expand Down Expand Up @@ -2978,7 +2979,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;

if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && LAYER_CHECK) {
if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && (LAYER_CHECK & cull_data.cull->shadows[j].caster_mask)) {
cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
mesh_visible = true;
}
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/renderer_scene_cull.h
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ class RendererSceneCull : public RenderingMethod {
struct Cull {
struct Shadow {
RID light_instance;
uint32_t caster_mask;
struct Cascade {
Frustum frustum;

Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/rendering_server_default.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ class RenderingServerDefault : public RenderingServer {
FUNC2(light_set_cull_mask, RID, uint32_t)
FUNC5(light_set_distance_fade, RID, bool, float, float, float)
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
FUNC2(light_set_shadow_caster_mask, RID, uint32_t)
FUNC1RC(uint32_t, light_get_shadow_caster_mask, RID)
FUNC2(light_set_bake_mode, RID, LightBakeMode)
FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)

Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class RendererLightStorage {
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0;
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const = 0;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;

Expand Down
2 changes: 2 additions & 0 deletions servers/rendering_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2467,6 +2467,8 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask);
ClassDB::bind_method(D_METHOD("light_set_distance_fade", "decal", "enabled", "begin", "shadow", "length"), &RenderingServer::light_set_distance_fade);
ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode);
ClassDB::bind_method(D_METHOD("light_set_shadow_caster_mask", "light", "mask"), &RenderingServer::light_set_shadow_caster_mask);
ClassDB::bind_method(D_METHOD("light_get_shadow_caster_mask", "light"), &RenderingServer::light_get_shadow_caster_mask);
ClassDB::bind_method(D_METHOD("light_set_bake_mode", "light", "bake_mode"), &RenderingServer::light_set_bake_mode);
ClassDB::bind_method(D_METHOD("light_set_max_sdfgi_cascade", "light", "cascade"), &RenderingServer::light_set_max_sdfgi_cascade);

Expand Down
2 changes: 2 additions & 0 deletions servers/rendering_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,8 @@ class RenderingServer : public Object {
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0;
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const = 0;

enum LightBakeMode {
LIGHT_BAKE_DISABLED,
Expand Down

0 comments on commit 5f02cb2

Please sign in to comment.