Path: blob/master/drivers/gles3/storage/light_storage.cpp
10000 views
/**************************************************************************/1/* light_storage.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#ifdef GLES3_ENABLED3132#include "light_storage.h"33#include "../rasterizer_gles3.h"34#include "../rasterizer_scene_gles3.h"35#include "core/config/project_settings.h"36#include "texture_storage.h"3738using namespace GLES3;3940LightStorage *LightStorage::singleton = nullptr;4142LightStorage *LightStorage::get_singleton() {43return singleton;44}4546LightStorage::LightStorage() {47singleton = this;4849directional_shadow.size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size");50directional_shadow.use_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits");5152// lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");53}5455LightStorage::~LightStorage() {56singleton = nullptr;57}5859/* Light API */6061void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {62Light light;63light.type = p_type;6465light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;66light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;67light.param[RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY] = 1.0;68light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;69light.param[RS::LIGHT_PARAM_RANGE] = 1.0;70light.param[RS::LIGHT_PARAM_SIZE] = 0.0;71light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;72light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;73light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;74light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;75light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;76light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;77light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;78light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;79light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;80light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0;81light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;82light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;83light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;84light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;85light.param[RS::LIGHT_PARAM_INTENSITY] = p_type == RS::LIGHT_DIRECTIONAL ? 100000.0 : 1000.0;8687light_owner.initialize_rid(p_light, light);88}8990RID LightStorage::directional_light_allocate() {91return light_owner.allocate_rid();92}9394void LightStorage::directional_light_initialize(RID p_rid) {95_light_initialize(p_rid, RS::LIGHT_DIRECTIONAL);96}9798RID LightStorage::omni_light_allocate() {99return light_owner.allocate_rid();100}101102void LightStorage::omni_light_initialize(RID p_rid) {103_light_initialize(p_rid, RS::LIGHT_OMNI);104}105106RID LightStorage::spot_light_allocate() {107return light_owner.allocate_rid();108}109110void LightStorage::spot_light_initialize(RID p_rid) {111_light_initialize(p_rid, RS::LIGHT_SPOT);112}113114void LightStorage::light_free(RID p_rid) {115light_set_projector(p_rid, RID()); //clear projector116117// delete the texture118Light *light = light_owner.get_or_null(p_rid);119light->dependency.deleted_notify(p_rid);120light_owner.free(p_rid);121}122123void LightStorage::light_set_color(RID p_light, const Color &p_color) {124Light *light = light_owner.get_or_null(p_light);125ERR_FAIL_NULL(light);126127light->color = p_color;128}129130void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {131Light *light = light_owner.get_or_null(p_light);132ERR_FAIL_NULL(light);133ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);134135if (light->param[p_param] == p_value) {136return;137}138139switch (p_param) {140case RS::LIGHT_PARAM_RANGE:141case RS::LIGHT_PARAM_SPOT_ANGLE:142case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:143case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:144case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:145case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:146case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:147case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:148case RS::LIGHT_PARAM_SHADOW_BIAS: {149light->version++;150light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);151} break;152case RS::LIGHT_PARAM_SIZE: {153if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {154//changing from no size to size and the opposite155light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);156}157} break;158default: {159}160}161162light->param[p_param] = p_value;163}164165void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {166Light *light = light_owner.get_or_null(p_light);167ERR_FAIL_NULL(light);168light->shadow = p_enabled;169170light->version++;171light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);172}173174void LightStorage::light_set_projector(RID p_light, RID p_texture) {175GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();176Light *light = light_owner.get_or_null(p_light);177ERR_FAIL_NULL(light);178179if (light->projector == p_texture) {180return;181}182183if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {184texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);185}186187light->projector = p_texture;188189if (light->type != RS::LIGHT_DIRECTIONAL) {190if (light->projector.is_valid()) {191texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);192}193light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);194}195}196197void LightStorage::light_set_negative(RID p_light, bool p_enable) {198Light *light = light_owner.get_or_null(p_light);199ERR_FAIL_NULL(light);200201light->negative = p_enable;202}203204void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {205Light *light = light_owner.get_or_null(p_light);206ERR_FAIL_NULL(light);207208light->cull_mask = p_mask;209210light->version++;211light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_CULL_MASK);212}213214void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {215Light *light = light_owner.get_or_null(p_light);216ERR_FAIL_NULL(light);217218light->shadow_caster_mask = p_caster_mask;219220light->version++;221light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);222}223224uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {225Light *light = light_owner.get_or_null(p_light);226ERR_FAIL_NULL_V(light, 0);227228return light->shadow_caster_mask;229}230231void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {232Light *light = light_owner.get_or_null(p_light);233ERR_FAIL_NULL(light);234235light->distance_fade = p_enabled;236light->distance_fade_begin = p_begin;237light->distance_fade_shadow = p_shadow;238light->distance_fade_length = p_length;239}240241void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {242Light *light = light_owner.get_or_null(p_light);243ERR_FAIL_NULL(light);244245light->reverse_cull = p_enabled;246247light->version++;248light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);249}250251void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {252Light *light = light_owner.get_or_null(p_light);253ERR_FAIL_NULL(light);254255light->bake_mode = p_bake_mode;256257light->version++;258light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);259}260261void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {262Light *light = light_owner.get_or_null(p_light);263ERR_FAIL_NULL(light);264265light->omni_shadow_mode = p_mode;266267light->version++;268light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);269}270271RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {272const Light *light = light_owner.get_or_null(p_light);273ERR_FAIL_NULL_V(light, RS::LIGHT_OMNI_SHADOW_CUBE);274275return light->omni_shadow_mode;276}277278void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {279Light *light = light_owner.get_or_null(p_light);280ERR_FAIL_NULL(light);281282light->directional_shadow_mode = p_mode;283light->version++;284light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);285}286287void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {288Light *light = light_owner.get_or_null(p_light);289ERR_FAIL_NULL(light);290291light->directional_blend_splits = p_enable;292light->version++;293light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);294}295296bool LightStorage::light_directional_get_blend_splits(RID p_light) const {297const Light *light = light_owner.get_or_null(p_light);298ERR_FAIL_NULL_V(light, false);299300return light->directional_blend_splits;301}302303void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {304Light *light = light_owner.get_or_null(p_light);305ERR_FAIL_NULL(light);306307light->directional_sky_mode = p_mode;308}309310RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const {311const Light *light = light_owner.get_or_null(p_light);312ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY);313314return light->directional_sky_mode;315}316317RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) {318const Light *light = light_owner.get_or_null(p_light);319ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);320321return light->directional_shadow_mode;322}323324RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) {325const Light *light = light_owner.get_or_null(p_light);326ERR_FAIL_NULL_V(light, RS::LIGHT_BAKE_DISABLED);327328return light->bake_mode;329}330331uint64_t LightStorage::light_get_version(RID p_light) const {332const Light *light = light_owner.get_or_null(p_light);333ERR_FAIL_NULL_V(light, 0);334335return light->version;336}337338uint32_t LightStorage::light_get_cull_mask(RID p_light) const {339const Light *light = light_owner.get_or_null(p_light);340ERR_FAIL_NULL_V(light, 0);341342return light->cull_mask;343}344345AABB LightStorage::light_get_aabb(RID p_light) const {346const Light *light = light_owner.get_or_null(p_light);347ERR_FAIL_NULL_V(light, AABB());348349switch (light->type) {350case RS::LIGHT_SPOT: {351float len = light->param[RS::LIGHT_PARAM_RANGE];352float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;353return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));354};355case RS::LIGHT_OMNI: {356float r = light->param[RS::LIGHT_PARAM_RANGE];357return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);358};359case RS::LIGHT_DIRECTIONAL: {360return AABB();361};362}363364ERR_FAIL_V(AABB());365}366367/* LIGHT INSTANCE API */368369RID LightStorage::light_instance_create(RID p_light) {370RID li = light_instance_owner.make_rid(LightInstance());371372LightInstance *light_instance = light_instance_owner.get_or_null(li);373374light_instance->self = li;375light_instance->light = p_light;376light_instance->light_type = light_get_type(p_light);377378return li;379}380381void LightStorage::light_instance_free(RID p_light_instance) {382LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);383ERR_FAIL_NULL(light_instance);384385// Remove from shadow atlases.386for (const RID &E : light_instance->shadow_atlases) {387ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E);388ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_light_instance));389uint32_t key = shadow_atlas->shadow_owners[p_light_instance];390uint32_t q = (key >> QUADRANT_SHIFT) & 0x3;391uint32_t s = key & SHADOW_INDEX_MASK;392393shadow_atlas->quadrants[q].shadows.write[s].owner = RID();394395shadow_atlas->shadow_owners.erase(p_light_instance);396}397398light_instance_owner.free(p_light_instance);399}400401void LightStorage::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) {402LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);403ERR_FAIL_NULL(light_instance);404405light_instance->transform = p_transform;406}407408void LightStorage::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {409LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);410ERR_FAIL_NULL(light_instance);411412light_instance->aabb = p_aabb;413}414415void LightStorage::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {416LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);417ERR_FAIL_NULL(light_instance);418419ERR_FAIL_INDEX(p_pass, 6);420421light_instance->shadow_transform[p_pass].camera = p_projection;422light_instance->shadow_transform[p_pass].transform = p_transform;423light_instance->shadow_transform[p_pass].farplane = p_far;424light_instance->shadow_transform[p_pass].split = p_split;425light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;426light_instance->shadow_transform[p_pass].range_begin = p_range_begin;427light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size;428light_instance->shadow_transform[p_pass].uv_scale = p_uv_scale;429}430431void LightStorage::light_instance_mark_visible(RID p_light_instance) {432LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);433ERR_FAIL_NULL(light_instance);434435light_instance->last_scene_pass = RasterizerSceneGLES3::get_singleton()->get_scene_pass();436}437438/* PROBE API */439440RID LightStorage::reflection_probe_allocate() {441return reflection_probe_owner.allocate_rid();442}443444void LightStorage::reflection_probe_initialize(RID p_rid) {445ReflectionProbe probe;446447reflection_probe_owner.initialize_rid(p_rid, probe);448}449450void LightStorage::reflection_probe_free(RID p_rid) {451ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);452reflection_probe->dependency.deleted_notify(p_rid);453454reflection_probe_owner.free(p_rid);455}456457void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {458ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);459ERR_FAIL_NULL(reflection_probe);460461reflection_probe->update_mode = p_mode;462reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);463}464465void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {466ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);467ERR_FAIL_NULL(reflection_probe);468469reflection_probe->intensity = p_intensity;470}471472void LightStorage::reflection_probe_set_blend_distance(RID p_probe, float p_blend_distance) {473ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);474ERR_FAIL_NULL(reflection_probe);475476reflection_probe->blend_distance = p_blend_distance;477}478479void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {480ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);481ERR_FAIL_NULL(reflection_probe);482483reflection_probe->ambient_mode = p_mode;484}485486void LightStorage::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {487ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);488ERR_FAIL_NULL(reflection_probe);489490reflection_probe->ambient_color = p_color;491}492493void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {494ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);495ERR_FAIL_NULL(reflection_probe);496497reflection_probe->ambient_color_energy = p_energy;498}499500void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) {501ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);502ERR_FAIL_NULL(reflection_probe);503504reflection_probe->max_distance = p_distance;505reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);506}507508void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) {509ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);510ERR_FAIL_NULL(reflection_probe);511512reflection_probe->size = p_size;513reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);514}515516void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {517ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);518ERR_FAIL_NULL(reflection_probe);519520reflection_probe->origin_offset = p_offset;521reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);522}523524void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {525ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);526ERR_FAIL_NULL(reflection_probe);527528reflection_probe->interior = p_enable;529reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);530}531532void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {533ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);534ERR_FAIL_NULL(reflection_probe);535536reflection_probe->box_projection = p_enable;537}538539void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {540ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);541ERR_FAIL_NULL(reflection_probe);542543reflection_probe->enable_shadows = p_enable;544reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);545}546547void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {548ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);549ERR_FAIL_NULL(reflection_probe);550551reflection_probe->cull_mask = p_layers;552reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);553}554555void LightStorage::reflection_probe_set_reflection_mask(RID p_probe, uint32_t p_layers) {556ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);557ERR_FAIL_NULL(reflection_probe);558559reflection_probe->reflection_mask = p_layers;560reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);561}562563void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {564ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);565ERR_FAIL_NULL(reflection_probe);566567reflection_probe->resolution = p_resolution;568}569570AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {571const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);572ERR_FAIL_NULL_V(reflection_probe, AABB());573574AABB aabb;575aabb.position = -reflection_probe->size / 2;576aabb.size = reflection_probe->size;577578return aabb;579}580581RS::ReflectionProbeUpdateMode LightStorage::reflection_probe_get_update_mode(RID p_probe) const {582const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);583ERR_FAIL_NULL_V(reflection_probe, RenderingServer::REFLECTION_PROBE_UPDATE_ONCE);584585return reflection_probe->update_mode;586}587588uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const {589const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);590ERR_FAIL_NULL_V(reflection_probe, 0);591592return reflection_probe->cull_mask;593}594595uint32_t LightStorage::reflection_probe_get_reflection_mask(RID p_probe) const {596const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);597ERR_FAIL_NULL_V(reflection_probe, 0);598599return reflection_probe->reflection_mask;600}601602Vector3 LightStorage::reflection_probe_get_size(RID p_probe) const {603const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);604ERR_FAIL_NULL_V(reflection_probe, Vector3());605606return reflection_probe->size;607}608609Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const {610const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);611ERR_FAIL_NULL_V(reflection_probe, Vector3());612613return reflection_probe->origin_offset;614}615616float LightStorage::reflection_probe_get_origin_max_distance(RID p_probe) const {617const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);618ERR_FAIL_NULL_V(reflection_probe, 0.0);619620return reflection_probe->max_distance;621}622623bool LightStorage::reflection_probe_renders_shadows(RID p_probe) const {624const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);625ERR_FAIL_NULL_V(reflection_probe, false);626627return reflection_probe->enable_shadows;628}629630void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {631ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);632ERR_FAIL_NULL(reflection_probe);633634reflection_probe->mesh_lod_threshold = p_ratio;635reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);636}637638float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {639const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);640ERR_FAIL_NULL_V(reflection_probe, 0.0);641642return reflection_probe->mesh_lod_threshold;643}644645Dependency *LightStorage::reflection_probe_get_dependency(RID p_probe) const {646ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);647ERR_FAIL_NULL_V(reflection_probe, nullptr);648649return &reflection_probe->dependency;650}651652/* REFLECTION ATLAS */653654RID LightStorage::reflection_atlas_create() {655ReflectionAtlas ra;656ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count");657ra.size = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_size");658659return reflection_atlas_owner.make_rid(ra);660}661662void LightStorage::reflection_atlas_free(RID p_ref_atlas) {663reflection_atlas_set_size(p_ref_atlas, 0, 0);664665reflection_atlas_owner.free(p_ref_atlas);666}667668int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const {669ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);670ERR_FAIL_NULL_V(ra, 0);671672return ra->size;673}674675void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {676ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);677ERR_FAIL_NULL(ra);678679if (ra->size == p_reflection_size && ra->count == p_reflection_count) {680return; //no changes681}682683ra->size = p_reflection_size;684ra->count = p_reflection_count;685686if (ra->depth != 0) {687//clear and invalidate everything688for (int i = 0; i < ra->reflections.size(); i++) {689for (int j = 0; j < 7; j++) {690if (ra->reflections[i].fbos[j] != 0) {691glDeleteFramebuffers(1, &ra->reflections[i].fbos[j]);692ra->reflections.write[i].fbos[j] = 0;693}694}695696GLES3::Utilities::get_singleton()->texture_free_data(ra->reflections[i].color);697ra->reflections.write[i].color = 0;698699GLES3::Utilities::get_singleton()->texture_free_data(ra->reflections[i].radiance);700ra->reflections.write[i].radiance = 0;701702if (ra->reflections[i].owner.is_null()) {703continue;704}705reflection_probe_release_atlas_index(ra->reflections[i].owner);706//rp->atlasindex clear707}708709ra->reflections.clear();710711GLES3::Utilities::get_singleton()->texture_free_data(ra->depth);712ra->depth = 0;713}714715if (ra->render_buffers.is_valid()) {716ra->render_buffers->free_render_buffer_data();717}718}719720/* REFLECTION PROBE INSTANCE */721722RID LightStorage::reflection_probe_instance_create(RID p_probe) {723ReflectionProbeInstance rpi;724rpi.probe = p_probe;725726return reflection_probe_instance_owner.make_rid(rpi);727}728729void LightStorage::reflection_probe_instance_free(RID p_instance) {730reflection_probe_release_atlas_index(p_instance);731reflection_probe_instance_owner.free(p_instance);732}733734void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {735ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);736ERR_FAIL_NULL(rpi);737738rpi->transform = p_transform;739rpi->dirty = true;740}741742bool LightStorage::reflection_probe_has_atlas_index(RID p_instance) {743ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);744ERR_FAIL_NULL_V(rpi, false);745746if (rpi->atlas.is_null()) {747return false;748}749750return rpi->atlas_index >= 0;751}752753void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {754ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);755ERR_FAIL_NULL(rpi);756757if (rpi->atlas.is_null()) {758return; //nothing to release759}760ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);761ERR_FAIL_NULL(atlas);762763ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size());764atlas->reflections.write[rpi->atlas_index].owner = RID();765766if (rpi->rendering) {767// We were cancelled mid rendering, trigger refresh.768rpi->rendering = false;769rpi->dirty = true;770rpi->processing_layer = 0;771}772773rpi->atlas_index = -1;774rpi->atlas = RID();775}776777bool LightStorage::reflection_probe_instance_needs_redraw(RID p_instance) {778ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);779ERR_FAIL_NULL_V(rpi, false);780781if (rpi->rendering) {782return false;783}784785if (rpi->dirty) {786return true;787}788789if (reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {790return true;791}792793return rpi->atlas_index == -1;794}795796bool LightStorage::reflection_probe_instance_has_reflection(RID p_instance) {797ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);798ERR_FAIL_NULL_V(rpi, false);799800return rpi->atlas.is_valid();801}802803bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {804TextureStorage *texture_storage = TextureStorage::get_singleton();805ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas);806807ERR_FAIL_NULL_V(atlas, false);808809ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);810ERR_FAIL_NULL_V(rpi, false);811812if (atlas->render_buffers.is_null()) {813atlas->render_buffers.instantiate();814atlas->render_buffers->configure_for_probe(Size2i(atlas->size, atlas->size));815}816817// First we check if our atlas is initialized.818819// Not making an exception for update_mode = REFLECTION_PROBE_UPDATE_ALWAYS, we are using820// the same render techniques regardless of realtime or update once (for now).821822if (atlas->depth == 0) {823// We need to create our textures824atlas->mipmap_count = Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) - 1;825atlas->mipmap_count = MIN(atlas->mipmap_count, 8); // No more than 8 please..826827glActiveTexture(GL_TEXTURE0);828829{830// We create one set of 6 layers for depth, we can reuse this when rendering.831glGenTextures(1, &atlas->depth);832glBindTexture(GL_TEXTURE_2D_ARRAY, atlas->depth);833834glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, atlas->size, atlas->size, 6, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);835836GLES3::Utilities::get_singleton()->texture_allocated_data(atlas->depth, atlas->size * atlas->size * 6 * 3, "Reflection probe atlas (depth)");837}838839// Make room for our atlas entries840atlas->reflections.resize(atlas->count);841842for (int i = 0; i < atlas->count; i++) {843// Create a cube map for this atlas entry844GLuint color = 0;845glGenTextures(1, &color);846glBindTexture(GL_TEXTURE_CUBE_MAP, color);847atlas->reflections.write[i].color = color;848849#ifdef GL_API_ENABLED850if (RasterizerGLES3::is_gles_over_gl()) {851for (int s = 0; s < 6; s++) {852glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + s, 0, GL_RGB10_A2, atlas->size, atlas->size, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, nullptr);853}854glGenerateMipmap(GL_TEXTURE_CUBE_MAP);855}856#endif857#ifdef GLES_API_ENABLED858if (!RasterizerGLES3::is_gles_over_gl()) {859glTexStorage2D(GL_TEXTURE_CUBE_MAP, atlas->mipmap_count, GL_RGB10_A2, atlas->size, atlas->size);860}861#endif // GLES_API_ENABLED862863glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);864glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);865glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);866glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);867glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);868glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, atlas->mipmap_count - 1);869870// Setup sizes and calculate how much memory we're using.871int mipmap_size = atlas->size;872uint32_t data_size = 0;873for (int m = 0; m < atlas->mipmap_count; m++) {874atlas->mipmap_size[m] = mipmap_size;875data_size += mipmap_size * mipmap_size * 6 * 4;876mipmap_size = MAX(mipmap_size >> 1, 1);877}878879GLES3::Utilities::get_singleton()->texture_allocated_data(color, data_size, String("Reflection probe atlas (") + String::num_int64(i) + String(", color)"));880881// Create a radiance map for this atlas entry882GLuint radiance = 0;883glGenTextures(1, &radiance);884glBindTexture(GL_TEXTURE_CUBE_MAP, radiance);885atlas->reflections.write[i].radiance = radiance;886887#ifdef GL_API_ENABLED888if (RasterizerGLES3::is_gles_over_gl()) {889for (int s = 0; s < 6; s++) {890glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + s, 0, GL_RGB10_A2, atlas->size, atlas->size, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, nullptr);891}892glGenerateMipmap(GL_TEXTURE_CUBE_MAP);893}894#endif895#ifdef GLES_API_ENABLED896if (!RasterizerGLES3::is_gles_over_gl()) {897glTexStorage2D(GL_TEXTURE_CUBE_MAP, atlas->mipmap_count, GL_RGB10_A2, atlas->size, atlas->size);898}899#endif // GLES_API_ENABLED900901glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);902glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);903glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);904glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);905glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);906glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, atlas->mipmap_count - 1);907908// Same data size as our color buffer909GLES3::Utilities::get_singleton()->texture_allocated_data(radiance, data_size, String("Reflection probe atlas (") + String::num_int64(i) + String(", radiance)"));910911// Create our framebuffers so we can draw to all sides912for (int side = 0; side < 6; side++) {913GLuint fbo = 0;914glGenFramebuffers(1, &fbo);915glBindFramebuffer(GL_FRAMEBUFFER, fbo);916917// We use glFramebufferTexture2D for the color buffer as glFramebufferTextureLayer doesn't always work with cubemaps.918glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + side, color, 0);919glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, atlas->depth, 0, side);920921// Validate framebuffer922GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);923if (status != GL_FRAMEBUFFER_COMPLETE) {924WARN_PRINT("Could not create reflections framebuffer, status: " + texture_storage->get_framebuffer_error(status));925}926927atlas->reflections.write[i].fbos[side] = fbo;928}929930// Create an extra framebuffer for building our radiance931{932GLuint fbo = 0;933glGenFramebuffers(1, &fbo);934glBindFramebuffer(GL_FRAMEBUFFER, fbo);935936atlas->reflections.write[i].fbos[6] = fbo;937}938}939940glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);941glBindTexture(GL_TEXTURE_CUBE_MAP, 0);942glBindTexture(GL_TEXTURE_2D_ARRAY, 0);943}944945// Then we find a free slot for our reflection probe946947if (rpi->atlas_index == -1) {948for (int i = 0; i < atlas->reflections.size(); i++) {949if (atlas->reflections[i].owner.is_null()) {950rpi->atlas_index = i;951break;952}953}954//find the one used last955if (rpi->atlas_index == -1) {956//everything is in use, find the one least used via LRU957uint64_t pass_min = 0;958959for (int i = 0; i < atlas->reflections.size(); i++) {960ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.get_or_null(atlas->reflections[i].owner);961if (rpi2->last_pass < pass_min) {962pass_min = rpi2->last_pass;963rpi->atlas_index = i;964}965}966}967}968969if (rpi->atlas_index != -1) { // should we fail if this is still -1 ?970atlas->reflections.write[rpi->atlas_index].owner = p_instance;971}972973rpi->atlas = p_reflection_atlas;974rpi->rendering = true;975rpi->dirty = false;976rpi->processing_layer = 0;977978return true;979}980981Ref<RenderSceneBuffers> LightStorage::reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) {982ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas);983ERR_FAIL_NULL_V(atlas, Ref<RenderSceneBuffersGLES3>());984985return atlas->render_buffers;986}987988bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {989GLES3::CubemapFilter *cubemap_filter = GLES3::CubemapFilter::get_singleton();990ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);991ERR_FAIL_NULL_V(rpi, false);992ERR_FAIL_COND_V(!rpi->rendering, false);993ERR_FAIL_COND_V(rpi->atlas.is_null(), false);994995ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);996if (!atlas || rpi->atlas_index == -1) {997//does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering)998rpi->rendering = false;999rpi->processing_layer = 0;1000return false;1001}10021003if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {1004// Using real time reflections, all roughness is done in one step1005for (int m = 0; m < atlas->mipmap_count; m++) {1006const GLES3::ReflectionAtlas::Reflection &reflection = atlas->reflections[rpi->atlas_index];1007cubemap_filter->filter_radiance(reflection.color, reflection.radiance, reflection.fbos[6], atlas->size, atlas->mipmap_count, m);1008}10091010rpi->rendering = false;1011rpi->processing_layer = 0;1012return true;1013} else {1014const GLES3::ReflectionAtlas::Reflection &reflection = atlas->reflections[rpi->atlas_index];1015cubemap_filter->filter_radiance(reflection.color, reflection.radiance, reflection.fbos[6], atlas->size, atlas->mipmap_count, rpi->processing_layer);10161017rpi->processing_layer++;1018if (rpi->processing_layer == atlas->mipmap_count) {1019rpi->rendering = false;1020rpi->processing_layer = 0;1021return true;1022}1023}10241025return false;1026}10271028GLuint LightStorage::reflection_probe_instance_get_texture(RID p_instance) {1029ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);1030ERR_FAIL_NULL_V(rpi, 0);10311032ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);1033ERR_FAIL_NULL_V(atlas, 0);1034ERR_FAIL_COND_V(rpi->atlas_index < 0, 0);10351036return atlas->reflections[rpi->atlas_index].radiance;1037}10381039GLuint LightStorage::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) {1040ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);1041ERR_FAIL_NULL_V(rpi, 0);1042ERR_FAIL_INDEX_V(p_index, 6, 0);10431044ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);1045ERR_FAIL_NULL_V(atlas, 0);1046ERR_FAIL_COND_V(rpi->atlas_index < 0, 0);10471048return atlas->reflections[rpi->atlas_index].fbos[p_index];1049}10501051/* LIGHTMAP CAPTURE */10521053RID LightStorage::lightmap_allocate() {1054return lightmap_owner.allocate_rid();1055}10561057void LightStorage::lightmap_initialize(RID p_rid) {1058lightmap_owner.initialize_rid(p_rid, Lightmap());1059}10601061void LightStorage::lightmap_free(RID p_rid) {1062Lightmap *lightmap = lightmap_owner.get_or_null(p_rid);1063ERR_FAIL_NULL(lightmap);1064lightmap->dependency.deleted_notify(p_rid);1065lightmap_owner.free(p_rid);1066}10671068void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {1069Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1070ERR_FAIL_NULL(lightmap);1071lightmap->light_texture = p_light;1072lightmap->uses_spherical_harmonics = p_uses_spherical_haromics;10731074Vector3i light_texture_size = GLES3::TextureStorage::get_singleton()->texture_get_size(lightmap->light_texture);1075lightmap->light_texture_size = Vector2i(light_texture_size.x, light_texture_size.y);10761077GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->light_texture);1078glBindTexture(GL_TEXTURE_2D_ARRAY, tex);1079glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);1080glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1081glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);1082glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);1083glBindTexture(GL_TEXTURE_2D_ARRAY, 0);1084}10851086void LightStorage::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {1087Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1088ERR_FAIL_NULL(lightmap);1089lightmap->bounds = p_bounds;1090}10911092void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {1093Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1094ERR_FAIL_NULL(lightmap);1095lightmap->interior = p_interior;1096}10971098void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {1099Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1100ERR_FAIL_NULL(lightmap);11011102if (p_points.size()) {1103ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size());1104ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);1105ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);1106}11071108lightmap->points = p_points;1109lightmap->point_sh = p_point_sh;1110lightmap->tetrahedra = p_tetrahedra;1111lightmap->bsp_tree = p_bsp_tree;1112}11131114void LightStorage::lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) {1115Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1116ERR_FAIL_NULL(lightmap);11171118lightmap->baked_exposure = p_exposure;1119}11201121PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {1122Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1123ERR_FAIL_NULL_V(lightmap, PackedVector3Array());1124return lightmap->points;1125}11261127PackedColorArray LightStorage::lightmap_get_probe_capture_sh(RID p_lightmap) const {1128Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1129ERR_FAIL_NULL_V(lightmap, PackedColorArray());1130return lightmap->point_sh;1131}11321133PackedInt32Array LightStorage::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {1134Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1135ERR_FAIL_NULL_V(lightmap, PackedInt32Array());1136return lightmap->tetrahedra;1137}11381139PackedInt32Array LightStorage::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {1140Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1141ERR_FAIL_NULL_V(lightmap, PackedInt32Array());1142return lightmap->bsp_tree;1143}11441145AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const {1146Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1147ERR_FAIL_NULL_V(lightmap, AABB());1148return lightmap->bounds;1149}11501151void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {1152Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);1153ERR_FAIL_NULL(lm);11541155for (int i = 0; i < 9; i++) {1156r_sh[i] = Color(0, 0, 0, 0);1157}11581159if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) {1160return;1161}11621163static_assert(sizeof(Lightmap::BSP) == 24);11641165const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr();1166int32_t node = 0;1167while (node >= 0) {1168if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) {1169#ifdef DEBUG_ENABLED1170ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node);1171#endif11721173node = bsp[node].over;1174} else {1175#ifdef DEBUG_ENABLED1176ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node);1177#endif1178node = bsp[node].under;1179}1180}11811182if (node == Lightmap::BSP::EMPTY_LEAF) {1183return; // Nothing could be done.1184}11851186node = Math::abs(node) - 1;11871188uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];1189Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };1190const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };1191Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);11921193for (int i = 0; i < 4; i++) {1194float c = CLAMP(barycentric[i], 0.0, 1.0);1195for (int j = 0; j < 9; j++) {1196r_sh[j] += sh_colors[i][j] * c;1197}1198}1199}12001201bool LightStorage::lightmap_is_interior(RID p_lightmap) const {1202Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1203ERR_FAIL_NULL_V(lightmap, false);1204return lightmap->interior;1205}12061207void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {1208lightmap_probe_capture_update_speed = p_speed;1209}12101211float LightStorage::lightmap_get_probe_capture_update_speed() const {1212return lightmap_probe_capture_update_speed;1213}12141215void LightStorage::lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) {1216Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1217ERR_FAIL_NULL(lightmap);1218lightmap->shadow_texture = p_shadow;12191220GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->shadow_texture);1221glBindTexture(GL_TEXTURE_2D_ARRAY, tex);1222glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);1223glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1224glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);1225glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);1226glBindTexture(GL_TEXTURE_2D_ARRAY, 0);1227}12281229RS::ShadowmaskMode LightStorage::lightmap_get_shadowmask_mode(RID p_lightmap) {1230Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1231ERR_FAIL_NULL_V(lightmap, RS::SHADOWMASK_MODE_NONE);12321233return lightmap->shadowmask_mode;1234}12351236void LightStorage::lightmap_set_shadowmask_mode(RID p_lightmap, RS::ShadowmaskMode p_mode) {1237Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);1238ERR_FAIL_NULL(lightmap);1239lightmap->shadowmask_mode = p_mode;1240}12411242/* LIGHTMAP INSTANCE */12431244RID LightStorage::lightmap_instance_create(RID p_lightmap) {1245LightmapInstance li;1246li.lightmap = p_lightmap;1247return lightmap_instance_owner.make_rid(li);1248}12491250void LightStorage::lightmap_instance_free(RID p_lightmap) {1251lightmap_instance_owner.free(p_lightmap);1252}12531254void LightStorage::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {1255LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap);1256ERR_FAIL_NULL(li);1257li->transform = p_transform;1258}12591260/* SHADOW ATLAS API */12611262RID LightStorage::shadow_atlas_create() {1263return shadow_atlas_owner.make_rid(ShadowAtlas());1264}12651266void LightStorage::shadow_atlas_free(RID p_atlas) {1267shadow_atlas_set_size(p_atlas, 0);1268shadow_atlas_owner.free(p_atlas);1269}12701271void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {1272ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);1273ERR_FAIL_NULL(shadow_atlas);1274ERR_FAIL_COND(p_size < 0);1275p_size = next_power_of_2((uint32_t)p_size);12761277if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {1278return;1279}12801281for (uint32_t i = 0; i < 4; i++) {1282// Clear all subdivisions and free shadows.1283for (uint32_t j = 0; j < shadow_atlas->quadrants[i].textures.size(); j++) {1284glDeleteTextures(1, &shadow_atlas->quadrants[i].textures[j]);1285glDeleteFramebuffers(1, &shadow_atlas->quadrants[i].fbos[j]);1286}1287shadow_atlas->quadrants[i].textures.clear();1288shadow_atlas->quadrants[i].fbos.clear();12891290shadow_atlas->quadrants[i].shadows.clear();1291shadow_atlas->quadrants[i].shadows.resize(shadow_atlas->quadrants[i].subdivision * shadow_atlas->quadrants[i].subdivision);1292}12931294// Erase shadow atlas reference from lights.1295for (const KeyValue<RID, uint32_t> &E : shadow_atlas->shadow_owners) {1296LightInstance *li = light_instance_owner.get_or_null(E.key);1297ERR_CONTINUE(!li);1298li->shadow_atlases.erase(p_atlas);1299}13001301if (shadow_atlas->debug_texture != 0) {1302glDeleteTextures(1, &shadow_atlas->debug_texture);1303}13041305if (shadow_atlas->debug_fbo != 0) {1306glDeleteFramebuffers(1, &shadow_atlas->debug_fbo);1307}13081309// Clear owners.1310shadow_atlas->shadow_owners.clear();13111312shadow_atlas->size = p_size;1313shadow_atlas->use_16_bits = p_16_bits;1314}13151316void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {1317ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);1318ERR_FAIL_NULL(shadow_atlas);1319ERR_FAIL_INDEX(p_quadrant, 4);1320ERR_FAIL_INDEX(p_subdivision, 16384);13211322uint32_t subdiv = next_power_of_2((uint32_t)p_subdivision);1323if (subdiv & 0xaaaaaaaa) { // sqrt(subdiv) must be integer.1324subdiv <<= 1;1325}13261327subdiv = int(Math::sqrt((float)subdiv));13281329if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) {1330return;1331}13321333// Erase all data from quadrant.1334for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {1335if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {1336shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);1337LightInstance *li = light_instance_owner.get_or_null(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);1338ERR_CONTINUE(!li);1339li->shadow_atlases.erase(p_atlas);1340}1341}13421343for (uint32_t j = 0; j < shadow_atlas->quadrants[p_quadrant].textures.size(); j++) {1344glDeleteTextures(1, &shadow_atlas->quadrants[p_quadrant].textures[j]);1345glDeleteFramebuffers(1, &shadow_atlas->quadrants[p_quadrant].fbos[j]);1346}13471348shadow_atlas->quadrants[p_quadrant].textures.clear();1349shadow_atlas->quadrants[p_quadrant].fbos.clear();13501351shadow_atlas->quadrants[p_quadrant].shadows.clear();1352shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv);1353shadow_atlas->quadrants[p_quadrant].subdivision = subdiv;13541355// Cache the smallest subdiv (for faster allocation in light update).13561357shadow_atlas->smallest_subdiv = 1 << 30;13581359for (int i = 0; i < 4; i++) {1360if (shadow_atlas->quadrants[i].subdivision) {1361shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision);1362}1363}13641365if (shadow_atlas->smallest_subdiv == 1 << 30) {1366shadow_atlas->smallest_subdiv = 0;1367}13681369// Re-sort the size orders, simple bubblesort for 4 elements.13701371int swaps = 0;1372do {1373swaps = 0;13741375for (int i = 0; i < 3; i++) {1376if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) {1377SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]);1378swaps++;1379}1380}1381} while (swaps > 0);1382}13831384bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) {1385ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);1386ERR_FAIL_NULL_V(shadow_atlas, false);13871388LightInstance *li = light_instance_owner.get_or_null(p_light_instance);1389ERR_FAIL_NULL_V(li, false);13901391if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {1392return false;1393}13941395uint32_t quad_size = shadow_atlas->size >> 1;1396int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(uint32_t(quad_size * p_coverage)));13971398int valid_quadrants[4];1399int valid_quadrant_count = 0;1400int best_size = -1; // Best size found.1401int best_subdiv = -1; // Subdiv for the best size.14021403// Find the quadrants this fits into, and the best possible size it can fit into.1404for (int i = 0; i < 4; i++) {1405int q = shadow_atlas->size_order[i];1406int sd = shadow_atlas->quadrants[q].subdivision;1407if (sd == 0) {1408continue; // Unused.1409}14101411int max_fit = quad_size / sd;14121413if (best_size != -1 && max_fit > best_size) {1414break; // Too large.1415}14161417valid_quadrants[valid_quadrant_count++] = q;1418best_subdiv = sd;14191420if (max_fit >= desired_fit) {1421best_size = max_fit;1422}1423}14241425ERR_FAIL_COND_V(valid_quadrant_count == 0, false);14261427uint64_t tick = OS::get_singleton()->get_ticks_msec();14281429uint32_t old_key = SHADOW_INVALID;1430uint32_t old_quadrant = SHADOW_INVALID;1431uint32_t old_shadow = SHADOW_INVALID;1432int old_subdivision = -1;14331434bool should_realloc = false;1435bool should_redraw = false;14361437if (shadow_atlas->shadow_owners.has(p_light_instance)) {1438old_key = shadow_atlas->shadow_owners[p_light_instance];1439old_quadrant = (old_key >> QUADRANT_SHIFT) & 0x3;1440old_shadow = old_key & SHADOW_INDEX_MASK;14411442// Only re-allocate if a better option is available, and enough time has passed.1443should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (tick - shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick > shadow_atlas_realloc_tolerance_msec);1444should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version;14451446if (!should_realloc) {1447shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = p_light_version;1448// Already existing, see if it should redraw or it's just OK.1449return should_redraw;1450}14511452old_subdivision = shadow_atlas->quadrants[old_quadrant].subdivision;1453}14541455bool is_omni = li->light_type == RS::LIGHT_OMNI;1456bool found_shadow = false;1457int new_quadrant = -1;1458int new_shadow = -1;14591460found_shadow = _shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, is_omni, new_quadrant, new_shadow);14611462// For new shadows if we found an atlas.1463// Or for existing shadows that found a better atlas.1464if (found_shadow) {1465if (old_quadrant != SHADOW_INVALID) {1466shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = 0;1467shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].owner = RID();1468}14691470uint32_t new_key = new_quadrant << QUADRANT_SHIFT;1471new_key |= new_shadow;14721473ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];1474_shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow);14751476sh->owner = p_light_instance;1477sh->owner_is_omni = is_omni;1478sh->alloc_tick = tick;1479sh->version = p_light_version;14801481li->shadow_atlases.insert(p_atlas);14821483// Update it in map.1484shadow_atlas->shadow_owners[p_light_instance] = new_key;1485// Make it dirty, as it should redraw anyway.1486return true;1487}14881489return should_redraw;1490}14911492bool LightStorage::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, bool is_omni, int &r_quadrant, int &r_shadow) {1493for (int i = p_quadrant_count - 1; i >= 0; i--) {1494int qidx = p_in_quadrants[i];14951496if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {1497return false;1498}14991500// Look for an empty space.1501int sc = shadow_atlas->quadrants[qidx].shadows.size();1502const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr();15031504// We have a free space in this quadrant, allocate a texture and use it.1505if (sc > (int)shadow_atlas->quadrants[qidx].textures.size()) {1506GLuint fbo_id = 0;1507glGenFramebuffers(1, &fbo_id);1508glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);15091510GLuint texture_id = 0;1511glGenTextures(1, &texture_id);1512glActiveTexture(GL_TEXTURE0);15131514int size = (shadow_atlas->size >> 1) / shadow_atlas->quadrants[qidx].subdivision;15151516GLenum format = shadow_atlas->use_16_bits ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24;1517GLenum type = shadow_atlas->use_16_bits ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;15181519if (is_omni) {1520glBindTexture(GL_TEXTURE_CUBE_MAP, texture_id);1521for (int id = 0; id < 6; id++) {1522glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + id, 0, format, size / 2, size / 2, 0, GL_DEPTH_COMPONENT, type, nullptr);1523}15241525glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1526glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);15271528glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);1529glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);1530glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);15311532glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);1533glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);15341535glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texture_id, 0);15361537#ifdef DEBUG_ENABLED1538GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);1539if (status != GL_FRAMEBUFFER_COMPLETE) {1540ERR_PRINT("Could not create omni light shadow framebuffer, status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));1541}1542#endif1543glBindTexture(GL_TEXTURE_CUBE_MAP, 0);1544} else {1545glBindTexture(GL_TEXTURE_2D, texture_id);15461547glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, GL_DEPTH_COMPONENT, type, nullptr);15481549glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1550glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);1551glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);1552glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);15531554glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);1555glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);15561557glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture_id, 0);15581559glBindTexture(GL_TEXTURE_2D, 0);1560}1561glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);15621563r_quadrant = qidx;1564r_shadow = shadow_atlas->quadrants[qidx].textures.size();15651566shadow_atlas->quadrants[qidx].textures.push_back(texture_id);1567shadow_atlas->quadrants[qidx].fbos.push_back(fbo_id);15681569return true;1570}15711572int found_used_idx = -1; // Found existing one, must steal it.1573uint64_t min_pass = 0; // Pass of the existing one, try to use the least recently used one (LRU fashion).15741575for (int j = 0; j < sc; j++) {1576if (sarr[j].owner_is_omni != is_omni) {1577// Existing light instance type doesn't match new light instance type skip.1578continue;1579}15801581LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);1582if (!sli) {1583// Found a released light instance.1584found_used_idx = j;1585break;1586}15871588if (sli->last_scene_pass != RasterizerSceneGLES3::get_singleton()->get_scene_pass()) {1589// Was just allocated, don't kill it so soon, wait a bit.1590if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) {1591continue;1592}15931594if (found_used_idx == -1 || sli->last_scene_pass < min_pass) {1595found_used_idx = j;1596min_pass = sli->last_scene_pass;1597}1598}1599}16001601if (found_used_idx != -1) {1602r_quadrant = qidx;1603r_shadow = found_used_idx;16041605return true;1606}1607}16081609return false;1610}16111612void LightStorage::_shadow_atlas_invalidate_shadow(ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx) {1613if (p_shadow->owner.is_valid()) {1614LightInstance *sli = light_instance_owner.get_or_null(p_shadow->owner);16151616p_shadow_atlas->shadow_owners.erase(p_shadow->owner);1617p_shadow->version = 0;1618p_shadow->owner = RID();1619sli->shadow_atlases.erase(p_atlas);1620}1621}16221623void LightStorage::shadow_atlas_update(RID p_atlas) {1624// Do nothing as there is no shadow atlas texture.1625}16261627/* DIRECTIONAL SHADOW */16281629// Create if necessary and clear.1630void LightStorage::update_directional_shadow_atlas() {1631if (directional_shadow.depth == 0 && directional_shadow.size > 0) {1632glGenFramebuffers(1, &directional_shadow.fbo);1633glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo);16341635glGenTextures(1, &directional_shadow.depth);1636glActiveTexture(GL_TEXTURE0);1637glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);16381639GLenum format = directional_shadow.use_16_bits ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24;1640GLenum type = directional_shadow.use_16_bits ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;16411642glTexImage2D(GL_TEXTURE_2D, 0, format, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, type, nullptr);16431644glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1645glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);1646glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);1647glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);16481649glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);1650glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);16511652glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0);1653}1654glUseProgram(0);1655glDepthMask(GL_TRUE);1656glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo);1657RasterizerGLES3::clear_depth(0.0);1658glClear(GL_DEPTH_BUFFER_BIT);16591660glBindTexture(GL_TEXTURE_2D, 0);1661glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);1662}16631664void LightStorage::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {1665p_size = nearest_power_of_2_templated(p_size);16661667if (directional_shadow.size == p_size && directional_shadow.use_16_bits == p_16_bits) {1668return;1669}16701671directional_shadow.size = p_size;1672directional_shadow.use_16_bits = p_16_bits;16731674if (directional_shadow.depth != 0) {1675glDeleteTextures(1, &directional_shadow.depth);1676directional_shadow.depth = 0;1677glDeleteFramebuffers(1, &directional_shadow.fbo);1678directional_shadow.fbo = 0;1679}1680}16811682void LightStorage::set_directional_shadow_count(int p_count) {1683directional_shadow.light_count = p_count;1684directional_shadow.current_light = 0;1685}16861687static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) {1688int split_h = 1;1689int split_v = 1;16901691while (split_h * split_v < p_shadow_count) {1692if (split_h == split_v) {1693split_h <<= 1;1694} else {1695split_v <<= 1;1696}1697}16981699Rect2i rect(0, 0, p_size, p_size);1700rect.size.width /= split_h;1701rect.size.height /= split_v;17021703rect.position.x = rect.size.width * (p_shadow_index % split_h);1704rect.position.y = rect.size.height * (p_shadow_index / split_h);17051706return rect;1707}17081709Rect2i LightStorage::get_directional_shadow_rect() {1710return _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);1711}17121713int LightStorage::get_directional_light_shadow_size(RID p_light_instance) {1714ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);17151716Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);17171718LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);1719ERR_FAIL_NULL_V(light_instance, 0);17201721switch (light_directional_get_shadow_mode(light_instance->light)) {1722case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:1723break; //none1724case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:1725r.size.height /= 2;1726break;1727case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:1728r.size /= 2;1729break;1730}17311732return MAX(r.size.width, r.size.height);1733}17341735#endif // !GLES3_ENABLED173617371738