diff options
-rw-r--r-- | doc/classes/DirectionalLight3D.xml | 3 | ||||
-rw-r--r-- | doc/classes/RenderingServer.xml | 11 | ||||
-rw-r--r-- | drivers/dummy/rasterizer_dummy.h | 2 | ||||
-rw-r--r-- | scene/3d/light_3d.cpp | 14 | ||||
-rw-r--r-- | scene/3d/light_3d.h | 4 | ||||
-rw-r--r-- | servers/rendering/rasterizer.h | 2 | ||||
-rw-r--r-- | servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp | 66 | ||||
-rw-r--r-- | servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp | 14 | ||||
-rw-r--r-- | servers/rendering/rasterizer_rd/rasterizer_storage_rd.h | 3 | ||||
-rw-r--r-- | servers/rendering/rendering_server_raster.h | 1 | ||||
-rw-r--r-- | servers/rendering/rendering_server_scene.cpp | 6 | ||||
-rw-r--r-- | servers/rendering/rendering_server_scene.h | 1 | ||||
-rw-r--r-- | servers/rendering/rendering_server_wrap_mt.h | 1 | ||||
-rw-r--r-- | servers/rendering_server.cpp | 1 | ||||
-rw-r--r-- | servers/rendering_server.h | 1 |
15 files changed, 106 insertions, 24 deletions
diff --git a/doc/classes/DirectionalLight3D.xml b/doc/classes/DirectionalLight3D.xml index afd85a9cb7..233b1f0c16 100644 --- a/doc/classes/DirectionalLight3D.xml +++ b/doc/classes/DirectionalLight3D.xml @@ -41,6 +41,9 @@ </member> <member name="shadow_bias" type="float" setter="set_param" getter="get_param" override="true" default="0.05" /> <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" override="true" default="1.0" /> + <member name="use_in_sky_only" type="bool" setter="set_sky_only" getter="is_sky_only" default="false"> + If [code]true[/code], this [DirectionalLight3D] will not be used for anything except sky shaders. Use this for lights that impact your sky shader that you may want to hide from affecting the rest of the scene. For example, you may want to enable this when the sun in your sky shader falls below the horizon. + </member> </members> <constants> <constant name="SHADOW_ORTHOGONAL" value="0" enum="ShadowMode"> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 857c13deb5..4c5ec13cd0 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1432,6 +1432,17 @@ Sets the shadow mode for this directional light. Equivalent to [member DirectionalLight3D.directional_shadow_mode]. See [enum LightDirectionalShadowMode] for options. </description> </method> + <method name="light_directional_set_sky_only"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + If [code]true[/code], this light will not be used for anything except sky shaders. Use this for lights that impact your sky shader that you may want to hide from affecting the rest of the scene. For example, you may want to enable this when the sun in your sky shader falls below the horizon. + </description> + </method> <method name="light_omni_set_shadow_mode"> <return type="void"> </return> diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index bef4d999af..37bfa981d9 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -591,6 +591,8 @@ public: void light_directional_set_blend_splits(RID p_light, bool p_enable) override {} bool light_directional_get_blend_splits(RID p_light) const override { return false; } void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) override {} + void light_directional_set_sky_only(RID p_light, bool p_sky_only) override {} + bool light_directional_is_sky_only(RID p_light) const override { return false; } RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; } RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; } diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 46c3f18c38..73228959d5 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -394,6 +394,15 @@ bool DirectionalLight3D::is_blend_splits_enabled() const { return blend_splits; } +void DirectionalLight3D::set_sky_only(bool p_sky_only) { + sky_only = p_sky_only; + RS::get_singleton()->light_directional_set_sky_only(light, p_sky_only); +} + +bool DirectionalLight3D::is_sky_only() const { + return sky_only; +} + void DirectionalLight3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight3D::set_shadow_mode); ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight3D::get_shadow_mode); @@ -404,6 +413,9 @@ void DirectionalLight3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight3D::set_blend_splits); ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight3D::is_blend_splits_enabled); + ClassDB::bind_method(D_METHOD("set_sky_only", "priority"), &DirectionalLight3D::set_sky_only); + ClassDB::bind_method(D_METHOD("is_sky_only"), &DirectionalLight3D::is_sky_only); + ADD_GROUP("Directional Shadow", "directional_shadow_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal (Fast),PSSM 2 Splits (Average),PSSM 4 Splits (Slow)"), "set_shadow_mode", "get_shadow_mode"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET); @@ -415,6 +427,8 @@ void DirectionalLight3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_EXP_RANGE, "0,1024,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_in_sky_only"), "set_sky_only", "is_sky_only"); + BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 69c0478b86..08287a3313 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -158,6 +158,7 @@ private: bool blend_splits; ShadowMode shadow_mode; ShadowDepthRange shadow_depth_range; + bool sky_only = false; protected: static void _bind_methods(); @@ -172,6 +173,9 @@ public: void set_blend_splits(bool p_enable); bool is_blend_splits_enabled() const; + void set_sky_only(bool p_sky_only); + bool is_sky_only() const; + DirectionalLight3D(); }; diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index cecd313fbd..dad45bafa9 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -517,6 +517,8 @@ public: virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; virtual bool light_directional_get_blend_splits(RID p_light) const = 0; + virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0; + virtual bool light_directional_is_sky_only(RID p_light) const = 0; virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0; virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index f708b6ce00..2b1fea2aa1 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -1187,6 +1187,11 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm LightInstance *li = light_instance_owner.getornull(p_directional_light_instances[j]); ERR_CONTINUE(!li); + + if (storage->light_directional_is_sky_only(li->light)) { + continue; + } + Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); dir.y *= rb->sdfgi->y_mult; dir.normalize(); @@ -4391,6 +4396,11 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc RID light = light_instance_get_base_light(light_instance); l.type = storage->light_get_type(light); + if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_is_sky_only(light)) { + light_count--; + continue; + } + l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length(); @@ -5930,7 +5940,40 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull RS::LightType type = storage->light_get_type(base); switch (type) { case RS::LIGHT_DIRECTIONAL: { - if (r_directional_light_count >= cluster.max_directional_lights) { + // Copy to SkyDirectionalLightData + if (r_directional_light_count < sky_scene_state.max_directional_lights) { + SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count]; + Transform light_transform = light_instance_get_base_transform(li); + Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); + + sky_light_data.direction[0] = world_direction.x; + sky_light_data.direction[1] = world_direction.y; + sky_light_data.direction[2] = -world_direction.z; + + float sign = storage->light_is_negative(base) ? -1 : 1; + sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); + + Color linear_col = storage->light_get_color(base).to_linear(); + sky_light_data.color[0] = linear_col.r; + sky_light_data.color[1] = linear_col.g; + sky_light_data.color[2] = linear_col.b; + + sky_light_data.enabled = true; + + float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); + if (angular_diameter > 0.0) { + // I know tan(0) is 0, but let's not risk it with numerical precision. + // technically this will keep expanding until reaching the sun, but all we care + // is expand until we reach the radius of the near plane (there can't be more occluders than that) + angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + } else { + angular_diameter = 0.0; + } + sky_light_data.size = angular_diameter; + sky_scene_state.ubo.directional_light_count++; + } + + if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) { continue; } @@ -6073,27 +6116,6 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull } } - // Copy to SkyDirectionalLightData - if (r_directional_light_count < sky_scene_state.max_directional_lights) { - SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count]; - - Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); - - sky_light_data.direction[0] = world_direction.x; - sky_light_data.direction[1] = world_direction.y; - sky_light_data.direction[2] = -world_direction.z; - - sky_light_data.energy = light_data.energy / Math_PI; - - sky_light_data.color[0] = light_data.color[0]; - sky_light_data.color[1] = light_data.color[1]; - sky_light_data.color[2] = light_data.color[2]; - - sky_light_data.enabled = true; - sky_light_data.size = angular_diameter; - sky_scene_state.ubo.directional_light_count++; - } - r_directional_light_count++; } break; case RS::LIGHT_SPOT: diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index e723028e56..0bbbc68c94 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -4950,6 +4950,20 @@ bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const return light->directional_blend_splits; } +void RasterizerStorageRD::light_directional_set_sky_only(RID p_light, bool p_sky_only) { + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->directional_sky_only = p_sky_only; +} + +bool RasterizerStorageRD::light_directional_is_sky_only(RID p_light) const { + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, false); + + return light->directional_sky_only; +} + RS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h index b03a26e200..2fa6ce5867 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h @@ -823,6 +823,7 @@ private: RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; RS::LightDirectionalShadowDepthRangeMode directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; bool directional_blend_splits = false; + bool directional_sky_only = false; uint64_t version = 0; RasterizerScene::InstanceDependency instance_dependency; @@ -1459,6 +1460,8 @@ public: void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode); void light_directional_set_blend_splits(RID p_light, bool p_enable); bool light_directional_get_blend_splits(RID p_light) const; + void light_directional_set_sky_only(RID p_light, bool p_sky_only); + bool light_directional_is_sky_only(RID p_light) const; void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode); RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index 97477f1d3e..436577fae3 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -337,6 +337,7 @@ public: BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) BIND2(light_directional_set_blend_splits, RID, bool) + BIND2(light_directional_set_sky_only, RID, bool) BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp index ae6786090a..b933a550e2 100644 --- a/servers/rendering/rendering_server_scene.cpp +++ b/servers/rendering/rendering_server_scene.cpp @@ -2169,7 +2169,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const //check shadow.. if (light) { - if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base)) { + if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base) && !(RSG::storage->light_get_type(E->get()->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->get()->base))) { lights_with_shadow[directional_shadow_count++] = E->get(); } //add to list @@ -2595,7 +2595,8 @@ void RenderingServerScene::render_probes() { cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) || cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || - cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) { + cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) || + cache->sky_only != RSG::storage->light_directional_is_sky_only(instance->base)) { cache_dirty = true; } } @@ -2664,6 +2665,7 @@ void RenderingServerScene::render_probes() { cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); + cache->sky_only = RSG::storage->light_directional_is_sky_only(instance->base); idx++; } diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h index 1b0a617627..aa8439c164 100644 --- a/servers/rendering/rendering_server_scene.h +++ b/servers/rendering/rendering_server_scene.h @@ -351,6 +351,7 @@ public: float spot_angle; float spot_attenuation; bool has_shadow; + bool sky_only; }; Vector<LightCache> light_cache; diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index c2337f8c9e..d3319c7ed2 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -244,6 +244,7 @@ public: FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) FUNC2(light_directional_set_blend_splits, RID, bool) + FUNC2(light_directional_set_sky_only, RID, bool) FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index e2f1ddb224..4b79660d22 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1618,6 +1618,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &RenderingServer::light_directional_set_shadow_mode); ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &RenderingServer::light_directional_set_blend_splits); + ClassDB::bind_method(D_METHOD("light_directional_set_sky_only", "light", "enable"), &RenderingServer::light_directional_set_sky_only); ClassDB::bind_method(D_METHOD("light_directional_set_shadow_depth_range_mode", "light", "range_mode"), &RenderingServer::light_directional_set_shadow_depth_range_mode); ClassDB::bind_method(D_METHOD("reflection_probe_create"), &RenderingServer::reflection_probe_create); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index e50170bdf7..9ffdd15f5a 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -435,6 +435,7 @@ public: virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; + virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0; enum LightDirectionalShadowDepthRangeMode { LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, |