Skip to content

Commit 19bb187

Browse files
committed
Merge pull request godotengine#102399 from clayjohn/cull-mask-overhaul
Overhaul the cull mask internals for Lights, Decals, and Particle Colliders
2 parents 3c90a0e + 305216f commit 19bb187

13 files changed

+67
-14
lines changed

drivers/gles3/storage/light_storage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
209209
light->cull_mask = p_mask;
210210

211211
light->version++;
212-
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
212+
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_CULL_MASK);
213213
}
214214

215215
void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {

drivers/gles3/storage/particles_storage.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,13 @@ void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collisi
13191319
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
13201320
ERR_FAIL_NULL(particles_collision);
13211321
particles_collision->cull_mask = p_cull_mask;
1322+
particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_CULL_MASK);
1323+
}
1324+
1325+
uint32_t ParticlesStorage::particles_collision_get_cull_mask(RID p_particles_collision) const {
1326+
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
1327+
ERR_FAIL_NULL_V(particles_collision, 0);
1328+
return particles_collision->cull_mask;
13221329
}
13231330

13241331
void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {

drivers/gles3/storage/particles_storage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ class ParticlesStorage : public RendererParticlesStorage {
436436
GLuint particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
437437
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const override;
438438
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) override;
439+
virtual uint32_t particles_collision_get_cull_mask(RID p_particles_collision) const override;
439440

440441
_FORCE_INLINE_ Size2i particles_collision_get_heightfield_size(RID p_particles_collision) const {
441442
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);

servers/rendering/dummy/storage/particles_storage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class ParticlesStorage : public RendererParticlesStorage {
115115
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
116116
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const override { return 0; }
117117
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) override {}
118+
virtual uint32_t particles_collision_get_cull_mask(RID p_particles_collision) const override { return 0; }
118119

119120
virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); }
120121
virtual void particles_collision_instance_free(RID p_rid) override {}

servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,9 +1120,6 @@ void main() {
11201120
uvec2 decal_indices = instances.data[draw_call.instance_index].decals;
11211121
for (uint i = 0; i < sc_decals(); i++) {
11221122
uint decal_index = (i > 3) ? ((decal_indices.y >> ((i - 4) * 8)) & 0xFF) : ((decal_indices.x >> (i * 8)) & 0xFF);
1123-
if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) {
1124-
continue; //not masked
1125-
}
11261123

11271124
vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
11281125
if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {

servers/rendering/renderer_rd/storage_rd/light_storage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
268268
light->cull_mask = p_mask;
269269

270270
light->version++;
271-
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
271+
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_CULL_MASK);
272272
}
273273

274274
void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {

servers/rendering/renderer_rd/storage_rd/particles_storage.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,13 @@ void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collisi
18501850
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
18511851
ERR_FAIL_NULL(particles_collision);
18521852
particles_collision->cull_mask = p_cull_mask;
1853+
particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_CULL_MASK);
1854+
}
1855+
1856+
uint32_t ParticlesStorage::particles_collision_get_cull_mask(RID p_particles_collision) const {
1857+
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
1858+
ERR_FAIL_NULL_V(particles_collision, 0);
1859+
return particles_collision->cull_mask;
18531860
}
18541861

18551862
uint32_t ParticlesStorage::particles_collision_get_height_field_mask(RID p_particles_collision) const {

servers/rendering/renderer_rd/storage_rd/particles_storage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ class ParticlesStorage : public RendererParticlesStorage {
583583
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
584584
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const override;
585585
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) override;
586+
virtual uint32_t particles_collision_get_cull_mask(RID p_particles_collision) const override;
586587

587588
Dependency *particles_collision_get_dependency(RID p_particles) const;
588589

servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2744,7 +2744,7 @@ void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
27442744
Decal *decal = decal_owner.get_or_null(p_decal);
27452745
ERR_FAIL_NULL(decal);
27462746
decal->cull_mask = p_layers;
2747-
decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL);
2747+
decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_CULL_MASK);
27482748
}
27492749

