Path: blob/master/servers/rendering/renderer_scene_cull.cpp
20892 views
/**************************************************************************/1/* renderer_scene_cull.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "renderer_scene_cull.h"3132#include "core/config/project_settings.h"33#include "core/math/geometry_3d.h"34#include "core/object/worker_thread_pool.h"35#include "rendering_light_culler.h"36#include "rendering_server_default.h"3738#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)39// This is used only to obtain node paths for user-friendly physics interpolation warnings.40#include "scene/main/node.h"41#endif4243/* HALTON SEQUENCE */4445#ifndef _3D_DISABLED46static float get_halton_value(int p_index, int p_base) {47float f = 1;48float r = 0;49while (p_index > 0) {50f = f / static_cast<float>(p_base);51r = r + f * (p_index % p_base);52p_index = p_index / p_base;53}54return r * 2.0f - 1.0f;55}56#endif // _3D_DISABLED5758/* EVENT QUEUING */5960void RendererSceneCull::tick() {61if (_interpolation_data.interpolation_enabled) {62update_interpolation_tick(true);63}64}6566void RendererSceneCull::pre_draw(bool p_will_draw) {67if (_interpolation_data.interpolation_enabled) {68update_interpolation_frame(p_will_draw);69}70}7172/* CAMERA API */7374RID RendererSceneCull::camera_allocate() {75return camera_owner.allocate_rid();76}77void RendererSceneCull::camera_initialize(RID p_rid) {78camera_owner.initialize_rid(p_rid);79}8081void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {82Camera *camera = camera_owner.get_or_null(p_camera);83ERR_FAIL_NULL(camera);84camera->type = Camera::PERSPECTIVE;85camera->fov = p_fovy_degrees;86camera->znear = p_z_near;87camera->zfar = p_z_far;88}8990void RendererSceneCull::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) {91Camera *camera = camera_owner.get_or_null(p_camera);92ERR_FAIL_NULL(camera);93camera->type = Camera::ORTHOGONAL;94camera->size = p_size;95camera->znear = p_z_near;96camera->zfar = p_z_far;97}9899void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {100Camera *camera = camera_owner.get_or_null(p_camera);101ERR_FAIL_NULL(camera);102camera->type = Camera::FRUSTUM;103camera->size = p_size;104camera->offset = p_offset;105camera->znear = p_z_near;106camera->zfar = p_z_far;107}108109void RendererSceneCull::camera_set_transform(RID p_camera, const Transform3D &p_transform) {110Camera *camera = camera_owner.get_or_null(p_camera);111ERR_FAIL_NULL(camera);112113camera->transform = p_transform.orthonormalized();114}115116void RendererSceneCull::camera_set_cull_mask(RID p_camera, uint32_t p_layers) {117Camera *camera = camera_owner.get_or_null(p_camera);118ERR_FAIL_NULL(camera);119120camera->visible_layers = p_layers;121}122123void RendererSceneCull::camera_set_environment(RID p_camera, RID p_env) {124Camera *camera = camera_owner.get_or_null(p_camera);125ERR_FAIL_NULL(camera);126camera->env = p_env;127}128129void RendererSceneCull::camera_set_camera_attributes(RID p_camera, RID p_attributes) {130Camera *camera = camera_owner.get_or_null(p_camera);131ERR_FAIL_NULL(camera);132camera->attributes = p_attributes;133}134135void RendererSceneCull::camera_set_compositor(RID p_camera, RID p_compositor) {136Camera *camera = camera_owner.get_or_null(p_camera);137ERR_FAIL_NULL(camera);138camera->compositor = p_compositor;139}140141void RendererSceneCull::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) {142Camera *camera = camera_owner.get_or_null(p_camera);143ERR_FAIL_NULL(camera);144camera->vaspect = p_enable;145}146147bool RendererSceneCull::is_camera(RID p_camera) const {148return camera_owner.owns(p_camera);149}150151/* OCCLUDER API */152153RID RendererSceneCull::occluder_allocate() {154return RendererSceneOcclusionCull::get_singleton()->occluder_allocate();155}156157void RendererSceneCull::occluder_initialize(RID p_rid) {158RendererSceneOcclusionCull::get_singleton()->occluder_initialize(p_rid);159}160161void RendererSceneCull::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {162RendererSceneOcclusionCull::get_singleton()->occluder_set_mesh(p_occluder, p_vertices, p_indices);163}164165/* SCENARIO API */166167void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {168RendererSceneCull *self = (RendererSceneCull *)singleton;169Instance *A = p_A;170Instance *B = p_B;171172//instance indices are designed so greater always contains lesser173if (A->base_type > B->base_type) {174SWAP(A, B); //lesser always first175}176177if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {178InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);179InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);180181if (!(light->cull_mask & A->layer_mask)) {182// Early return if the object's layer mask doesn't match the light's cull mask.183return;184}185186geom->lights.insert(B);187light->geometries.insert(A);188189if (geom->can_cast_shadows) {190light->make_shadow_dirty();191}192193if (A->scenario && A->array_index >= 0) {194InstanceData &idata = A->scenario->instance_data[A->array_index];195idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;196}197198if (light->uses_projector) {199geom->projector_count++;200if (geom->projector_count == 1) {201InstanceData &idata = A->scenario->instance_data[A->array_index];202idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;203}204}205206if (light->uses_softshadow) {207geom->softshadow_count++;208if (geom->softshadow_count == 1) {209InstanceData &idata = A->scenario->instance_data[A->array_index];210idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;211}212}213214} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {215if (!(A->layer_mask & RSG::light_storage->reflection_probe_get_reflection_mask(B->base))) {216// Early return if the object's layer mask doesn't match the reflection mask.217return;218}219220InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);221InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);222223geom->reflection_probes.insert(B);224reflection_probe->geometries.insert(A);225226if (A->scenario && A->array_index >= 0) {227InstanceData &idata = A->scenario->instance_data[A->array_index];228idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;229}230231} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {232InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);233InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);234235if (!(decal->cull_mask & A->layer_mask)) {236// Early return if the object's layer mask doesn't match the decal's cull mask.237return;238}239240geom->decals.insert(B);241decal->geometries.insert(A);242243if (A->scenario && A->array_index >= 0) {244InstanceData &idata = A->scenario->instance_data[A->array_index];245idata.flags |= InstanceData::FLAG_GEOM_DECAL_DIRTY;246}247248} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {249InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);250InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);251252if (A->dynamic_gi) {253geom->lightmap_captures.insert(B);254lightmap_data->geometries.insert(A);255256if (A->scenario && A->array_index >= 0) {257InstanceData &idata = A->scenario->instance_data[A->array_index];258idata.flags |= InstanceData::FLAG_LIGHTMAP_CAPTURE;259}260((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture261}262263} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_VOXEL_GI) && B->base_type == RS::INSTANCE_VOXEL_GI && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {264InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);265InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);266267geom->voxel_gi_instances.insert(B);268269if (A->dynamic_gi) {270voxel_gi->dynamic_geometries.insert(A);271} else {272voxel_gi->geometries.insert(A);273}274275if (A->scenario && A->array_index >= 0) {276InstanceData &idata = A->scenario->instance_data[A->array_index];277idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;278}279280} else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) {281InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);282voxel_gi->lights.insert(A);283} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {284InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);285286if ((collision->cull_mask & A->layer_mask)) {287RSG::particles_storage->particles_add_collision(A->base, collision->instance);288}289}290}291292void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {293RendererSceneCull *self = singleton;294Instance *A = p_A;295Instance *B = p_B;296297//instance indices are designed so greater always contains lesser298if (A->base_type > B->base_type) {299SWAP(A, B); //lesser always first300}301302if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {303InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);304InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);305306if (!(light->cull_mask & A->layer_mask)) {307// Early return if the object's layer mask doesn't match the light's cull mask.308return;309}310311geom->lights.erase(B);312light->geometries.erase(A);313314if (geom->can_cast_shadows) {315light->make_shadow_dirty();316}317318if (A->scenario && A->array_index >= 0) {319InstanceData &idata = A->scenario->instance_data[A->array_index];320idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;321}322323if (light->uses_projector) {324#ifdef DEBUG_ENABLED325if (geom->projector_count == 0) {326ERR_PRINT("geom->projector_count==0 - BUG!");327}328#endif329geom->projector_count--;330if (geom->projector_count == 0) {331InstanceData &idata = A->scenario->instance_data[A->array_index];332idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;333}334}335336if (light->uses_softshadow) {337#ifdef DEBUG_ENABLED338if (geom->softshadow_count == 0) {339ERR_PRINT("geom->softshadow_count==0 - BUG!");340}341#endif342geom->softshadow_count--;343if (geom->softshadow_count == 0) {344InstanceData &idata = A->scenario->instance_data[A->array_index];345idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;346}347}348349} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {350InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);351InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);352353geom->reflection_probes.erase(B);354reflection_probe->geometries.erase(A);355356if (A->scenario && A->array_index >= 0) {357InstanceData &idata = A->scenario->instance_data[A->array_index];358idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;359}360361} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {362InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);363InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);364365if (!(decal->cull_mask & A->layer_mask)) {366// Early return if the object's layer mask doesn't match the decal's cull mask.367return;368}369370geom->decals.erase(B);371decal->geometries.erase(A);372373if (A->scenario && A->array_index >= 0) {374InstanceData &idata = A->scenario->instance_data[A->array_index];375idata.flags |= InstanceData::FLAG_GEOM_DECAL_DIRTY;376}377378} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {379InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);380InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);381if (A->dynamic_gi) {382geom->lightmap_captures.erase(B);383384if (geom->lightmap_captures.is_empty() && A->scenario && A->array_index >= 0) {385InstanceData &idata = A->scenario->instance_data[A->array_index];386idata.flags &= ~InstanceData::FLAG_LIGHTMAP_CAPTURE;387}388389lightmap_data->geometries.erase(A);390self->_instance_queue_update(A, false, false); //need to update capture391}392393} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_VOXEL_GI) && B->base_type == RS::INSTANCE_VOXEL_GI && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {394InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);395InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);396397geom->voxel_gi_instances.erase(B);398if (A->dynamic_gi) {399voxel_gi->dynamic_geometries.erase(A);400} else {401voxel_gi->geometries.erase(A);402}403404if (A->scenario && A->array_index >= 0) {405InstanceData &idata = A->scenario->instance_data[A->array_index];406idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;407}408409} else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) {410InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);411voxel_gi->lights.erase(A);412} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {413InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);414415if ((collision->cull_mask & A->layer_mask)) {416RSG::particles_storage->particles_remove_collision(A->base, collision->instance);417}418}419}420421RID RendererSceneCull::scenario_allocate() {422return scenario_owner.allocate_rid();423}424void RendererSceneCull::scenario_initialize(RID p_rid) {425scenario_owner.initialize_rid(p_rid);426427Scenario *scenario = scenario_owner.get_or_null(p_rid);428scenario->self = p_rid;429430scenario->reflection_probe_shadow_atlas = RSG::light_storage->shadow_atlas_create();431RSG::light_storage->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest432RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4);433RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);434RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);435RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);436437scenario->reflection_atlas = RSG::light_storage->reflection_atlas_create();438439scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool);440scenario->instance_data.set_page_pool(&instance_data_page_pool);441scenario->instance_visibility.set_page_pool(&instance_visibility_data_page_pool);442443RendererSceneOcclusionCull::get_singleton()->add_scenario(p_rid);444}445446void RendererSceneCull::scenario_set_environment(RID p_scenario, RID p_environment) {447Scenario *scenario = scenario_owner.get_or_null(p_scenario);448ERR_FAIL_NULL(scenario);449scenario->environment = p_environment;450}451452void RendererSceneCull::scenario_set_camera_attributes(RID p_scenario, RID p_camera_attributes) {453Scenario *scenario = scenario_owner.get_or_null(p_scenario);454ERR_FAIL_NULL(scenario);455scenario->camera_attributes = p_camera_attributes;456}457458void RendererSceneCull::scenario_set_compositor(RID p_scenario, RID p_compositor) {459Scenario *scenario = scenario_owner.get_or_null(p_scenario);460ERR_FAIL_NULL(scenario);461scenario->compositor = p_compositor;462}463464void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {465Scenario *scenario = scenario_owner.get_or_null(p_scenario);466ERR_FAIL_NULL(scenario);467scenario->fallback_environment = p_environment;468}469470void RendererSceneCull::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {471Scenario *scenario = scenario_owner.get_or_null(p_scenario);472ERR_FAIL_NULL(scenario);473RSG::light_storage->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);474}475476bool RendererSceneCull::is_scenario(RID p_scenario) const {477return scenario_owner.owns(p_scenario);478}479480RID RendererSceneCull::scenario_get_environment(RID p_scenario) {481Scenario *scenario = scenario_owner.get_or_null(p_scenario);482ERR_FAIL_NULL_V(scenario, RID());483return scenario->environment;484}485486void RendererSceneCull::scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport) {487Scenario *scenario = scenario_owner.get_or_null(p_scenario);488ERR_FAIL_NULL(scenario);489if (!scenario->viewport_visibility_masks.has(p_viewport)) {490return;491}492493uint64_t mask = scenario->viewport_visibility_masks[p_viewport];494scenario->used_viewport_visibility_bits &= ~mask;495scenario->viewport_visibility_masks.erase(p_viewport);496}497498void RendererSceneCull::scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport) {499Scenario *scenario = scenario_owner.get_or_null(p_scenario);500ERR_FAIL_NULL(scenario);501ERR_FAIL_COND(scenario->viewport_visibility_masks.has(p_viewport));502503uint64_t new_mask = 1;504while (new_mask & scenario->used_viewport_visibility_bits) {505new_mask <<= 1;506}507508if (new_mask == 0) {509ERR_PRINT("Only 64 viewports per scenario allowed when using visibility ranges.");510new_mask = ((uint64_t)1) << 63;511}512513scenario->viewport_visibility_masks[p_viewport] = new_mask;514scenario->used_viewport_visibility_bits |= new_mask;515}516517/* INSTANCING API */518519void RendererSceneCull::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) const {520if (p_update_aabb) {521p_instance->update_aabb = true;522}523if (p_update_dependencies) {524p_instance->update_dependencies = true;525}526527if (p_instance->update_item.in_list()) {528return;529}530531_instance_update_list.add(&p_instance->update_item);532}533534RID RendererSceneCull::instance_allocate() {535return instance_owner.allocate_rid();536}537void RendererSceneCull::instance_initialize(RID p_rid) {538instance_owner.initialize_rid(p_rid);539Instance *instance = instance_owner.get_or_null(p_rid);540instance->self = p_rid;541}542543void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) const {544bool needs_instance = RSG::mesh_storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid());545if (needs_instance != p_instance->mesh_instance.is_valid()) {546if (needs_instance) {547p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base);548549} else {550RSG::mesh_storage->mesh_instance_free(p_instance->mesh_instance);551p_instance->mesh_instance = RID();552}553554InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);555geom->geometry_instance->set_mesh_instance(p_instance->mesh_instance);556557if (p_instance->scenario && p_instance->array_index >= 0) {558InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];559if (p_instance->mesh_instance.is_valid()) {560idata.flags |= InstanceData::FLAG_USES_MESH_INSTANCE;561} else {562idata.flags &= ~InstanceData::FLAG_USES_MESH_INSTANCE;563}564}565}566567if (p_instance->mesh_instance.is_valid()) {568RSG::mesh_storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);569}570}571572void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {573Instance *instance = instance_owner.get_or_null(p_instance);574ERR_FAIL_NULL(instance);575576Scenario *scenario = instance->scenario;577578if (instance->base_type != RS::INSTANCE_NONE) {579//free anything related to that base580581if (scenario && instance->indexer_id.is_valid()) {582_unpair_instance(instance);583}584585if (instance->mesh_instance.is_valid()) {586RSG::mesh_storage->mesh_instance_free(instance->mesh_instance);587instance->mesh_instance = RID();588// no need to set instance data flag here, as it was freed above589}590591switch (instance->base_type) {592case RS::INSTANCE_MESH:593case RS::INSTANCE_MULTIMESH:594case RS::INSTANCE_PARTICLES: {595InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);596scene_render->geometry_instance_free(geom->geometry_instance);597} break;598case RS::INSTANCE_LIGHT: {599InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);600601if (scenario && instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {602scenario->dynamic_lights.erase(light->instance);603}604605#ifdef DEBUG_ENABLED606if (light->geometries.size()) {607ERR_PRINT("BUG, indexing did not unpair geometries from light.");608}609#endif610if (scenario && light->D) {611scenario->directional_lights.erase(light->D);612light->D = nullptr;613}614RSG::light_storage->light_instance_free(light->instance);615} break;616case RS::INSTANCE_PARTICLES_COLLISION: {617InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);618RSG::utilities->free(collision->instance);619} break;620case RS::INSTANCE_FOG_VOLUME: {621InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);622scene_render->free(volume->instance);623} break;624case RS::INSTANCE_VISIBLITY_NOTIFIER: {625//none626} break;627case RS::INSTANCE_REFLECTION_PROBE: {628InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);629RSG::light_storage->reflection_probe_instance_free(reflection_probe->instance);630if (reflection_probe->update_list.in_list()) {631reflection_probe_render_list.remove(&reflection_probe->update_list);632}633} break;634case RS::INSTANCE_DECAL: {635InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);636RSG::texture_storage->decal_instance_free(decal->instance);637638} break;639case RS::INSTANCE_LIGHTMAP: {640InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(instance->base_data);641//erase dependencies, since no longer a lightmap642while (lightmap_data->users.begin()) {643instance_geometry_set_lightmap((*lightmap_data->users.begin())->self, RID(), Rect2(), 0);644}645RSG::light_storage->lightmap_instance_free(lightmap_data->instance);646} break;647case RS::INSTANCE_VOXEL_GI: {648InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);649#ifdef DEBUG_ENABLED650if (voxel_gi->geometries.size()) {651ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI.");652}653#endif654#ifdef DEBUG_ENABLED655if (voxel_gi->lights.size()) {656ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI.");657}658#endif659if (voxel_gi->update_element.in_list()) {660voxel_gi_update_list.remove(&voxel_gi->update_element);661}662663scene_render->free(voxel_gi->probe_instance);664665} break;666case RS::INSTANCE_OCCLUDER: {667if (scenario && instance->visible) {668RendererSceneOcclusionCull::get_singleton()->scenario_remove_instance(instance->scenario->self, p_instance);669}670} break;671default: {672}673}674675if (instance->base_data) {676memdelete(instance->base_data);677instance->base_data = nullptr;678}679680instance->materials.clear();681}682683instance->base_type = RS::INSTANCE_NONE;684instance->base = RID();685686if (p_base.is_valid()) {687instance->base_type = RSG::utilities->get_base_type(p_base);688689// fix up a specific malfunctioning case before the switch, so it can be handled690if (instance->base_type == RS::INSTANCE_NONE && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_base)) {691instance->base_type = RS::INSTANCE_OCCLUDER;692}693694switch (instance->base_type) {695case RS::INSTANCE_NONE: {696ERR_PRINT_ONCE("unimplemented base type encountered in renderer scene cull");697return;698}699case RS::INSTANCE_LIGHT: {700InstanceLightData *light = memnew(InstanceLightData);701702if (scenario && RSG::light_storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {703light->D = scenario->directional_lights.push_back(instance);704}705706light->instance = RSG::light_storage->light_instance_create(p_base);707708instance->base_data = light;709} break;710case RS::INSTANCE_MESH:711case RS::INSTANCE_MULTIMESH:712case RS::INSTANCE_PARTICLES: {713InstanceGeometryData *geom = memnew(InstanceGeometryData);714instance->base_data = geom;715geom->geometry_instance = scene_render->geometry_instance_create(p_base);716717ERR_FAIL_NULL(geom->geometry_instance);718719geom->geometry_instance->set_skeleton(instance->skeleton);720geom->geometry_instance->set_material_override(instance->material_override);721geom->geometry_instance->set_material_overlay(instance->material_overlay);722geom->geometry_instance->set_surface_materials(instance->materials);723geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb);724geom->geometry_instance->set_layer_mask(instance->layer_mask);725geom->geometry_instance->set_pivot_data(instance->sorting_offset, instance->use_aabb_center);726geom->geometry_instance->set_lod_bias(instance->lod_bias);727geom->geometry_instance->set_transparency(instance->transparency);728geom->geometry_instance->set_use_baked_light(instance->baked_light);729geom->geometry_instance->set_use_dynamic_gi(instance->dynamic_gi);730geom->geometry_instance->set_use_lightmap(RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);731geom->geometry_instance->set_instance_shader_uniforms_offset(instance->instance_uniforms.location());732geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);733if (instance->lightmap_sh.size() == 9) {734geom->geometry_instance->set_lightmap_capture(instance->lightmap_sh.ptr());735}736737for (Instance *E : instance->visibility_dependencies) {738Instance *dep_instance = E;739ERR_CONTINUE(dep_instance->array_index == -1);740ERR_CONTINUE(dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index != -1);741dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = instance->array_index;742}743} break;744case RS::INSTANCE_PARTICLES_COLLISION: {745InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);746collision->instance = RSG::particles_storage->particles_collision_instance_create(p_base);747RSG::particles_storage->particles_collision_instance_set_active(collision->instance, instance->visible);748instance->base_data = collision;749} break;750case RS::INSTANCE_FOG_VOLUME: {751InstanceFogVolumeData *volume = memnew(InstanceFogVolumeData);752volume->instance = scene_render->fog_volume_instance_create(p_base);753scene_render->fog_volume_instance_set_active(volume->instance, instance->visible);754instance->base_data = volume;755} break;756case RS::INSTANCE_VISIBLITY_NOTIFIER: {757InstanceVisibilityNotifierData *vnd = memnew(InstanceVisibilityNotifierData);758vnd->base = p_base;759instance->base_data = vnd;760} break;761case RS::INSTANCE_REFLECTION_PROBE: {762InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);763reflection_probe->owner = instance;764instance->base_data = reflection_probe;765766reflection_probe->instance = RSG::light_storage->reflection_probe_instance_create(p_base);767} break;768case RS::INSTANCE_DECAL: {769InstanceDecalData *decal = memnew(InstanceDecalData);770decal->owner = instance;771instance->base_data = decal;772773decal->instance = RSG::texture_storage->decal_instance_create(p_base);774RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);775} break;776case RS::INSTANCE_LIGHTMAP: {777InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);778instance->base_data = lightmap_data;779lightmap_data->instance = RSG::light_storage->lightmap_instance_create(p_base);780} break;781case RS::INSTANCE_VOXEL_GI: {782InstanceVoxelGIData *voxel_gi = memnew(InstanceVoxelGIData);783instance->base_data = voxel_gi;784voxel_gi->owner = instance;785786if (scenario && !voxel_gi->update_element.in_list()) {787voxel_gi_update_list.add(&voxel_gi->update_element);788}789790voxel_gi->probe_instance = scene_render->voxel_gi_instance_create(p_base);791792} break;793case RS::INSTANCE_OCCLUDER: {794if (scenario) {795RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(scenario->self, p_instance, p_base, instance->transform, instance->visible);796}797} break;798default: {799}800}801802instance->base = p_base;803804if (instance->base_type == RS::INSTANCE_MESH) {805_instance_update_mesh_instance(instance);806}807808//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it809RSG::utilities->base_update_dependency(p_base, &instance->dependency_tracker);810}811812_instance_queue_update(instance, true, true);813}814815void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {816Instance *instance = instance_owner.get_or_null(p_instance);817ERR_FAIL_NULL(instance);818819if (instance->scenario) {820instance->scenario->instances.remove(&instance->scenario_item);821822if (instance->indexer_id.is_valid()) {823_unpair_instance(instance);824}825826switch (instance->base_type) {827case RS::INSTANCE_LIGHT: {828InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);829if (instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {830instance->scenario->dynamic_lights.erase(light->instance);831}832833#ifdef DEBUG_ENABLED834if (light->geometries.size()) {835ERR_PRINT("BUG, indexing did not unpair geometries from light.");836}837#endif838if (light->D) {839instance->scenario->directional_lights.erase(light->D);840light->D = nullptr;841}842} break;843case RS::INSTANCE_REFLECTION_PROBE: {844InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);845RSG::light_storage->reflection_probe_release_atlas_index(reflection_probe->instance);846847} break;848case RS::INSTANCE_PARTICLES_COLLISION: {849heightfield_particle_colliders_update_list.erase(instance);850} break;851case RS::INSTANCE_VOXEL_GI: {852InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);853854#ifdef DEBUG_ENABLED855if (voxel_gi->geometries.size()) {856ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI.");857}858#endif859#ifdef DEBUG_ENABLED860if (voxel_gi->lights.size()) {861ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI.");862}863#endif864865if (voxel_gi->update_element.in_list()) {866voxel_gi_update_list.remove(&voxel_gi->update_element);867}868} break;869case RS::INSTANCE_OCCLUDER: {870if (instance->visible) {871RendererSceneOcclusionCull::get_singleton()->scenario_remove_instance(instance->scenario->self, p_instance);872}873} break;874default: {875}876}877878instance->scenario = nullptr;879}880881if (p_scenario.is_valid()) {882Scenario *scenario = scenario_owner.get_or_null(p_scenario);883ERR_FAIL_NULL(scenario);884885instance->scenario = scenario;886887scenario->instances.add(&instance->scenario_item);888889switch (instance->base_type) {890case RS::INSTANCE_LIGHT: {891InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);892893if (RSG::light_storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {894light->D = scenario->directional_lights.push_back(instance);895}896} break;897case RS::INSTANCE_VOXEL_GI: {898InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);899if (!voxel_gi->update_element.in_list()) {900voxel_gi_update_list.add(&voxel_gi->update_element);901}902} break;903case RS::INSTANCE_OCCLUDER: {904RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(scenario->self, p_instance, instance->base, instance->transform, instance->visible);905} break;906default: {907}908}909910_instance_queue_update(instance, true, true);911}912}913914void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) {915Instance *instance = instance_owner.get_or_null(p_instance);916ERR_FAIL_NULL(instance);917918if (instance->layer_mask == p_mask) {919return;920}921922// Particles always need to be unpaired. Geometry may need to be unpaired, but only if lights or decals use pairing.923// Needs to happen before layer mask changes so we can avoid attempting to unpair something that was never paired.924if (instance->base_type == RS::INSTANCE_PARTICLES ||925(((geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT)) || (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL))) && ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK))) {926_unpair_instance(instance);927singleton->_instance_queue_update(instance, false, false);928}929930instance->layer_mask = p_mask;931if (instance->scenario && instance->array_index >= 0) {932instance->scenario->instance_data[instance->array_index].layer_mask = p_mask;933}934935if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {936InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);937ERR_FAIL_NULL(geom->geometry_instance);938geom->geometry_instance->set_layer_mask(p_mask);939940if (geom->can_cast_shadows) {941for (HashSet<RendererSceneCull::Instance *>::Iterator I = geom->lights.begin(); I != geom->lights.end(); ++I) {942InstanceLightData *light = static_cast<InstanceLightData *>((*I)->base_data);943light->make_shadow_dirty();944}945}946}947}948949void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) {950Instance *instance = instance_owner.get_or_null(p_instance);951ERR_FAIL_NULL(instance);952953instance->sorting_offset = p_sorting_offset;954instance->use_aabb_center = p_use_aabb_center;955956if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {957InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);958ERR_FAIL_NULL(geom->geometry_instance);959geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center);960} else if (instance->base_type == RS::INSTANCE_DECAL && instance->base_data) {961InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);962RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);963}964}965966void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float p_transparency) {967Instance *instance = instance_owner.get_or_null(p_instance);968ERR_FAIL_NULL(instance);969970instance->transparency = p_transparency;971972if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {973InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);974ERR_FAIL_NULL(geom->geometry_instance);975geom->geometry_instance->set_transparency(p_transparency);976}977}978979void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D &p_transform) {980Instance *instance = instance_owner.get_or_null(p_instance);981ERR_FAIL_NULL(instance);982983if (instance->transform == p_transform) {984return; // Must be checked to avoid worst evil.985}986987#ifdef DEBUG_ENABLED988989for (int i = 0; i < 4; i++) {990const Vector3 &v = i < 3 ? p_transform.basis.rows[i] : p_transform.origin;991ERR_FAIL_COND(!v.is_finite());992}993994#endif995instance->transform = p_transform;996_instance_queue_update(instance, true);997}998999void RendererSceneCull::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {1000Instance *instance = instance_owner.get_or_null(p_instance);1001ERR_FAIL_NULL(instance);10021003instance->object_id = p_id;1004}10051006void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {1007Instance *instance = instance_owner.get_or_null(p_instance);1008ERR_FAIL_NULL(instance);10091010if (instance->update_item.in_list()) {1011_update_dirty_instance(instance);1012}10131014if (instance->mesh_instance.is_valid()) {1015RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);1016}10171018_instance_queue_update(instance, false, false);1019}10201021void RendererSceneCull::instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) {1022Instance *instance = instance_owner.get_or_null(p_instance);1023ERR_FAIL_NULL(instance);10241025if (instance->base_type == RS::INSTANCE_MESH) {1026//may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case1027instance->materials.resize(MAX(p_surface + 1, RSG::mesh_storage->mesh_get_surface_count(instance->base)));1028}10291030ERR_FAIL_INDEX(p_surface, instance->materials.size());10311032instance->materials.write[p_surface] = p_material;10331034_instance_queue_update(instance, false, true);1035}10361037void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {1038Instance *instance = instance_owner.get_or_null(p_instance);1039ERR_FAIL_NULL(instance);10401041if (instance->visible == p_visible) {1042return;1043}10441045instance->visible = p_visible;10461047if (p_visible) {1048if (instance->scenario != nullptr) {1049_instance_queue_update(instance, true, false);1050}1051} else if (instance->indexer_id.is_valid()) {1052_unpair_instance(instance);1053}10541055if (instance->base_type == RS::INSTANCE_LIGHT) {1056InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);1057if (instance->scenario && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1058if (p_visible) {1059instance->scenario->dynamic_lights.push_back(light->instance);1060} else {1061instance->scenario->dynamic_lights.erase(light->instance);1062}1063}1064}10651066if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {1067InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);1068RSG::particles_storage->particles_collision_instance_set_active(collision->instance, p_visible);1069}10701071if (instance->base_type == RS::INSTANCE_FOG_VOLUME) {1072InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);1073scene_render->fog_volume_instance_set_active(volume->instance, p_visible);1074}10751076if (instance->base_type == RS::INSTANCE_OCCLUDER) {1077if (instance->scenario) {1078RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(instance->scenario->self, p_instance, instance->base, instance->transform, p_visible);1079}1080}1081}10821083void RendererSceneCull::instance_teleport(RID p_instance) {1084Instance *instance = instance_owner.get_or_null(p_instance);1085ERR_FAIL_NULL(instance);1086instance->teleported = true;1087}10881089void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {1090Instance *instance = instance_owner.get_or_null(p_instance);1091ERR_FAIL_NULL(instance);10921093if (p_aabb != AABB()) {1094// Set custom AABB1095if (instance->custom_aabb == nullptr) {1096instance->custom_aabb = memnew(AABB);1097}1098*instance->custom_aabb = p_aabb;10991100} else {1101// Clear custom AABB1102if (instance->custom_aabb != nullptr) {1103memdelete(instance->custom_aabb);1104instance->custom_aabb = nullptr;1105}1106}11071108if (instance->scenario) {1109_instance_queue_update(instance, true, false);1110}1111}11121113void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton) {1114Instance *instance = instance_owner.get_or_null(p_instance);1115ERR_FAIL_NULL(instance);11161117if (instance->skeleton == p_skeleton) {1118return;1119}11201121instance->skeleton = p_skeleton;11221123if (p_skeleton.is_valid()) {1124//update the dependency now, so if cleared, we remove it1125RSG::mesh_storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);1126}11271128_instance_queue_update(instance, true, true);11291130if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1131_instance_update_mesh_instance(instance);11321133InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1134ERR_FAIL_NULL(geom->geometry_instance);1135geom->geometry_instance->set_skeleton(p_skeleton);1136}1137}11381139void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {1140Instance *instance = instance_owner.get_or_null(p_instance);1141ERR_FAIL_NULL(instance);11421143instance->extra_margin = p_margin;1144_instance_queue_update(instance, true, false);1145}11461147void RendererSceneCull::instance_set_ignore_culling(RID p_instance, bool p_enabled) {1148Instance *instance = instance_owner.get_or_null(p_instance);1149ERR_FAIL_NULL(instance);1150instance->ignore_all_culling = p_enabled;11511152if (instance->scenario && instance->array_index >= 0) {1153InstanceData &idata = instance->scenario->instance_data[instance->array_index];1154if (instance->ignore_all_culling) {1155idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;1156} else {1157idata.flags &= ~InstanceData::FLAG_IGNORE_ALL_CULLING;1158}1159}1160}11611162Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {1163Vector<ObjectID> instances;1164Scenario *scenario = scenario_owner.get_or_null(p_scenario);1165ERR_FAIL_NULL_V(scenario, instances);11661167update_dirty_instances(); // check dirty instances before culling11681169struct CullAABB {1170Vector<ObjectID> instances;1171_FORCE_INLINE_ bool operator()(void *p_data) {1172Instance *p_instance = (Instance *)p_data;1173if (!p_instance->object_id.is_null()) {1174instances.push_back(p_instance->object_id);1175}1176return false;1177}1178};11791180CullAABB cull_aabb;1181scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(p_aabb, cull_aabb);1182scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(p_aabb, cull_aabb);1183return cull_aabb.instances;1184}11851186Vector<ObjectID> RendererSceneCull::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {1187Vector<ObjectID> instances;1188Scenario *scenario = scenario_owner.get_or_null(p_scenario);1189ERR_FAIL_NULL_V(scenario, instances);1190update_dirty_instances(); // check dirty instances before culling11911192struct CullRay {1193Vector<ObjectID> instances;1194_FORCE_INLINE_ bool operator()(void *p_data) {1195Instance *p_instance = (Instance *)p_data;1196if (!p_instance->object_id.is_null()) {1197instances.push_back(p_instance->object_id);1198}1199return false;1200}1201};12021203CullRay cull_ray;1204scenario->indexers[Scenario::INDEXER_GEOMETRY].ray_query(p_from, p_to, cull_ray);1205scenario->indexers[Scenario::INDEXER_VOLUMES].ray_query(p_from, p_to, cull_ray);1206return cull_ray.instances;1207}12081209Vector<ObjectID> RendererSceneCull::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {1210Vector<ObjectID> instances;1211Scenario *scenario = scenario_owner.get_or_null(p_scenario);1212ERR_FAIL_NULL_V(scenario, instances);1213update_dirty_instances(); // check dirty instances before culling12141215Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&p_convex[0], p_convex.size());12161217struct CullConvex {1218Vector<ObjectID> instances;1219_FORCE_INLINE_ bool operator()(void *p_data) {1220Instance *p_instance = (Instance *)p_data;1221if (!p_instance->object_id.is_null()) {1222instances.push_back(p_instance->object_id);1223}1224return false;1225}1226};12271228CullConvex cull_convex;1229scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex);1230scenario->indexers[Scenario::INDEXER_VOLUMES].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex);1231return cull_convex.instances;1232}12331234void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) {1235Instance *instance = instance_owner.get_or_null(p_instance);1236ERR_FAIL_NULL(instance);12371238//ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK));12391240switch (p_flags) {1241case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: {1242instance->baked_light = p_enabled;12431244if (instance->scenario && instance->array_index >= 0) {1245InstanceData &idata = instance->scenario->instance_data[instance->array_index];1246if (instance->baked_light) {1247idata.flags |= InstanceData::FLAG_USES_BAKED_LIGHT;1248} else {1249idata.flags &= ~InstanceData::FLAG_USES_BAKED_LIGHT;1250}1251}12521253if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1254InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1255ERR_FAIL_NULL(geom->geometry_instance);1256geom->geometry_instance->set_use_baked_light(p_enabled);1257}12581259} break;1260case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {1261if (p_enabled == instance->dynamic_gi) {1262//bye, redundant1263return;1264}12651266if (instance->indexer_id.is_valid()) {1267_unpair_instance(instance);1268_instance_queue_update(instance, true, true);1269}12701271//once out of octree, can be changed1272instance->dynamic_gi = p_enabled;12731274if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1275InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1276ERR_FAIL_NULL(geom->geometry_instance);1277geom->geometry_instance->set_use_dynamic_gi(p_enabled);1278}12791280} break;1281case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {1282instance->redraw_if_visible = p_enabled;12831284if (instance->scenario && instance->array_index >= 0) {1285InstanceData &idata = instance->scenario->instance_data[instance->array_index];1286if (instance->redraw_if_visible) {1287idata.flags |= InstanceData::FLAG_REDRAW_IF_VISIBLE;1288} else {1289idata.flags &= ~InstanceData::FLAG_REDRAW_IF_VISIBLE;1290}1291}12921293} break;1294case RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING: {1295instance->ignore_occlusion_culling = p_enabled;12961297if (instance->scenario && instance->array_index >= 0) {1298InstanceData &idata = instance->scenario->instance_data[instance->array_index];1299if (instance->ignore_occlusion_culling) {1300idata.flags |= InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;1301} else {1302idata.flags &= ~InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;1303}1304}1305} break;1306default: {1307}1308}1309}13101311void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {1312Instance *instance = instance_owner.get_or_null(p_instance);1313ERR_FAIL_NULL(instance);13141315instance->cast_shadows = p_shadow_casting_setting;13161317if (instance->scenario && instance->array_index >= 0) {1318InstanceData &idata = instance->scenario->instance_data[instance->array_index];13191320if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {1321idata.flags |= InstanceData::FLAG_CAST_SHADOWS;1322} else {1323idata.flags &= ~InstanceData::FLAG_CAST_SHADOWS;1324}13251326if (instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {1327idata.flags |= InstanceData::FLAG_CAST_SHADOWS_ONLY;1328} else {1329idata.flags &= ~InstanceData::FLAG_CAST_SHADOWS_ONLY;1330}1331}13321333if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1334InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1335ERR_FAIL_NULL(geom->geometry_instance);13361337geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);1338}13391340_instance_queue_update(instance, false, true);1341}13421343void RendererSceneCull::instance_geometry_set_material_override(RID p_instance, RID p_material) {1344Instance *instance = instance_owner.get_or_null(p_instance);1345ERR_FAIL_NULL(instance);13461347instance->material_override = p_material;1348_instance_queue_update(instance, false, true);13491350if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1351InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1352ERR_FAIL_NULL(geom->geometry_instance);1353geom->geometry_instance->set_material_override(p_material);1354}1355}13561357void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, RID p_material) {1358Instance *instance = instance_owner.get_or_null(p_instance);1359ERR_FAIL_NULL(instance);13601361instance->material_overlay = p_material;1362_instance_queue_update(instance, false, true);13631364if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1365InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1366ERR_FAIL_NULL(geom->geometry_instance);1367geom->geometry_instance->set_material_overlay(p_material);1368}1369}13701371void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) {1372Instance *instance = instance_owner.get_or_null(p_instance);1373ERR_FAIL_NULL(instance);13741375instance->visibility_range_begin = p_min;1376instance->visibility_range_end = p_max;1377instance->visibility_range_begin_margin = p_min_margin;1378instance->visibility_range_end_margin = p_max_margin;1379instance->visibility_range_fade_mode = p_fade_mode;13801381_update_instance_visibility_dependencies(instance);13821383if (instance->scenario && instance->visibility_index != -1) {1384InstanceVisibilityData &vd = instance->scenario->instance_visibility[instance->visibility_index];1385vd.range_begin = instance->visibility_range_begin;1386vd.range_end = instance->visibility_range_end;1387vd.range_begin_margin = instance->visibility_range_begin_margin;1388vd.range_end_margin = instance->visibility_range_end_margin;1389vd.fade_mode = p_fade_mode;1390}1391}13921393void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_parent_instance) {1394Instance *instance = instance_owner.get_or_null(p_instance);1395ERR_FAIL_NULL(instance);13961397Instance *old_parent = instance->visibility_parent;1398if (old_parent) {1399old_parent->visibility_dependencies.erase(instance);1400instance->visibility_parent = nullptr;1401_update_instance_visibility_depth(old_parent);1402}14031404Instance *parent = instance_owner.get_or_null(p_parent_instance);1405ERR_FAIL_COND(p_parent_instance.is_valid() && !parent);14061407if (parent) {1408parent->visibility_dependencies.insert(instance);1409instance->visibility_parent = parent;14101411bool cycle_detected = _update_instance_visibility_depth(parent);1412if (cycle_detected) {1413ERR_PRINT("Cycle detected in the visibility dependencies tree. The latest change to visibility_parent will have no effect.");1414parent->visibility_dependencies.erase(instance);1415instance->visibility_parent = nullptr;1416}1417}14181419_update_instance_visibility_dependencies(instance);1420}14211422bool RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {1423bool cycle_detected = false;1424HashSet<Instance *> traversed_nodes;14251426{1427Instance *instance = p_instance;1428while (instance) {1429if (!instance->visibility_dependencies.is_empty()) {1430uint32_t depth = 0;1431for (const Instance *E : instance->visibility_dependencies) {1432depth = MAX(depth, E->visibility_dependencies_depth);1433}1434instance->visibility_dependencies_depth = depth + 1;1435} else {1436instance->visibility_dependencies_depth = 0;1437}14381439if (instance->scenario && instance->visibility_index != -1) {1440instance->scenario->instance_visibility.move(instance->visibility_index, instance->visibility_dependencies_depth);1441}14421443traversed_nodes.insert(instance);14441445instance = instance->visibility_parent;1446if (traversed_nodes.has(instance)) {1447cycle_detected = true;1448break;1449}1450}1451}14521453return cycle_detected;1454}14551456void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_instance) const {1457bool is_geometry_instance = ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && p_instance->base_data;1458bool has_visibility_range = p_instance->visibility_range_begin > 0.0 || p_instance->visibility_range_end > 0.0;1459bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1;14601461if (!needs_visibility_cull && p_instance->visibility_index != -1) {1462p_instance->scenario->instance_visibility.remove_at(p_instance->visibility_index);1463p_instance->visibility_index = -1;1464} else if (needs_visibility_cull && p_instance->visibility_index == -1) {1465InstanceVisibilityData vd;1466vd.instance = p_instance;1467vd.range_begin = p_instance->visibility_range_begin;1468vd.range_end = p_instance->visibility_range_end;1469vd.range_begin_margin = p_instance->visibility_range_begin_margin;1470vd.range_end_margin = p_instance->visibility_range_end_margin;1471vd.position = p_instance->transformed_aabb.get_center();1472vd.array_index = p_instance->array_index;1473vd.fade_mode = p_instance->visibility_range_fade_mode;14741475p_instance->scenario->instance_visibility.insert(vd, p_instance->visibility_dependencies_depth);1476}14771478if (p_instance->scenario && p_instance->array_index != -1) {1479InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];1480idata.visibility_index = p_instance->visibility_index;14811482if (is_geometry_instance) {1483if (has_visibility_range && p_instance->visibility_range_fade_mode == RS::VISIBILITY_RANGE_FADE_SELF) {1484bool begin_enabled = p_instance->visibility_range_begin > 0.0f;1485float begin_min = p_instance->visibility_range_begin - p_instance->visibility_range_begin_margin;1486float begin_max = p_instance->visibility_range_begin + p_instance->visibility_range_begin_margin;1487bool end_enabled = p_instance->visibility_range_end > 0.0f;1488float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin;1489float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin;1490idata.instance_geometry->set_fade_range(begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);1491} else {1492idata.instance_geometry->set_fade_range(false, 0.0f, 0.0f, false, 0.0f, 0.0f);1493}1494}14951496if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || p_instance->visibility_dependencies_depth == 0)) {1497idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;1498} else {1499idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;1500}15011502if (p_instance->visibility_parent) {1503idata.parent_array_index = p_instance->visibility_parent->array_index;1504} else {1505idata.parent_array_index = -1;1506if (is_geometry_instance) {1507idata.instance_geometry->set_parent_fade_alpha(1.0f);1508}1509}1510}1511}15121513void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {1514Instance *instance = instance_owner.get_or_null(p_instance);1515ERR_FAIL_NULL(instance);15161517if (instance->lightmap) {1518InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(((Instance *)instance->lightmap)->base_data);1519lightmap_data->users.erase(instance);1520instance->lightmap = nullptr;1521}15221523Instance *lightmap_instance = instance_owner.get_or_null(p_lightmap);15241525instance->lightmap = lightmap_instance;1526instance->lightmap_uv_scale = p_lightmap_uv_scale;1527instance->lightmap_slice_index = p_slice_index;15281529RID lightmap_instance_rid;15301531if (lightmap_instance) {1532InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);1533lightmap_data->users.insert(instance);1534lightmap_instance_rid = lightmap_data->instance;1535}15361537if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1538InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1539ERR_FAIL_NULL(geom->geometry_instance);1540geom->geometry_instance->set_use_lightmap(lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);1541}1542}15431544void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) {1545Instance *instance = instance_owner.get_or_null(p_instance);1546ERR_FAIL_NULL(instance);15471548instance->lod_bias = p_lod_bias;15491550if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1551InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1552ERR_FAIL_NULL(geom->geometry_instance);1553geom->geometry_instance->set_lod_bias(p_lod_bias);1554}1555}15561557void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {1558Instance *instance = instance_owner.get_or_null(p_instance);1559ERR_FAIL_NULL(instance);15601561instance->instance_uniforms.set(instance->self, p_parameter, p_value);1562}15631564Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {1565const Instance *instance = instance_owner.get_or_null(p_instance);1566ERR_FAIL_NULL_V(instance, Variant());15671568return instance->instance_uniforms.get(p_parameter);1569}15701571Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {1572const Instance *instance = instance_owner.get_or_null(p_instance);1573ERR_FAIL_NULL_V(instance, Variant());15741575return instance->instance_uniforms.get_default(p_parameter);1576}15771578void RendererSceneCull::mesh_generate_pipelines(RID p_mesh, bool p_background_compilation) {1579scene_render->mesh_generate_pipelines(p_mesh, p_background_compilation);1580}15811582uint32_t RendererSceneCull::get_pipeline_compilations(RS::PipelineSource p_source) {1583return scene_render->get_pipeline_compilations(p_source);1584}15851586void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {1587ERR_FAIL_NULL(p_parameters);1588const Instance *instance = instance_owner.get_or_null(p_instance);1589ERR_FAIL_NULL(instance);15901591update_dirty_instances();15921593instance->instance_uniforms.get_property_list(*p_parameters);1594}15951596void RendererSceneCull::_update_instance(Instance *p_instance) const {1597p_instance->version++;15981599// When not using interpolation the transform is used straight.1600const Transform3D *instance_xform = &p_instance->transform;16011602// Can possibly use the most up to date current transform here when using physics interpolation ...1603// uncomment the next line for this..1604//if (_interpolation_data.interpolation_enabled && p_instance->interpolated) {1605// instance_xform = &p_instance->transform_curr;1606//}1607// However it does seem that using the interpolated transform (transform) works for keeping AABBs1608// up to date to avoid culling errors.16091610if (p_instance->base_type == RS::INSTANCE_LIGHT) {1611InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);16121613RSG::light_storage->light_instance_set_transform(light->instance, *instance_xform);1614RSG::light_storage->light_instance_set_aabb(light->instance, instance_xform->xform(p_instance->aabb));1615light->make_shadow_dirty();16161617RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);1618if (RSG::light_storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {1619if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1620p_instance->scenario->dynamic_lights.erase(light->instance);1621}16221623light->bake_mode = bake_mode;16241625if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1626p_instance->scenario->dynamic_lights.push_back(light->instance);1627}1628}16291630uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(p_instance->base);1631if (light->max_sdfgi_cascade != max_sdfgi_cascade) {1632light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario1633}1634light->cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base);1635} else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {1636InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);16371638RSG::light_storage->reflection_probe_instance_set_transform(reflection_probe->instance, *instance_xform);16391640if (p_instance->scenario && p_instance->array_index >= 0) {1641InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];1642idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;1643}1644} else if (p_instance->base_type == RS::INSTANCE_DECAL) {1645InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);16461647RSG::texture_storage->decal_instance_set_transform(decal->instance, *instance_xform);1648decal->cull_mask = RSG::texture_storage->decal_get_cull_mask(p_instance->base);1649} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {1650InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data);16511652RSG::light_storage->lightmap_instance_set_transform(lightmap->instance, *instance_xform);1653} else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) {1654InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(p_instance->base_data);16551656scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->probe_instance, *instance_xform);1657} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {1658RSG::particles_storage->particles_set_emission_transform(p_instance->base, *instance_xform);1659} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {1660InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data);16611662//remove materials no longer used and un-own them1663if (RSG::particles_storage->particles_collision_is_heightfield(p_instance->base)) {1664heightfield_particle_colliders_update_list.insert(p_instance);1665}1666RSG::particles_storage->particles_collision_instance_set_transform(collision->instance, *instance_xform);1667collision->cull_mask = RSG::particles_storage->particles_collision_get_cull_mask(p_instance->base);1668} else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {1669InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);1670scene_render->fog_volume_instance_set_transform(volume->instance, *instance_xform);1671} else if (p_instance->base_type == RS::INSTANCE_OCCLUDER) {1672if (p_instance->scenario) {1673RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(p_instance->scenario->self, p_instance->self, p_instance->base, *instance_xform, p_instance->visible);1674}1675} else if (p_instance->base_type == RS::INSTANCE_NONE) {1676return;1677}16781679if (!p_instance->aabb.has_surface()) {1680return;1681}16821683if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {1684//if this moved, update the captured objects1685InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);1686//erase dependencies, since no longer a lightmap16871688for (Instance *E : lightmap_data->geometries) {1689Instance *geom = E;1690_instance_queue_update(geom, true, false);1691}1692}16931694AABB new_aabb;1695new_aabb = instance_xform->xform(p_instance->aabb);1696p_instance->transformed_aabb = new_aabb;16971698if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1699InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);1700//make sure lights are updated if it casts shadow17011702if (geom->can_cast_shadows) {1703for (const Instance *E : geom->lights) {1704InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);1705light->make_shadow_dirty();1706}1707}17081709if (!p_instance->lightmap && geom->lightmap_captures.size()) {1710//affected by lightmap captures, must update capture info!1711_update_instance_lightmap_captures(p_instance);1712} else {1713if (!p_instance->lightmap_sh.is_empty()) {1714p_instance->lightmap_sh.clear(); //don't need SH1715p_instance->lightmap_target_sh.clear(); //don't need SH1716ERR_FAIL_NULL(geom->geometry_instance);1717geom->geometry_instance->set_lightmap_capture(nullptr);1718}1719}17201721ERR_FAIL_NULL(geom->geometry_instance);17221723geom->geometry_instance->set_transform(*instance_xform, p_instance->aabb, p_instance->transformed_aabb);1724if (p_instance->teleported) {1725geom->geometry_instance->reset_motion_vectors();1726}1727}17281729// note: we had to remove is equal approx check here, it meant that det == 0.000004 won't work, which is the case for some of our scenes.1730if (p_instance->scenario == nullptr || !p_instance->visible || instance_xform->basis.determinant() == 0) {1731p_instance->prev_transformed_aabb = p_instance->transformed_aabb;1732return;1733}17341735//quantize to improve moving object performance1736AABB bvh_aabb = p_instance->transformed_aabb;17371738if (p_instance->indexer_id.is_valid() && bvh_aabb != p_instance->prev_transformed_aabb) {1739//assume motion, see if bounds need to be quantized1740AABB motion_aabb = bvh_aabb.merge(p_instance->prev_transformed_aabb);1741float motion_longest_axis = motion_aabb.get_longest_axis_size();1742float longest_axis = p_instance->transformed_aabb.get_longest_axis_size();17431744if (motion_longest_axis < longest_axis * 2) {1745//moved but not a lot, use motion aabb quantizing1746float quantize_size = Math::pow(2.0, Math::ceil(Math::log(motion_longest_axis) / Math::log(2.0))) * 0.5; //one fifth1747bvh_aabb.quantize(quantize_size);1748}1749}17501751if (!p_instance->indexer_id.is_valid()) {1752if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1753p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].insert(bvh_aabb, p_instance);1754} else {1755p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(bvh_aabb, p_instance);1756}17571758p_instance->array_index = p_instance->scenario->instance_data.size();1759InstanceData idata;1760idata.instance = p_instance;1761idata.layer_mask = p_instance->layer_mask;1762idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later1763idata.base_rid = p_instance->base;1764idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;1765idata.visibility_index = p_instance->visibility_index;1766idata.occlusion_timeout = 0;17671768for (Instance *E : p_instance->visibility_dependencies) {1769Instance *dep_instance = E;1770if (dep_instance->array_index != -1) {1771dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;1772}1773}17741775switch (p_instance->base_type) {1776case RS::INSTANCE_MESH:1777case RS::INSTANCE_MULTIMESH:1778case RS::INSTANCE_PARTICLES: {1779InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);1780idata.instance_geometry = geom->geometry_instance;1781} break;1782case RS::INSTANCE_LIGHT: {1783InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);1784idata.instance_data_rid = light_data->instance.get_id();1785light_data->uses_projector = RSG::light_storage->light_has_projector(p_instance->base);1786light_data->uses_softshadow = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;17871788} break;1789case RS::INSTANCE_REFLECTION_PROBE: {1790idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance.get_id();1791} break;1792case RS::INSTANCE_DECAL: {1793idata.instance_data_rid = static_cast<InstanceDecalData *>(p_instance->base_data)->instance.get_id();1794} break;1795case RS::INSTANCE_LIGHTMAP: {1796idata.instance_data_rid = static_cast<InstanceLightmapData *>(p_instance->base_data)->instance.get_id();1797} break;1798case RS::INSTANCE_VOXEL_GI: {1799idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();1800} break;1801case RS::INSTANCE_FOG_VOLUME: {1802idata.instance_data_rid = static_cast<InstanceFogVolumeData *>(p_instance->base_data)->instance.get_id();1803} break;1804case RS::INSTANCE_VISIBLITY_NOTIFIER: {1805idata.visibility_notifier = static_cast<InstanceVisibilityNotifierData *>(p_instance->base_data);1806} break;1807default: {1808}1809}18101811if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {1812//always dirty when added1813idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;1814}1815if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {1816idata.flags |= InstanceData::FLAG_CAST_SHADOWS;1817}1818if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {1819idata.flags |= InstanceData::FLAG_CAST_SHADOWS_ONLY;1820}1821if (p_instance->redraw_if_visible) {1822idata.flags |= InstanceData::FLAG_REDRAW_IF_VISIBLE;1823}1824// dirty flags should not be set here, since no pairing has happened1825if (p_instance->baked_light) {1826idata.flags |= InstanceData::FLAG_USES_BAKED_LIGHT;1827}1828if (p_instance->mesh_instance.is_valid()) {1829idata.flags |= InstanceData::FLAG_USES_MESH_INSTANCE;1830}1831if (p_instance->ignore_occlusion_culling) {1832idata.flags |= InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;1833}1834if (p_instance->ignore_all_culling) {1835idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;1836}18371838p_instance->scenario->instance_data.push_back(idata);1839p_instance->scenario->instance_aabbs.push_back(InstanceBounds(p_instance->transformed_aabb));1840_update_instance_visibility_dependencies(p_instance);1841} else {1842if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1843p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, bvh_aabb);1844} else {1845p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].update(p_instance->indexer_id, bvh_aabb);1846}1847p_instance->scenario->instance_aabbs[p_instance->array_index] = InstanceBounds(p_instance->transformed_aabb);1848}18491850if (p_instance->visibility_index != -1) {1851p_instance->scenario->instance_visibility[p_instance->visibility_index].position = p_instance->transformed_aabb.get_center();1852}18531854//move instance and repair1855pair_pass++;18561857PairInstances pair;18581859pair.instance = p_instance;1860pair.pair_allocator = &pair_allocator;1861pair.pair_pass = pair_pass;1862pair.pair_mask = 0;18631864if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1865pair.pair_mask |= 1 << RS::INSTANCE_LIGHT;1866pair.pair_mask |= 1 << RS::INSTANCE_VOXEL_GI;1867pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP;1868if (p_instance->base_type == RS::INSTANCE_PARTICLES) {1869pair.pair_mask |= 1 << RS::INSTANCE_PARTICLES_COLLISION;1870}18711872pair.pair_mask |= geometry_instance_pair_mask;18731874pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];1875} else if (p_instance->base_type == RS::INSTANCE_LIGHT) {1876pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;1877pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];18781879RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);1880if (bake_mode == RS::LIGHT_BAKE_STATIC || bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1881pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI);1882pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];1883}1884} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {1885pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;1886pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1887} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) {1888pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;1889pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1890} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) {1891pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;1892pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1893} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {1894pair.pair_mask = (1 << RS::INSTANCE_PARTICLES);1895pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1896} else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) {1897//lights and geometries1898pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT);1899pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1900pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];1901}19021903pair.pair();19041905p_instance->prev_transformed_aabb = p_instance->transformed_aabb;1906}19071908void RendererSceneCull::_unpair_instance(Instance *p_instance) {1909if (!p_instance->indexer_id.is_valid()) {1910return; //nothing to do1911}19121913while (p_instance->pairs.first()) {1914InstancePair *pair = p_instance->pairs.first()->self();1915Instance *other_instance = p_instance == pair->a ? pair->b : pair->a;1916_instance_unpair(p_instance, other_instance);1917pair_allocator.free(pair);1918}19191920if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1921p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].remove(p_instance->indexer_id);1922} else {1923p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].remove(p_instance->indexer_id);1924}19251926p_instance->indexer_id = DynamicBVH::ID();19271928//replace this by last1929int32_t swap_with_index = p_instance->scenario->instance_data.size() - 1;1930if (swap_with_index != p_instance->array_index) {1931Instance *swapped_instance = p_instance->scenario->instance_data[swap_with_index].instance;1932swapped_instance->array_index = p_instance->array_index; //swap1933p_instance->scenario->instance_data[p_instance->array_index] = p_instance->scenario->instance_data[swap_with_index];1934p_instance->scenario->instance_aabbs[p_instance->array_index] = p_instance->scenario->instance_aabbs[swap_with_index];19351936if (swapped_instance->visibility_index != -1) {1937swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index;1938}19391940for (Instance *E : swapped_instance->visibility_dependencies) {1941Instance *dep_instance = E;1942if (dep_instance != p_instance && dep_instance->array_index != -1) {1943dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;1944}1945}1946}19471948// pop last1949p_instance->scenario->instance_data.pop_back();1950p_instance->scenario->instance_aabbs.pop_back();19511952//uninitialize1953p_instance->array_index = -1;1954if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1955// Clear these now because the InstanceData containing the dirty flags is gone1956InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);1957ERR_FAIL_NULL(geom->geometry_instance);19581959geom->geometry_instance->clear_light_instances();1960geom->geometry_instance->pair_reflection_probe_instances(nullptr, 0);1961geom->geometry_instance->pair_decal_instances(nullptr, 0);1962geom->geometry_instance->pair_voxel_gi_instances(nullptr, 0);1963}19641965for (Instance *E : p_instance->visibility_dependencies) {1966Instance *dep_instance = E;1967if (dep_instance->array_index != -1) {1968dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;1969if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1970dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry->set_parent_fade_alpha(1.0f);1971}1972}1973}19741975_update_instance_visibility_dependencies(p_instance);1976}19771978void RendererSceneCull::_update_instance_aabb(Instance *p_instance) const {1979AABB new_aabb;19801981ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid());19821983switch (p_instance->base_type) {1984case RenderingServer::INSTANCE_NONE: {1985// do nothing1986} break;1987case RenderingServer::INSTANCE_MESH: {1988if (p_instance->custom_aabb) {1989new_aabb = *p_instance->custom_aabb;1990} else {1991new_aabb = RSG::mesh_storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);1992}19931994} break;19951996case RenderingServer::INSTANCE_MULTIMESH: {1997if (p_instance->custom_aabb) {1998new_aabb = *p_instance->custom_aabb;1999} else {2000new_aabb = RSG::mesh_storage->multimesh_get_aabb(p_instance->base);2001}20022003} break;2004case RenderingServer::INSTANCE_PARTICLES: {2005if (p_instance->custom_aabb) {2006new_aabb = *p_instance->custom_aabb;2007} else {2008new_aabb = RSG::particles_storage->particles_get_aabb(p_instance->base);2009}20102011} break;2012case RenderingServer::INSTANCE_PARTICLES_COLLISION: {2013new_aabb = RSG::particles_storage->particles_collision_get_aabb(p_instance->base);20142015} break;2016case RenderingServer::INSTANCE_FOG_VOLUME: {2017new_aabb = RSG::fog->fog_volume_get_aabb(p_instance->base);2018} break;2019case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {2020new_aabb = RSG::utilities->visibility_notifier_get_aabb(p_instance->base);2021} break;2022case RenderingServer::INSTANCE_LIGHT: {2023new_aabb = RSG::light_storage->light_get_aabb(p_instance->base);20242025} break;2026case RenderingServer::INSTANCE_REFLECTION_PROBE: {2027new_aabb = RSG::light_storage->reflection_probe_get_aabb(p_instance->base);20282029} break;2030case RenderingServer::INSTANCE_DECAL: {2031new_aabb = RSG::texture_storage->decal_get_aabb(p_instance->base);20322033} break;2034case RenderingServer::INSTANCE_VOXEL_GI: {2035new_aabb = RSG::gi->voxel_gi_get_bounds(p_instance->base);20362037} break;2038case RenderingServer::INSTANCE_LIGHTMAP: {2039new_aabb = RSG::light_storage->lightmap_get_aabb(p_instance->base);20402041} break;2042default: {2043}2044}20452046if (p_instance->extra_margin) {2047new_aabb.grow_by(p_instance->extra_margin);2048}20492050p_instance->aabb = new_aabb;2051}20522053void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance) const {2054bool first_set = p_instance->lightmap_sh.is_empty();2055p_instance->lightmap_sh.resize(9); //using SH2056p_instance->lightmap_target_sh.resize(9); //using SH2057Color *instance_sh = p_instance->lightmap_target_sh.ptrw();2058bool inside = false;2059Color accum_sh[9];2060float accum_blend = 0.0;20612062InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);2063for (Instance *E : geom->lightmap_captures) {2064Instance *lightmap = E;20652066bool interior = RSG::light_storage->lightmap_is_interior(lightmap->base);20672068if (inside && !interior) {2069continue; //we are inside, ignore exteriors2070}20712072Transform3D to_bounds = lightmap->transform.affine_inverse();2073Vector3 center = p_instance->transform.xform(p_instance->aabb.get_center()); //use aabb center20742075Vector3 lm_pos = to_bounds.xform(center);20762077AABB bounds = RSG::light_storage->lightmap_get_aabb(lightmap->base);2078if (!bounds.has_point(lm_pos)) {2079continue; //not in this lightmap2080}20812082Color sh[9];2083RSG::light_storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);20842085//rotate it2086Basis rot = lightmap->transform.basis.orthonormalized();2087for (int i = 0; i < 3; i++) {2088real_t csh[9];2089for (int j = 0; j < 9; j++) {2090csh[j] = sh[j][i];2091}2092rot.rotate_sh(csh);2093for (int j = 0; j < 9; j++) {2094sh[j][i] = csh[j];2095}2096}20972098Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);20992100real_t blend = MAX(Math::abs(inner_pos.x), MAX(Math::abs(inner_pos.y), Math::abs(inner_pos.z)));2101//make blend more rounded2102blend = Math::lerp(inner_pos.length(), blend, blend);2103blend *= blend;2104blend = MAX(0.0, 1.0 - blend);21052106if (interior && !inside) {2107//do not blend, just replace2108for (int j = 0; j < 9; j++) {2109accum_sh[j] = sh[j] * blend;2110}2111accum_blend = blend;2112inside = true;2113} else {2114for (int j = 0; j < 9; j++) {2115accum_sh[j] += sh[j] * blend;2116}2117accum_blend += blend;2118}2119}21202121if (accum_blend > 0.0) {2122for (int j = 0; j < 9; j++) {2123instance_sh[j] = accum_sh[j] / accum_blend;2124if (first_set) {2125p_instance->lightmap_sh.write[j] = instance_sh[j];2126}2127}2128}21292130ERR_FAIL_NULL(geom->geometry_instance);2131geom->geometry_instance->set_lightmap_capture(p_instance->lightmap_sh.ptr());2132}21332134void RendererSceneCull::_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) {2135// For later tight culling, the light culler needs to know the details of the directional light.2136light_culler->prepare_directional_light(p_instance, p_shadow_index);21372138InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);21392140Transform3D light_transform = p_instance->transform;2141light_transform.orthonormalize(); //scale does not count on lights21422143real_t max_distance = p_cam_projection.get_z_far();2144real_t shadow_max = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);2145if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera2146max_distance = MIN(shadow_max, max_distance);2147}2148max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);2149real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);21502151real_t pancake_size = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);21522153real_t range = max_distance - min_distance;21542155int splits = 0;2156switch (RSG::light_storage->light_directional_get_shadow_mode(p_instance->base)) {2157case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:2158splits = 1;2159break;2160case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:2161splits = 2;2162break;2163case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:2164splits = 4;2165break;2166}21672168real_t distances[5];21692170distances[0] = min_distance;2171for (int i = 0; i < splits; i++) {2172distances[i + 1] = min_distance + RSG::light_storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;2173};21742175distances[splits] = max_distance;21762177real_t texture_size = RSG::light_storage->get_directional_light_shadow_size(light->instance);21782179bool overlap = RSG::light_storage->light_directional_get_blend_splits(p_instance->base);21802181cull.shadow_count = p_shadow_index + 1;2182cull.shadows[p_shadow_index].cascade_count = splits;2183cull.shadows[p_shadow_index].light_instance = light->instance;2184cull.shadows[p_shadow_index].caster_mask = RSG::light_storage->light_get_shadow_caster_mask(p_instance->base);21852186for (int i = 0; i < splits; i++) {2187RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));21882189// setup a camera matrix for that range!2190Projection camera_matrix;21912192real_t aspect = p_cam_projection.get_aspect();21932194if (p_cam_orthogonal) {2195Vector2 vp_he = p_cam_projection.get_viewport_half_extents();21962197camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);2198} else {2199real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it2200camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);2201}22022203//obtain the frustum endpoints22042205Vector3 endpoints[8]; // frustum plane endpoints2206bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints);2207ERR_CONTINUE(!res);22082209// obtain the light frustum ranges (given endpoints)22102211Transform3D transform = light_transform; //discard scale and stabilize light22122213Vector3 x_vec = transform.basis.get_column(Vector3::AXIS_X).normalized();2214Vector3 y_vec = transform.basis.get_column(Vector3::AXIS_Y).normalized();2215Vector3 z_vec = transform.basis.get_column(Vector3::AXIS_Z).normalized();2216//z_vec points against the camera, like in default opengl22172218real_t x_min = 0.f, x_max = 0.f;2219real_t y_min = 0.f, y_max = 0.f;2220real_t z_min = 0.f, z_max = 0.f;22212222// FIXME: z_max_cam is defined, computed, but not used below when setting up2223// ortho_camera. Commented out for now to fix warnings but should be investigated.2224real_t x_min_cam = 0.f, x_max_cam = 0.f;2225real_t y_min_cam = 0.f, y_max_cam = 0.f;2226real_t z_min_cam = 0.f;2227//real_t z_max_cam = 0.f;22282229//real_t bias_scale = 1.0;2230//real_t aspect_bias_scale = 1.0;22312232//used for culling22332234for (int j = 0; j < 8; j++) {2235real_t d_x = x_vec.dot(endpoints[j]);2236real_t d_y = y_vec.dot(endpoints[j]);2237real_t d_z = z_vec.dot(endpoints[j]);22382239if (j == 0 || d_x < x_min) {2240x_min = d_x;2241}2242if (j == 0 || d_x > x_max) {2243x_max = d_x;2244}22452246if (j == 0 || d_y < y_min) {2247y_min = d_y;2248}2249if (j == 0 || d_y > y_max) {2250y_max = d_y;2251}22522253if (j == 0 || d_z < z_min) {2254z_min = d_z;2255}2256if (j == 0 || d_z > z_max) {2257z_max = d_z;2258}2259}22602261real_t radius = 0;2262real_t soft_shadow_expand = 0;2263Vector3 center;22642265{2266//camera viewport stuff22672268for (int j = 0; j < 8; j++) {2269center += endpoints[j];2270}2271center /= 8.0;22722273//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;22742275for (int j = 0; j < 8; j++) {2276real_t d = center.distance_to(endpoints[j]);2277if (d > radius) {2278radius = d;2279}2280}22812282radius *= texture_size / (texture_size - 2.0); //add a texel by each side22832284z_min_cam = z_vec.dot(center) - radius;22852286{2287float soft_shadow_angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);22882289if (soft_shadow_angle > 0.0) {2290float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;2291soft_shadow_expand = Math::tan(Math::deg_to_rad(soft_shadow_angle)) * z_range;22922293x_max += soft_shadow_expand;2294y_max += soft_shadow_expand;22952296x_min -= soft_shadow_expand;2297y_min -= soft_shadow_expand;2298}2299}23002301// This trick here is what stabilizes the shadow (make potential jaggies to not move)2302// at the cost of some wasted resolution. Still, the quality increase is very well worth it.2303const real_t unit = (radius + soft_shadow_expand) * 4.0 / texture_size;2304x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);2305x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);2306y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);2307y_min_cam = Math::snapped(y_vec.dot(center) - radius - soft_shadow_expand, unit);2308}23092310//now that we know all ranges, we can proceed to make the light frustum planes, for culling octree23112312Vector<Plane> light_frustum_planes;2313light_frustum_planes.resize(6);23142315//right/left2316light_frustum_planes.write[0] = Plane(x_vec, x_max);2317light_frustum_planes.write[1] = Plane(-x_vec, -x_min);2318//top/bottom2319light_frustum_planes.write[2] = Plane(y_vec, y_max);2320light_frustum_planes.write[3] = Plane(-y_vec, -y_min);2321//near/far2322light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6);2323light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed23242325// a pre pass will need to be needed to determine the actual z-near to be used23262327z_max = z_vec.dot(center) + radius + pancake_size;23282329{2330Projection ortho_camera;2331real_t half_x = (x_max_cam - x_min_cam) * 0.5;2332real_t half_y = (y_max_cam - y_min_cam) * 0.5;23332334ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam));23352336Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam));23372338Transform3D ortho_transform;2339ortho_transform.basis = transform.basis;2340ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;23412342cull.shadows[p_shadow_index].cascades[i].frustum = Frustum(light_frustum_planes);2343cull.shadows[p_shadow_index].cascades[i].projection = ortho_camera;2344cull.shadows[p_shadow_index].cascades[i].transform = ortho_transform;2345cull.shadows[p_shadow_index].cascades[i].zfar = z_max - z_min_cam;2346cull.shadows[p_shadow_index].cascades[i].split = distances[i + 1];2347cull.shadows[p_shadow_index].cascades[i].shadow_texel_size = radius * 2.0 / texture_size;2348cull.shadows[p_shadow_index].cascades[i].bias_scale = (z_max - z_min_cam);2349cull.shadows[p_shadow_index].cascades[i].range_begin = z_max;2350cull.shadows[p_shadow_index].cascades[i].uv_scale = uv_scale;2351}2352}2353}23542355bool 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) {2356InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);23572358Transform3D light_transform = p_instance->transform;2359light_transform.orthonormalize(); //scale does not count on lights23602361bool animated_material_found = false;23622363switch (RSG::light_storage->light_get_type(p_instance->base)) {2364case RS::LIGHT_DIRECTIONAL: {2365} break;2366case RS::LIGHT_OMNI: {2367RS::LightOmniShadowMode shadow_mode = RSG::light_storage->light_omni_get_shadow_mode(p_instance->base);23682369if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::light_storage->light_instances_can_render_shadow_cube()) {2370if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) {2371return true;2372}2373for (int i = 0; i < 2; i++) {2374//using this one ensures that raster deferred will have it2375RENDER_TIMESTAMP("Cull OmniLight3D Shadow Paraboloid, Half " + itos(i));23762377real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);23782379real_t z = i == 0 ? -1 : 1;2380Vector<Plane> planes;2381planes.resize(6);2382planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));2383planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));2384planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));2385planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));2386planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));2387planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));23882389instance_shadow_cull_result.clear();23902391Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());23922393struct CullConvex {2394PagedArray<Instance *> *result;2395_FORCE_INLINE_ bool operator()(void *p_data) {2396Instance *p_instance = (Instance *)p_data;2397result->push_back(p_instance);2398return false;2399}2400};24012402CullConvex cull_convex;2403cull_convex.result = &instance_shadow_cull_result;24042405p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);24062407RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];24082409if (!light->is_shadow_update_full()) {2410light_culler->cull_regular_light(instance_shadow_cull_result);2411}24122413for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {2414Instance *instance = instance_shadow_cull_result[j];2415if (!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))) {2416continue;2417} else {2418if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {2419animated_material_found = true;2420}24212422if (instance->mesh_instance.is_valid()) {2423RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);2424}2425}24262427shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);2428}24292430RSG::mesh_storage->update_mesh_instances();24312432RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0);2433shadow_data.light = light->instance;2434shadow_data.pass = i;2435}2436} else { //shadow cube24372438if (max_shadows_used + 6 > MAX_UPDATE_SHADOWS) {2439return true;2440}24412442real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);2443real_t z_near = MIN(0.025f, radius);2444Projection cm;2445cm.set_perspective(90, 1, z_near, radius);24462447for (int i = 0; i < 6; i++) {2448RENDER_TIMESTAMP("Cull OmniLight3D Shadow Cube, Side " + itos(i));2449//using this one ensures that raster deferred will have it24502451static const Vector3 view_normals[6] = {2452Vector3(+1, 0, 0),2453Vector3(-1, 0, 0),2454Vector3(0, -1, 0),2455Vector3(0, +1, 0),2456Vector3(0, 0, +1),2457Vector3(0, 0, -1)2458};2459static const Vector3 view_up[6] = {2460Vector3(0, -1, 0),2461Vector3(0, -1, 0),2462Vector3(0, 0, -1),2463Vector3(0, 0, +1),2464Vector3(0, -1, 0),2465Vector3(0, -1, 0)2466};24672468Transform3D xform = light_transform * Transform3D().looking_at(view_normals[i], view_up[i]);24692470Vector<Plane> planes = cm.get_projection_planes(xform);24712472instance_shadow_cull_result.clear();24732474Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());24752476struct CullConvex {2477PagedArray<Instance *> *result;2478_FORCE_INLINE_ bool operator()(void *p_data) {2479Instance *p_instance = (Instance *)p_data;2480result->push_back(p_instance);2481return false;2482}2483};24842485CullConvex cull_convex;2486cull_convex.result = &instance_shadow_cull_result;24872488p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);24892490RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];24912492if (!light->is_shadow_update_full()) {2493light_culler->cull_regular_light(instance_shadow_cull_result);2494}24952496for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {2497Instance *instance = instance_shadow_cull_result[j];2498if (!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))) {2499continue;2500} else {2501if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {2502animated_material_found = true;2503}2504if (instance->mesh_instance.is_valid()) {2505RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);2506}2507}25082509shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);2510}25112512RSG::mesh_storage->update_mesh_instances();2513RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);25142515shadow_data.light = light->instance;2516shadow_data.pass = i;2517}25182519//restore the regular DP matrix2520//RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0);2521}25222523} break;2524case RS::LIGHT_SPOT: {2525RENDER_TIMESTAMP("Cull SpotLight3D Shadow");25262527if (max_shadows_used + 1 > MAX_UPDATE_SHADOWS) {2528return true;2529}25302531real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);2532real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);2533real_t z_near = MIN(0.025f, radius);25342535Projection cm;2536cm.set_perspective(angle * 2.0, 1.0, z_near, radius);25372538Vector<Plane> planes = cm.get_projection_planes(light_transform);25392540instance_shadow_cull_result.clear();25412542Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());25432544struct CullConvex {2545PagedArray<Instance *> *result;2546_FORCE_INLINE_ bool operator()(void *p_data) {2547Instance *p_instance = (Instance *)p_data;2548result->push_back(p_instance);2549return false;2550}2551};25522553CullConvex cull_convex;2554cull_convex.result = &instance_shadow_cull_result;25552556p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);25572558RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];25592560if (!light->is_shadow_update_full()) {2561light_culler->cull_regular_light(instance_shadow_cull_result);2562}25632564for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {2565Instance *instance = instance_shadow_cull_result[j];2566if (!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))) {2567continue;2568} else {2569if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {2570animated_material_found = true;2571}25722573if (instance->mesh_instance.is_valid()) {2574RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);2575}2576}2577shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);2578}25792580RSG::mesh_storage->update_mesh_instances();25812582RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);2583shadow_data.light = light->instance;2584shadow_data.pass = 0;25852586} break;2587}25882589return animated_material_found;2590}25912592void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, uint32_t p_jitter_phase_count, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {2593#ifndef _3D_DISABLED25942595Camera *camera = camera_owner.get_or_null(p_camera);2596ERR_FAIL_NULL(camera);25972598Vector2 jitter;2599float taa_frame_count = 0.0f;2600if (p_jitter_phase_count > 0) {2601uint32_t current_jitter_count = camera_jitter_array.size();2602if (p_jitter_phase_count != current_jitter_count) {2603// Resize the jitter array and fill it with the pre-computed Halton sequence.2604camera_jitter_array.resize(p_jitter_phase_count);26052606for (uint32_t i = current_jitter_count; i < p_jitter_phase_count; i++) {2607camera_jitter_array[i].x = get_halton_value(i, 2);2608camera_jitter_array[i].y = get_halton_value(i, 3);2609}2610}26112612jitter = camera_jitter_array[RSG::rasterizer->get_frame_number() % p_jitter_phase_count] / p_viewport_size;2613taa_frame_count = float(RSG::rasterizer->get_frame_number() % p_jitter_phase_count);2614}26152616RendererSceneRender::CameraData camera_data;26172618// Setup Camera(s)2619if (p_xr_interface.is_null()) {2620// Normal camera2621Transform3D transform = camera->transform;2622Projection projection;2623bool vaspect = camera->vaspect;2624bool is_orthogonal = false;2625bool is_frustum = false;26262627switch (camera->type) {2628case Camera::ORTHOGONAL: {2629projection.set_orthogonal(2630camera->size,2631p_viewport_size.width / (float)p_viewport_size.height,2632camera->znear,2633camera->zfar,2634camera->vaspect);2635is_orthogonal = true;2636} break;2637case Camera::PERSPECTIVE: {2638projection.set_perspective(2639camera->fov,2640p_viewport_size.width / (float)p_viewport_size.height,2641camera->znear,2642camera->zfar,2643camera->vaspect);26442645} break;2646case Camera::FRUSTUM: {2647projection.set_frustum(2648camera->size,2649p_viewport_size.width / (float)p_viewport_size.height,2650camera->offset,2651camera->znear,2652camera->zfar,2653camera->vaspect);2654is_frustum = true;2655} break;2656}26572658camera_data.set_camera(transform, projection, is_orthogonal, is_frustum, vaspect, jitter, taa_frame_count, camera->visible_layers);2659#ifndef XR_DISABLED2660} else {2661XRServer *xr_server = XRServer::get_singleton();26622663// Setup our camera for our XR interface.2664// We can support multiple views here each with their own camera2665Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];2666Projection projections[RendererSceneRender::MAX_RENDER_VIEWS];26672668uint32_t view_count = p_xr_interface->get_view_count();2669ERR_FAIL_COND_MSG(view_count == 0 || view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");26702671float aspect = p_viewport_size.width / (float)p_viewport_size.height;26722673Transform3D world_origin = xr_server->get_world_origin();26742675// We ignore our camera position, it will have been positioned with a slightly old tracking position.2676// Instead we take our origin point and have our XR interface add fresh tracking data! Whoohoo!2677for (uint32_t v = 0; v < view_count; v++) {2678transforms[v] = p_xr_interface->get_transform_for_view(v, world_origin);2679projections[v] = p_xr_interface->get_projection_for_view(v, aspect, camera->znear, camera->zfar);2680}26812682// If requested, we move the views to be rendered as if the HMD is at the XROrigin.2683if (unlikely(xr_server->is_camera_locked_to_origin())) {2684Transform3D camera_reset = p_xr_interface->get_camera_transform().affine_inverse() * xr_server->get_reference_frame().affine_inverse();2685for (uint32_t v = 0; v < view_count; v++) {2686transforms[v] *= camera_reset;2687}2688}26892690if (view_count == 1) {2691camera_data.set_camera(transforms[0], projections[0], false, false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers);2692} else if (view_count == 2) {2693camera_data.set_multiview_camera(view_count, transforms, projections, false, false, camera->vaspect, camera->visible_layers);2694} else {2695// this won't be called (see fail check above) but keeping this comment to indicate we may support more then 2 views in the future...2696}2697#endif // XR_DISABLED2698}26992700RID environment = _render_get_environment(p_camera, p_scenario);2701RID compositor = _render_get_compositor(p_camera, p_scenario);27022703RENDER_TIMESTAMP("Update Occlusion Buffer")2704// For now just cull on the first camera2705RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal);27062707_render_scene(&camera_data, p_render_buffers, environment, camera->attributes, compositor, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info);2708#endif2709}27102711void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) {2712uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();2713uint32_t bin_from = p_thread * cull_data->cull_count / total_threads;2714uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads);27152716_visibility_cull(*cull_data, cull_data->cull_offset + bin_from, cull_data->cull_offset + bin_to);2717}27182719void RendererSceneCull::_visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to) {2720Scenario *scenario = cull_data.scenario;2721for (unsigned int i = p_from; i < p_to; i++) {2722InstanceVisibilityData &vd = scenario->instance_visibility[i];2723InstanceData &idata = scenario->instance_data[vd.array_index];27242725if (idata.parent_array_index >= 0) {2726uint32_t parent_flags = scenario->instance_data[idata.parent_array_index].flags;27272728if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || !(parent_flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN))) {2729idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2730idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2731idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2732continue;2733}2734}27352736int range_check = _visibility_range_check<true>(vd, cull_data.camera_position, cull_data.viewport_mask);27372738if (range_check == -1) {2739idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2740idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2741idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2742} else if (range_check == 1) {2743idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2744idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2745idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2746} else {2747idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2748idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2749if (range_check == 2) {2750idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2751} else {2752idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2753}2754}2755}2756}27572758template <bool p_fade_check>2759int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask) {2760float dist = p_camera_pos.distance_to(r_vis_data.position);2761const RS::VisibilityRangeFadeMode &fade_mode = r_vis_data.fade_mode;27622763float begin_offset = -r_vis_data.range_begin_margin;2764float end_offset = r_vis_data.range_end_margin;27652766if (fade_mode == RS::VISIBILITY_RANGE_FADE_DISABLED && !(p_viewport_mask & r_vis_data.viewport_state)) {2767begin_offset = -begin_offset;2768end_offset = -end_offset;2769}27702771if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end + end_offset) {2772r_vis_data.viewport_state &= ~p_viewport_mask;2773return -1;2774} else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin + begin_offset) {2775r_vis_data.viewport_state &= ~p_viewport_mask;2776return 1;2777} else {2778r_vis_data.viewport_state |= p_viewport_mask;2779if (p_fade_check) {2780if (fade_mode != RS::VISIBILITY_RANGE_FADE_DISABLED) {2781r_vis_data.children_fade_alpha = 1.0f;2782if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end - end_offset) {2783if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {2784r_vis_data.children_fade_alpha = MIN(1.0f, (dist - (r_vis_data.range_end - end_offset)) / (2.0f * r_vis_data.range_end_margin));2785}2786return 2;2787} else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin - begin_offset) {2788if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {2789r_vis_data.children_fade_alpha = MIN(1.0f, 1.0 - (dist - (r_vis_data.range_begin + begin_offset)) / (2.0f * r_vis_data.range_begin_margin));2790}2791return 2;2792}2793}2794}2795return 0;2796}2797}27982799bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data) {2800if (p_instance_data.parent_array_index == -1) {2801return true;2802}2803const uint32_t &parent_flags = p_cull_data.scenario->instance_data[p_instance_data.parent_array_index].flags;2804return ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);2805}28062807void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {2808uint32_t cull_total = cull_data->scenario->instance_data.size();2809uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();2810uint32_t cull_from = p_thread * cull_total / total_threads;2811uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);28122813_scene_cull(*cull_data, scene_cull_result_threads[p_thread], cull_from, cull_to);2814}28152816void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to) {2817uint64_t frame_number = RSG::rasterizer->get_frame_number();2818float lightmap_probe_update_speed = RSG::light_storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();28192820uint32_t sdfgi_last_light_index = 0xFFFFFFFF;2821uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;28222823RID instance_pair_buffer[MAX_INSTANCE_PAIRS];28242825// Minimize allocations when picking the most relevant lights per mesh.2826// We need to track the score and current index of the best N lights.2827thread_local LocalVector<Pair<float, uint32_t>> omni_score_idx, spot_score_idx;2828omni_score_idx.clear();2829spot_score_idx.clear();2830uint32_t max_lights_per_mesh = scene_render->get_max_lights_per_mesh();2831uint32_t max_lights_total = scene_render->get_max_lights_total();28322833Transform3D inv_cam_transform = cull_data.cam_transform.inverse();2834float z_near = cull_data.camera_matrix->get_z_near();2835bool is_orthogonal = cull_data.camera_matrix->is_orthogonal();28362837for (uint64_t i = p_from; i < p_to; i++) {2838bool mesh_visible = false;28392840InstanceData &idata = cull_data.scenario->instance_data[i];2841uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);2842int32_t visibility_check = -1;28432844#define HIDDEN_BY_VISIBILITY_CHECKS (visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE || visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN)2845#define LAYER_CHECK (cull_data.visible_layers & idata.layer_mask)2846#define IN_FRUSTUM(f) (cull_data.scenario->instance_aabbs[i].in_frustum(f))2847#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check<false>(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)2848#define VIS_PARENT_CHECK (_visibility_parent_check(cull_data, idata))2849#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)2850#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near, is_orthogonal, cull_data.scenario->instance_data[i].occlusion_timeout))28512852if (!HIDDEN_BY_VISIBILITY_CHECKS) {2853if ((LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) || (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_ALL_CULLING)) {2854uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;2855if (base_type == RS::INSTANCE_LIGHT) {2856cull_result.lights.push_back(idata.instance);2857cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));2858if (cull_data.shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(idata.base_rid)) {2859RSG::light_storage->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later2860}28612862} else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {2863if (cull_data.render_reflection_probe != idata.instance) {2864//avoid entering The Matrix28652866if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || RSG::light_storage->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {2867InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);2868cull_data.cull->lock.lock();2869if (!reflection_probe->update_list.in_list()) {2870reflection_probe->render_step = 0;2871reflection_probe_render_list.add_last(&reflection_probe->update_list);2872}2873cull_data.cull->lock.unlock();28742875idata.flags &= ~InstanceData::FLAG_REFLECTION_PROBE_DIRTY;2876}28772878if (RSG::light_storage->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {2879cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));2880}2881}2882} else if (base_type == RS::INSTANCE_DECAL) {2883cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid));28842885} else if (base_type == RS::INSTANCE_VOXEL_GI) {2886InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(idata.instance->base_data);2887cull_data.cull->lock.lock();2888if (!voxel_gi->update_element.in_list()) {2889voxel_gi_update_list.add(&voxel_gi->update_element);2890}2891cull_data.cull->lock.unlock();2892cull_result.voxel_gi_instances.push_back(RID::from_uint64(idata.instance_data_rid));28932894} else if (base_type == RS::INSTANCE_LIGHTMAP) {2895cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));2896} else if (base_type == RS::INSTANCE_FOG_VOLUME) {2897cull_result.fog_volumes.push_back(RID::from_uint64(idata.instance_data_rid));2898} else if (base_type == RS::INSTANCE_VISIBLITY_NOTIFIER) {2899InstanceVisibilityNotifierData *vnd = idata.visibility_notifier;2900if (!vnd->list_element.in_list()) {2901visible_notifier_list_lock.lock();2902visible_notifier_list.add(&vnd->list_element);2903visible_notifier_list_lock.unlock();2904vnd->just_visible = true;2905}2906vnd->visible_in_frame = RSG::rasterizer->get_frame_number();2907} else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {2908bool keep = true;29092910if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {2911RenderingServerDefault::redraw_request();2912}29132914if (base_type == RS::INSTANCE_MESH) {2915mesh_visible = true;2916} else if (base_type == RS::INSTANCE_PARTICLES) {2917//particles visible? process them2918if (RSG::particles_storage->particles_is_inactive(idata.base_rid)) {2919//but if nothing is going on, don't do it.2920keep = false;2921} else {2922cull_data.cull->lock.lock();2923RSG::particles_storage->particles_request_process(idata.base_rid);2924cull_data.cull->lock.unlock();29252926RS::get_singleton()->call_on_render_thread(callable_mp_static(&RendererSceneCull::_scene_particles_set_view_axis).bind(idata.base_rid, -cull_data.cam_transform.basis.get_column(2).normalized(), cull_data.cam_transform.basis.get_column(1).normalized()));2927//particles visible? request redraw2928RenderingServerDefault::redraw_request();2929}2930}29312932if (idata.parent_array_index != -1) {2933float fade = 1.0f;2934const uint32_t &parent_flags = cull_data.scenario->instance_data[idata.parent_array_index].flags;2935if (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN) {2936const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index;2937fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha;2938}2939idata.instance_geometry->set_parent_fade_alpha(fade);2940}29412942if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {2943InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);2944ERR_FAIL_NULL(geom->geometry_instance);2945// Clear any existing light instances for this mesh and find the max count per-mesh, and total (per-scene).2946geom->geometry_instance->clear_light_instances();2947if ((max_lights_per_mesh > 0) && (max_lights_total > 0)) {2948// For the top N lights, track the score and the index into the internal light storage array.2949uint32_t total_omni_count = 0, total_spot_count = 0;2950bool omni_needs_heap = true, spot_needs_heap = true;2951uint32_t omni_count = 0, spot_count = 0;2952omni_score_idx.clear();2953spot_score_idx.clear();2954SortArray<Pair<float, uint32_t>> heapify; // SortArray has heap functions, but no local storage.2955// Iterate over the lights (possibly > max_renderable_lights), keeping the closest to the mesh center.2956Vector3 mesh_center = idata.instance->transformed_aabb.get_center();2957for (const Instance *E : geom->lights) {2958RS::LightType light_type = RSG::light_storage->light_get_type(E->base);2959if (((RS::LIGHT_OMNI == light_type) && (total_omni_count++ < max_lights_total)) ||2960((RS::LIGHT_SPOT == light_type) && (total_spot_count++ < max_lights_total))) {2961// Perform culling.2962if (!(RSG::light_storage->light_get_cull_mask(E->base) & idata.layer_mask)) {2963continue;2964}2965if ((RSG::light_storage->light_get_bake_mode(E->base) == RS::LIGHT_BAKE_STATIC) && idata.instance->lightmap) {2966continue;2967}29682969InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);2970// Large scores are worse, so linear with distance, inverse with energy and range.2971Vector3 light_center = E->transformed_aabb.get_center();2972float light_range_energy =2973RSG::light_storage->light_get_param(E->base, RS::LightParam::LIGHT_PARAM_RANGE) *2974RSG::light_storage->light_get_param(E->base, RS::LightParam::LIGHT_PARAM_ENERGY);2975float light_inst_score = mesh_center.distance_to(light_center) / MAX(0.01f, light_range_energy);2976// Of the N lights (on a per-light-type basis, Omni or Spot) keep only the M "best" lights.2977// If N <= M, we can simply store the lights, but once we exceed M, we need check each new2978// light and see if it's score is better than the worst light stored to date. If the new2979// light is better, we can replace the current worst light with the new one. In order to2980// efficiently track our currently worst light we use a "max heap". This loosely orders2981// the elements in an array as a binary-tree structure, and has the properties that finding2982// the worst score element is O(1) (it will always be stored in element [0]), and removing2983// the old max and inserting a new value is O(log M).2984#define VERIFY_RELEVANT_LIGHT_HEAP 02985#if VERIFY_RELEVANT_LIGHT_HEAP2986WARN_PRINT_ONCE("VERIFY_RELEVANT_LIGHT_HEAP is True");2987#endif2988switch (light_type) {2989case RS::LIGHT_OMNI: {2990if (omni_count < max_lights_per_mesh) {2991// We have room to just add it, and track the score and where it goes.2992omni_score_idx.push_back(Pair(light_inst_score, omni_count));2993geom->geometry_instance->pair_light_instance(light->instance, light_type, omni_count++);2994} else {2995if (omni_needs_heap) {2996// We need to make this a heap one time.2997heapify.make_heap(0, omni_count, &omni_score_idx[0]);2998omni_needs_heap = false;2999}3000if (light_inst_score < omni_score_idx[0].first) {3001#if VERIFY_RELEVANT_LIGHT_HEAP3002// The [0] element should have the max score.3003for (uint32_t vi = 1; vi < max_lights_per_mesh; ++vi) {3004if (omni_score_idx[vi].first > omni_score_idx[0].first) {3005ERR_PRINT_ONCE("Relevant Omni Light Heap Error");3006}3007}3008#endif3009uint32_t replace_index = omni_score_idx[0].second;3010geom->geometry_instance->pair_light_instance(light->instance, light_type, replace_index);3011heapify.adjust_heap(0, 0, omni_count, Pair(light_inst_score, replace_index), &omni_score_idx[0]);3012}3013}3014} break;3015case RS::LIGHT_SPOT: {3016if (spot_count < max_lights_per_mesh) {3017// We have room to just add it, and track the score and where it goes.3018spot_score_idx.push_back(Pair(light_inst_score, spot_count));3019geom->geometry_instance->pair_light_instance(light->instance, light_type, spot_count++);3020} else {3021if (spot_needs_heap) {3022// We need to make this a heap one time.3023heapify.make_heap(0, spot_count, &spot_score_idx[0]);3024spot_needs_heap = false;3025}3026if (light_inst_score < spot_score_idx[0].first) {3027#if VERIFY_RELEVANT_LIGHT_HEAP3028// The [0] element should have the max score.3029for (uint32_t vi = 1; vi < max_lights_per_mesh; ++vi) {3030if (spot_score_idx[vi].first > spot_score_idx[0].first) {3031ERR_PRINT_ONCE("Relevant Spot Light Heap Error");3032}3033}3034#endif3035uint32_t replace_index = spot_score_idx[0].second;3036geom->geometry_instance->pair_light_instance(light->instance, light_type, replace_index);3037heapify.adjust_heap(0, 0, spot_count, Pair(light_inst_score, replace_index), &spot_score_idx[0]);3038}3039}3040} break;3041default:3042break;3043}3044}3045}3046}3047idata.flags &= ~InstanceData::FLAG_GEOM_LIGHTING_DIRTY;3048}30493050if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {3051InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);30523053ERR_FAIL_NULL(geom->geometry_instance);3054cull_data.cull->lock.lock();3055geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0);3056cull_data.cull->lock.unlock();3057idata.flags &= ~InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;3058}30593060if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {3061InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);3062uint32_t idx = 0;30633064for (const Instance *E : geom->reflection_probes) {3065InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->base_data);30663067instance_pair_buffer[idx++] = reflection_probe->instance;3068if (idx == MAX_INSTANCE_PAIRS) {3069break;3070}3071}30723073ERR_FAIL_NULL(geom->geometry_instance);3074geom->geometry_instance->pair_reflection_probe_instances(instance_pair_buffer, idx);3075idata.flags &= ~InstanceData::FLAG_GEOM_REFLECTION_DIRTY;3076}30773078if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {3079InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);3080uint32_t idx = 0;30813082for (const Instance *E : geom->decals) {3083InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->base_data);30843085instance_pair_buffer[idx++] = decal->instance;3086if (idx == MAX_INSTANCE_PAIRS) {3087break;3088}3089}30903091ERR_FAIL_NULL(geom->geometry_instance);3092geom->geometry_instance->pair_decal_instances(instance_pair_buffer, idx);30933094idata.flags &= ~InstanceData::FLAG_GEOM_DECAL_DIRTY;3095}30963097if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) {3098InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);3099uint32_t idx = 0;3100for (const Instance *E : geom->voxel_gi_instances) {3101InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->base_data);31023103instance_pair_buffer[idx++] = voxel_gi->probe_instance;3104if (idx == MAX_INSTANCE_PAIRS) {3105break;3106}3107}31083109ERR_FAIL_NULL(geom->geometry_instance);3110geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);31113112idata.flags &= ~InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;3113}31143115if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {3116InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);3117Color *sh = idata.instance->lightmap_sh.ptrw();3118const Color *target_sh = idata.instance->lightmap_target_sh.ptr();3119for (uint32_t j = 0; j < 9; j++) {3120sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));3121}3122ERR_FAIL_NULL(geom->geometry_instance);3123cull_data.cull->lock.lock();3124geom->geometry_instance->set_lightmap_capture(sh);3125cull_data.cull->lock.unlock();3126idata.instance->last_frame_pass = frame_number;3127}31283129if (keep) {3130cull_result.geometry_instances.push_back(idata.instance_geometry);3131}3132}3133}31343135for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) {3136for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) {3137if (!light_culler->cull_directional_light(cull_data.scenario->instance_aabbs[i], j, k)) { // pass the cascade index3138continue;3139}3140if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {3141uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;31423143if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && (LAYER_CHECK & cull_data.cull->shadows[j].caster_mask)) {3144cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);3145mesh_visible = true;3146}3147}3148}3149}3150}31513152#undef HIDDEN_BY_VISIBILITY_CHECKS3153#undef LAYER_CHECK3154#undef IN_FRUSTUM3155#undef VIS_RANGE_CHECK3156#undef VIS_PARENT_CHECK3157#undef VIS_CHECK3158#undef OCCLUSION_CULLED31593160for (uint32_t j = 0; j < cull_data.cull->sdfgi.region_count; j++) {3161if (cull_data.scenario->instance_aabbs[i].in_aabb(cull_data.cull->sdfgi.region_aabb[j])) {3162uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;31633164if (base_type == RS::INSTANCE_LIGHT) {3165InstanceLightData *instance_light = (InstanceLightData *)idata.instance->base_data;3166if (instance_light->bake_mode == RS::LIGHT_BAKE_STATIC && cull_data.cull->sdfgi.region_cascade[j] <= instance_light->max_sdfgi_cascade) {3167if (sdfgi_last_light_index != i || sdfgi_last_light_cascade != cull_data.cull->sdfgi.region_cascade[j]) {3168sdfgi_last_light_index = i;3169sdfgi_last_light_cascade = cull_data.cull->sdfgi.region_cascade[j];3170cull_result.sdfgi_cascade_lights[sdfgi_last_light_cascade].push_back(instance_light->instance);3171}3172}3173} else if ((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) {3174if (idata.flags & InstanceData::FLAG_USES_BAKED_LIGHT) {3175cull_result.sdfgi_region_geometry_instances[j].push_back(idata.instance_geometry);3176mesh_visible = true;3177}3178}3179}3180}31813182if (mesh_visible && cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_USES_MESH_INSTANCE) {3183cull_result.mesh_instances.push_back(cull_data.scenario->instance_data[i].instance->mesh_instance);3184}3185}3186}31873188void RendererSceneCull::_scene_particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {3189RSG::particles_storage->particles_set_view_axis(p_particles, p_axis, p_up_axis);3190}31913192void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, RID p_compositor, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RenderingMethod::RenderInfo *r_render_info) {3193Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it31943195// Prepare the light - camera volume culling system.3196light_culler->prepare_camera(p_camera_data->main_transform, p_camera_data->main_projection);31973198Scenario *scenario = scenario_owner.get_or_null(p_scenario);3199Vector3 camera_position = p_camera_data->main_transform.origin;32003201ERR_FAIL_COND(p_render_buffers.is_null());32023203render_pass++;32043205scene_render->set_scene_pass(render_pass);32063207if (p_reflection_probe.is_null()) {3208//no rendering code here, this is only to set up what needs to be done, request regions, etc.3209scene_render->sdfgi_update(p_render_buffers, p_environment, camera_position); //update conditions for SDFGI (whether its used or not)3210}32113212RENDER_TIMESTAMP("Update Visibility Dependencies");32133214if (scenario->instance_visibility.get_bin_count() > 0) {3215if (!scenario->viewport_visibility_masks.has(p_viewport)) {3216scenario_add_viewport_visibility_mask(scenario->self, p_viewport);3217}32183219VisibilityCullData visibility_cull_data;3220visibility_cull_data.scenario = scenario;3221visibility_cull_data.viewport_mask = scenario->viewport_visibility_masks[p_viewport];3222visibility_cull_data.camera_position = camera_position;32233224for (int i = scenario->instance_visibility.get_bin_count() - 1; i > 0; i--) { // We skip bin 03225visibility_cull_data.cull_offset = scenario->instance_visibility.get_bin_start(i);3226visibility_cull_data.cull_count = scenario->instance_visibility.get_bin_size(i);32273228if (visibility_cull_data.cull_count == 0) {3229continue;3230}32313232if (visibility_cull_data.cull_count > thread_cull_threshold) {3233WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data, WorkerThreadPool::get_singleton()->get_thread_count(), -1, true, SNAME("VisibilityCullInstances"));3234WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);3235} else {3236_visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count);3237}3238}3239}32403241RENDER_TIMESTAMP("Cull 3D Scene");32423243//rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_orthogonal);32443245/* STEP 2 - CULL */32463247Vector<Plane> planes = p_camera_data->main_projection.get_projection_planes(p_camera_data->main_transform);3248cull.frustum = Frustum(planes);32493250Vector<RID> directional_lights;3251// directional lights3252{3253cull.shadow_count = 0;32543255Vector<Instance *> lights_with_shadow;32563257for (Instance *E : scenario->directional_lights) {3258if (!E->visible || !(E->layer_mask & p_visible_layers)) {3259continue;3260}32613262if (directional_lights.size() >= RendererSceneRender::MAX_DIRECTIONAL_LIGHTS) {3263break;3264}32653266InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);32673268//check shadow..32693270if (light) {3271if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(E->base) && !(RSG::light_storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(E->base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY)) {3272lights_with_shadow.push_back(E);3273}3274//add to list3275directional_lights.push_back(light->instance);3276}3277}32783279RSG::light_storage->set_directional_shadow_count(lights_with_shadow.size());32803281for (int i = 0; i < lights_with_shadow.size(); i++) {3282_light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect);3283}3284}32853286{ //sdfgi3287cull.sdfgi.region_count = 0;32883289if (p_reflection_probe.is_null()) {3290cull.sdfgi.cascade_light_count = 0;32913292uint32_t prev_cascade = 0xFFFFFFFF;3293uint32_t pending_region_count = scene_render->sdfgi_get_pending_region_count(p_render_buffers);32943295for (uint32_t i = 0; i < pending_region_count; i++) {3296cull.sdfgi.region_aabb[i] = scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i);3297uint32_t region_cascade = scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i);3298cull.sdfgi.region_cascade[i] = region_cascade;32993300if (region_cascade != prev_cascade) {3301cull.sdfgi.cascade_light_index[cull.sdfgi.cascade_light_count] = region_cascade;3302cull.sdfgi.cascade_light_count++;3303prev_cascade = region_cascade;3304}3305}33063307cull.sdfgi.region_count = pending_region_count;3308}3309}33103311scene_cull_result.clear();33123313{3314uint64_t cull_from = 0;3315uint64_t cull_to = scenario->instance_data.size();33163317CullData cull_data;33183319//prepare for eventual thread usage3320cull_data.cull = &cull;3321cull_data.scenario = scenario;3322cull_data.shadow_atlas = p_shadow_atlas;3323cull_data.cam_transform = p_camera_data->main_transform;3324cull_data.visible_layers = p_visible_layers;3325cull_data.render_reflection_probe = render_reflection_probe;3326cull_data.occlusion_buffer = RendererSceneOcclusionCull::get_singleton()->buffer_get_ptr(p_viewport);3327cull_data.camera_matrix = &p_camera_data->main_projection;3328cull_data.visibility_viewport_mask = scenario->viewport_visibility_masks.has(p_viewport) ? scenario->viewport_visibility_masks[p_viewport] : 0;3329//#define DEBUG_CULL_TIME3330#ifdef DEBUG_CULL_TIME3331uint64_t time_from = OS::get_singleton()->get_ticks_usec();3332#endif33333334if (cull_to > thread_cull_threshold) {3335//multiple threads3336for (InstanceCullResult &thread : scene_cull_result_threads) {3337thread.clear();3338}33393340WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances"));3341WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);33423343for (InstanceCullResult &thread : scene_cull_result_threads) {3344scene_cull_result.append_from(thread);3345}33463347} else {3348//single threaded3349_scene_cull(cull_data, scene_cull_result, cull_from, cull_to);3350}33513352#ifdef DEBUG_CULL_TIME3353static float time_avg = 0;3354static uint32_t time_count = 0;3355time_avg += double(OS::get_singleton()->get_ticks_usec() - time_from) / 1000.0;3356time_count++;3357print_line("time taken: " + rtos(time_avg / time_count));3358#endif33593360if (scene_cull_result.mesh_instances.size()) {3361for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) {3362RSG::mesh_storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);3363}3364RSG::mesh_storage->update_mesh_instances();3365}3366}33673368//render shadows33693370max_shadows_used = 0;33713372if (p_using_shadows) { //setup shadow maps33733374// Directional Shadows33753376for (uint32_t i = 0; i < cull.shadow_count; i++) {3377for (uint32_t j = 0; j < cull.shadows[i].cascade_count; j++) {3378const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j];3379// print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size()));3380RSG::light_storage->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale);3381if (max_shadows_used == MAX_UPDATE_SHADOWS) {3382continue;3383}3384render_shadow_data[max_shadows_used].light = cull.shadows[i].light_instance;3385render_shadow_data[max_shadows_used].pass = j;3386render_shadow_data[max_shadows_used].instances.merge_unordered(scene_cull_result.directional_shadows[i].cascade_geometry_instances[j]);3387max_shadows_used++;3388}3389}33903391// Positional Shadows3392for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) {3393Instance *ins = scene_cull_result.lights[i];33943395if (!p_shadow_atlas.is_valid()) {3396continue;3397}33983399InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);34003401if (!RSG::light_storage->light_instance_is_shadow_visible_at_position(light->instance, camera_position)) {3402continue;3403}34043405float coverage = 0.f;34063407{ //compute coverage34083409Transform3D cam_xf = p_camera_data->main_transform;3410float zn = p_camera_data->main_projection.get_z_near();3411Plane p(-cam_xf.basis.get_column(2), cam_xf.origin + cam_xf.basis.get_column(2) * -zn); //camera near plane34123413// near plane half width and height3414Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();34153416switch (RSG::light_storage->light_get_type(ins->base)) {3417case RS::LIGHT_OMNI: {3418float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);34193420//get two points parallel to near plane3421Vector3 points[2] = {3422ins->transform.origin,3423ins->transform.origin + cam_xf.basis.get_column(0) * radius3424};34253426if (!p_camera_data->is_orthogonal) {3427//if using perspetive, map them to near plane3428for (int j = 0; j < 2; j++) {3429if (p.distance_to(points[j]) < 0) {3430points[j].z = -zn; //small hack to keep size constant when hitting the screen3431}34323433p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane3434}3435}34363437float screen_diameter = points[0].distance_to(points[1]) * 2;3438coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);3439} break;3440case RS::LIGHT_SPOT: {3441float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);3442float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);34433444float w = radius * Math::sin(Math::deg_to_rad(angle));3445float d = radius * Math::cos(Math::deg_to_rad(angle));34463447Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d;34483449Vector3 points[2] = {3450base,3451base + cam_xf.basis.get_column(0) * w3452};34533454if (!p_camera_data->is_orthogonal) {3455//if using perspetive, map them to near plane3456for (int j = 0; j < 2; j++) {3457if (p.distance_to(points[j]) < 0) {3458points[j].z = -zn; //small hack to keep size constant when hitting the screen3459}34603461p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane3462}3463}34643465float screen_diameter = points[0].distance_to(points[1]) * 2;3466coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);34673468} break;3469default: {3470ERR_PRINT("Invalid Light Type");3471}3472}3473}34743475// We can detect whether multiple cameras are hitting this light, whether or not the shadow is dirty,3476// so that we can turn off tighter caster culling.3477light->detect_light_intersects_multiple_cameras(Engine::get_singleton()->get_frames_drawn());34783479if (light->is_shadow_dirty()) {3480// Dirty shadows have no need to be drawn if3481// the light volume doesn't intersect the camera frustum.34823483// Returns false if the entire light can be culled.3484bool allow_redraw = light_culler->prepare_regular_light(*ins);34853486// Directional lights aren't handled here, _light_instance_update_shadow is called from elsewhere.3487// Checking for this in case this changes, as this is assumed.3488DEV_CHECK_ONCE(RSG::light_storage->light_get_type(ins->base) != RS::LIGHT_DIRECTIONAL);34893490// Tighter caster culling to the camera frustum should work correctly with multiple viewports + cameras.3491// The first camera will cull tightly, but if the light is present on more than 1 camera, the second will3492// do a full render, and mark the light as non-dirty.3493// There is however a cost to tighter shadow culling in this situation (2 shadow updates in 1 frame),3494// so we should detect this and switch off tighter caster culling automatically.3495// This is done in the logic for `decrement_shadow_dirty()`.3496if (allow_redraw) {3497light->last_version++;3498light->decrement_shadow_dirty();3499}3500}35013502bool redraw = RSG::light_storage->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);35033504if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {3505//must redraw!3506RENDER_TIMESTAMP("> Render Light3D " + itos(i));3507if (_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)) {3508light->make_shadow_dirty();3509}3510RENDER_TIMESTAMP("< Render Light3D " + itos(i));3511} else {3512if (redraw) {3513light->make_shadow_dirty();3514}3515}3516}3517}35183519//render SDFGI35203521{3522// Q: Should this whole block be skipped if we're rendering our reflection probe?35233524sdfgi_update_data.update_static = false;35253526if (cull.sdfgi.region_count > 0) {3527//update regions3528for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {3529render_sdfgi_data[i].instances.merge_unordered(scene_cull_result.sdfgi_region_geometry_instances[i]);3530render_sdfgi_data[i].region = i;3531}3532//check if static lights were culled3533bool static_lights_culled = false;3534for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) {3535if (scene_cull_result.sdfgi_cascade_lights[i].size()) {3536static_lights_culled = true;3537break;3538}3539}35403541if (static_lights_culled) {3542sdfgi_update_data.static_cascade_count = cull.sdfgi.cascade_light_count;3543sdfgi_update_data.static_cascade_indices = cull.sdfgi.cascade_light_index;3544sdfgi_update_data.static_positional_lights = scene_cull_result.sdfgi_cascade_lights;3545sdfgi_update_data.update_static = true;3546}3547}35483549if (p_reflection_probe.is_null()) {3550sdfgi_update_data.directional_lights = &directional_lights;3551sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr();3552sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size();3553}3554}35553556//append the directional lights to the lights culled3557for (int i = 0; i < directional_lights.size(); i++) {3558scene_cull_result.light_instances.push_back(directional_lights[i]);3559}35603561RID camera_attributes;3562if (p_force_camera_attributes.is_valid()) {3563camera_attributes = p_force_camera_attributes;3564} else {3565camera_attributes = scenario->camera_attributes;3566}35673568/* PROCESS GEOMETRY AND DRAW SCENE */35693570RID occluders_tex;3571const RendererSceneRender::CameraData *prev_camera_data = p_camera_data;3572if (p_viewport.is_valid()) {3573occluders_tex = RSG::viewport->viewport_get_occluder_debug_texture(p_viewport);3574prev_camera_data = RSG::viewport->viewport_get_prev_camera_data(p_viewport);3575}35763577RENDER_TIMESTAMP("Render 3D Scene");3578scene_render->render_scene(p_render_buffers, p_camera_data, prev_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_attributes, p_compositor, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);35793580if (p_viewport.is_valid()) {3581RSG::viewport->viewport_set_prev_camera_data(p_viewport, p_camera_data);3582}35833584for (uint32_t i = 0; i < max_shadows_used; i++) {3585render_shadow_data[i].instances.clear();3586}3587max_shadows_used = 0;35883589for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {3590render_sdfgi_data[i].instances.clear();3591}3592}35933594RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {3595Camera *camera = camera_owner.get_or_null(p_camera);3596if (camera && scene_render->is_environment(camera->env)) {3597return camera->env;3598}35993600Scenario *scenario = scenario_owner.get_or_null(p_scenario);3601if (!scenario) {3602return RID();3603}3604if (scene_render->is_environment(scenario->environment)) {3605return scenario->environment;3606}36073608if (scene_render->is_environment(scenario->fallback_environment)) {3609return scenario->fallback_environment;3610}36113612return RID();3613}36143615RID RendererSceneCull::_render_get_compositor(RID p_camera, RID p_scenario) {3616Camera *camera = camera_owner.get_or_null(p_camera);3617if (camera && scene_render->is_compositor(camera->compositor)) {3618return camera->compositor;3619}36203621Scenario *scenario = scenario_owner.get_or_null(p_scenario);3622if (scenario && scene_render->is_compositor(scenario->compositor)) {3623return scenario->compositor;3624}36253626return RID();3627}36283629void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) {3630#ifndef _3D_DISABLED3631Scenario *scenario = scenario_owner.get_or_null(p_scenario);36323633RID environment;3634if (scenario->environment.is_valid()) {3635environment = scenario->environment;3636} else {3637environment = scenario->fallback_environment;3638}3639RID compositor = scenario->compositor;3640RENDER_TIMESTAMP("Render Empty 3D Scene");36413642RendererSceneRender::CameraData camera_data;3643camera_data.set_camera(Transform3D(), Projection(), true, false, false);36443645scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), environment, RID(), compositor, p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);3646#endif3647}36483649bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int p_step) {3650InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);3651Scenario *scenario = p_instance->scenario;3652ERR_FAIL_NULL_V(scenario, true);36533654RenderingServerDefault::redraw_request(); //update, so it updates in editor36553656if (p_step == 0) {3657if (!RSG::light_storage->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {3658return true; // All full, no atlas entry to render to.3659}3660} else if (!RSG::light_storage->reflection_probe_has_atlas_index(reflection_probe->instance)) {3661// We don't have an atlas to render to, just round off.3662// This is likely due to the atlas being reset.3663// If so the probe will be marked as dirty and start over.3664return true;3665}36663667if (p_step == 0) {3668static const Vector3 view_normals[6] = {3669Vector3(+1, 0, 0),3670Vector3(-1, 0, 0),3671Vector3(0, +1, 0),3672Vector3(0, -1, 0),3673Vector3(0, 0, +1),3674Vector3(0, 0, -1)3675};3676static const Vector3 view_up[6] = {3677Vector3(0, -1, 0),3678Vector3(0, -1, 0),3679Vector3(0, 0, +1),3680Vector3(0, 0, -1),3681Vector3(0, -1, 0),3682Vector3(0, -1, 0)3683};36843685Vector3 probe_size = RSG::light_storage->reflection_probe_get_size(p_instance->base);3686Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base);3687float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base);3688float atlas_size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas);3689float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / atlas_size;3690bool use_shadows = RSG::light_storage->reflection_probe_renders_shadows(p_instance->base);3691RID shadow_atlas = use_shadows ? scenario->reflection_probe_shadow_atlas : RID();3692RID environment = scenario->environment.is_valid() ? scenario->environment : scenario->fallback_environment;3693Ref<RenderSceneBuffers> render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas);3694for (uint32_t face = 0; face < 6; face++) {3695// Compute distance from origin offset to the actual view distance limit.3696Vector3 edge = view_normals[face] * probe_size / 2;3697float distance = Math::abs(view_normals[face].dot(edge) - view_normals[face].dot(origin_offset));3698max_distance = MAX(max_distance, distance);36993700// Render cubemap side.3701Projection cm;3702cm.set_perspective(90, 1, 0.01, max_distance);37033704Transform3D local_view;3705local_view.set_look_at(origin_offset, origin_offset + view_normals[face], view_up[face]);37063707RendererSceneRender::CameraData camera_data;3708Transform3D xform = p_instance->transform * local_view;3709camera_data.set_camera(xform, cm, false, false, false);37103711RENDER_TIMESTAMP("Render ReflectionProbe, Face " + itos(face));3712_render_scene(&camera_data, render_buffers, environment, RID(), RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, face, mesh_lod_threshold, use_shadows);3713}37143715RSG::light_storage->reflection_probe_instance_end_render(reflection_probe->instance, scenario->reflection_atlas);3716} else {3717// Do roughness postprocess step until it believes it's done.3718RENDER_TIMESTAMP("Post-Process ReflectionProbe, Step " + itos(p_step));3719return RSG::light_storage->reflection_probe_instance_postprocess_step(reflection_probe->instance);3720}37213722return false;3723}37243725void RendererSceneCull::render_probes() {3726/* REFLECTION PROBES */37273728SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();3729Vector<SelfList<InstanceReflectionProbeData> *> done_list;37303731bool busy = false;37323733if (ref_probe) {3734RENDER_TIMESTAMP("Render ReflectionProbes");37353736while (ref_probe) {3737SelfList<InstanceReflectionProbeData> *next = ref_probe->next();3738RID base = ref_probe->self()->owner->base;37393740switch (RSG::light_storage->reflection_probe_get_update_mode(base)) {3741case RS::REFLECTION_PROBE_UPDATE_ONCE: {3742if (busy) { // Already rendering something.3743break;3744}37453746bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);3747if (done) {3748done_list.push_back(ref_probe);3749} else {3750ref_probe->self()->render_step++;3751}37523753busy = true; // Do not render another one of this kind.3754} break;3755case RS::REFLECTION_PROBE_UPDATE_ALWAYS: {3756int step = 0;3757bool done = false;3758while (!done) {3759done = _render_reflection_probe_step(ref_probe->self()->owner, step);3760step++;3761}37623763done_list.push_back(ref_probe);3764} break;3765}37663767ref_probe = next;3768}37693770// Now remove from our list3771for (SelfList<InstanceReflectionProbeData> *rp : done_list) {3772reflection_probe_render_list.remove(rp);3773}3774}37753776/* VOXEL GIS */37773778SelfList<InstanceVoxelGIData> *voxel_gi = voxel_gi_update_list.first();37793780if (voxel_gi) {3781RENDER_TIMESTAMP("Render VoxelGI");3782}37833784while (voxel_gi) {3785SelfList<InstanceVoxelGIData> *next = voxel_gi->next();37863787InstanceVoxelGIData *probe = voxel_gi->self();3788//Instance *instance_probe = probe->owner;37893790//check if probe must be setup, but don't do if on the lighting thread37913792bool cache_dirty = false;3793int cache_count = 0;3794{3795int light_cache_size = probe->light_cache.size();3796const InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptr();3797const RID *instance_caches = probe->light_instances.ptr();37983799int idx = 0; //must count visible lights3800for (Instance *E : probe->lights) {3801Instance *instance = E;3802InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3803if (!instance->visible) {3804continue;3805}3806if (cache_dirty) {3807//do nothing, since idx must count all visible lights anyway3808} else if (idx >= light_cache_size) {3809cache_dirty = true;3810} else {3811const InstanceVoxelGIData::LightCache *cache = &caches[idx];38123813if (3814instance_caches[idx] != instance_light->instance ||3815cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||3816cache->type != RSG::light_storage->light_get_type(instance->base) ||3817cache->transform != instance->transform ||3818cache->color != RSG::light_storage->light_get_color(instance->base) ||3819cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||3820cache->intensity != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY) ||3821cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||3822cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||3823cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||3824cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||3825cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {3826cache_dirty = true;3827}3828}38293830idx++;3831}38323833for (const Instance *instance : probe->owner->scenario->directional_lights) {3834InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3835if (!instance->visible) {3836continue;3837}3838if (cache_dirty) {3839//do nothing, since idx must count all visible lights anyway3840} else if (idx >= light_cache_size) {3841cache_dirty = true;3842} else {3843const InstanceVoxelGIData::LightCache *cache = &caches[idx];38443845if (3846instance_caches[idx] != instance_light->instance ||3847cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||3848cache->type != RSG::light_storage->light_get_type(instance->base) ||3849cache->transform != instance->transform ||3850cache->color != RSG::light_storage->light_get_color(instance->base) ||3851cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||3852cache->intensity != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY) ||3853cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||3854cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||3855cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||3856cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||3857cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||3858cache->sky_mode != RSG::light_storage->light_directional_get_sky_mode(instance->base)) {3859cache_dirty = true;3860}3861}38623863idx++;3864}38653866if (idx != light_cache_size) {3867cache_dirty = true;3868}38693870cache_count = idx;3871}38723873bool update_lights = scene_render->voxel_gi_needs_update(probe->probe_instance);38743875if (cache_dirty) {3876probe->light_cache.resize(cache_count);3877probe->light_instances.resize(cache_count);38783879if (cache_count) {3880InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptrw();3881RID *instance_caches = probe->light_instances.ptrw();38823883int idx = 0; //must count visible lights3884for (Instance *E : probe->lights) {3885Instance *instance = E;3886InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3887if (!instance->visible) {3888continue;3889}38903891InstanceVoxelGIData::LightCache *cache = &caches[idx];38923893instance_caches[idx] = instance_light->instance;3894cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);3895cache->type = RSG::light_storage->light_get_type(instance->base);3896cache->transform = instance->transform;3897cache->color = RSG::light_storage->light_get_color(instance->base);3898cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);3899cache->intensity = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY);3900cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);3901cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);3902cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);3903cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);3904cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);39053906idx++;3907}3908for (const Instance *instance : probe->owner->scenario->directional_lights) {3909InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3910if (!instance->visible) {3911continue;3912}39133914InstanceVoxelGIData::LightCache *cache = &caches[idx];39153916instance_caches[idx] = instance_light->instance;3917cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);3918cache->type = RSG::light_storage->light_get_type(instance->base);3919cache->transform = instance->transform;3920cache->color = RSG::light_storage->light_get_color(instance->base);3921cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);3922cache->intensity = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY);3923cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);3924cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);3925cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);3926cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);3927cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);3928cache->sky_mode = RSG::light_storage->light_directional_get_sky_mode(instance->base);39293930idx++;3931}3932}39333934update_lights = true;3935}39363937scene_cull_result.geometry_instances.clear();39383939RID instance_pair_buffer[MAX_INSTANCE_PAIRS];39403941for (Instance *E : probe->dynamic_geometries) {3942Instance *ins = E;3943if (!ins->visible) {3944continue;3945}3946InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;39473948if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY)) {3949uint32_t idx = 0;3950for (const Instance *F : geom->voxel_gi_instances) {3951InstanceVoxelGIData *voxel_gi2 = static_cast<InstanceVoxelGIData *>(F->base_data);39523953instance_pair_buffer[idx++] = voxel_gi2->probe_instance;3954if (idx == MAX_INSTANCE_PAIRS) {3955break;3956}3957}39583959ERR_FAIL_NULL(geom->geometry_instance);3960geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);39613962ins->scenario->instance_data[ins->array_index].flags &= ~InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;3963}39643965ERR_FAIL_NULL(geom->geometry_instance);3966scene_cull_result.geometry_instances.push_back(geom->geometry_instance);3967}39683969scene_render->voxel_gi_update(probe->probe_instance, update_lights, probe->light_instances, scene_cull_result.geometry_instances);39703971voxel_gi_update_list.remove(voxel_gi);39723973voxel_gi = next;3974}3975}39763977void RendererSceneCull::render_particle_colliders() {3978while (heightfield_particle_colliders_update_list.begin()) {3979Instance *hfpc = *heightfield_particle_colliders_update_list.begin();39803981if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::particles_storage->particles_collision_is_heightfield(hfpc->base)) {3982//update heightfield3983instance_cull_result.clear();3984scene_cull_result.geometry_instances.clear();39853986struct CullAABB {3987PagedArray<Instance *> *result;3988uint32_t heightfield_mask;3989_FORCE_INLINE_ bool operator()(void *p_data) {3990Instance *p_instance = (Instance *)p_data;3991if (p_instance->layer_mask & heightfield_mask) {3992result->push_back(p_instance);3993}3994return false;3995}3996};39973998CullAABB cull_aabb;3999cull_aabb.result = &instance_cull_result;4000cull_aabb.heightfield_mask = RSG::particles_storage->particles_collision_get_height_field_mask(hfpc->base);4001hfpc->scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(hfpc->transformed_aabb, cull_aabb);4002hfpc->scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(hfpc->transformed_aabb, cull_aabb);40034004for (int i = 0; i < (int)instance_cull_result.size(); i++) {4005Instance *instance = instance_cull_result[i];4006if (!instance || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision4007continue;4008}4009InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);4010ERR_FAIL_NULL(geom->geometry_instance);4011scene_cull_result.geometry_instances.push_back(geom->geometry_instance);4012}40134014scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, scene_cull_result.geometry_instances);4015}4016heightfield_particle_colliders_update_list.remove(heightfield_particle_colliders_update_list.begin());4017}4018}40194020void RendererSceneCull::_update_dirty_instance(Instance *p_instance) const {4021if (p_instance->update_aabb) {4022_update_instance_aabb(p_instance);4023}40244025if (p_instance->update_dependencies) {4026p_instance->dependency_tracker.update_begin();40274028if (p_instance->base.is_valid()) {4029RSG::utilities->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);4030}40314032if (p_instance->material_override.is_valid()) {4033RSG::material_storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);4034}40354036if (p_instance->material_overlay.is_valid()) {4037RSG::material_storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);4038}40394040if (p_instance->base_type == RS::INSTANCE_MESH) {4041//remove materials no longer used and un-own them40424043int new_mat_count = RSG::mesh_storage->mesh_get_surface_count(p_instance->base);4044p_instance->materials.resize(new_mat_count);40454046_instance_update_mesh_instance(p_instance);4047}40484049if (p_instance->base_type == RS::INSTANCE_PARTICLES) {4050// update the process material dependency40514052RID particle_material = RSG::particles_storage->particles_get_process_material(p_instance->base);4053if (particle_material.is_valid()) {4054RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);4055}4056}40574058if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {4059InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);40604061bool can_cast_shadows = true;4062bool is_animated = false;40634064p_instance->instance_uniforms.materials_start();40654066if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {4067can_cast_shadows = false;4068}40694070if (p_instance->material_override.is_valid()) {4071if (!RSG::material_storage->material_casts_shadows(p_instance->material_override)) {4072can_cast_shadows = false;4073}4074is_animated = RSG::material_storage->material_is_animated(p_instance->material_override);4075p_instance->instance_uniforms.materials_append(p_instance->material_override);4076} else {4077if (p_instance->base_type == RS::INSTANCE_MESH) {4078RID mesh = p_instance->base;40794080if (mesh.is_valid()) {4081bool cast_shadows = false;40824083for (int i = 0; i < p_instance->materials.size(); i++) {4084RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::mesh_storage->mesh_surface_get_material(mesh, i);40854086if (!mat.is_valid()) {4087cast_shadows = true;4088} else {4089if (RSG::material_storage->material_casts_shadows(mat)) {4090cast_shadows = true;4091}40924093if (RSG::material_storage->material_is_animated(mat)) {4094is_animated = true;4095}40964097p_instance->instance_uniforms.materials_append(mat);40984099RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);4100}4101}41024103if (!cast_shadows) {4104can_cast_shadows = false;4105}4106}41074108} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {4109RID mesh = RSG::mesh_storage->multimesh_get_mesh(p_instance->base);4110if (mesh.is_valid()) {4111bool cast_shadows = false;41124113int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);4114for (int i = 0; i < sc; i++) {4115RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, i);41164117if (!mat.is_valid()) {4118cast_shadows = true;41194120} else {4121if (RSG::material_storage->material_casts_shadows(mat)) {4122cast_shadows = true;4123}4124if (RSG::material_storage->material_is_animated(mat)) {4125is_animated = true;4126}41274128p_instance->instance_uniforms.materials_append(mat);41294130RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);4131}4132}41334134if (!cast_shadows) {4135can_cast_shadows = false;4136}41374138RSG::utilities->base_update_dependency(mesh, &p_instance->dependency_tracker);4139}4140} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {4141bool cast_shadows = false;41424143int dp = RSG::particles_storage->particles_get_draw_passes(p_instance->base);41444145for (int i = 0; i < dp; i++) {4146RID mesh = RSG::particles_storage->particles_get_draw_pass_mesh(p_instance->base, i);4147if (!mesh.is_valid()) {4148continue;4149}41504151int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);4152for (int j = 0; j < sc; j++) {4153RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, j);41544155if (!mat.is_valid()) {4156cast_shadows = true;4157} else {4158if (RSG::material_storage->material_casts_shadows(mat)) {4159cast_shadows = true;4160}41614162if (RSG::material_storage->material_is_animated(mat)) {4163is_animated = true;4164}41654166p_instance->instance_uniforms.materials_append(mat);41674168RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);4169}4170}4171}41724173if (!cast_shadows) {4174can_cast_shadows = false;4175}4176}4177}41784179if (p_instance->material_overlay.is_valid()) {4180can_cast_shadows = can_cast_shadows && RSG::material_storage->material_casts_shadows(p_instance->material_overlay);4181is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay);4182p_instance->instance_uniforms.materials_append(p_instance->material_overlay);4183}41844185if (can_cast_shadows != geom->can_cast_shadows) {4186//ability to cast shadows change, let lights now4187for (const Instance *E : geom->lights) {4188InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);4189light->make_shadow_dirty();4190}41914192geom->can_cast_shadows = can_cast_shadows;4193}41944195geom->material_is_animated = is_animated;41964197if (p_instance->instance_uniforms.materials_finish(p_instance->self)) {4198geom->geometry_instance->set_instance_shader_uniforms_offset(p_instance->instance_uniforms.location());4199}4200}42014202if (p_instance->skeleton.is_valid()) {4203RSG::mesh_storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);4204}42054206p_instance->dependency_tracker.update_end();42074208if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {4209InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);4210ERR_FAIL_NULL(geom->geometry_instance);4211geom->geometry_instance->set_surface_materials(p_instance->materials);4212}4213}42144215_instance_update_list.remove(&p_instance->update_item);42164217_update_instance(p_instance);42184219p_instance->teleported = false;4220p_instance->update_aabb = false;4221p_instance->update_dependencies = false;4222}42234224void RendererSceneCull::update_dirty_instances() const {4225while (_instance_update_list.first()) {4226_update_dirty_instance(_instance_update_list.first()->self());4227}42284229// Update dirty resources after dirty instances as instance updates may affect resources.4230RSG::utilities->update_dirty_resources();4231}42324233void RendererSceneCull::update() {4234//optimize bvhs42354236uint32_t rid_count = scenario_owner.get_rid_count();4237RID *rids = (RID *)alloca(sizeof(RID) * rid_count);4238scenario_owner.fill_owned_buffer(rids);4239for (uint32_t i = 0; i < rid_count; i++) {4240Scenario *s = scenario_owner.get_or_null(rids[i]);4241s->indexers[Scenario::INDEXER_GEOMETRY].optimize_incremental(indexer_update_iterations);4242s->indexers[Scenario::INDEXER_VOLUMES].optimize_incremental(indexer_update_iterations);4243}4244scene_render->update();4245update_dirty_instances();4246render_particle_colliders();4247}42484249bool RendererSceneCull::free(RID p_rid) {4250if (p_rid.is_null()) {4251return true;4252}42534254if (scene_render->free(p_rid)) {4255return true;4256}42574258if (camera_owner.owns(p_rid)) {4259camera_owner.free(p_rid);42604261} else if (scenario_owner.owns(p_rid)) {4262Scenario *scenario = scenario_owner.get_or_null(p_rid);42634264while (scenario->instances.first()) {4265instance_set_scenario(scenario->instances.first()->self()->self, RID());4266}4267scenario->instance_aabbs.reset();4268scenario->instance_data.reset();4269scenario->instance_visibility.reset();42704271RSG::light_storage->shadow_atlas_free(scenario->reflection_probe_shadow_atlas);4272RSG::light_storage->reflection_atlas_free(scenario->reflection_atlas);4273scenario_owner.free(p_rid);4274RendererSceneOcclusionCull::get_singleton()->remove_scenario(p_rid);42754276} else if (RendererSceneOcclusionCull::get_singleton() && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_rid)) {4277RendererSceneOcclusionCull::get_singleton()->free_occluder(p_rid);4278} else if (instance_owner.owns(p_rid)) {4279// delete the instance42804281update_dirty_instances();42824283Instance *instance = instance_owner.get_or_null(p_rid);42844285instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0);4286instance_set_scenario(p_rid, RID());4287instance_set_base(p_rid, RID());4288instance_geometry_set_material_override(p_rid, RID());4289instance_geometry_set_material_overlay(p_rid, RID());4290instance_attach_skeleton(p_rid, RID());42914292instance->instance_uniforms.free(instance->self);4293update_dirty_instances(); //in case something changed this42944295instance_owner.free(p_rid);4296} else {4297return false;4298}42994300return true;4301}43024303TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) {4304return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);4305}43064307void RendererSceneCull::update_visibility_notifiers() {4308SelfList<InstanceVisibilityNotifierData> *E = visible_notifier_list.first();4309while (E) {4310SelfList<InstanceVisibilityNotifierData> *N = E->next();43114312InstanceVisibilityNotifierData *visibility_notifier = E->self();4313if (visibility_notifier->just_visible) {4314visibility_notifier->just_visible = false;43154316RSG::utilities->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);4317} else {4318if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {4319visible_notifier_list.remove(E);43204321RSG::utilities->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);4322}4323}43244325E = N;4326}4327}43284329/*******************************/4330/* Passthrough to Scene Render */4331/*******************************/43324333/* ENVIRONMENT API */43344335RendererSceneCull *RendererSceneCull::singleton = nullptr;43364337void RendererSceneCull::set_scene_render(RendererSceneRender *p_scene_render) {4338scene_render = p_scene_render;4339geometry_instance_pair_mask = scene_render->geometry_instance_get_pair_mask();4340}43414342/* INTERPOLATION API */43434344void RendererSceneCull::update_interpolation_tick(bool p_process) {4345// MultiMesh: Update interpolation in storage.4346RSG::mesh_storage->update_interpolation_tick(p_process);4347}43484349void RendererSceneCull::update_interpolation_frame(bool p_process) {4350// MultiMesh: Update interpolation in storage.4351RSG::mesh_storage->update_interpolation_frame(p_process);4352}43534354void RendererSceneCull::set_physics_interpolation_enabled(bool p_enabled) {4355_interpolation_data.interpolation_enabled = p_enabled;4356}43574358RendererSceneCull::RendererSceneCull() {4359render_pass = 1;4360singleton = this;43614362instance_cull_result.set_page_pool(&instance_cull_page_pool);4363instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool);43644365for (uint32_t i = 0; i < MAX_UPDATE_SHADOWS; i++) {4366render_shadow_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);4367}4368for (uint32_t i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {4369render_sdfgi_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);4370}43714372scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);4373scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count());4374for (InstanceCullResult &thread : scene_cull_result_threads) {4375thread.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);4376}43774378indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");4379thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances");4380thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)WorkerThreadPool::get_singleton()->get_thread_count()); //make sure there is at least one thread per CPU4381RendererSceneOcclusionCull::HZBuffer::occlusion_jitter_enabled = GLOBAL_GET("rendering/occlusion_culling/jitter_projection");43824383dummy_occlusion_culling = memnew(RendererSceneOcclusionCull);43844385light_culler = memnew(RenderingLightCuller);43864387bool tighter_caster_culling = GLOBAL_DEF("rendering/lights_and_shadows/tighter_shadow_caster_culling", true);4388light_culler->set_caster_culling_active(tighter_caster_culling);4389light_culler->set_light_culling_active(tighter_caster_culling);4390}43914392RendererSceneCull::~RendererSceneCull() {4393instance_cull_result.reset();4394instance_shadow_cull_result.reset();43954396for (uint32_t i = 0; i < MAX_UPDATE_SHADOWS; i++) {4397render_shadow_data[i].instances.reset();4398}4399for (uint32_t i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {4400render_sdfgi_data[i].instances.reset();4401}44024403scene_cull_result.reset();4404for (InstanceCullResult &thread : scene_cull_result_threads) {4405thread.reset();4406}4407scene_cull_result_threads.clear();44084409if (dummy_occlusion_culling) {4410memdelete(dummy_occlusion_culling);4411}44124413if (light_culler) {4414memdelete(light_culler);4415light_culler = nullptr;4416}4417}441844194420