Skip to content

Commit cfc05c5

Browse files
committed
Merge pull request godotengine#85338 from EMBYRDEV/shadow-caster-mask
Add `shadow_caster_mask` to Light3D.
2 parents ba4e67e + a54b71b commit cfc05c5

File tree

15 files changed

+82
-5
lines changed

15 files changed

+82
-5
lines changed

doc/classes/Light3D.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@
115115
<member name="shadow_blur" type="float" setter="set_param" getter="get_param" default="1.0">
116116
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.
117117
</member>
118+
<member name="shadow_caster_mask" type="int" setter="set_shadow_caster_mask" getter="get_shadow_caster_mask" default="4294967295">
119+
The light will only cast shadows using objects in the selected layers.
120+
</member>
118121
<member name="shadow_enabled" type="bool" setter="set_shadow" getter="has_shadow" default="false">
119122
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].
120123
</member>

doc/classes/RenderingServer.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,6 +2137,14 @@
21372137
If [code]true[/code], light will cast shadows. Equivalent to [member Light3D.shadow_enabled].
21382138
</description>
21392139
</method>
2140+
<method name="light_set_shadow_caster_mask">
2141+
<return type="void" />
2142+
<param index="0" name="light" type="RID" />
2143+
<param index="1" name="mask" type="int" />
2144+
<description>
2145+
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].
2146+
</description>
2147+
</method>
21402148
<method name="lightmap_create">
21412149
<return type="RID" />
21422150
<description>

drivers/gles3/storage/light_storage.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,23 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
213213
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
214214
}
215215

216+
void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
217+
Light *light = light_owner.get_or_null(p_light);
218+
ERR_FAIL_NULL(light);
219+
220+
light->shadow_caster_mask = p_caster_mask;
221+
222+
light->version++;
223+
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
224+
}
225+
226+
uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
227+
Light *light = light_owner.get_or_null(p_light);
228+
ERR_FAIL_NULL_V(light, 0);
229+
230+
return light->shadow_caster_mask;
231+
}
232+
216233
void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
217234
Light *light = light_owner.get_or_null(p_light);
218235
ERR_FAIL_NULL(light);