27502750
void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {

servers/rendering/renderer_scene_cull.cpp

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
178178
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
179179
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
180180

181+
if (!(light->cull_mask & A->layer_mask)) {
182+
// Early return if the object's layer mask doesn't match the light's cull mask.
183+
return;
184+
}
185+
181186
geom->lights.insert(B);
182187
light->geometries.insert(A);
183188

@@ -222,6 +227,11 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
222227
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
223228
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
224229

230+
if (!(decal->cull_mask & A->layer_mask)) {
231+
// Early return if the object's layer mask doesn't match the decal's cull mask.
232+
return;
233+
}
234+
225235
geom->decals.insert(B);
226236
decal->geometries.insert(A);
227237

@@ -267,7 +277,10 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
267277
voxel_gi->lights.insert(A);
268278
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
269279
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
270-
RSG::particles_storage->particles_add_collision(A->base, collision->instance);
280+
281+
if ((collision->cull_mask & A->layer_mask)) {
282+
RSG::particles_storage->particles_add_collision(A->base, collision->instance);
283+
}
271284
}
272285
}
273286

@@ -285,6 +298,11 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
285298
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
286299
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
287300

301+
if (!(light->cull_mask & A->layer_mask)) {
302+
// Early return if the object's layer mask doesn't match the light's cull mask.
303+
return;
304+
}
305+
288306
geom->lights.erase(B);
289307
light->geometries.erase(A);
290308

@@ -339,6 +357,11 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
339357
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
340358
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
341359

360+
if (!(decal->cull_mask & A->layer_mask)) {
361+
// Early return if the object's layer mask doesn't match the decal's cull mask.
362+
return;
363+
}
364+
342365
geom->decals.erase(B);
343366
decal->geometries.erase(A);
344367

@@ -383,7 +406,10 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
383406
voxel_gi->lights.erase(A);
384407
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
385408
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
386-
RSG::particles_storage->particles_remove_collision(A->base, collision->instance);
409+
410+
if ((collision->cull_mask & A->layer_mask)) {
411+
RSG::particles_storage->particles_remove_collision(A->base, collision->instance);
412+
}
387413
}
388414
}
389415

@@ -888,6 +914,14 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
888914
return;
889915
}
890916

917+
// Particles always need to be unpaired. Geometry may need to be unpaired, but only if lights or decals use pairing.
918+
// Needs to happen before layer mask changes so we can avoid attempting to unpair something that was never paired.
919+
if (instance->base_type == RS::INSTANCE_PARTICLES ||
920+
(((geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT)) || (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL))) && ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK))) {
921+
_unpair_instance(instance);
922+
singleton->_instance_queue_update(instance, false, false);
923+
}
924+
891925
instance->layer_mask = p_mask;
892926
if (instance->scenario && instance->array_index >= 0) {
893927
instance->scenario->instance_data[instance->array_index].layer_mask = p_mask;
@@ -1592,6 +1626,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) const {
15921626
if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
15931627
light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
15941628
}
1629+
light->cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base);
15951630
} else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
15961631
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
15971632

@@ -1605,6 +1640,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) const {
16051640
InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
16061641

16071642
RSG::texture_storage->decal_instance_set_transform(decal->instance, *instance_xform);
1643+
decal->cull_mask = RSG::texture_storage->decal_get_cull_mask(p_instance->base);
16081644
} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
16091645
InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data);
16101646

