Path: blob/master/servers/rendering/renderer_scene_cull.cpp
10277 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/object/worker_thread_pool.h"34#include "rendering_light_culler.h"35#include "rendering_server_default.h"3637#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)38// This is used only to obtain node paths for user-friendly physics interpolation warnings.39#include "scene/main/node.h"40#endif4142/* HALTON SEQUENCE */4344#ifndef _3D_DISABLED45static float get_halton_value(int p_index, int p_base) {46float f = 1;47float r = 0;48while (p_index > 0) {49f = f / static_cast<float>(p_base);50r = r + f * (p_index % p_base);51p_index = p_index / p_base;52}53return r * 2.0f - 1.0f;54}55#endif // _3D_DISABLED5657/* EVENT QUEUING */5859void RendererSceneCull::tick() {60if (_interpolation_data.interpolation_enabled) {61update_interpolation_tick(true);62}63}6465void RendererSceneCull::pre_draw(bool p_will_draw) {66if (_interpolation_data.interpolation_enabled) {67update_interpolation_frame(p_will_draw);68}69}7071/* CAMERA API */7273RID RendererSceneCull::camera_allocate() {74return camera_owner.allocate_rid();75}76void RendererSceneCull::camera_initialize(RID p_rid) {77camera_owner.initialize_rid(p_rid);78}7980void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {81Camera *camera = camera_owner.get_or_null(p_camera);82ERR_FAIL_NULL(camera);83camera->type = Camera::PERSPECTIVE;84camera->fov = p_fovy_degrees;85camera->znear = p_z_near;86camera->zfar = p_z_far;87}8889void RendererSceneCull::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) {90Camera *camera = camera_owner.get_or_null(p_camera);91ERR_FAIL_NULL(camera);92camera->type = Camera::ORTHOGONAL;93camera->size = p_size;94camera->znear = p_z_near;95camera->zfar = p_z_far;96}9798void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {99Camera *camera = camera_owner.get_or_null(p_camera);100ERR_FAIL_NULL(camera);101camera->type = Camera::FRUSTUM;102camera->size = p_size;103camera->offset = p_offset;104camera->znear = p_z_near;105camera->zfar = p_z_far;106}107108void RendererSceneCull::camera_set_transform(RID p_camera, const Transform3D &p_transform) {109Camera *camera = camera_owner.get_or_null(p_camera);110ERR_FAIL_NULL(camera);111112camera->transform = p_transform.orthonormalized();113}114115void RendererSceneCull::camera_set_cull_mask(RID p_camera, uint32_t p_layers) {116Camera *camera = camera_owner.get_or_null(p_camera);117ERR_FAIL_NULL(camera);118119camera->visible_layers = p_layers;120}121122void RendererSceneCull::camera_set_environment(RID p_camera, RID p_env) {123Camera *camera = camera_owner.get_or_null(p_camera);124ERR_FAIL_NULL(camera);125camera->env = p_env;126}127128void RendererSceneCull::camera_set_camera_attributes(RID p_camera, RID p_attributes) {129Camera *camera = camera_owner.get_or_null(p_camera);130ERR_FAIL_NULL(camera);131camera->attributes = p_attributes;132}133134void RendererSceneCull::camera_set_compositor(RID p_camera, RID p_compositor) {135Camera *camera = camera_owner.get_or_null(p_camera);136ERR_FAIL_NULL(camera);137camera->compositor = p_compositor;138}139140void RendererSceneCull::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) {141Camera *camera = camera_owner.get_or_null(p_camera);142ERR_FAIL_NULL(camera);143camera->vaspect = p_enable;144}145146bool RendererSceneCull::is_camera(RID p_camera) const {147return camera_owner.owns(p_camera);148}149150/* OCCLUDER API */151152RID RendererSceneCull::occluder_allocate() {153return RendererSceneOcclusionCull::get_singleton()->occluder_allocate();154}155156void RendererSceneCull::occluder_initialize(RID p_rid) {157RendererSceneOcclusionCull::get_singleton()->occluder_initialize(p_rid);158}159160void RendererSceneCull::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {161RendererSceneOcclusionCull::get_singleton()->occluder_set_mesh(p_occluder, p_vertices, p_indices);162}163164/* SCENARIO API */165166void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {167RendererSceneCull *self = (RendererSceneCull *)singleton;168Instance *A = p_A;169Instance *B = p_B;170171//instance indices are designed so greater always contains lesser172if (A->base_type > B->base_type) {173SWAP(A, B); //lesser always first174}175176if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {177InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);178InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);179180if (!(light->cull_mask & A->layer_mask)) {181// Early return if the object's layer mask doesn't match the light's cull mask.182return;183}184185geom->lights.insert(B);186light->geometries.insert(A);187188if (geom->can_cast_shadows) {189light->make_shadow_dirty();190}191192if (A->scenario && A->array_index >= 0) {193InstanceData &idata = A->scenario->instance_data[A->array_index];194idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;195}196197if (light->uses_projector) {198geom->projector_count++;199if (geom->projector_count == 1) {200InstanceData &idata = A->scenario->instance_data[A->array_index];201idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;202}203}204205if (light->uses_softshadow) {206geom->softshadow_count++;207if (geom->softshadow_count == 1) {208InstanceData &idata = A->scenario->instance_data[A->array_index];209idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;210}211}212213} 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)) {214if (!(A->layer_mask & RSG::light_storage->reflection_probe_get_reflection_mask(B->base))) {215// Early return if the object's layer mask doesn't match the reflection mask.216return;217}218219InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);220InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);221222geom->reflection_probes.insert(B);223reflection_probe->geometries.insert(A);224225if (A->scenario && A->array_index >= 0) {226InstanceData &idata = A->scenario->instance_data[A->array_index];227idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;228}229230} 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)) {231InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);232InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);233234if (!(decal->cull_mask & A->layer_mask)) {235// Early return if the object's layer mask doesn't match the decal's cull mask.236return;237}238239geom->decals.insert(B);240decal->geometries.insert(A);241242if (A->scenario && A->array_index >= 0) {243InstanceData &idata = A->scenario->instance_data[A->array_index];244idata.flags |= InstanceData::FLAG_GEOM_DECAL_DIRTY;245}246247} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {248InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);249InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);250251if (A->dynamic_gi) {252geom->lightmap_captures.insert(B);253lightmap_data->geometries.insert(A);254255if (A->scenario && A->array_index >= 0) {256InstanceData &idata = A->scenario->instance_data[A->array_index];257idata.flags |= InstanceData::FLAG_LIGHTMAP_CAPTURE;258}259((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture260}261262} 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)) {263InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);264InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);265266geom->voxel_gi_instances.insert(B);267268if (A->dynamic_gi) {269voxel_gi->dynamic_geometries.insert(A);270} else {271voxel_gi->geometries.insert(A);272}273274if (A->scenario && A->array_index >= 0) {275InstanceData &idata = A->scenario->instance_data[A->array_index];276idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;277}278279} else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) {280InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);281voxel_gi->lights.insert(A);282} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {283InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);284285if ((collision->cull_mask & A->layer_mask)) {286RSG::particles_storage->particles_add_collision(A->base, collision->instance);287}288}289}290291void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {292RendererSceneCull *self = singleton;293Instance *A = p_A;294Instance *B = p_B;295296//instance indices are designed so greater always contains lesser297if (A->base_type > B->base_type) {298SWAP(A, B); //lesser always first299}300301if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {302InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);303InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);304305if (!(light->cull_mask & A->layer_mask)) {306// Early return if the object's layer mask doesn't match the light's cull mask.307return;308}309310geom->lights.erase(B);311light->geometries.erase(A);312313if (geom->can_cast_shadows) {314light->make_shadow_dirty();315}316317if (A->scenario && A->array_index >= 0) {318InstanceData &idata = A->scenario->instance_data[A->array_index];319idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;320}321322if (light->uses_projector) {323#ifdef DEBUG_ENABLED324if (geom->projector_count == 0) {325ERR_PRINT("geom->projector_count==0 - BUG!");326}327#endif328geom->projector_count--;329if (geom->projector_count == 0) {330InstanceData &idata = A->scenario->instance_data[A->array_index];331idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;332}333}334335if (light->uses_softshadow) {336#ifdef DEBUG_ENABLED337if (geom->softshadow_count == 0) {338ERR_PRINT("geom->softshadow_count==0 - BUG!");339}340#endif341geom->softshadow_count--;342if (geom->softshadow_count == 0) {343InstanceData &idata = A->scenario->instance_data[A->array_index];344idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;345}346}347348} 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)) {349InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);350InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);351352geom->reflection_probes.erase(B);353reflection_probe->geometries.erase(A);354355if (A->scenario && A->array_index >= 0) {356InstanceData &idata = A->scenario->instance_data[A->array_index];357idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;358}359360} 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)) {361InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);362InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);363364if (!(decal->cull_mask & A->layer_mask)) {365// Early return if the object's layer mask doesn't match the decal's cull mask.366return;367}368369geom->decals.erase(B);370decal->geometries.erase(A);371372if (A->scenario && A->array_index >= 0) {373InstanceData &idata = A->scenario->instance_data[A->array_index];374idata.flags |= InstanceData::FLAG_GEOM_DECAL_DIRTY;375}376377} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {378InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);379InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);380if (A->dynamic_gi) {381geom->lightmap_captures.erase(B);382383if (geom->lightmap_captures.is_empty() && A->scenario && A->array_index >= 0) {384InstanceData &idata = A->scenario->instance_data[A->array_index];385idata.flags &= ~InstanceData::FLAG_LIGHTMAP_CAPTURE;386}387388lightmap_data->geometries.erase(A);389self->_instance_queue_update(A, false, false); //need to update capture390}391392} 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)) {393InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);394InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);395396geom->voxel_gi_instances.erase(B);397if (A->dynamic_gi) {398voxel_gi->dynamic_geometries.erase(A);399} else {400voxel_gi->geometries.erase(A);401}402403if (A->scenario && A->array_index >= 0) {404InstanceData &idata = A->scenario->instance_data[A->array_index];405idata.flags |= InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;406}407408} else if (B->base_type == RS::INSTANCE_VOXEL_GI && A->base_type == RS::INSTANCE_LIGHT) {409InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(B->base_data);410voxel_gi->lights.erase(A);411} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {412InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);413414if ((collision->cull_mask & A->layer_mask)) {415RSG::particles_storage->particles_remove_collision(A->base, collision->instance);416}417}418}419420RID RendererSceneCull::scenario_allocate() {421return scenario_owner.allocate_rid();422}423void RendererSceneCull::scenario_initialize(RID p_rid) {424scenario_owner.initialize_rid(p_rid);425426Scenario *scenario = scenario_owner.get_or_null(p_rid);427scenario->self = p_rid;428429scenario->reflection_probe_shadow_atlas = RSG::light_storage->shadow_atlas_create();430RSG::light_storage->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest431RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4);432RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);433RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);434RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);435436scenario->reflection_atlas = RSG::light_storage->reflection_atlas_create();437438scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool);439scenario->instance_data.set_page_pool(&instance_data_page_pool);440scenario->instance_visibility.set_page_pool(&instance_visibility_data_page_pool);441442RendererSceneOcclusionCull::get_singleton()->add_scenario(p_rid);443}444445void RendererSceneCull::scenario_set_environment(RID p_scenario, RID p_environment) {446Scenario *scenario = scenario_owner.get_or_null(p_scenario);447ERR_FAIL_NULL(scenario);448scenario->environment = p_environment;449}450451void RendererSceneCull::scenario_set_camera_attributes(RID p_scenario, RID p_camera_attributes) {452Scenario *scenario = scenario_owner.get_or_null(p_scenario);453ERR_FAIL_NULL(scenario);454scenario->camera_attributes = p_camera_attributes;455}456457void RendererSceneCull::scenario_set_compositor(RID p_scenario, RID p_compositor) {458Scenario *scenario = scenario_owner.get_or_null(p_scenario);459ERR_FAIL_NULL(scenario);460scenario->compositor = p_compositor;461}462463void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {464Scenario *scenario = scenario_owner.get_or_null(p_scenario);465ERR_FAIL_NULL(scenario);466scenario->fallback_environment = p_environment;467}468469void RendererSceneCull::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {470Scenario *scenario = scenario_owner.get_or_null(p_scenario);471ERR_FAIL_NULL(scenario);472RSG::light_storage->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);473}474475bool RendererSceneCull::is_scenario(RID p_scenario) const {476return scenario_owner.owns(p_scenario);477}478479RID RendererSceneCull::scenario_get_environment(RID p_scenario) {480Scenario *scenario = scenario_owner.get_or_null(p_scenario);481ERR_FAIL_NULL_V(scenario, RID());482return scenario->environment;483}484485void RendererSceneCull::scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport) {486Scenario *scenario = scenario_owner.get_or_null(p_scenario);487ERR_FAIL_NULL(scenario);488if (!scenario->viewport_visibility_masks.has(p_viewport)) {489return;490}491492uint64_t mask = scenario->viewport_visibility_masks[p_viewport];493scenario->used_viewport_visibility_bits &= ~mask;494scenario->viewport_visibility_masks.erase(p_viewport);495}496497void RendererSceneCull::scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport) {498Scenario *scenario = scenario_owner.get_or_null(p_scenario);499ERR_FAIL_NULL(scenario);500ERR_FAIL_COND(scenario->viewport_visibility_masks.has(p_viewport));501502uint64_t new_mask = 1;503while (new_mask & scenario->used_viewport_visibility_bits) {504new_mask <<= 1;505}506507if (new_mask == 0) {508ERR_PRINT("Only 64 viewports per scenario allowed when using visibility ranges.");509new_mask = ((uint64_t)1) << 63;510}511512scenario->viewport_visibility_masks[p_viewport] = new_mask;513scenario->used_viewport_visibility_bits |= new_mask;514}515516/* INSTANCING API */517518void RendererSceneCull::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) const {519if (p_update_aabb) {520p_instance->update_aabb = true;521}522if (p_update_dependencies) {523p_instance->update_dependencies = true;524}525526if (p_instance->update_item.in_list()) {527return;528}529530_instance_update_list.add(&p_instance->update_item);531}532533RID RendererSceneCull::instance_allocate() {534return instance_owner.allocate_rid();535}536void RendererSceneCull::instance_initialize(RID p_rid) {537instance_owner.initialize_rid(p_rid);538Instance *instance = instance_owner.get_or_null(p_rid);539instance->self = p_rid;540}541542void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) const {543bool needs_instance = RSG::mesh_storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid());544if (needs_instance != p_instance->mesh_instance.is_valid()) {545if (needs_instance) {546p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base);547548} else {549RSG::mesh_storage->mesh_instance_free(p_instance->mesh_instance);550p_instance->mesh_instance = RID();551}552553InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);554geom->geometry_instance->set_mesh_instance(p_instance->mesh_instance);555556if (p_instance->scenario && p_instance->array_index >= 0) {557InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];558if (p_instance->mesh_instance.is_valid()) {559idata.flags |= InstanceData::FLAG_USES_MESH_INSTANCE;560} else {561idata.flags &= ~InstanceData::FLAG_USES_MESH_INSTANCE;562}563}564}565566if (p_instance->mesh_instance.is_valid()) {567RSG::mesh_storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);568}569}570571void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {572Instance *instance = instance_owner.get_or_null(p_instance);573ERR_FAIL_NULL(instance);574575Scenario *scenario = instance->scenario;576577if (instance->base_type != RS::INSTANCE_NONE) {578//free anything related to that base579580if (scenario && instance->indexer_id.is_valid()) {581_unpair_instance(instance);582}583584if (instance->mesh_instance.is_valid()) {585RSG::mesh_storage->mesh_instance_free(instance->mesh_instance);586instance->mesh_instance = RID();587// no need to set instance data flag here, as it was freed above588}589590switch (instance->base_type) {591case RS::INSTANCE_MESH:592case RS::INSTANCE_MULTIMESH:593case RS::INSTANCE_PARTICLES: {594InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);595scene_render->geometry_instance_free(geom->geometry_instance);596} break;597case RS::INSTANCE_LIGHT: {598InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);599600if (scenario && instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {601scenario->dynamic_lights.erase(light->instance);602}603604#ifdef DEBUG_ENABLED605if (light->geometries.size()) {606ERR_PRINT("BUG, indexing did not unpair geometries from light.");607}608#endif609if (scenario && light->D) {610scenario->directional_lights.erase(light->D);611light->D = nullptr;612}613RSG::light_storage->light_instance_free(light->instance);614} break;615case RS::INSTANCE_PARTICLES_COLLISION: {616InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);617RSG::utilities->free(collision->instance);618} break;619case RS::INSTANCE_FOG_VOLUME: {620InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);621scene_render->free(volume->instance);622} break;623case RS::INSTANCE_VISIBLITY_NOTIFIER: {624//none625} break;626case RS::INSTANCE_REFLECTION_PROBE: {627InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);628RSG::light_storage->reflection_probe_instance_free(reflection_probe->instance);629if (reflection_probe->update_list.in_list()) {630reflection_probe_render_list.remove(&reflection_probe->update_list);631}632} break;633case RS::INSTANCE_DECAL: {634InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);635RSG::texture_storage->decal_instance_free(decal->instance);636637} break;638case RS::INSTANCE_LIGHTMAP: {639InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(instance->base_data);640//erase dependencies, since no longer a lightmap641while (lightmap_data->users.begin()) {642instance_geometry_set_lightmap((*lightmap_data->users.begin())->self, RID(), Rect2(), 0);643}644RSG::light_storage->lightmap_instance_free(lightmap_data->instance);645} break;646case RS::INSTANCE_VOXEL_GI: {647InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);648#ifdef DEBUG_ENABLED649if (voxel_gi->geometries.size()) {650ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI.");651}652#endif653#ifdef DEBUG_ENABLED654if (voxel_gi->lights.size()) {655ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI.");656}657#endif658if (voxel_gi->update_element.in_list()) {659voxel_gi_update_list.remove(&voxel_gi->update_element);660}661662scene_render->free(voxel_gi->probe_instance);663664} break;665case RS::INSTANCE_OCCLUDER: {666if (scenario && instance->visible) {667RendererSceneOcclusionCull::get_singleton()->scenario_remove_instance(instance->scenario->self, p_instance);668}669} break;670default: {671}672}673674if (instance->base_data) {675memdelete(instance->base_data);676instance->base_data = nullptr;677}678679instance->materials.clear();680}681682instance->base_type = RS::INSTANCE_NONE;683instance->base = RID();684685if (p_base.is_valid()) {686instance->base_type = RSG::utilities->get_base_type(p_base);687688// fix up a specific malfunctioning case before the switch, so it can be handled689if (instance->base_type == RS::INSTANCE_NONE && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_base)) {690instance->base_type = RS::INSTANCE_OCCLUDER;691}692693switch (instance->base_type) {694case RS::INSTANCE_NONE: {695ERR_PRINT_ONCE("unimplemented base type encountered in renderer scene cull");696return;697}698case RS::INSTANCE_LIGHT: {699InstanceLightData *light = memnew(InstanceLightData);700701if (scenario && RSG::light_storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {702light->D = scenario->directional_lights.push_back(instance);703}704705light->instance = RSG::light_storage->light_instance_create(p_base);706707instance->base_data = light;708} break;709case RS::INSTANCE_MESH:710case RS::INSTANCE_MULTIMESH:711case RS::INSTANCE_PARTICLES: {712InstanceGeometryData *geom = memnew(InstanceGeometryData);713instance->base_data = geom;714geom->geometry_instance = scene_render->geometry_instance_create(p_base);715716ERR_FAIL_NULL(geom->geometry_instance);717718geom->geometry_instance->set_skeleton(instance->skeleton);719geom->geometry_instance->set_material_override(instance->material_override);720geom->geometry_instance->set_material_overlay(instance->material_overlay);721geom->geometry_instance->set_surface_materials(instance->materials);722geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb);723geom->geometry_instance->set_layer_mask(instance->layer_mask);724geom->geometry_instance->set_pivot_data(instance->sorting_offset, instance->use_aabb_center);725geom->geometry_instance->set_lod_bias(instance->lod_bias);726geom->geometry_instance->set_transparency(instance->transparency);727geom->geometry_instance->set_use_baked_light(instance->baked_light);728geom->geometry_instance->set_use_dynamic_gi(instance->dynamic_gi);729geom->geometry_instance->set_use_lightmap(RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);730geom->geometry_instance->set_instance_shader_uniforms_offset(instance->instance_uniforms.location());731geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);732if (instance->lightmap_sh.size() == 9) {733geom->geometry_instance->set_lightmap_capture(instance->lightmap_sh.ptr());734}735736for (Instance *E : instance->visibility_dependencies) {737Instance *dep_instance = E;738ERR_CONTINUE(dep_instance->array_index == -1);739ERR_CONTINUE(dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index != -1);740dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = instance->array_index;741}742} break;743case RS::INSTANCE_PARTICLES_COLLISION: {744InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);745collision->instance = RSG::particles_storage->particles_collision_instance_create(p_base);746RSG::particles_storage->particles_collision_instance_set_active(collision->instance, instance->visible);747instance->base_data = collision;748} break;749case RS::INSTANCE_FOG_VOLUME: {750InstanceFogVolumeData *volume = memnew(InstanceFogVolumeData);751volume->instance = scene_render->fog_volume_instance_create(p_base);752scene_render->fog_volume_instance_set_active(volume->instance, instance->visible);753instance->base_data = volume;754} break;755case RS::INSTANCE_VISIBLITY_NOTIFIER: {756InstanceVisibilityNotifierData *vnd = memnew(InstanceVisibilityNotifierData);757vnd->base = p_base;758instance->base_data = vnd;759} break;760case RS::INSTANCE_REFLECTION_PROBE: {761InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);762reflection_probe->owner = instance;763instance->base_data = reflection_probe;764765reflection_probe->instance = RSG::light_storage->reflection_probe_instance_create(p_base);766} break;767case RS::INSTANCE_DECAL: {768InstanceDecalData *decal = memnew(InstanceDecalData);769decal->owner = instance;770instance->base_data = decal;771772decal->instance = RSG::texture_storage->decal_instance_create(p_base);773RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);774} break;775case RS::INSTANCE_LIGHTMAP: {776InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);777instance->base_data = lightmap_data;778lightmap_data->instance = RSG::light_storage->lightmap_instance_create(p_base);779} break;780case RS::INSTANCE_VOXEL_GI: {781InstanceVoxelGIData *voxel_gi = memnew(InstanceVoxelGIData);782instance->base_data = voxel_gi;783voxel_gi->owner = instance;784785if (scenario && !voxel_gi->update_element.in_list()) {786voxel_gi_update_list.add(&voxel_gi->update_element);787}788789voxel_gi->probe_instance = scene_render->voxel_gi_instance_create(p_base);790791} break;792case RS::INSTANCE_OCCLUDER: {793if (scenario) {794RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(scenario->self, p_instance, p_base, instance->transform, instance->visible);795}796} break;797default: {798}799}800801instance->base = p_base;802803if (instance->base_type == RS::INSTANCE_MESH) {804_instance_update_mesh_instance(instance);805}806807//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it808RSG::utilities->base_update_dependency(p_base, &instance->dependency_tracker);809}810811_instance_queue_update(instance, true, true);812}813814void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {815Instance *instance = instance_owner.get_or_null(p_instance);816ERR_FAIL_NULL(instance);817818if (instance->scenario) {819instance->scenario->instances.remove(&instance->scenario_item);820821if (instance->indexer_id.is_valid()) {822_unpair_instance(instance);823}824825switch (instance->base_type) {826case RS::INSTANCE_LIGHT: {827InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);828if (instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {829instance->scenario->dynamic_lights.erase(light->instance);830}831832#ifdef DEBUG_ENABLED833if (light->geometries.size()) {834ERR_PRINT("BUG, indexing did not unpair geometries from light.");835}836#endif837if (light->D) {838instance->scenario->directional_lights.erase(light->D);839light->D = nullptr;840}841} break;842case RS::INSTANCE_REFLECTION_PROBE: {843InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);844RSG::light_storage->reflection_probe_release_atlas_index(reflection_probe->instance);845846} break;847case RS::INSTANCE_PARTICLES_COLLISION: {848heightfield_particle_colliders_update_list.erase(instance);849} break;850case RS::INSTANCE_VOXEL_GI: {851InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);852853#ifdef DEBUG_ENABLED854if (voxel_gi->geometries.size()) {855ERR_PRINT("BUG, indexing did not unpair geometries from VoxelGI.");856}857#endif858#ifdef DEBUG_ENABLED859if (voxel_gi->lights.size()) {860ERR_PRINT("BUG, indexing did not unpair lights from VoxelGI.");861}862#endif863864if (voxel_gi->update_element.in_list()) {865voxel_gi_update_list.remove(&voxel_gi->update_element);866}867} break;868case RS::INSTANCE_OCCLUDER: {869if (instance->visible) {870RendererSceneOcclusionCull::get_singleton()->scenario_remove_instance(instance->scenario->self, p_instance);871}872} break;873default: {874}875}876877instance->scenario = nullptr;878}879880if (p_scenario.is_valid()) {881Scenario *scenario = scenario_owner.get_or_null(p_scenario);882ERR_FAIL_NULL(scenario);883884instance->scenario = scenario;885886scenario->instances.add(&instance->scenario_item);887888switch (instance->base_type) {889case RS::INSTANCE_LIGHT: {890InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);891892if (RSG::light_storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {893light->D = scenario->directional_lights.push_back(instance);894}895} break;896case RS::INSTANCE_VOXEL_GI: {897InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);898if (!voxel_gi->update_element.in_list()) {899voxel_gi_update_list.add(&voxel_gi->update_element);900}901} break;902case RS::INSTANCE_OCCLUDER: {903RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(scenario->self, p_instance, instance->base, instance->transform, instance->visible);904} break;905default: {906}907}908909_instance_queue_update(instance, true, true);910}911}912913void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) {914Instance *instance = instance_owner.get_or_null(p_instance);915ERR_FAIL_NULL(instance);916917if (instance->layer_mask == p_mask) {918return;919}920921// Particles always need to be unpaired. Geometry may need to be unpaired, but only if lights or decals use pairing.922// Needs to happen before layer mask changes so we can avoid attempting to unpair something that was never paired.923if (instance->base_type == RS::INSTANCE_PARTICLES ||924(((geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT)) || (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL))) && ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK))) {925_unpair_instance(instance);926singleton->_instance_queue_update(instance, false, false);927}928929instance->layer_mask = p_mask;930if (instance->scenario && instance->array_index >= 0) {931instance->scenario->instance_data[instance->array_index].layer_mask = p_mask;932}933934if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {935InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);936ERR_FAIL_NULL(geom->geometry_instance);937geom->geometry_instance->set_layer_mask(p_mask);938939if (geom->can_cast_shadows) {940for (HashSet<RendererSceneCull::Instance *>::Iterator I = geom->lights.begin(); I != geom->lights.end(); ++I) {941InstanceLightData *light = static_cast<InstanceLightData *>((*I)->base_data);942light->make_shadow_dirty();943}944}945}946}947948void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) {949Instance *instance = instance_owner.get_or_null(p_instance);950ERR_FAIL_NULL(instance);951952instance->sorting_offset = p_sorting_offset;953instance->use_aabb_center = p_use_aabb_center;954955if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {956InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);957ERR_FAIL_NULL(geom->geometry_instance);958geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center);959} else if (instance->base_type == RS::INSTANCE_DECAL && instance->base_data) {960InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);961RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);962}963}964965void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float p_transparency) {966Instance *instance = instance_owner.get_or_null(p_instance);967ERR_FAIL_NULL(instance);968969instance->transparency = p_transparency;970971if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {972InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);973ERR_FAIL_NULL(geom->geometry_instance);974geom->geometry_instance->set_transparency(p_transparency);975}976}977978void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D &p_transform) {979Instance *instance = instance_owner.get_or_null(p_instance);980ERR_FAIL_NULL(instance);981982if (instance->transform == p_transform) {983return; // Must be checked to avoid worst evil.984}985986#ifdef DEBUG_ENABLED987988for (int i = 0; i < 4; i++) {989const Vector3 &v = i < 3 ? p_transform.basis.rows[i] : p_transform.origin;990ERR_FAIL_COND(!v.is_finite());991}992993#endif994instance->transform = p_transform;995_instance_queue_update(instance, true);996}997998void RendererSceneCull::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {999Instance *instance = instance_owner.get_or_null(p_instance);1000ERR_FAIL_NULL(instance);10011002instance->object_id = p_id;1003}10041005void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {1006Instance *instance = instance_owner.get_or_null(p_instance);1007ERR_FAIL_NULL(instance);10081009if (instance->update_item.in_list()) {1010_update_dirty_instance(instance);1011}10121013if (instance->mesh_instance.is_valid()) {1014RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);1015}10161017_instance_queue_update(instance, false, false);1018}10191020void RendererSceneCull::instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) {1021Instance *instance = instance_owner.get_or_null(p_instance);1022ERR_FAIL_NULL(instance);10231024if (instance->base_type == RS::INSTANCE_MESH) {1025//may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case1026instance->materials.resize(MAX(p_surface + 1, RSG::mesh_storage->mesh_get_surface_count(instance->base)));1027}10281029ERR_FAIL_INDEX(p_surface, instance->materials.size());10301031instance->materials.write[p_surface] = p_material;10321033_instance_queue_update(instance, false, true);1034}10351036void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {1037Instance *instance = instance_owner.get_or_null(p_instance);1038ERR_FAIL_NULL(instance);10391040if (instance->visible == p_visible) {1041return;1042}10431044instance->visible = p_visible;10451046if (p_visible) {1047if (instance->scenario != nullptr) {1048_instance_queue_update(instance, true, false);1049}1050} else if (instance->indexer_id.is_valid()) {1051_unpair_instance(instance);1052}10531054if (instance->base_type == RS::INSTANCE_LIGHT) {1055InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);1056if (instance->scenario && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1057if (p_visible) {1058instance->scenario->dynamic_lights.push_back(light->instance);1059} else {1060instance->scenario->dynamic_lights.erase(light->instance);1061}1062}1063}10641065if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {1066InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);1067RSG::particles_storage->particles_collision_instance_set_active(collision->instance, p_visible);1068}10691070if (instance->base_type == RS::INSTANCE_FOG_VOLUME) {1071InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);1072scene_render->fog_volume_instance_set_active(volume->instance, p_visible);1073}10741075if (instance->base_type == RS::INSTANCE_OCCLUDER) {1076if (instance->scenario) {1077RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(instance->scenario->self, p_instance, instance->base, instance->transform, p_visible);1078}1079}1080}10811082void RendererSceneCull::instance_teleport(RID p_instance) {1083Instance *instance = instance_owner.get_or_null(p_instance);1084ERR_FAIL_NULL(instance);1085instance->teleported = true;1086}10871088void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {1089Instance *instance = instance_owner.get_or_null(p_instance);1090ERR_FAIL_NULL(instance);10911092if (p_aabb != AABB()) {1093// Set custom AABB1094if (instance->custom_aabb == nullptr) {1095instance->custom_aabb = memnew(AABB);1096}1097*instance->custom_aabb = p_aabb;10981099} else {1100// Clear custom AABB1101if (instance->custom_aabb != nullptr) {1102memdelete(instance->custom_aabb);1103instance->custom_aabb = nullptr;1104}1105}11061107if (instance->scenario) {1108_instance_queue_update(instance, true, false);1109}1110}11111112void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton) {1113Instance *instance = instance_owner.get_or_null(p_instance);1114ERR_FAIL_NULL(instance);11151116if (instance->skeleton == p_skeleton) {1117return;1118}11191120instance->skeleton = p_skeleton;11211122if (p_skeleton.is_valid()) {1123//update the dependency now, so if cleared, we remove it1124RSG::mesh_storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);1125}11261127_instance_queue_update(instance, true, true);11281129if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1130_instance_update_mesh_instance(instance);11311132InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1133ERR_FAIL_NULL(geom->geometry_instance);1134geom->geometry_instance->set_skeleton(p_skeleton);1135}1136}11371138void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {1139Instance *instance = instance_owner.get_or_null(p_instance);1140ERR_FAIL_NULL(instance);11411142instance->extra_margin = p_margin;1143_instance_queue_update(instance, true, false);1144}11451146void RendererSceneCull::instance_set_ignore_culling(RID p_instance, bool p_enabled) {1147Instance *instance = instance_owner.get_or_null(p_instance);1148ERR_FAIL_NULL(instance);1149instance->ignore_all_culling = p_enabled;11501151if (instance->scenario && instance->array_index >= 0) {1152InstanceData &idata = instance->scenario->instance_data[instance->array_index];1153if (instance->ignore_all_culling) {1154idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;1155} else {1156idata.flags &= ~InstanceData::FLAG_IGNORE_ALL_CULLING;1157}1158}1159}11601161Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {1162Vector<ObjectID> instances;1163Scenario *scenario = scenario_owner.get_or_null(p_scenario);1164ERR_FAIL_NULL_V(scenario, instances);11651166update_dirty_instances(); // check dirty instances before culling11671168struct CullAABB {1169Vector<ObjectID> instances;1170_FORCE_INLINE_ bool operator()(void *p_data) {1171Instance *p_instance = (Instance *)p_data;1172if (!p_instance->object_id.is_null()) {1173instances.push_back(p_instance->object_id);1174}1175return false;1176}1177};11781179CullAABB cull_aabb;1180scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(p_aabb, cull_aabb);1181scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(p_aabb, cull_aabb);1182return cull_aabb.instances;1183}11841185Vector<ObjectID> RendererSceneCull::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {1186Vector<ObjectID> instances;1187Scenario *scenario = scenario_owner.get_or_null(p_scenario);1188ERR_FAIL_NULL_V(scenario, instances);1189update_dirty_instances(); // check dirty instances before culling11901191struct CullRay {1192Vector<ObjectID> instances;1193_FORCE_INLINE_ bool operator()(void *p_data) {1194Instance *p_instance = (Instance *)p_data;1195if (!p_instance->object_id.is_null()) {1196instances.push_back(p_instance->object_id);1197}1198return false;1199}1200};12011202CullRay cull_ray;1203scenario->indexers[Scenario::INDEXER_GEOMETRY].ray_query(p_from, p_to, cull_ray);1204scenario->indexers[Scenario::INDEXER_VOLUMES].ray_query(p_from, p_to, cull_ray);1205return cull_ray.instances;1206}12071208Vector<ObjectID> RendererSceneCull::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {1209Vector<ObjectID> instances;1210Scenario *scenario = scenario_owner.get_or_null(p_scenario);1211ERR_FAIL_NULL_V(scenario, instances);1212update_dirty_instances(); // check dirty instances before culling12131214Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&p_convex[0], p_convex.size());12151216struct CullConvex {1217Vector<ObjectID> instances;1218_FORCE_INLINE_ bool operator()(void *p_data) {1219Instance *p_instance = (Instance *)p_data;1220if (!p_instance->object_id.is_null()) {1221instances.push_back(p_instance->object_id);1222}1223return false;1224}1225};12261227CullConvex cull_convex;1228scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex);1229scenario->indexers[Scenario::INDEXER_VOLUMES].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex);1230return cull_convex.instances;1231}12321233void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) {1234Instance *instance = instance_owner.get_or_null(p_instance);1235ERR_FAIL_NULL(instance);12361237//ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK));12381239switch (p_flags) {1240case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: {1241instance->baked_light = p_enabled;12421243if (instance->scenario && instance->array_index >= 0) {1244InstanceData &idata = instance->scenario->instance_data[instance->array_index];1245if (instance->baked_light) {1246idata.flags |= InstanceData::FLAG_USES_BAKED_LIGHT;1247} else {1248idata.flags &= ~InstanceData::FLAG_USES_BAKED_LIGHT;1249}1250}12511252if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1253InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1254ERR_FAIL_NULL(geom->geometry_instance);1255geom->geometry_instance->set_use_baked_light(p_enabled);1256}12571258} break;1259case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {1260if (p_enabled == instance->dynamic_gi) {1261//bye, redundant1262return;1263}12641265if (instance->indexer_id.is_valid()) {1266_unpair_instance(instance);1267_instance_queue_update(instance, true, true);1268}12691270//once out of octree, can be changed1271instance->dynamic_gi = p_enabled;12721273if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1274InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1275ERR_FAIL_NULL(geom->geometry_instance);1276geom->geometry_instance->set_use_dynamic_gi(p_enabled);1277}12781279} break;1280case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {1281instance->redraw_if_visible = p_enabled;12821283if (instance->scenario && instance->array_index >= 0) {1284InstanceData &idata = instance->scenario->instance_data[instance->array_index];1285if (instance->redraw_if_visible) {1286idata.flags |= InstanceData::FLAG_REDRAW_IF_VISIBLE;1287} else {1288idata.flags &= ~InstanceData::FLAG_REDRAW_IF_VISIBLE;1289}1290}12911292} break;1293case RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING: {1294instance->ignore_occlusion_culling = p_enabled;12951296if (instance->scenario && instance->array_index >= 0) {1297InstanceData &idata = instance->scenario->instance_data[instance->array_index];1298if (instance->ignore_occlusion_culling) {1299idata.flags |= InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;1300} else {1301idata.flags &= ~InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;1302}1303}1304} break;1305default: {1306}1307}1308}13091310void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {1311Instance *instance = instance_owner.get_or_null(p_instance);1312ERR_FAIL_NULL(instance);13131314instance->cast_shadows = p_shadow_casting_setting;13151316if (instance->scenario && instance->array_index >= 0) {1317InstanceData &idata = instance->scenario->instance_data[instance->array_index];13181319if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {1320idata.flags |= InstanceData::FLAG_CAST_SHADOWS;1321} else {1322idata.flags &= ~InstanceData::FLAG_CAST_SHADOWS;1323}13241325if (instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {1326idata.flags |= InstanceData::FLAG_CAST_SHADOWS_ONLY;1327} else {1328idata.flags &= ~InstanceData::FLAG_CAST_SHADOWS_ONLY;1329}1330}13311332if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1333InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1334ERR_FAIL_NULL(geom->geometry_instance);13351336geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);1337}13381339_instance_queue_update(instance, false, true);1340}13411342void RendererSceneCull::instance_geometry_set_material_override(RID p_instance, RID p_material) {1343Instance *instance = instance_owner.get_or_null(p_instance);1344ERR_FAIL_NULL(instance);13451346instance->material_override = p_material;1347_instance_queue_update(instance, false, true);13481349if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1350InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1351ERR_FAIL_NULL(geom->geometry_instance);1352geom->geometry_instance->set_material_override(p_material);1353}1354}13551356void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, RID p_material) {1357Instance *instance = instance_owner.get_or_null(p_instance);1358ERR_FAIL_NULL(instance);13591360instance->material_overlay = p_material;1361_instance_queue_update(instance, false, true);13621363if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1364InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1365ERR_FAIL_NULL(geom->geometry_instance);1366geom->geometry_instance->set_material_overlay(p_material);1367}1368}13691370void 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) {1371Instance *instance = instance_owner.get_or_null(p_instance);1372ERR_FAIL_NULL(instance);13731374instance->visibility_range_begin = p_min;1375instance->visibility_range_end = p_max;1376instance->visibility_range_begin_margin = p_min_margin;1377instance->visibility_range_end_margin = p_max_margin;1378instance->visibility_range_fade_mode = p_fade_mode;13791380_update_instance_visibility_dependencies(instance);13811382if (instance->scenario && instance->visibility_index != -1) {1383InstanceVisibilityData &vd = instance->scenario->instance_visibility[instance->visibility_index];1384vd.range_begin = instance->visibility_range_begin;1385vd.range_end = instance->visibility_range_end;1386vd.range_begin_margin = instance->visibility_range_begin_margin;1387vd.range_end_margin = instance->visibility_range_end_margin;1388vd.fade_mode = p_fade_mode;1389}1390}13911392void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_parent_instance) {1393Instance *instance = instance_owner.get_or_null(p_instance);1394ERR_FAIL_NULL(instance);13951396Instance *old_parent = instance->visibility_parent;1397if (old_parent) {1398old_parent->visibility_dependencies.erase(instance);1399instance->visibility_parent = nullptr;1400_update_instance_visibility_depth(old_parent);1401}14021403Instance *parent = instance_owner.get_or_null(p_parent_instance);1404ERR_FAIL_COND(p_parent_instance.is_valid() && !parent);14051406if (parent) {1407parent->visibility_dependencies.insert(instance);1408instance->visibility_parent = parent;14091410bool cycle_detected = _update_instance_visibility_depth(parent);1411if (cycle_detected) {1412ERR_PRINT("Cycle detected in the visibility dependencies tree. The latest change to visibility_parent will have no effect.");1413parent->visibility_dependencies.erase(instance);1414instance->visibility_parent = nullptr;1415}1416}14171418_update_instance_visibility_dependencies(instance);1419}14201421bool RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {1422bool cycle_detected = false;1423HashSet<Instance *> traversed_nodes;14241425{1426Instance *instance = p_instance;1427while (instance) {1428if (!instance->visibility_dependencies.is_empty()) {1429uint32_t depth = 0;1430for (const Instance *E : instance->visibility_dependencies) {1431depth = MAX(depth, E->visibility_dependencies_depth);1432}1433instance->visibility_dependencies_depth = depth + 1;1434} else {1435instance->visibility_dependencies_depth = 0;1436}14371438if (instance->scenario && instance->visibility_index != -1) {1439instance->scenario->instance_visibility.move(instance->visibility_index, instance->visibility_dependencies_depth);1440}14411442traversed_nodes.insert(instance);14431444instance = instance->visibility_parent;1445if (traversed_nodes.has(instance)) {1446cycle_detected = true;1447break;1448}1449}1450}14511452return cycle_detected;1453}14541455void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_instance) const {1456bool is_geometry_instance = ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && p_instance->base_data;1457bool has_visibility_range = p_instance->visibility_range_begin > 0.0 || p_instance->visibility_range_end > 0.0;1458bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1;14591460if (!needs_visibility_cull && p_instance->visibility_index != -1) {1461p_instance->scenario->instance_visibility.remove_at(p_instance->visibility_index);1462p_instance->visibility_index = -1;1463} else if (needs_visibility_cull && p_instance->visibility_index == -1) {1464InstanceVisibilityData vd;1465vd.instance = p_instance;1466vd.range_begin = p_instance->visibility_range_begin;1467vd.range_end = p_instance->visibility_range_end;1468vd.range_begin_margin = p_instance->visibility_range_begin_margin;1469vd.range_end_margin = p_instance->visibility_range_end_margin;1470vd.position = p_instance->transformed_aabb.get_center();1471vd.array_index = p_instance->array_index;1472vd.fade_mode = p_instance->visibility_range_fade_mode;14731474p_instance->scenario->instance_visibility.insert(vd, p_instance->visibility_dependencies_depth);1475}14761477if (p_instance->scenario && p_instance->array_index != -1) {1478InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];1479idata.visibility_index = p_instance->visibility_index;14801481if (is_geometry_instance) {1482if (has_visibility_range && p_instance->visibility_range_fade_mode == RS::VISIBILITY_RANGE_FADE_SELF) {1483bool begin_enabled = p_instance->visibility_range_begin > 0.0f;1484float begin_min = p_instance->visibility_range_begin - p_instance->visibility_range_begin_margin;1485float begin_max = p_instance->visibility_range_begin + p_instance->visibility_range_begin_margin;1486bool end_enabled = p_instance->visibility_range_end > 0.0f;1487float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin;1488float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin;1489idata.instance_geometry->set_fade_range(begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);1490} else {1491idata.instance_geometry->set_fade_range(false, 0.0f, 0.0f, false, 0.0f, 0.0f);1492}1493}14941495if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || p_instance->visibility_dependencies_depth == 0)) {1496idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;1497} else {1498idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;1499}15001501if (p_instance->visibility_parent) {1502idata.parent_array_index = p_instance->visibility_parent->array_index;1503} else {1504idata.parent_array_index = -1;1505if (is_geometry_instance) {1506idata.instance_geometry->set_parent_fade_alpha(1.0f);1507}1508}1509}1510}15111512void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {1513Instance *instance = instance_owner.get_or_null(p_instance);1514ERR_FAIL_NULL(instance);15151516if (instance->lightmap) {1517InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(((Instance *)instance->lightmap)->base_data);1518lightmap_data->users.erase(instance);1519instance->lightmap = nullptr;1520}15211522Instance *lightmap_instance = instance_owner.get_or_null(p_lightmap);15231524instance->lightmap = lightmap_instance;1525instance->lightmap_uv_scale = p_lightmap_uv_scale;1526instance->lightmap_slice_index = p_slice_index;15271528RID lightmap_instance_rid;15291530if (lightmap_instance) {1531InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);1532lightmap_data->users.insert(instance);1533lightmap_instance_rid = lightmap_data->instance;1534}15351536if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1537InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1538ERR_FAIL_NULL(geom->geometry_instance);1539geom->geometry_instance->set_use_lightmap(lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);1540}1541}15421543void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) {1544Instance *instance = instance_owner.get_or_null(p_instance);1545ERR_FAIL_NULL(instance);15461547instance->lod_bias = p_lod_bias;15481549if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {1550InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);1551ERR_FAIL_NULL(geom->geometry_instance);1552geom->geometry_instance->set_lod_bias(p_lod_bias);1553}1554}15551556void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {1557Instance *instance = instance_owner.get_or_null(p_instance);1558ERR_FAIL_NULL(instance);15591560instance->instance_uniforms.set(instance->self, p_parameter, p_value);1561}15621563Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {1564const Instance *instance = instance_owner.get_or_null(p_instance);1565ERR_FAIL_NULL_V(instance, Variant());15661567return instance->instance_uniforms.get(p_parameter);1568}15691570Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {1571const Instance *instance = instance_owner.get_or_null(p_instance);1572ERR_FAIL_NULL_V(instance, Variant());15731574return instance->instance_uniforms.get_default(p_parameter);1575}15761577void RendererSceneCull::mesh_generate_pipelines(RID p_mesh, bool p_background_compilation) {1578scene_render->mesh_generate_pipelines(p_mesh, p_background_compilation);1579}15801581uint32_t RendererSceneCull::get_pipeline_compilations(RS::PipelineSource p_source) {1582return scene_render->get_pipeline_compilations(p_source);1583}15841585void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {1586ERR_FAIL_NULL(p_parameters);1587const Instance *instance = instance_owner.get_or_null(p_instance);1588ERR_FAIL_NULL(instance);15891590update_dirty_instances();15911592instance->instance_uniforms.get_property_list(*p_parameters);1593}15941595void RendererSceneCull::_update_instance(Instance *p_instance) const {1596p_instance->version++;15971598// When not using interpolation the transform is used straight.1599const Transform3D *instance_xform = &p_instance->transform;16001601// Can possibly use the most up to date current transform here when using physics interpolation ...1602// uncomment the next line for this..1603//if (_interpolation_data.interpolation_enabled && p_instance->interpolated) {1604// instance_xform = &p_instance->transform_curr;1605//}1606// However it does seem that using the interpolated transform (transform) works for keeping AABBs1607// up to date to avoid culling errors.16081609if (p_instance->base_type == RS::INSTANCE_LIGHT) {1610InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);16111612RSG::light_storage->light_instance_set_transform(light->instance, *instance_xform);1613RSG::light_storage->light_instance_set_aabb(light->instance, instance_xform->xform(p_instance->aabb));1614light->make_shadow_dirty();16151616RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);1617if (RSG::light_storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {1618if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1619p_instance->scenario->dynamic_lights.erase(light->instance);1620}16211622light->bake_mode = bake_mode;16231624if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1625p_instance->scenario->dynamic_lights.push_back(light->instance);1626}1627}16281629uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(p_instance->base);1630if (light->max_sdfgi_cascade != max_sdfgi_cascade) {1631light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario1632}1633light->cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base);1634} else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {1635InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);16361637RSG::light_storage->reflection_probe_instance_set_transform(reflection_probe->instance, *instance_xform);16381639if (p_instance->scenario && p_instance->array_index >= 0) {1640InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];1641idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;1642}1643} else if (p_instance->base_type == RS::INSTANCE_DECAL) {1644InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);16451646RSG::texture_storage->decal_instance_set_transform(decal->instance, *instance_xform);1647decal->cull_mask = RSG::texture_storage->decal_get_cull_mask(p_instance->base);1648} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {1649InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data);16501651RSG::light_storage->lightmap_instance_set_transform(lightmap->instance, *instance_xform);1652} else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) {1653InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(p_instance->base_data);16541655scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->probe_instance, *instance_xform);1656} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {1657RSG::particles_storage->particles_set_emission_transform(p_instance->base, *instance_xform);1658} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {1659InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data);16601661//remove materials no longer used and un-own them1662if (RSG::particles_storage->particles_collision_is_heightfield(p_instance->base)) {1663heightfield_particle_colliders_update_list.insert(p_instance);1664}1665RSG::particles_storage->particles_collision_instance_set_transform(collision->instance, *instance_xform);1666collision->cull_mask = RSG::particles_storage->particles_collision_get_cull_mask(p_instance->base);1667} else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {1668InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);1669scene_render->fog_volume_instance_set_transform(volume->instance, *instance_xform);1670} else if (p_instance->base_type == RS::INSTANCE_OCCLUDER) {1671if (p_instance->scenario) {1672RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(p_instance->scenario->self, p_instance->self, p_instance->base, *instance_xform, p_instance->visible);1673}1674} else if (p_instance->base_type == RS::INSTANCE_NONE) {1675return;1676}16771678if (!p_instance->aabb.has_surface()) {1679return;1680}16811682if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {1683//if this moved, update the captured objects1684InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);1685//erase dependencies, since no longer a lightmap16861687for (Instance *E : lightmap_data->geometries) {1688Instance *geom = E;1689_instance_queue_update(geom, true, false);1690}1691}16921693AABB new_aabb;1694new_aabb = instance_xform->xform(p_instance->aabb);1695p_instance->transformed_aabb = new_aabb;16961697if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1698InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);1699//make sure lights are updated if it casts shadow17001701if (geom->can_cast_shadows) {1702for (const Instance *E : geom->lights) {1703InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);1704light->make_shadow_dirty();1705}1706}17071708if (!p_instance->lightmap && geom->lightmap_captures.size()) {1709//affected by lightmap captures, must update capture info!1710_update_instance_lightmap_captures(p_instance);1711} else {1712if (!p_instance->lightmap_sh.is_empty()) {1713p_instance->lightmap_sh.clear(); //don't need SH1714p_instance->lightmap_target_sh.clear(); //don't need SH1715ERR_FAIL_NULL(geom->geometry_instance);1716geom->geometry_instance->set_lightmap_capture(nullptr);1717}1718}17191720ERR_FAIL_NULL(geom->geometry_instance);17211722geom->geometry_instance->set_transform(*instance_xform, p_instance->aabb, p_instance->transformed_aabb);1723if (p_instance->teleported) {1724geom->geometry_instance->reset_motion_vectors();1725}1726}17271728// 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.1729if (p_instance->scenario == nullptr || !p_instance->visible || instance_xform->basis.determinant() == 0) {1730p_instance->prev_transformed_aabb = p_instance->transformed_aabb;1731return;1732}17331734//quantize to improve moving object performance1735AABB bvh_aabb = p_instance->transformed_aabb;17361737if (p_instance->indexer_id.is_valid() && bvh_aabb != p_instance->prev_transformed_aabb) {1738//assume motion, see if bounds need to be quantized1739AABB motion_aabb = bvh_aabb.merge(p_instance->prev_transformed_aabb);1740float motion_longest_axis = motion_aabb.get_longest_axis_size();1741float longest_axis = p_instance->transformed_aabb.get_longest_axis_size();17421743if (motion_longest_axis < longest_axis * 2) {1744//moved but not a lot, use motion aabb quantizing1745float quantize_size = Math::pow(2.0, Math::ceil(Math::log(motion_longest_axis) / Math::log(2.0))) * 0.5; //one fifth1746bvh_aabb.quantize(quantize_size);1747}1748}17491750if (!p_instance->indexer_id.is_valid()) {1751if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1752p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].insert(bvh_aabb, p_instance);1753} else {1754p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(bvh_aabb, p_instance);1755}17561757p_instance->array_index = p_instance->scenario->instance_data.size();1758InstanceData idata;1759idata.instance = p_instance;1760idata.layer_mask = p_instance->layer_mask;1761idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later1762idata.base_rid = p_instance->base;1763idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;1764idata.visibility_index = p_instance->visibility_index;1765idata.occlusion_timeout = 0;17661767for (Instance *E : p_instance->visibility_dependencies) {1768Instance *dep_instance = E;1769if (dep_instance->array_index != -1) {1770dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;1771}1772}17731774switch (p_instance->base_type) {1775case RS::INSTANCE_MESH:1776case RS::INSTANCE_MULTIMESH:1777case RS::INSTANCE_PARTICLES: {1778InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);1779idata.instance_geometry = geom->geometry_instance;1780} break;1781case RS::INSTANCE_LIGHT: {1782InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);1783idata.instance_data_rid = light_data->instance.get_id();1784light_data->uses_projector = RSG::light_storage->light_has_projector(p_instance->base);1785light_data->uses_softshadow = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;17861787} break;1788case RS::INSTANCE_REFLECTION_PROBE: {1789idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance.get_id();1790} break;1791case RS::INSTANCE_DECAL: {1792idata.instance_data_rid = static_cast<InstanceDecalData *>(p_instance->base_data)->instance.get_id();1793} break;1794case RS::INSTANCE_LIGHTMAP: {1795idata.instance_data_rid = static_cast<InstanceLightmapData *>(p_instance->base_data)->instance.get_id();1796} break;1797case RS::INSTANCE_VOXEL_GI: {1798idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();1799} break;1800case RS::INSTANCE_FOG_VOLUME: {1801idata.instance_data_rid = static_cast<InstanceFogVolumeData *>(p_instance->base_data)->instance.get_id();1802} break;1803case RS::INSTANCE_VISIBLITY_NOTIFIER: {1804idata.visibility_notifier = static_cast<InstanceVisibilityNotifierData *>(p_instance->base_data);1805} break;1806default: {1807}1808}18091810if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {1811//always dirty when added1812idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;1813}1814if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {1815idata.flags |= InstanceData::FLAG_CAST_SHADOWS;1816}1817if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {1818idata.flags |= InstanceData::FLAG_CAST_SHADOWS_ONLY;1819}1820if (p_instance->redraw_if_visible) {1821idata.flags |= InstanceData::FLAG_REDRAW_IF_VISIBLE;1822}1823// dirty flags should not be set here, since no pairing has happened1824if (p_instance->baked_light) {1825idata.flags |= InstanceData::FLAG_USES_BAKED_LIGHT;1826}1827if (p_instance->mesh_instance.is_valid()) {1828idata.flags |= InstanceData::FLAG_USES_MESH_INSTANCE;1829}1830if (p_instance->ignore_occlusion_culling) {1831idata.flags |= InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;1832}1833if (p_instance->ignore_all_culling) {1834idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;1835}18361837p_instance->scenario->instance_data.push_back(idata);1838p_instance->scenario->instance_aabbs.push_back(InstanceBounds(p_instance->transformed_aabb));1839_update_instance_visibility_dependencies(p_instance);1840} else {1841if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1842p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, bvh_aabb);1843} else {1844p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].update(p_instance->indexer_id, bvh_aabb);1845}1846p_instance->scenario->instance_aabbs[p_instance->array_index] = InstanceBounds(p_instance->transformed_aabb);1847}18481849if (p_instance->visibility_index != -1) {1850p_instance->scenario->instance_visibility[p_instance->visibility_index].position = p_instance->transformed_aabb.get_center();1851}18521853//move instance and repair1854pair_pass++;18551856PairInstances pair;18571858pair.instance = p_instance;1859pair.pair_allocator = &pair_allocator;1860pair.pair_pass = pair_pass;1861pair.pair_mask = 0;18621863if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1864pair.pair_mask |= 1 << RS::INSTANCE_LIGHT;1865pair.pair_mask |= 1 << RS::INSTANCE_VOXEL_GI;1866pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP;1867if (p_instance->base_type == RS::INSTANCE_PARTICLES) {1868pair.pair_mask |= 1 << RS::INSTANCE_PARTICLES_COLLISION;1869}18701871pair.pair_mask |= geometry_instance_pair_mask;18721873pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];1874} else if (p_instance->base_type == RS::INSTANCE_LIGHT) {1875pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;1876pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];18771878RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);1879if (bake_mode == RS::LIGHT_BAKE_STATIC || bake_mode == RS::LIGHT_BAKE_DYNAMIC) {1880pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI);1881pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];1882}1883} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {1884pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;1885pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1886} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) {1887pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;1888pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1889} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) {1890pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;1891pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1892} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {1893pair.pair_mask = (1 << RS::INSTANCE_PARTICLES);1894pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1895} else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) {1896//lights and geometries1897pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT);1898pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];1899pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];1900}19011902pair.pair();19031904p_instance->prev_transformed_aabb = p_instance->transformed_aabb;1905}19061907void RendererSceneCull::_unpair_instance(Instance *p_instance) {1908if (!p_instance->indexer_id.is_valid()) {1909return; //nothing to do1910}19111912while (p_instance->pairs.first()) {1913InstancePair *pair = p_instance->pairs.first()->self();1914Instance *other_instance = p_instance == pair->a ? pair->b : pair->a;1915_instance_unpair(p_instance, other_instance);1916pair_allocator.free(pair);1917}19181919if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1920p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].remove(p_instance->indexer_id);1921} else {1922p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].remove(p_instance->indexer_id);1923}19241925p_instance->indexer_id = DynamicBVH::ID();19261927//replace this by last1928int32_t swap_with_index = p_instance->scenario->instance_data.size() - 1;1929if (swap_with_index != p_instance->array_index) {1930Instance *swapped_instance = p_instance->scenario->instance_data[swap_with_index].instance;1931swapped_instance->array_index = p_instance->array_index; //swap1932p_instance->scenario->instance_data[p_instance->array_index] = p_instance->scenario->instance_data[swap_with_index];1933p_instance->scenario->instance_aabbs[p_instance->array_index] = p_instance->scenario->instance_aabbs[swap_with_index];19341935if (swapped_instance->visibility_index != -1) {1936swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index;1937}19381939for (Instance *E : swapped_instance->visibility_dependencies) {1940Instance *dep_instance = E;1941if (dep_instance != p_instance && dep_instance->array_index != -1) {1942dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;1943}1944}1945}19461947// pop last1948p_instance->scenario->instance_data.pop_back();1949p_instance->scenario->instance_aabbs.pop_back();19501951//uninitialize1952p_instance->array_index = -1;1953if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1954// Clear these now because the InstanceData containing the dirty flags is gone1955InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);1956ERR_FAIL_NULL(geom->geometry_instance);19571958geom->geometry_instance->pair_light_instances(nullptr, 0);1959geom->geometry_instance->pair_reflection_probe_instances(nullptr, 0);1960geom->geometry_instance->pair_decal_instances(nullptr, 0);1961geom->geometry_instance->pair_voxel_gi_instances(nullptr, 0);1962}19631964for (Instance *E : p_instance->visibility_dependencies) {1965Instance *dep_instance = E;1966if (dep_instance->array_index != -1) {1967dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;1968if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {1969dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry->set_parent_fade_alpha(1.0f);1970}1971}1972}19731974_update_instance_visibility_dependencies(p_instance);1975}19761977void RendererSceneCull::_update_instance_aabb(Instance *p_instance) const {1978AABB new_aabb;19791980ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid());19811982switch (p_instance->base_type) {1983case RenderingServer::INSTANCE_NONE: {1984// do nothing1985} break;1986case RenderingServer::INSTANCE_MESH: {1987if (p_instance->custom_aabb) {1988new_aabb = *p_instance->custom_aabb;1989} else {1990new_aabb = RSG::mesh_storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);1991}19921993} break;19941995case RenderingServer::INSTANCE_MULTIMESH: {1996if (p_instance->custom_aabb) {1997new_aabb = *p_instance->custom_aabb;1998} else {1999new_aabb = RSG::mesh_storage->multimesh_get_aabb(p_instance->base);2000}20012002} break;2003case RenderingServer::INSTANCE_PARTICLES: {2004if (p_instance->custom_aabb) {2005new_aabb = *p_instance->custom_aabb;2006} else {2007new_aabb = RSG::particles_storage->particles_get_aabb(p_instance->base);2008}20092010} break;2011case RenderingServer::INSTANCE_PARTICLES_COLLISION: {2012new_aabb = RSG::particles_storage->particles_collision_get_aabb(p_instance->base);20132014} break;2015case RenderingServer::INSTANCE_FOG_VOLUME: {2016new_aabb = RSG::fog->fog_volume_get_aabb(p_instance->base);2017} break;2018case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {2019new_aabb = RSG::utilities->visibility_notifier_get_aabb(p_instance->base);2020} break;2021case RenderingServer::INSTANCE_LIGHT: {2022new_aabb = RSG::light_storage->light_get_aabb(p_instance->base);20232024} break;2025case RenderingServer::INSTANCE_REFLECTION_PROBE: {2026new_aabb = RSG::light_storage->reflection_probe_get_aabb(p_instance->base);20272028} break;2029case RenderingServer::INSTANCE_DECAL: {2030new_aabb = RSG::texture_storage->decal_get_aabb(p_instance->base);20312032} break;2033case RenderingServer::INSTANCE_VOXEL_GI: {2034new_aabb = RSG::gi->voxel_gi_get_bounds(p_instance->base);20352036} break;2037case RenderingServer::INSTANCE_LIGHTMAP: {2038new_aabb = RSG::light_storage->lightmap_get_aabb(p_instance->base);20392040} break;2041default: {2042}2043}20442045if (p_instance->extra_margin) {2046new_aabb.grow_by(p_instance->extra_margin);2047}20482049p_instance->aabb = new_aabb;2050}20512052void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance) const {2053bool first_set = p_instance->lightmap_sh.is_empty();2054p_instance->lightmap_sh.resize(9); //using SH2055p_instance->lightmap_target_sh.resize(9); //using SH2056Color *instance_sh = p_instance->lightmap_target_sh.ptrw();2057bool inside = false;2058Color accum_sh[9];2059float accum_blend = 0.0;20602061InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);2062for (Instance *E : geom->lightmap_captures) {2063Instance *lightmap = E;20642065bool interior = RSG::light_storage->lightmap_is_interior(lightmap->base);20662067if (inside && !interior) {2068continue; //we are inside, ignore exteriors2069}20702071Transform3D to_bounds = lightmap->transform.affine_inverse();2072Vector3 center = p_instance->transform.xform(p_instance->aabb.get_center()); //use aabb center20732074Vector3 lm_pos = to_bounds.xform(center);20752076AABB bounds = RSG::light_storage->lightmap_get_aabb(lightmap->base);2077if (!bounds.has_point(lm_pos)) {2078continue; //not in this lightmap2079}20802081Color sh[9];2082RSG::light_storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);20832084//rotate it2085Basis rot = lightmap->transform.basis.orthonormalized();2086for (int i = 0; i < 3; i++) {2087real_t csh[9];2088for (int j = 0; j < 9; j++) {2089csh[j] = sh[j][i];2090}2091rot.rotate_sh(csh);2092for (int j = 0; j < 9; j++) {2093sh[j][i] = csh[j];2094}2095}20962097Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);20982099real_t blend = MAX(Math::abs(inner_pos.x), MAX(Math::abs(inner_pos.y), Math::abs(inner_pos.z)));2100//make blend more rounded2101blend = Math::lerp(inner_pos.length(), blend, blend);2102blend *= blend;2103blend = MAX(0.0, 1.0 - blend);21042105if (interior && !inside) {2106//do not blend, just replace2107for (int j = 0; j < 9; j++) {2108accum_sh[j] = sh[j] * blend;2109}2110accum_blend = blend;2111inside = true;2112} else {2113for (int j = 0; j < 9; j++) {2114accum_sh[j] += sh[j] * blend;2115}2116accum_blend += blend;2117}2118}21192120if (accum_blend > 0.0) {2121for (int j = 0; j < 9; j++) {2122instance_sh[j] = accum_sh[j] / accum_blend;2123if (first_set) {2124p_instance->lightmap_sh.write[j] = instance_sh[j];2125}2126}2127}21282129ERR_FAIL_NULL(geom->geometry_instance);2130geom->geometry_instance->set_lightmap_capture(p_instance->lightmap_sh.ptr());2131}21322133void 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) {2134// For later tight culling, the light culler needs to know the details of the directional light.2135light_culler->prepare_directional_light(p_instance, p_shadow_index);21362137InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);21382139Transform3D light_transform = p_instance->transform;2140light_transform.orthonormalize(); //scale does not count on lights21412142real_t max_distance = p_cam_projection.get_z_far();2143real_t shadow_max = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);2144if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera2145max_distance = MIN(shadow_max, max_distance);2146}2147max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);2148real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);21492150real_t pancake_size = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);21512152real_t range = max_distance - min_distance;21532154int splits = 0;2155switch (RSG::light_storage->light_directional_get_shadow_mode(p_instance->base)) {2156case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:2157splits = 1;2158break;2159case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:2160splits = 2;2161break;2162case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:2163splits = 4;2164break;2165}21662167real_t distances[5];21682169distances[0] = min_distance;2170for (int i = 0; i < splits; i++) {2171distances[i + 1] = min_distance + RSG::light_storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;2172};21732174distances[splits] = max_distance;21752176real_t texture_size = RSG::light_storage->get_directional_light_shadow_size(light->instance);21772178bool overlap = RSG::light_storage->light_directional_get_blend_splits(p_instance->base);21792180cull.shadow_count = p_shadow_index + 1;2181cull.shadows[p_shadow_index].cascade_count = splits;2182cull.shadows[p_shadow_index].light_instance = light->instance;2183cull.shadows[p_shadow_index].caster_mask = RSG::light_storage->light_get_shadow_caster_mask(p_instance->base);21842185for (int i = 0; i < splits; i++) {2186RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));21872188// setup a camera matrix for that range!2189Projection camera_matrix;21902191real_t aspect = p_cam_projection.get_aspect();21922193if (p_cam_orthogonal) {2194Vector2 vp_he = p_cam_projection.get_viewport_half_extents();21952196camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);2197} else {2198real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it2199camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);2200}22012202//obtain the frustum endpoints22032204Vector3 endpoints[8]; // frustum plane endpoints2205bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints);2206ERR_CONTINUE(!res);22072208// obtain the light frustum ranges (given endpoints)22092210Transform3D transform = light_transform; //discard scale and stabilize light22112212Vector3 x_vec = transform.basis.get_column(Vector3::AXIS_X).normalized();2213Vector3 y_vec = transform.basis.get_column(Vector3::AXIS_Y).normalized();2214Vector3 z_vec = transform.basis.get_column(Vector3::AXIS_Z).normalized();2215//z_vec points against the camera, like in default opengl22162217real_t x_min = 0.f, x_max = 0.f;2218real_t y_min = 0.f, y_max = 0.f;2219real_t z_min = 0.f, z_max = 0.f;22202221// FIXME: z_max_cam is defined, computed, but not used below when setting up2222// ortho_camera. Commented out for now to fix warnings but should be investigated.2223real_t x_min_cam = 0.f, x_max_cam = 0.f;2224real_t y_min_cam = 0.f, y_max_cam = 0.f;2225real_t z_min_cam = 0.f;2226//real_t z_max_cam = 0.f;22272228//real_t bias_scale = 1.0;2229//real_t aspect_bias_scale = 1.0;22302231//used for culling22322233for (int j = 0; j < 8; j++) {2234real_t d_x = x_vec.dot(endpoints[j]);2235real_t d_y = y_vec.dot(endpoints[j]);2236real_t d_z = z_vec.dot(endpoints[j]);22372238if (j == 0 || d_x < x_min) {2239x_min = d_x;2240}2241if (j == 0 || d_x > x_max) {2242x_max = d_x;2243}22442245if (j == 0 || d_y < y_min) {2246y_min = d_y;2247}2248if (j == 0 || d_y > y_max) {2249y_max = d_y;2250}22512252if (j == 0 || d_z < z_min) {2253z_min = d_z;2254}2255if (j == 0 || d_z > z_max) {2256z_max = d_z;2257}2258}22592260real_t radius = 0;2261real_t soft_shadow_expand = 0;2262Vector3 center;22632264{2265//camera viewport stuff22662267for (int j = 0; j < 8; j++) {2268center += endpoints[j];2269}2270center /= 8.0;22712272//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;22732274for (int j = 0; j < 8; j++) {2275real_t d = center.distance_to(endpoints[j]);2276if (d > radius) {2277radius = d;2278}2279}22802281radius *= texture_size / (texture_size - 2.0); //add a texel by each side22822283z_min_cam = z_vec.dot(center) - radius;22842285{2286float soft_shadow_angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);22872288if (soft_shadow_angle > 0.0) {2289float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;2290soft_shadow_expand = Math::tan(Math::deg_to_rad(soft_shadow_angle)) * z_range;22912292x_max += soft_shadow_expand;2293y_max += soft_shadow_expand;22942295x_min -= soft_shadow_expand;2296y_min -= soft_shadow_expand;2297}2298}22992300// This trick here is what stabilizes the shadow (make potential jaggies to not move)2301// at the cost of some wasted resolution. Still, the quality increase is very well worth it.2302const real_t unit = (radius + soft_shadow_expand) * 4.0 / texture_size;2303x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);2304x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);2305y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);2306y_min_cam = Math::snapped(y_vec.dot(center) - radius - soft_shadow_expand, unit);2307}23082309//now that we know all ranges, we can proceed to make the light frustum planes, for culling octree23102311Vector<Plane> light_frustum_planes;2312light_frustum_planes.resize(6);23132314//right/left2315light_frustum_planes.write[0] = Plane(x_vec, x_max);2316light_frustum_planes.write[1] = Plane(-x_vec, -x_min);2317//top/bottom2318light_frustum_planes.write[2] = Plane(y_vec, y_max);2319light_frustum_planes.write[3] = Plane(-y_vec, -y_min);2320//near/far2321light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6);2322light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed23232324// a pre pass will need to be needed to determine the actual z-near to be used23252326z_max = z_vec.dot(center) + radius + pancake_size;23272328{2329Projection ortho_camera;2330real_t half_x = (x_max_cam - x_min_cam) * 0.5;2331real_t half_y = (y_max_cam - y_min_cam) * 0.5;23322333ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam));23342335Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam));23362337Transform3D ortho_transform;2338ortho_transform.basis = transform.basis;2339ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;23402341cull.shadows[p_shadow_index].cascades[i].frustum = Frustum(light_frustum_planes);2342cull.shadows[p_shadow_index].cascades[i].projection = ortho_camera;2343cull.shadows[p_shadow_index].cascades[i].transform = ortho_transform;2344cull.shadows[p_shadow_index].cascades[i].zfar = z_max - z_min_cam;2345cull.shadows[p_shadow_index].cascades[i].split = distances[i + 1];2346cull.shadows[p_shadow_index].cascades[i].shadow_texel_size = radius * 2.0 / texture_size;2347cull.shadows[p_shadow_index].cascades[i].bias_scale = (z_max - z_min_cam);2348cull.shadows[p_shadow_index].cascades[i].range_begin = z_max;2349cull.shadows[p_shadow_index].cascades[i].uv_scale = uv_scale;2350}2351}2352}23532354bool 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) {2355InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);23562357Transform3D light_transform = p_instance->transform;2358light_transform.orthonormalize(); //scale does not count on lights23592360bool animated_material_found = false;23612362switch (RSG::light_storage->light_get_type(p_instance->base)) {2363case RS::LIGHT_DIRECTIONAL: {2364} break;2365case RS::LIGHT_OMNI: {2366RS::LightOmniShadowMode shadow_mode = RSG::light_storage->light_omni_get_shadow_mode(p_instance->base);23672368if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::light_storage->light_instances_can_render_shadow_cube()) {2369if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) {2370return true;2371}2372for (int i = 0; i < 2; i++) {2373//using this one ensures that raster deferred will have it2374RENDER_TIMESTAMP("Cull OmniLight3D Shadow Paraboloid, Half " + itos(i));23752376real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);23772378real_t z = i == 0 ? -1 : 1;2379Vector<Plane> planes;2380planes.resize(6);2381planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));2382planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));2383planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));2384planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));2385planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));2386planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));23872388instance_shadow_cull_result.clear();23892390Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());23912392struct CullConvex {2393PagedArray<Instance *> *result;2394_FORCE_INLINE_ bool operator()(void *p_data) {2395Instance *p_instance = (Instance *)p_data;2396result->push_back(p_instance);2397return false;2398}2399};24002401CullConvex cull_convex;2402cull_convex.result = &instance_shadow_cull_result;24032404p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);24052406RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];24072408if (!light->is_shadow_update_full()) {2409light_culler->cull_regular_light(instance_shadow_cull_result);2410}24112412for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {2413Instance *instance = instance_shadow_cull_result[j];2414if (!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))) {2415continue;2416} else {2417if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {2418animated_material_found = true;2419}24202421if (instance->mesh_instance.is_valid()) {2422RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);2423}2424}24252426shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);2427}24282429RSG::mesh_storage->update_mesh_instances();24302431RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0);2432shadow_data.light = light->instance;2433shadow_data.pass = i;2434}2435} else { //shadow cube24362437if (max_shadows_used + 6 > MAX_UPDATE_SHADOWS) {2438return true;2439}24402441real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);2442real_t z_near = MIN(0.025f, radius);2443Projection cm;2444cm.set_perspective(90, 1, z_near, radius);24452446for (int i = 0; i < 6; i++) {2447RENDER_TIMESTAMP("Cull OmniLight3D Shadow Cube, Side " + itos(i));2448//using this one ensures that raster deferred will have it24492450static const Vector3 view_normals[6] = {2451Vector3(+1, 0, 0),2452Vector3(-1, 0, 0),2453Vector3(0, -1, 0),2454Vector3(0, +1, 0),2455Vector3(0, 0, +1),2456Vector3(0, 0, -1)2457};2458static const Vector3 view_up[6] = {2459Vector3(0, -1, 0),2460Vector3(0, -1, 0),2461Vector3(0, 0, -1),2462Vector3(0, 0, +1),2463Vector3(0, -1, 0),2464Vector3(0, -1, 0)2465};24662467Transform3D xform = light_transform * Transform3D().looking_at(view_normals[i], view_up[i]);24682469Vector<Plane> planes = cm.get_projection_planes(xform);24702471instance_shadow_cull_result.clear();24722473Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());24742475struct CullConvex {2476PagedArray<Instance *> *result;2477_FORCE_INLINE_ bool operator()(void *p_data) {2478Instance *p_instance = (Instance *)p_data;2479result->push_back(p_instance);2480return false;2481}2482};24832484CullConvex cull_convex;2485cull_convex.result = &instance_shadow_cull_result;24862487p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);24882489RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];24902491if (!light->is_shadow_update_full()) {2492light_culler->cull_regular_light(instance_shadow_cull_result);2493}24942495for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {2496Instance *instance = instance_shadow_cull_result[j];2497if (!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))) {2498continue;2499} else {2500if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {2501animated_material_found = true;2502}2503if (instance->mesh_instance.is_valid()) {2504RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);2505}2506}25072508shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);2509}25102511RSG::mesh_storage->update_mesh_instances();2512RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);25132514shadow_data.light = light->instance;2515shadow_data.pass = i;2516}25172518//restore the regular DP matrix2519//RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0);2520}25212522} break;2523case RS::LIGHT_SPOT: {2524RENDER_TIMESTAMP("Cull SpotLight3D Shadow");25252526if (max_shadows_used + 1 > MAX_UPDATE_SHADOWS) {2527return true;2528}25292530real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);2531real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);2532real_t z_near = MIN(0.025f, radius);25332534Projection cm;2535cm.set_perspective(angle * 2.0, 1.0, z_near, radius);25362537Vector<Plane> planes = cm.get_projection_planes(light_transform);25382539instance_shadow_cull_result.clear();25402541Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());25422543struct CullConvex {2544PagedArray<Instance *> *result;2545_FORCE_INLINE_ bool operator()(void *p_data) {2546Instance *p_instance = (Instance *)p_data;2547result->push_back(p_instance);2548return false;2549}2550};25512552CullConvex cull_convex;2553cull_convex.result = &instance_shadow_cull_result;25542555p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);25562557RendererSceneRender::RenderShadowData &shadow_data = render_shadow_data[max_shadows_used++];25582559if (!light->is_shadow_update_full()) {2560light_culler->cull_regular_light(instance_shadow_cull_result);2561}25622563for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {2564Instance *instance = instance_shadow_cull_result[j];2565if (!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))) {2566continue;2567} else {2568if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {2569animated_material_found = true;2570}25712572if (instance->mesh_instance.is_valid()) {2573RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);2574}2575}2576shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);2577}25782579RSG::mesh_storage->update_mesh_instances();25802581RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);2582shadow_data.light = light->instance;2583shadow_data.pass = 0;25842585} break;2586}25872588return animated_material_found;2589}25902591void 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) {2592#ifndef _3D_DISABLED25932594Camera *camera = camera_owner.get_or_null(p_camera);2595ERR_FAIL_NULL(camera);25962597Vector2 jitter;2598float taa_frame_count = 0.0f;2599if (p_jitter_phase_count > 0) {2600uint32_t current_jitter_count = camera_jitter_array.size();2601if (p_jitter_phase_count != current_jitter_count) {2602// Resize the jitter array and fill it with the pre-computed Halton sequence.2603camera_jitter_array.resize(p_jitter_phase_count);26042605for (uint32_t i = current_jitter_count; i < p_jitter_phase_count; i++) {2606camera_jitter_array[i].x = get_halton_value(i, 2);2607camera_jitter_array[i].y = get_halton_value(i, 3);2608}2609}26102611jitter = camera_jitter_array[RSG::rasterizer->get_frame_number() % p_jitter_phase_count] / p_viewport_size;2612taa_frame_count = float(RSG::rasterizer->get_frame_number() % p_jitter_phase_count);2613}26142615RendererSceneRender::CameraData camera_data;26162617// Setup Camera(s)2618if (p_xr_interface.is_null()) {2619// Normal camera2620Transform3D transform = camera->transform;2621Projection projection;2622bool vaspect = camera->vaspect;2623bool is_orthogonal = false;2624bool is_frustum = false;26252626switch (camera->type) {2627case Camera::ORTHOGONAL: {2628projection.set_orthogonal(2629camera->size,2630p_viewport_size.width / (float)p_viewport_size.height,2631camera->znear,2632camera->zfar,2633camera->vaspect);2634is_orthogonal = true;2635} break;2636case Camera::PERSPECTIVE: {2637projection.set_perspective(2638camera->fov,2639p_viewport_size.width / (float)p_viewport_size.height,2640camera->znear,2641camera->zfar,2642camera->vaspect);26432644} break;2645case Camera::FRUSTUM: {2646projection.set_frustum(2647camera->size,2648p_viewport_size.width / (float)p_viewport_size.height,2649camera->offset,2650camera->znear,2651camera->zfar,2652camera->vaspect);2653is_frustum = true;2654} break;2655}26562657camera_data.set_camera(transform, projection, is_orthogonal, is_frustum, vaspect, jitter, taa_frame_count, camera->visible_layers);2658#ifndef XR_DISABLED2659} else {2660XRServer *xr_server = XRServer::get_singleton();26612662// Setup our camera for our XR interface.2663// We can support multiple views here each with their own camera2664Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];2665Projection projections[RendererSceneRender::MAX_RENDER_VIEWS];26662667uint32_t view_count = p_xr_interface->get_view_count();2668ERR_FAIL_COND_MSG(view_count == 0 || view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");26692670float aspect = p_viewport_size.width / (float)p_viewport_size.height;26712672Transform3D world_origin = xr_server->get_world_origin();26732674// We ignore our camera position, it will have been positioned with a slightly old tracking position.2675// Instead we take our origin point and have our XR interface add fresh tracking data! Whoohoo!2676for (uint32_t v = 0; v < view_count; v++) {2677transforms[v] = p_xr_interface->get_transform_for_view(v, world_origin);2678projections[v] = p_xr_interface->get_projection_for_view(v, aspect, camera->znear, camera->zfar);2679}26802681// If requested, we move the views to be rendered as if the HMD is at the XROrigin.2682if (unlikely(xr_server->is_camera_locked_to_origin())) {2683Transform3D camera_reset = p_xr_interface->get_camera_transform().affine_inverse() * xr_server->get_reference_frame().affine_inverse();2684for (uint32_t v = 0; v < view_count; v++) {2685transforms[v] *= camera_reset;2686}2687}26882689if (view_count == 1) {2690camera_data.set_camera(transforms[0], projections[0], false, false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers);2691} else if (view_count == 2) {2692camera_data.set_multiview_camera(view_count, transforms, projections, false, false, camera->vaspect);2693} else {2694// 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...2695}2696#endif // XR_DISABLED2697}26982699RID environment = _render_get_environment(p_camera, p_scenario);2700RID compositor = _render_get_compositor(p_camera, p_scenario);27012702RENDER_TIMESTAMP("Update Occlusion Buffer")2703// For now just cull on the first camera2704RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal);27052706_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);2707#endif2708}27092710void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) {2711uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();2712uint32_t bin_from = p_thread * cull_data->cull_count / total_threads;2713uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads);27142715_visibility_cull(*cull_data, cull_data->cull_offset + bin_from, cull_data->cull_offset + bin_to);2716}27172718void RendererSceneCull::_visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to) {2719Scenario *scenario = cull_data.scenario;2720for (unsigned int i = p_from; i < p_to; i++) {2721InstanceVisibilityData &vd = scenario->instance_visibility[i];2722InstanceData &idata = scenario->instance_data[vd.array_index];27232724if (idata.parent_array_index >= 0) {2725uint32_t parent_flags = scenario->instance_data[idata.parent_array_index].flags;27262727if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || !(parent_flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN))) {2728idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2729idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2730idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2731continue;2732}2733}27342735int range_check = _visibility_range_check<true>(vd, cull_data.camera_position, cull_data.viewport_mask);27362737if (range_check == -1) {2738idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2739idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2740idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2741} else if (range_check == 1) {2742idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2743idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2744idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2745} else {2746idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;2747idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;2748if (range_check == 2) {2749idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2750} else {2751idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;2752}2753}2754}2755}27562757template <bool p_fade_check>2758int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask) {2759float dist = p_camera_pos.distance_to(r_vis_data.position);2760const RS::VisibilityRangeFadeMode &fade_mode = r_vis_data.fade_mode;27612762float begin_offset = -r_vis_data.range_begin_margin;2763float end_offset = r_vis_data.range_end_margin;27642765if (fade_mode == RS::VISIBILITY_RANGE_FADE_DISABLED && !(p_viewport_mask & r_vis_data.viewport_state)) {2766begin_offset = -begin_offset;2767end_offset = -end_offset;2768}27692770if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end + end_offset) {2771r_vis_data.viewport_state &= ~p_viewport_mask;2772return -1;2773} else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin + begin_offset) {2774r_vis_data.viewport_state &= ~p_viewport_mask;2775return 1;2776} else {2777r_vis_data.viewport_state |= p_viewport_mask;2778if (p_fade_check) {2779if (fade_mode != RS::VISIBILITY_RANGE_FADE_DISABLED) {2780r_vis_data.children_fade_alpha = 1.0f;2781if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end - end_offset) {2782if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {2783r_vis_data.children_fade_alpha = MIN(1.0f, (dist - (r_vis_data.range_end - end_offset)) / (2.0f * r_vis_data.range_end_margin));2784}2785return 2;2786} else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin - begin_offset) {2787if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {2788r_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));2789}2790return 2;2791}2792}2793}2794return 0;2795}2796}27972798bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data) {2799if (p_instance_data.parent_array_index == -1) {2800return true;2801}2802const uint32_t &parent_flags = p_cull_data.scenario->instance_data[p_instance_data.parent_array_index].flags;2803return ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);2804}28052806void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {2807uint32_t cull_total = cull_data->scenario->instance_data.size();2808uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();2809uint32_t cull_from = p_thread * cull_total / total_threads;2810uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);28112812_scene_cull(*cull_data, scene_cull_result_threads[p_thread], cull_from, cull_to);2813}28142815void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to) {2816uint64_t frame_number = RSG::rasterizer->get_frame_number();2817float lightmap_probe_update_speed = RSG::light_storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();28182819uint32_t sdfgi_last_light_index = 0xFFFFFFFF;2820uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;28212822RID instance_pair_buffer[MAX_INSTANCE_PAIRS];28232824Transform3D inv_cam_transform = cull_data.cam_transform.inverse();2825float z_near = cull_data.camera_matrix->get_z_near();28262827for (uint64_t i = p_from; i < p_to; i++) {2828bool mesh_visible = false;28292830InstanceData &idata = cull_data.scenario->instance_data[i];2831uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);2832int32_t visibility_check = -1;28332834#define HIDDEN_BY_VISIBILITY_CHECKS (visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE || visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN)2835#define LAYER_CHECK (cull_data.visible_layers & idata.layer_mask)2836#define IN_FRUSTUM(f) (cull_data.scenario->instance_aabbs[i].in_frustum(f))2837#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)2838#define VIS_PARENT_CHECK (_visibility_parent_check(cull_data, idata))2839#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)2840#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, cull_data.scenario->instance_data[i].occlusion_timeout))28412842if (!HIDDEN_BY_VISIBILITY_CHECKS) {2843if ((LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) || (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_ALL_CULLING)) {2844uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;2845if (base_type == RS::INSTANCE_LIGHT) {2846cull_result.lights.push_back(idata.instance);2847cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));2848if (cull_data.shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(idata.base_rid)) {2849RSG::light_storage->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later2850}28512852} else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {2853if (cull_data.render_reflection_probe != idata.instance) {2854//avoid entering The Matrix28552856if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || RSG::light_storage->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {2857InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);2858cull_data.cull->lock.lock();2859if (!reflection_probe->update_list.in_list()) {2860reflection_probe->render_step = 0;2861reflection_probe_render_list.add_last(&reflection_probe->update_list);2862}2863cull_data.cull->lock.unlock();28642865idata.flags &= ~InstanceData::FLAG_REFLECTION_PROBE_DIRTY;2866}28672868if (RSG::light_storage->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {2869cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));2870}2871}2872} else if (base_type == RS::INSTANCE_DECAL) {2873cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid));28742875} else if (base_type == RS::INSTANCE_VOXEL_GI) {2876InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(idata.instance->base_data);2877cull_data.cull->lock.lock();2878if (!voxel_gi->update_element.in_list()) {2879voxel_gi_update_list.add(&voxel_gi->update_element);2880}2881cull_data.cull->lock.unlock();2882cull_result.voxel_gi_instances.push_back(RID::from_uint64(idata.instance_data_rid));28832884} else if (base_type == RS::INSTANCE_LIGHTMAP) {2885cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));2886} else if (base_type == RS::INSTANCE_FOG_VOLUME) {2887cull_result.fog_volumes.push_back(RID::from_uint64(idata.instance_data_rid));2888} else if (base_type == RS::INSTANCE_VISIBLITY_NOTIFIER) {2889InstanceVisibilityNotifierData *vnd = idata.visibility_notifier;2890if (!vnd->list_element.in_list()) {2891visible_notifier_list_lock.lock();2892visible_notifier_list.add(&vnd->list_element);2893visible_notifier_list_lock.unlock();2894vnd->just_visible = true;2895}2896vnd->visible_in_frame = RSG::rasterizer->get_frame_number();2897} else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {2898bool keep = true;28992900if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {2901RenderingServerDefault::redraw_request();2902}29032904if (base_type == RS::INSTANCE_MESH) {2905mesh_visible = true;2906} else if (base_type == RS::INSTANCE_PARTICLES) {2907//particles visible? process them2908if (RSG::particles_storage->particles_is_inactive(idata.base_rid)) {2909//but if nothing is going on, don't do it.2910keep = false;2911} else {2912cull_data.cull->lock.lock();2913RSG::particles_storage->particles_request_process(idata.base_rid);2914cull_data.cull->lock.unlock();29152916RS::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()));2917//particles visible? request redraw2918RenderingServerDefault::redraw_request();2919}2920}29212922if (idata.parent_array_index != -1) {2923float fade = 1.0f;2924const uint32_t &parent_flags = cull_data.scenario->instance_data[idata.parent_array_index].flags;2925if (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN) {2926const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index;2927fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha;2928}2929idata.instance_geometry->set_parent_fade_alpha(fade);2930}29312932if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {2933InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);2934uint32_t idx = 0;29352936for (const Instance *E : geom->lights) {2937InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);2938if (!(RSG::light_storage->light_get_cull_mask(E->base) & idata.layer_mask)) {2939continue;2940}29412942if ((RSG::light_storage->light_get_bake_mode(E->base) == RS::LIGHT_BAKE_STATIC) && idata.instance->lightmap) {2943continue;2944}29452946instance_pair_buffer[idx++] = light->instance;2947if (idx == MAX_INSTANCE_PAIRS) {2948break;2949}2950}29512952ERR_FAIL_NULL(geom->geometry_instance);2953geom->geometry_instance->pair_light_instances(instance_pair_buffer, idx);2954idata.flags &= ~InstanceData::FLAG_GEOM_LIGHTING_DIRTY;2955}29562957if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {2958InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);29592960ERR_FAIL_NULL(geom->geometry_instance);2961cull_data.cull->lock.lock();2962geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0);2963cull_data.cull->lock.unlock();2964idata.flags &= ~InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;2965}29662967if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {2968InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);2969uint32_t idx = 0;29702971for (const Instance *E : geom->reflection_probes) {2972InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->base_data);29732974instance_pair_buffer[idx++] = reflection_probe->instance;2975if (idx == MAX_INSTANCE_PAIRS) {2976break;2977}2978}29792980ERR_FAIL_NULL(geom->geometry_instance);2981geom->geometry_instance->pair_reflection_probe_instances(instance_pair_buffer, idx);2982idata.flags &= ~InstanceData::FLAG_GEOM_REFLECTION_DIRTY;2983}29842985if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {2986InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);2987uint32_t idx = 0;29882989for (const Instance *E : geom->decals) {2990InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->base_data);29912992instance_pair_buffer[idx++] = decal->instance;2993if (idx == MAX_INSTANCE_PAIRS) {2994break;2995}2996}29972998ERR_FAIL_NULL(geom->geometry_instance);2999geom->geometry_instance->pair_decal_instances(instance_pair_buffer, idx);30003001idata.flags &= ~InstanceData::FLAG_GEOM_DECAL_DIRTY;3002}30033004if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) {3005InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);3006uint32_t idx = 0;3007for (const Instance *E : geom->voxel_gi_instances) {3008InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->base_data);30093010instance_pair_buffer[idx++] = voxel_gi->probe_instance;3011if (idx == MAX_INSTANCE_PAIRS) {3012break;3013}3014}30153016ERR_FAIL_NULL(geom->geometry_instance);3017geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);30183019idata.flags &= ~InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;3020}30213022if ((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()) {3023InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);3024Color *sh = idata.instance->lightmap_sh.ptrw();3025const Color *target_sh = idata.instance->lightmap_target_sh.ptr();3026for (uint32_t j = 0; j < 9; j++) {3027sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));3028}3029ERR_FAIL_NULL(geom->geometry_instance);3030cull_data.cull->lock.lock();3031geom->geometry_instance->set_lightmap_capture(sh);3032cull_data.cull->lock.unlock();3033idata.instance->last_frame_pass = frame_number;3034}30353036if (keep) {3037cull_result.geometry_instances.push_back(idata.instance_geometry);3038}3039}3040}30413042for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) {3043if (!light_culler->cull_directional_light(cull_data.scenario->instance_aabbs[i], j)) {3044continue;3045}3046for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) {3047if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {3048uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;30493050if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && (LAYER_CHECK & cull_data.cull->shadows[j].caster_mask)) {3051cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);3052mesh_visible = true;3053}3054}3055}3056}3057}30583059#undef HIDDEN_BY_VISIBILITY_CHECKS3060#undef LAYER_CHECK3061#undef IN_FRUSTUM3062#undef VIS_RANGE_CHECK3063#undef VIS_PARENT_CHECK3064#undef VIS_CHECK3065#undef OCCLUSION_CULLED30663067for (uint32_t j = 0; j < cull_data.cull->sdfgi.region_count; j++) {3068if (cull_data.scenario->instance_aabbs[i].in_aabb(cull_data.cull->sdfgi.region_aabb[j])) {3069uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;30703071if (base_type == RS::INSTANCE_LIGHT) {3072InstanceLightData *instance_light = (InstanceLightData *)idata.instance->base_data;3073if (instance_light->bake_mode == RS::LIGHT_BAKE_STATIC && cull_data.cull->sdfgi.region_cascade[j] <= instance_light->max_sdfgi_cascade) {3074if (sdfgi_last_light_index != i || sdfgi_last_light_cascade != cull_data.cull->sdfgi.region_cascade[j]) {3075sdfgi_last_light_index = i;3076sdfgi_last_light_cascade = cull_data.cull->sdfgi.region_cascade[j];3077cull_result.sdfgi_cascade_lights[sdfgi_last_light_cascade].push_back(instance_light->instance);3078}3079}3080} else if ((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) {3081if (idata.flags & InstanceData::FLAG_USES_BAKED_LIGHT) {3082cull_result.sdfgi_region_geometry_instances[j].push_back(idata.instance_geometry);3083mesh_visible = true;3084}3085}3086}3087}30883089if (mesh_visible && cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_USES_MESH_INSTANCE) {3090cull_result.mesh_instances.push_back(cull_data.scenario->instance_data[i].instance->mesh_instance);3091}3092}3093}30943095void RendererSceneCull::_scene_particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {3096RSG::particles_storage->particles_set_view_axis(p_particles, p_axis, p_up_axis);3097}30983099void 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) {3100Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it31013102// Prepare the light - camera volume culling system.3103light_culler->prepare_camera(p_camera_data->main_transform, p_camera_data->main_projection);31043105Scenario *scenario = scenario_owner.get_or_null(p_scenario);3106Vector3 camera_position = p_camera_data->main_transform.origin;31073108ERR_FAIL_COND(p_render_buffers.is_null());31093110render_pass++;31113112scene_render->set_scene_pass(render_pass);31133114if (p_reflection_probe.is_null()) {3115//no rendering code here, this is only to set up what needs to be done, request regions, etc.3116scene_render->sdfgi_update(p_render_buffers, p_environment, camera_position); //update conditions for SDFGI (whether its used or not)3117}31183119RENDER_TIMESTAMP("Update Visibility Dependencies");31203121if (scenario->instance_visibility.get_bin_count() > 0) {3122if (!scenario->viewport_visibility_masks.has(p_viewport)) {3123scenario_add_viewport_visibility_mask(scenario->self, p_viewport);3124}31253126VisibilityCullData visibility_cull_data;3127visibility_cull_data.scenario = scenario;3128visibility_cull_data.viewport_mask = scenario->viewport_visibility_masks[p_viewport];3129visibility_cull_data.camera_position = camera_position;31303131for (int i = scenario->instance_visibility.get_bin_count() - 1; i > 0; i--) { // We skip bin 03132visibility_cull_data.cull_offset = scenario->instance_visibility.get_bin_start(i);3133visibility_cull_data.cull_count = scenario->instance_visibility.get_bin_size(i);31343135if (visibility_cull_data.cull_count == 0) {3136continue;3137}31383139if (visibility_cull_data.cull_count > thread_cull_threshold) {3140WorkerThreadPool::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"));3141WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);3142} else {3143_visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count);3144}3145}3146}31473148RENDER_TIMESTAMP("Cull 3D Scene");31493150//rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_orthogonal);31513152/* STEP 2 - CULL */31533154Vector<Plane> planes = p_camera_data->main_projection.get_projection_planes(p_camera_data->main_transform);3155cull.frustum = Frustum(planes);31563157Vector<RID> directional_lights;3158// directional lights3159{3160cull.shadow_count = 0;31613162Vector<Instance *> lights_with_shadow;31633164for (Instance *E : scenario->directional_lights) {3165if (!E->visible || !(E->layer_mask & p_visible_layers)) {3166continue;3167}31683169if (directional_lights.size() >= RendererSceneRender::MAX_DIRECTIONAL_LIGHTS) {3170break;3171}31723173InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);31743175//check shadow..31763177if (light) {3178if (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)) {3179lights_with_shadow.push_back(E);3180}3181//add to list3182directional_lights.push_back(light->instance);3183}3184}31853186RSG::light_storage->set_directional_shadow_count(lights_with_shadow.size());31873188for (int i = 0; i < lights_with_shadow.size(); i++) {3189_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);3190}3191}31923193{ //sdfgi3194cull.sdfgi.region_count = 0;31953196if (p_reflection_probe.is_null()) {3197cull.sdfgi.cascade_light_count = 0;31983199uint32_t prev_cascade = 0xFFFFFFFF;3200uint32_t pending_region_count = scene_render->sdfgi_get_pending_region_count(p_render_buffers);32013202for (uint32_t i = 0; i < pending_region_count; i++) {3203cull.sdfgi.region_aabb[i] = scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i);3204uint32_t region_cascade = scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i);3205cull.sdfgi.region_cascade[i] = region_cascade;32063207if (region_cascade != prev_cascade) {3208cull.sdfgi.cascade_light_index[cull.sdfgi.cascade_light_count] = region_cascade;3209cull.sdfgi.cascade_light_count++;3210prev_cascade = region_cascade;3211}3212}32133214cull.sdfgi.region_count = pending_region_count;3215}3216}32173218scene_cull_result.clear();32193220{3221uint64_t cull_from = 0;3222uint64_t cull_to = scenario->instance_data.size();32233224CullData cull_data;32253226//prepare for eventual thread usage3227cull_data.cull = &cull;3228cull_data.scenario = scenario;3229cull_data.shadow_atlas = p_shadow_atlas;3230cull_data.cam_transform = p_camera_data->main_transform;3231cull_data.visible_layers = p_visible_layers;3232cull_data.render_reflection_probe = render_reflection_probe;3233cull_data.occlusion_buffer = RendererSceneOcclusionCull::get_singleton()->buffer_get_ptr(p_viewport);3234cull_data.camera_matrix = &p_camera_data->main_projection;3235cull_data.visibility_viewport_mask = scenario->viewport_visibility_masks.has(p_viewport) ? scenario->viewport_visibility_masks[p_viewport] : 0;3236//#define DEBUG_CULL_TIME3237#ifdef DEBUG_CULL_TIME3238uint64_t time_from = OS::get_singleton()->get_ticks_usec();3239#endif32403241if (cull_to > thread_cull_threshold) {3242//multiple threads3243for (InstanceCullResult &thread : scene_cull_result_threads) {3244thread.clear();3245}32463247WorkerThreadPool::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"));3248WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);32493250for (InstanceCullResult &thread : scene_cull_result_threads) {3251scene_cull_result.append_from(thread);3252}32533254} else {3255//single threaded3256_scene_cull(cull_data, scene_cull_result, cull_from, cull_to);3257}32583259#ifdef DEBUG_CULL_TIME3260static float time_avg = 0;3261static uint32_t time_count = 0;3262time_avg += double(OS::get_singleton()->get_ticks_usec() - time_from) / 1000.0;3263time_count++;3264print_line("time taken: " + rtos(time_avg / time_count));3265#endif32663267if (scene_cull_result.mesh_instances.size()) {3268for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) {3269RSG::mesh_storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);3270}3271RSG::mesh_storage->update_mesh_instances();3272}3273}32743275//render shadows32763277max_shadows_used = 0;32783279if (p_using_shadows) { //setup shadow maps32803281// Directional Shadows32823283for (uint32_t i = 0; i < cull.shadow_count; i++) {3284for (uint32_t j = 0; j < cull.shadows[i].cascade_count; j++) {3285const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j];3286// print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size()));3287RSG::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);3288if (max_shadows_used == MAX_UPDATE_SHADOWS) {3289continue;3290}3291render_shadow_data[max_shadows_used].light = cull.shadows[i].light_instance;3292render_shadow_data[max_shadows_used].pass = j;3293render_shadow_data[max_shadows_used].instances.merge_unordered(scene_cull_result.directional_shadows[i].cascade_geometry_instances[j]);3294max_shadows_used++;3295}3296}32973298// Positional Shadows3299for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) {3300Instance *ins = scene_cull_result.lights[i];33013302if (!p_shadow_atlas.is_valid()) {3303continue;3304}33053306InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);33073308if (!RSG::light_storage->light_instance_is_shadow_visible_at_position(light->instance, camera_position)) {3309continue;3310}33113312float coverage = 0.f;33133314{ //compute coverage33153316Transform3D cam_xf = p_camera_data->main_transform;3317float zn = p_camera_data->main_projection.get_z_near();3318Plane p(-cam_xf.basis.get_column(2), cam_xf.origin + cam_xf.basis.get_column(2) * -zn); //camera near plane33193320// near plane half width and height3321Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();33223323switch (RSG::light_storage->light_get_type(ins->base)) {3324case RS::LIGHT_OMNI: {3325float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);33263327//get two points parallel to near plane3328Vector3 points[2] = {3329ins->transform.origin,3330ins->transform.origin + cam_xf.basis.get_column(0) * radius3331};33323333if (!p_camera_data->is_orthogonal) {3334//if using perspetive, map them to near plane3335for (int j = 0; j < 2; j++) {3336if (p.distance_to(points[j]) < 0) {3337points[j].z = -zn; //small hack to keep size constant when hitting the screen3338}33393340p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane3341}3342}33433344float screen_diameter = points[0].distance_to(points[1]) * 2;3345coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);3346} break;3347case RS::LIGHT_SPOT: {3348float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);3349float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);33503351float w = radius * Math::sin(Math::deg_to_rad(angle));3352float d = radius * Math::cos(Math::deg_to_rad(angle));33533354Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d;33553356Vector3 points[2] = {3357base,3358base + cam_xf.basis.get_column(0) * w3359};33603361if (!p_camera_data->is_orthogonal) {3362//if using perspetive, map them to near plane3363for (int j = 0; j < 2; j++) {3364if (p.distance_to(points[j]) < 0) {3365points[j].z = -zn; //small hack to keep size constant when hitting the screen3366}33673368p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane3369}3370}33713372float screen_diameter = points[0].distance_to(points[1]) * 2;3373coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);33743375} break;3376default: {3377ERR_PRINT("Invalid Light Type");3378}3379}3380}33813382// We can detect whether multiple cameras are hitting this light, whether or not the shadow is dirty,3383// so that we can turn off tighter caster culling.3384light->detect_light_intersects_multiple_cameras(Engine::get_singleton()->get_frames_drawn());33853386if (light->is_shadow_dirty()) {3387// Dirty shadows have no need to be drawn if3388// the light volume doesn't intersect the camera frustum.33893390// Returns false if the entire light can be culled.3391bool allow_redraw = light_culler->prepare_regular_light(*ins);33923393// Directional lights aren't handled here, _light_instance_update_shadow is called from elsewhere.3394// Checking for this in case this changes, as this is assumed.3395DEV_CHECK_ONCE(RSG::light_storage->light_get_type(ins->base) != RS::LIGHT_DIRECTIONAL);33963397// Tighter caster culling to the camera frustum should work correctly with multiple viewports + cameras.3398// The first camera will cull tightly, but if the light is present on more than 1 camera, the second will3399// do a full render, and mark the light as non-dirty.3400// There is however a cost to tighter shadow culling in this situation (2 shadow updates in 1 frame),3401// so we should detect this and switch off tighter caster culling automatically.3402// This is done in the logic for `decrement_shadow_dirty()`.3403if (allow_redraw) {3404light->last_version++;3405light->decrement_shadow_dirty();3406}3407}34083409bool redraw = RSG::light_storage->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);34103411if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {3412//must redraw!3413RENDER_TIMESTAMP("> Render Light3D " + itos(i));3414if (_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)) {3415light->make_shadow_dirty();3416}3417RENDER_TIMESTAMP("< Render Light3D " + itos(i));3418} else {3419if (redraw) {3420light->make_shadow_dirty();3421}3422}3423}3424}34253426//render SDFGI34273428{3429// Q: Should this whole block be skipped if we're rendering our reflection probe?34303431sdfgi_update_data.update_static = false;34323433if (cull.sdfgi.region_count > 0) {3434//update regions3435for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {3436render_sdfgi_data[i].instances.merge_unordered(scene_cull_result.sdfgi_region_geometry_instances[i]);3437render_sdfgi_data[i].region = i;3438}3439//check if static lights were culled3440bool static_lights_culled = false;3441for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) {3442if (scene_cull_result.sdfgi_cascade_lights[i].size()) {3443static_lights_culled = true;3444break;3445}3446}34473448if (static_lights_culled) {3449sdfgi_update_data.static_cascade_count = cull.sdfgi.cascade_light_count;3450sdfgi_update_data.static_cascade_indices = cull.sdfgi.cascade_light_index;3451sdfgi_update_data.static_positional_lights = scene_cull_result.sdfgi_cascade_lights;3452sdfgi_update_data.update_static = true;3453}3454}34553456if (p_reflection_probe.is_null()) {3457sdfgi_update_data.directional_lights = &directional_lights;3458sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr();3459sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size();3460}3461}34623463//append the directional lights to the lights culled3464for (int i = 0; i < directional_lights.size(); i++) {3465scene_cull_result.light_instances.push_back(directional_lights[i]);3466}34673468RID camera_attributes;3469if (p_force_camera_attributes.is_valid()) {3470camera_attributes = p_force_camera_attributes;3471} else {3472camera_attributes = scenario->camera_attributes;3473}34743475/* PROCESS GEOMETRY AND DRAW SCENE */34763477RID occluders_tex;3478const RendererSceneRender::CameraData *prev_camera_data = p_camera_data;3479if (p_viewport.is_valid()) {3480occluders_tex = RSG::viewport->viewport_get_occluder_debug_texture(p_viewport);3481prev_camera_data = RSG::viewport->viewport_get_prev_camera_data(p_viewport);3482}34833484RENDER_TIMESTAMP("Render 3D Scene");3485scene_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);34863487if (p_viewport.is_valid()) {3488RSG::viewport->viewport_set_prev_camera_data(p_viewport, p_camera_data);3489}34903491for (uint32_t i = 0; i < max_shadows_used; i++) {3492render_shadow_data[i].instances.clear();3493}3494max_shadows_used = 0;34953496for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {3497render_sdfgi_data[i].instances.clear();3498}3499}35003501RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {3502Camera *camera = camera_owner.get_or_null(p_camera);3503if (camera && scene_render->is_environment(camera->env)) {3504return camera->env;3505}35063507Scenario *scenario = scenario_owner.get_or_null(p_scenario);3508if (!scenario) {3509return RID();3510}3511if (scene_render->is_environment(scenario->environment)) {3512return scenario->environment;3513}35143515if (scene_render->is_environment(scenario->fallback_environment)) {3516return scenario->fallback_environment;3517}35183519return RID();3520}35213522RID RendererSceneCull::_render_get_compositor(RID p_camera, RID p_scenario) {3523Camera *camera = camera_owner.get_or_null(p_camera);3524if (camera && scene_render->is_compositor(camera->compositor)) {3525return camera->compositor;3526}35273528Scenario *scenario = scenario_owner.get_or_null(p_scenario);3529if (scenario && scene_render->is_compositor(scenario->compositor)) {3530return scenario->compositor;3531}35323533return RID();3534}35353536void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) {3537#ifndef _3D_DISABLED3538Scenario *scenario = scenario_owner.get_or_null(p_scenario);35393540RID environment;3541if (scenario->environment.is_valid()) {3542environment = scenario->environment;3543} else {3544environment = scenario->fallback_environment;3545}3546RID compositor = scenario->compositor;3547RENDER_TIMESTAMP("Render Empty 3D Scene");35483549RendererSceneRender::CameraData camera_data;3550camera_data.set_camera(Transform3D(), Projection(), true, false, false);35513552scene_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);3553#endif3554}35553556bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int p_step) {3557InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);3558Scenario *scenario = p_instance->scenario;3559ERR_FAIL_NULL_V(scenario, true);35603561RenderingServerDefault::redraw_request(); //update, so it updates in editor35623563if (p_step == 0) {3564if (!RSG::light_storage->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {3565return true; // All full, no atlas entry to render to.3566}3567} else if (!RSG::light_storage->reflection_probe_has_atlas_index(reflection_probe->instance)) {3568// We don't have an atlas to render to, just round off.3569// This is likely due to the atlas being reset.3570// If so the probe will be marked as dirty and start over.3571return true;3572}35733574if (p_step >= 0 && p_step < 6) {3575static const Vector3 view_normals[6] = {3576Vector3(+1, 0, 0),3577Vector3(-1, 0, 0),3578Vector3(0, +1, 0),3579Vector3(0, -1, 0),3580Vector3(0, 0, +1),3581Vector3(0, 0, -1)3582};3583static const Vector3 view_up[6] = {3584Vector3(0, -1, 0),3585Vector3(0, -1, 0),3586Vector3(0, 0, +1),3587Vector3(0, 0, -1),3588Vector3(0, -1, 0),3589Vector3(0, -1, 0)3590};35913592Vector3 probe_size = RSG::light_storage->reflection_probe_get_size(p_instance->base);3593Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base);3594float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base);3595float atlas_size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas);3596float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / atlas_size;35973598Vector3 edge = view_normals[p_step] * probe_size / 2;3599float distance = Math::abs(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit36003601max_distance = MAX(max_distance, distance);36023603//render cubemap side3604Projection cm;3605cm.set_perspective(90, 1, 0.01, max_distance);36063607Transform3D local_view;3608local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]);36093610Transform3D xform = p_instance->transform * local_view;36113612RID shadow_atlas;36133614bool use_shadows = RSG::light_storage->reflection_probe_renders_shadows(p_instance->base);3615if (use_shadows) {3616shadow_atlas = scenario->reflection_probe_shadow_atlas;3617}36183619RID environment;3620if (scenario->environment.is_valid()) {3621environment = scenario->environment;3622} else {3623environment = scenario->fallback_environment;3624}36253626RENDER_TIMESTAMP("Render ReflectionProbe, Step " + itos(p_step));3627RendererSceneRender::CameraData camera_data;3628camera_data.set_camera(xform, cm, false, false, false);36293630Ref<RenderSceneBuffers> render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas);3631_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, p_step, mesh_lod_threshold, use_shadows);36323633} else {3634//do roughness postprocess step until it believes it's done3635RENDER_TIMESTAMP("Post-Process ReflectionProbe, Step " + itos(p_step));3636return RSG::light_storage->reflection_probe_instance_postprocess_step(reflection_probe->instance);3637}36383639return false;3640}36413642void RendererSceneCull::render_probes() {3643/* REFLECTION PROBES */36443645SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();3646Vector<SelfList<InstanceReflectionProbeData> *> done_list;36473648bool busy = false;36493650if (ref_probe) {3651RENDER_TIMESTAMP("Render ReflectionProbes");36523653while (ref_probe) {3654SelfList<InstanceReflectionProbeData> *next = ref_probe->next();3655RID base = ref_probe->self()->owner->base;36563657switch (RSG::light_storage->reflection_probe_get_update_mode(base)) {3658case RS::REFLECTION_PROBE_UPDATE_ONCE: {3659if (busy) { // Already rendering something.3660break;3661}36623663bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);3664if (done) {3665done_list.push_back(ref_probe);3666} else {3667ref_probe->self()->render_step++;3668}36693670busy = true; // Do not render another one of this kind.3671} break;3672case RS::REFLECTION_PROBE_UPDATE_ALWAYS: {3673int step = 0;3674bool done = false;3675while (!done) {3676done = _render_reflection_probe_step(ref_probe->self()->owner, step);3677step++;3678}36793680done_list.push_back(ref_probe);3681} break;3682}36833684ref_probe = next;3685}36863687// Now remove from our list3688for (SelfList<InstanceReflectionProbeData> *rp : done_list) {3689reflection_probe_render_list.remove(rp);3690}3691}36923693/* VOXEL GIS */36943695SelfList<InstanceVoxelGIData> *voxel_gi = voxel_gi_update_list.first();36963697if (voxel_gi) {3698RENDER_TIMESTAMP("Render VoxelGI");3699}37003701while (voxel_gi) {3702SelfList<InstanceVoxelGIData> *next = voxel_gi->next();37033704InstanceVoxelGIData *probe = voxel_gi->self();3705//Instance *instance_probe = probe->owner;37063707//check if probe must be setup, but don't do if on the lighting thread37083709bool cache_dirty = false;3710int cache_count = 0;3711{3712int light_cache_size = probe->light_cache.size();3713const InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptr();3714const RID *instance_caches = probe->light_instances.ptr();37153716int idx = 0; //must count visible lights3717for (Instance *E : probe->lights) {3718Instance *instance = E;3719InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3720if (!instance->visible) {3721continue;3722}3723if (cache_dirty) {3724//do nothing, since idx must count all visible lights anyway3725} else if (idx >= light_cache_size) {3726cache_dirty = true;3727} else {3728const InstanceVoxelGIData::LightCache *cache = &caches[idx];37293730if (3731instance_caches[idx] != instance_light->instance ||3732cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||3733cache->type != RSG::light_storage->light_get_type(instance->base) ||3734cache->transform != instance->transform ||3735cache->color != RSG::light_storage->light_get_color(instance->base) ||3736cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||3737cache->intensity != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY) ||3738cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||3739cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||3740cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||3741cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||3742cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {3743cache_dirty = true;3744}3745}37463747idx++;3748}37493750for (const Instance *instance : probe->owner->scenario->directional_lights) {3751InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3752if (!instance->visible) {3753continue;3754}3755if (cache_dirty) {3756//do nothing, since idx must count all visible lights anyway3757} else if (idx >= light_cache_size) {3758cache_dirty = true;3759} else {3760const InstanceVoxelGIData::LightCache *cache = &caches[idx];37613762if (3763instance_caches[idx] != instance_light->instance ||3764cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||3765cache->type != RSG::light_storage->light_get_type(instance->base) ||3766cache->transform != instance->transform ||3767cache->color != RSG::light_storage->light_get_color(instance->base) ||3768cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||3769cache->intensity != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY) ||3770cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||3771cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||3772cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||3773cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||3774cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||3775cache->sky_mode != RSG::light_storage->light_directional_get_sky_mode(instance->base)) {3776cache_dirty = true;3777}3778}37793780idx++;3781}37823783if (idx != light_cache_size) {3784cache_dirty = true;3785}37863787cache_count = idx;3788}37893790bool update_lights = scene_render->voxel_gi_needs_update(probe->probe_instance);37913792if (cache_dirty) {3793probe->light_cache.resize(cache_count);3794probe->light_instances.resize(cache_count);37953796if (cache_count) {3797InstanceVoxelGIData::LightCache *caches = probe->light_cache.ptrw();3798RID *instance_caches = probe->light_instances.ptrw();37993800int idx = 0; //must count visible lights3801for (Instance *E : probe->lights) {3802Instance *instance = E;3803InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3804if (!instance->visible) {3805continue;3806}38073808InstanceVoxelGIData::LightCache *cache = &caches[idx];38093810instance_caches[idx] = instance_light->instance;3811cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);3812cache->type = RSG::light_storage->light_get_type(instance->base);3813cache->transform = instance->transform;3814cache->color = RSG::light_storage->light_get_color(instance->base);3815cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);3816cache->intensity = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY);3817cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);3818cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);3819cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);3820cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);3821cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);38223823idx++;3824}3825for (const Instance *instance : probe->owner->scenario->directional_lights) {3826InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;3827if (!instance->visible) {3828continue;3829}38303831InstanceVoxelGIData::LightCache *cache = &caches[idx];38323833instance_caches[idx] = instance_light->instance;3834cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);3835cache->type = RSG::light_storage->light_get_type(instance->base);3836cache->transform = instance->transform;3837cache->color = RSG::light_storage->light_get_color(instance->base);3838cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);3839cache->intensity = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY);3840cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);3841cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);3842cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);3843cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);3844cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);3845cache->sky_mode = RSG::light_storage->light_directional_get_sky_mode(instance->base);38463847idx++;3848}3849}38503851update_lights = true;3852}38533854scene_cull_result.geometry_instances.clear();38553856RID instance_pair_buffer[MAX_INSTANCE_PAIRS];38573858for (Instance *E : probe->dynamic_geometries) {3859Instance *ins = E;3860if (!ins->visible) {3861continue;3862}3863InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;38643865if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY)) {3866uint32_t idx = 0;3867for (const Instance *F : geom->voxel_gi_instances) {3868InstanceVoxelGIData *voxel_gi2 = static_cast<InstanceVoxelGIData *>(F->base_data);38693870instance_pair_buffer[idx++] = voxel_gi2->probe_instance;3871if (idx == MAX_INSTANCE_PAIRS) {3872break;3873}3874}38753876ERR_FAIL_NULL(geom->geometry_instance);3877geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);38783879ins->scenario->instance_data[ins->array_index].flags &= ~InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY;3880}38813882ERR_FAIL_NULL(geom->geometry_instance);3883scene_cull_result.geometry_instances.push_back(geom->geometry_instance);3884}38853886scene_render->voxel_gi_update(probe->probe_instance, update_lights, probe->light_instances, scene_cull_result.geometry_instances);38873888voxel_gi_update_list.remove(voxel_gi);38893890voxel_gi = next;3891}3892}38933894void RendererSceneCull::render_particle_colliders() {3895while (heightfield_particle_colliders_update_list.begin()) {3896Instance *hfpc = *heightfield_particle_colliders_update_list.begin();38973898if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::particles_storage->particles_collision_is_heightfield(hfpc->base)) {3899//update heightfield3900instance_cull_result.clear();3901scene_cull_result.geometry_instances.clear();39023903struct CullAABB {3904PagedArray<Instance *> *result;3905uint32_t heightfield_mask;3906_FORCE_INLINE_ bool operator()(void *p_data) {3907Instance *p_instance = (Instance *)p_data;3908if (p_instance->layer_mask & heightfield_mask) {3909result->push_back(p_instance);3910}3911return false;3912}3913};39143915CullAABB cull_aabb;3916cull_aabb.result = &instance_cull_result;3917cull_aabb.heightfield_mask = RSG::particles_storage->particles_collision_get_height_field_mask(hfpc->base);3918hfpc->scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(hfpc->transformed_aabb, cull_aabb);3919hfpc->scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(hfpc->transformed_aabb, cull_aabb);39203921for (int i = 0; i < (int)instance_cull_result.size(); i++) {3922Instance *instance = instance_cull_result[i];3923if (!instance || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision3924continue;3925}3926InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);3927ERR_FAIL_NULL(geom->geometry_instance);3928scene_cull_result.geometry_instances.push_back(geom->geometry_instance);3929}39303931scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, scene_cull_result.geometry_instances);3932}3933heightfield_particle_colliders_update_list.remove(heightfield_particle_colliders_update_list.begin());3934}3935}39363937void RendererSceneCull::_update_dirty_instance(Instance *p_instance) const {3938if (p_instance->update_aabb) {3939_update_instance_aabb(p_instance);3940}39413942if (p_instance->update_dependencies) {3943p_instance->dependency_tracker.update_begin();39443945if (p_instance->base.is_valid()) {3946RSG::utilities->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);3947}39483949if (p_instance->material_override.is_valid()) {3950RSG::material_storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);3951}39523953if (p_instance->material_overlay.is_valid()) {3954RSG::material_storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);3955}39563957if (p_instance->base_type == RS::INSTANCE_MESH) {3958//remove materials no longer used and un-own them39593960int new_mat_count = RSG::mesh_storage->mesh_get_surface_count(p_instance->base);3961p_instance->materials.resize(new_mat_count);39623963_instance_update_mesh_instance(p_instance);3964}39653966if (p_instance->base_type == RS::INSTANCE_PARTICLES) {3967// update the process material dependency39683969RID particle_material = RSG::particles_storage->particles_get_process_material(p_instance->base);3970if (particle_material.is_valid()) {3971RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);3972}3973}39743975if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {3976InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);39773978bool can_cast_shadows = true;3979bool is_animated = false;39803981p_instance->instance_uniforms.materials_start();39823983if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {3984can_cast_shadows = false;3985}39863987if (p_instance->material_override.is_valid()) {3988if (!RSG::material_storage->material_casts_shadows(p_instance->material_override)) {3989can_cast_shadows = false;3990}3991is_animated = RSG::material_storage->material_is_animated(p_instance->material_override);3992p_instance->instance_uniforms.materials_append(p_instance->material_override);3993} else {3994if (p_instance->base_type == RS::INSTANCE_MESH) {3995RID mesh = p_instance->base;39963997if (mesh.is_valid()) {3998bool cast_shadows = false;39994000for (int i = 0; i < p_instance->materials.size(); i++) {4001RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::mesh_storage->mesh_surface_get_material(mesh, i);40024003if (!mat.is_valid()) {4004cast_shadows = true;4005} else {4006if (RSG::material_storage->material_casts_shadows(mat)) {4007cast_shadows = true;4008}40094010if (RSG::material_storage->material_is_animated(mat)) {4011is_animated = true;4012}40134014p_instance->instance_uniforms.materials_append(mat);40154016RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);4017}4018}40194020if (!cast_shadows) {4021can_cast_shadows = false;4022}4023}40244025} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {4026RID mesh = RSG::mesh_storage->multimesh_get_mesh(p_instance->base);4027if (mesh.is_valid()) {4028bool cast_shadows = false;40294030int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);4031for (int i = 0; i < sc; i++) {4032RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, i);40334034if (!mat.is_valid()) {4035cast_shadows = true;40364037} else {4038if (RSG::material_storage->material_casts_shadows(mat)) {4039cast_shadows = true;4040}4041if (RSG::material_storage->material_is_animated(mat)) {4042is_animated = true;4043}40444045p_instance->instance_uniforms.materials_append(mat);40464047RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);4048}4049}40504051if (!cast_shadows) {4052can_cast_shadows = false;4053}40544055RSG::utilities->base_update_dependency(mesh, &p_instance->dependency_tracker);4056}4057} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {4058bool cast_shadows = false;40594060int dp = RSG::particles_storage->particles_get_draw_passes(p_instance->base);40614062for (int i = 0; i < dp; i++) {4063RID mesh = RSG::particles_storage->particles_get_draw_pass_mesh(p_instance->base, i);4064if (!mesh.is_valid()) {4065continue;4066}40674068int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);4069for (int j = 0; j < sc; j++) {4070RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, j);40714072if (!mat.is_valid()) {4073cast_shadows = true;4074} else {4075if (RSG::material_storage->material_casts_shadows(mat)) {4076cast_shadows = true;4077}40784079if (RSG::material_storage->material_is_animated(mat)) {4080is_animated = true;4081}40824083p_instance->instance_uniforms.materials_append(mat);40844085RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);4086}4087}4088}40894090if (!cast_shadows) {4091can_cast_shadows = false;4092}4093}4094}40954096if (p_instance->material_overlay.is_valid()) {4097can_cast_shadows = can_cast_shadows && RSG::material_storage->material_casts_shadows(p_instance->material_overlay);4098is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay);4099p_instance->instance_uniforms.materials_append(p_instance->material_overlay);4100}41014102if (can_cast_shadows != geom->can_cast_shadows) {4103//ability to cast shadows change, let lights now4104for (const Instance *E : geom->lights) {4105InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);4106light->make_shadow_dirty();4107}41084109geom->can_cast_shadows = can_cast_shadows;4110}41114112geom->material_is_animated = is_animated;41134114if (p_instance->instance_uniforms.materials_finish(p_instance->self)) {4115geom->geometry_instance->set_instance_shader_uniforms_offset(p_instance->instance_uniforms.location());4116}4117}41184119if (p_instance->skeleton.is_valid()) {4120RSG::mesh_storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);4121}41224123p_instance->dependency_tracker.update_end();41244125if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {4126InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);4127ERR_FAIL_NULL(geom->geometry_instance);4128geom->geometry_instance->set_surface_materials(p_instance->materials);4129}4130}41314132_instance_update_list.remove(&p_instance->update_item);41334134_update_instance(p_instance);41354136p_instance->teleported = false;4137p_instance->update_aabb = false;4138p_instance->update_dependencies = false;4139}41404141void RendererSceneCull::update_dirty_instances() const {4142while (_instance_update_list.first()) {4143_update_dirty_instance(_instance_update_list.first()->self());4144}41454146// Update dirty resources after dirty instances as instance updates may affect resources.4147RSG::utilities->update_dirty_resources();4148}41494150void RendererSceneCull::update() {4151//optimize bvhs41524153uint32_t rid_count = scenario_owner.get_rid_count();4154RID *rids = (RID *)alloca(sizeof(RID) * rid_count);4155scenario_owner.fill_owned_buffer(rids);4156for (uint32_t i = 0; i < rid_count; i++) {4157Scenario *s = scenario_owner.get_or_null(rids[i]);4158s->indexers[Scenario::INDEXER_GEOMETRY].optimize_incremental(indexer_update_iterations);4159s->indexers[Scenario::INDEXER_VOLUMES].optimize_incremental(indexer_update_iterations);4160}4161scene_render->update();4162update_dirty_instances();4163render_particle_colliders();4164}41654166bool RendererSceneCull::free(RID p_rid) {4167if (p_rid.is_null()) {4168return true;4169}41704171if (scene_render->free(p_rid)) {4172return true;4173}41744175if (camera_owner.owns(p_rid)) {4176camera_owner.free(p_rid);41774178} else if (scenario_owner.owns(p_rid)) {4179Scenario *scenario = scenario_owner.get_or_null(p_rid);41804181while (scenario->instances.first()) {4182instance_set_scenario(scenario->instances.first()->self()->self, RID());4183}4184scenario->instance_aabbs.reset();4185scenario->instance_data.reset();4186scenario->instance_visibility.reset();41874188RSG::light_storage->shadow_atlas_free(scenario->reflection_probe_shadow_atlas);4189RSG::light_storage->reflection_atlas_free(scenario->reflection_atlas);4190scenario_owner.free(p_rid);4191RendererSceneOcclusionCull::get_singleton()->remove_scenario(p_rid);41924193} else if (RendererSceneOcclusionCull::get_singleton() && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_rid)) {4194RendererSceneOcclusionCull::get_singleton()->free_occluder(p_rid);4195} else if (instance_owner.owns(p_rid)) {4196// delete the instance41974198update_dirty_instances();41994200Instance *instance = instance_owner.get_or_null(p_rid);42014202instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0);4203instance_set_scenario(p_rid, RID());4204instance_set_base(p_rid, RID());4205instance_geometry_set_material_override(p_rid, RID());4206instance_geometry_set_material_overlay(p_rid, RID());4207instance_attach_skeleton(p_rid, RID());42084209instance->instance_uniforms.free(instance->self);4210update_dirty_instances(); //in case something changed this42114212instance_owner.free(p_rid);4213} else {4214return false;4215}42164217return true;4218}42194220TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) {4221return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);4222}42234224void RendererSceneCull::update_visibility_notifiers() {4225SelfList<InstanceVisibilityNotifierData> *E = visible_notifier_list.first();4226while (E) {4227SelfList<InstanceVisibilityNotifierData> *N = E->next();42284229InstanceVisibilityNotifierData *visibility_notifier = E->self();4230if (visibility_notifier->just_visible) {4231visibility_notifier->just_visible = false;42324233RSG::utilities->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);4234} else {4235if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {4236visible_notifier_list.remove(E);42374238RSG::utilities->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);4239}4240}42414242E = N;4243}4244}42454246/*******************************/4247/* Passthrough to Scene Render */4248/*******************************/42494250/* ENVIRONMENT API */42514252RendererSceneCull *RendererSceneCull::singleton = nullptr;42534254void RendererSceneCull::set_scene_render(RendererSceneRender *p_scene_render) {4255scene_render = p_scene_render;4256geometry_instance_pair_mask = scene_render->geometry_instance_get_pair_mask();4257}42584259/* INTERPOLATION API */42604261void RendererSceneCull::update_interpolation_tick(bool p_process) {4262// MultiMesh: Update interpolation in storage.4263RSG::mesh_storage->update_interpolation_tick(p_process);4264}42654266void RendererSceneCull::update_interpolation_frame(bool p_process) {4267// MultiMesh: Update interpolation in storage.4268RSG::mesh_storage->update_interpolation_frame(p_process);4269}42704271void RendererSceneCull::set_physics_interpolation_enabled(bool p_enabled) {4272_interpolation_data.interpolation_enabled = p_enabled;4273}42744275RendererSceneCull::RendererSceneCull() {4276render_pass = 1;4277singleton = this;42784279instance_cull_result.set_page_pool(&instance_cull_page_pool);4280instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool);42814282for (uint32_t i = 0; i < MAX_UPDATE_SHADOWS; i++) {4283render_shadow_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);4284}4285for (uint32_t i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {4286render_sdfgi_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);4287}42884289scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);4290scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count());4291for (InstanceCullResult &thread : scene_cull_result_threads) {4292thread.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);4293}42944295indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");4296thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances");4297thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)WorkerThreadPool::get_singleton()->get_thread_count()); //make sure there is at least one thread per CPU4298RendererSceneOcclusionCull::HZBuffer::occlusion_jitter_enabled = GLOBAL_GET("rendering/occlusion_culling/jitter_projection");42994300dummy_occlusion_culling = memnew(RendererSceneOcclusionCull);43014302light_culler = memnew(RenderingLightCuller);43034304bool tighter_caster_culling = GLOBAL_DEF("rendering/lights_and_shadows/tighter_shadow_caster_culling", true);4305light_culler->set_caster_culling_active(tighter_caster_culling);4306light_culler->set_light_culling_active(tighter_caster_culling);4307}43084309RendererSceneCull::~RendererSceneCull() {4310instance_cull_result.reset();4311instance_shadow_cull_result.reset();43124313for (uint32_t i = 0; i < MAX_UPDATE_SHADOWS; i++) {4314render_shadow_data[i].instances.reset();4315}4316for (uint32_t i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {4317render_sdfgi_data[i].instances.reset();4318}43194320scene_cull_result.reset();4321for (InstanceCullResult &thread : scene_cull_result_threads) {4322thread.reset();4323}4324scene_cull_result_threads.clear();43254326if (dummy_occlusion_culling) {4327memdelete(dummy_occlusion_culling);4328}43294330if (light_culler) {4331memdelete(light_culler);4332light_culler = nullptr;4333}4334}433543364337