drivers/gles3/storage/light_storage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct Light {
5959
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
6060
uint32_t max_sdfgi_cascade = 2;
6161
uint32_t cull_mask = 0xFFFFFFFF;
62+
uint32_t shadow_caster_mask = 0xFFFFFFFF;
6263
bool distance_fade = false;
6364
real_t distance_fade_begin = 40.0;
6465
real_t distance_fade_shadow = 50.0;
@@ -327,6 +328,8 @@ class LightStorage : public RendererLightStorage {
327328
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
328329
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
329330
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
331+
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
332+
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
330333
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
331334
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
332335

scene/3d/light_3d.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ bool Light3D::get_shadow_reverse_cull_face() const {
146146
return reverse_cull;
147147
}
148148

149+
void Light3D::set_shadow_caster_mask(uint32_t p_caster_mask) {
150+
shadow_caster_mask = p_caster_mask;
151+
RS::get_singleton()->light_set_shadow_caster_mask(light, shadow_caster_mask);
152+
}
153+
154+
uint32_t Light3D::get_shadow_caster_mask() const {
155+
return shadow_caster_mask;
156+
}
157+
149158
AABB Light3D::get_aabb() const {
150159
if (type == RenderingServer::LIGHT_DIRECTIONAL) {
151160
return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
@@ -300,7 +309,7 @@ bool Light3D::is_editor_only() const {
300309
}
301310

302311
void Light3D::_validate_property(PropertyInfo &p_property) const {
303-
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")) {
312+
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")) {
304313
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
305314
}
306315

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

366+
ClassDB::bind_method(D_METHOD("set_shadow_caster_mask", "caster_mask"), &Light3D::set_shadow_caster_mask);
367+
ClassDB::bind_method(D_METHOD("get_shadow_caster_mask"), &Light3D::get_shadow_caster_mask);
368+
357369
ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &Light3D::set_bake_mode);
358370
ClassDB::bind_method(D_METHOD("get_bake_mode"), &Light3D::get_bake_mode);
359371

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

392405
ADD_GROUP("Distance Fade", "distance_fade_");
393406
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled");

scene/3d/light_3d.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class Light3D : public VisualInstance3D {
7575
bool negative = false;
7676
bool reverse_cull = false;
7777
uint32_t cull_mask = 0;
78+
uint32_t shadow_caster_mask = 0xFFFFFFFF;
7879
bool distance_fade_enabled = false;
7980
real_t distance_fade_begin = 40.0;
8081
real_t distance_fade_shadow = 50.0;
@@ -136,6 +137,9 @@ class Light3D : public VisualInstance3D {
136137
void set_shadow_reverse_cull_face(bool p_enable);
137138
bool get_shadow_reverse_cull_face() const;
138139

140+
void set_shadow_caster_mask(uint32_t p_caster_mask);
141+
uint32_t get_shadow_caster_mask() const;
142+
139143
void set_bake_mode(BakeMode p_mode);
140144
BakeMode get_bake_mode() const;
141145

servers/rendering/dummy/storage/light_storage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ class LightStorage : public RendererLightStorage {
7878
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
7979
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
8080
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
81+
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override {}
82+
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override { return 0xFFFFFFFF; }
8183
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
8284
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
8385

servers/rendering/renderer_rd/storage_rd/light_storage.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,23 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled)
285285
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
286286
}
287287

288+
void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
289+
Light *light = light_owner.get_or_null(p_light);
290+
ERR_FAIL_NULL(light);
291+
292+
light->shadow_caster_mask = p_caster_mask;
293+
294+
light->version++;
295+
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
296+
}
297+
298+
uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
299+
Light *light = light_owner.get_or_null(p_light);
300+
ERR_FAIL_NULL_V(light, 0);
301+
302+
return light->shadow_caster_mask;
303+
}
304+
288305
void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
289306
Light *light = light_owner.get_or_null(p_light);
290307
ERR_FAIL_NULL(light);

servers/rendering/renderer_rd/storage_rd/light_storage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class LightStorage : public RendererLightStorage {
7272
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
7373
uint32_t max_sdfgi_cascade = 2;
7474
uint32_t cull_mask = 0xFFFFFFFF;
75+
uint32_t shadow_caster_mask = 0xFFFFFFFF;
7576
bool distance_fade = false;
7677
real_t distance_fade_begin = 40.0;
7778
real_t distance_fade_shadow = 50.0;
@@ -480,6 +481,8 @@ class LightStorage : public RendererLightStorage {
480481
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
481482
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
482483
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
484+
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
485+
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
483486
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
484487
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
485488

servers/rendering/renderer_scene_cull.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,6 +2299,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
22992299
cull.shadow_count = p_shadow_index + 1;
23002300
cull.shadows[p_shadow_index].cascade_count = splits;
23012301
cull.shadows[p_shadow_index].light_instance = light->instance;
2302+
cull.shadows[p_shadow_index].caster_mask = RSG::light_storage->light_get_shadow_caster_mask(p_instance->base);
23022303

23032304
for (int i = 0; i < splits; i++) {
23042305
RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
@@ -2529,7 +2530,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
25292530

25302531
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
25312532
Instance *instance = instance_shadow_cull_result[j];
2532-
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)) {
2533+
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))) {
25332534
continue;
25342535
} else {
25352536
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -2611,7 +2612,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
26112612

26122613
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
26132614
Instance *instance = instance_shadow_cull_result[j];
2614-
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)) {
2615+
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))) {
26152616
continue;
26162617
} else {
26172618
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -2678,7 +2679,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
26782679

26792680
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
26802681
Instance *instance = instance_shadow_cull_result[j];
2681-
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)) {
2682+
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))) {
26822683
continue;
26832684
} else {
26842685
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -3144,7 +3145,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
31443145
if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {
31453146
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
31463147

3147-
if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && LAYER_CHECK) {
3148+
if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && (LAYER_CHECK & cull_data.cull->shadows[j].caster_mask)) {
31483149
cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
31493150
mesh_visible = true;
31503151
}

0 commit comments

Comments
 (0)