@@ -1623,6 +1659,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) const {
16231659
heightfield_particle_colliders_update_list.insert(p_instance);
16241660
}
16251661
RSG::particles_storage->particles_collision_instance_set_transform(collision->instance, *instance_xform);
1662+
collision->cull_mask = RSG::particles_storage->particles_collision_get_cull_mask(p_instance->base);
16261663
} else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {
16271664
InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);
16281665
scene_render->fog_volume_instance_set_transform(volume->instance, *instance_xform);
@@ -1818,7 +1855,6 @@ void RendererSceneCull::_update_instance(Instance *p_instance) const {
18181855
pair.pair_allocator = &pair_allocator;
18191856
pair.pair_pass = pair_pass;
18201857
pair.pair_mask = 0;
1821-
pair.cull_mask = 0xFFFFFFFF;
18221858

18231859
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
18241860
pair.pair_mask |= 1 << RS::INSTANCE_LIGHT;
@@ -1840,7 +1876,6 @@ void RendererSceneCull::_update_instance(Instance *p_instance) const {
18401876
pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI);
18411877
pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
18421878
}
1843-
pair.cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base);
18441879
} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
18451880
pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
18461881
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
@@ -1850,7 +1885,6 @@ void RendererSceneCull::_update_instance(Instance *p_instance) const {
18501885
} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) {
18511886
pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
18521887
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
1853-
pair.cull_mask = RSG::texture_storage->decal_get_cull_mask(p_instance->base);
18541888
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
18551889
pair.pair_mask = (1 << RS::INSTANCE_PARTICLES);
18561890
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];

servers/rendering/renderer_scene_cull.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,8 @@ class RendererSceneCull : public RenderingMethod {
508508
case Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
509509
singleton->_instance_queue_update(instance, true, true);
510510
} break;
511-
case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
511+
case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR:
512+
case Dependency::DEPENDENCY_CHANGED_CULL_MASK: {
512513
//requires repairing
513514
if (instance->indexer_id.is_valid()) {
514515
singleton->_unpair_instance(instance);
@@ -655,6 +656,7 @@ class RendererSceneCull : public RenderingMethod {
655656
struct InstanceDecalData : public InstanceBaseData {
656657
Instance *owner = nullptr;
657658
RID instance;
659+
uint32_t cull_mask = 0xFFFFFFFF;
658660

659661
HashSet<Instance *> geometries;
660662

@@ -666,6 +668,7 @@ class RendererSceneCull : public RenderingMethod {
666668

667669
struct InstanceParticlesCollisionData : public InstanceBaseData {
668670
RID instance;
671+
uint32_t cull_mask = 0xFFFFFFFF;
669672
};
670673

671674
struct InstanceFogVolumeData : public InstanceBaseData {
@@ -699,6 +702,7 @@ class RendererSceneCull : public RenderingMethod {
699702

700703
RS::LightBakeMode bake_mode;
701704
uint32_t max_sdfgi_cascade = 2;
705+
uint32_t cull_mask = 0xFFFFFFFF;
702706

703707
private:
704708
// Instead of a single dirty flag, we maintain a count
@@ -817,12 +821,11 @@ class RendererSceneCull : public RenderingMethod {
817821
DynamicBVH *bvh2 = nullptr; //some may need to cull in two
818822
uint32_t pair_mask;
819823
uint64_t pair_pass;
820-
uint32_t cull_mask = 0xFFFFFFFF; // Needed for decals and lights in the mobile and compatibility renderers.
821824

822825
_FORCE_INLINE_ bool operator()(void *p_data) {
823826
Instance *p_instance = (Instance *)p_data;
824827

825-
if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type)) && (cull_mask & p_instance->layer_mask)) {
828+
if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type))) {
826829
//test is more coarse in indexer
827830
p_instance->pair_check = pair_pass;
828831
InstancePair *pair = pair_allocator->alloc();

servers/rendering/storage/particles_storage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class RendererParticlesStorage {
121121
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
122122
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const = 0;
123123
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) = 0;
124+
virtual uint32_t particles_collision_get_cull_mask(RID p_particles_collision) const = 0;
124125

125126
//used from 2D and 3D
126127
virtual RID particles_collision_instance_create(RID p_collision) = 0;

servers/rendering/storage/utilities.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Dependency {
5050
DEPENDENCY_CHANGED_LIGHT,
5151
DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR,
5252
DEPENDENCY_CHANGED_REFLECTION_PROBE,
53+
DEPENDENCY_CHANGED_CULL_MASK,
5354
};
5455

5556
void changed_notify(DependencyChangedNotification p_notification);

0 commit comments

Comments
 (0)