visual instance layers are regarded during shadow culling

Partially cherry-picked from 16517ecb. Todos:
- setting Camera cull_mask should mark affected shadows dirty somehow
This commit is contained in:
Markus Grafen 2022-12-27 18:43:53 +01:00
parent b6e06038f8
commit 041b64ea7e
2 changed files with 18 additions and 7 deletions

View File

@ -833,6 +833,10 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
Instance *instance = instance_owner.get_or_null(p_instance); Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance); ERR_FAIL_COND(!instance);
if (instance->layer_mask == p_mask) {
return;
}
instance->layer_mask = p_mask; instance->layer_mask = p_mask;
if (instance->scenario && instance->array_index >= 0) { if (instance->scenario && instance->array_index >= 0) {
instance->scenario->instance_data[instance->array_index].layer_mask = p_mask; instance->scenario->instance_data[instance->array_index].layer_mask = p_mask;
@ -842,6 +846,13 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
ERR_FAIL_NULL(geom->geometry_instance); ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_layer_mask(p_mask); geom->geometry_instance->set_layer_mask(p_mask);
if (geom->can_cast_shadows) {
for (HashSet<RendererSceneCull::Instance *>::Iterator I = geom->lights.begin(); I != geom->lights.end(); ++I) {
InstanceLightData *light = static_cast<InstanceLightData *>((*I)->base_data);
light->shadow_dirty = true;
}
}
} }
} }
@ -2253,7 +2264,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
} }
} }
bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) { bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold, uint32_t p_visible_layers) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform; Transform3D light_transform = p_instance->transform;
@ -2309,7 +2320,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[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) { 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)) {
continue; continue;
} else { } else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@ -2387,7 +2398,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[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) { 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)) {
continue; continue;
} else { } else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@ -2450,7 +2461,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[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) { 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)) {
continue; continue;
} else { } else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@ -2891,7 +2902,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) { if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK; 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) { if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && LAYER_CHECK) {
cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry); cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
mesh_visible = true; mesh_visible = true;
} }
@ -3218,7 +3229,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) { if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {
//must redraw! //must redraw!
RENDER_TIMESTAMP("> Render Light3D " + itos(i)); RENDER_TIMESTAMP("> Render Light3D " + itos(i));
light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold); light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold, p_visible_layers);
RENDER_TIMESTAMP("< Render Light3D " + itos(i)); RENDER_TIMESTAMP("< Render Light3D " + itos(i));
} else { } else {
light->shadow_dirty = redraw; light->shadow_dirty = redraw;

View File

@ -988,7 +988,7 @@ public:
void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect); void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold); _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold, uint32_t p_visible_layers = 0xFFFFFF);
RID _render_get_environment(RID p_camera, RID p_scenario); RID _render_get_environment(RID p_camera, RID p_scenario);