diff options
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/camera_3d.cpp | 60 | ||||
-rw-r--r-- | scene/3d/camera_3d.h | 15 | ||||
-rw-r--r-- | scene/3d/collision_object_3d.cpp | 2 | ||||
-rw-r--r-- | scene/3d/collision_object_3d.h | 2 | ||||
-rw-r--r-- | scene/3d/cpu_particles_3d.cpp | 36 | ||||
-rw-r--r-- | scene/3d/fog_volume.cpp | 1 | ||||
-rw-r--r-- | scene/3d/label_3d.cpp | 20 | ||||
-rw-r--r-- | scene/3d/light_3d.cpp | 91 | ||||
-rw-r--r-- | scene/3d/light_3d.h | 9 | ||||
-rw-r--r-- | scene/3d/lightmap_gi.cpp | 49 | ||||
-rw-r--r-- | scene/3d/lightmap_gi.h | 11 | ||||
-rw-r--r-- | scene/3d/lightmapper.h | 2 | ||||
-rw-r--r-- | scene/3d/mesh_instance_3d.cpp | 9 | ||||
-rw-r--r-- | scene/3d/path_3d.cpp | 20 | ||||
-rw-r--r-- | scene/3d/skeleton_3d.cpp | 17 | ||||
-rw-r--r-- | scene/3d/skeleton_3d.h | 7 | ||||
-rw-r--r-- | scene/3d/sprite_3d.cpp | 19 | ||||
-rw-r--r-- | scene/3d/sprite_3d.h | 4 | ||||
-rw-r--r-- | scene/3d/voxel_gi.cpp | 23 | ||||
-rw-r--r-- | scene/3d/voxel_gi.h | 7 | ||||
-rw-r--r-- | scene/3d/voxelizer.cpp | 10 | ||||
-rw-r--r-- | scene/3d/voxelizer.h | 3 | ||||
-rw-r--r-- | scene/3d/world_environment.cpp | 54 | ||||
-rw-r--r-- | scene/3d/world_environment.h | 10 |
24 files changed, 347 insertions, 134 deletions
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index b8b6296c45..304e56326d 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -31,6 +31,7 @@ #include "camera_3d.h" #include "collision_object_3d.h" +#include "core/core_string_names.h" #include "core/math/projection.h" #include "scene/main/viewport.h" @@ -71,6 +72,17 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } + + if (attributes.is_valid()) { + const CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr()); + if (physical_attributes) { + if (p_property.name == "near" || p_property.name == "far" || p_property.name == "fov" || p_property.name == "keep_aspect") { + p_property.usage = PROPERTY_USAGE_READ_ONLY | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR; + } + } + } + + Node3D::_validate_property(p_property); } void Camera3D::_update_camera() { @@ -400,18 +412,44 @@ Ref<Environment> Camera3D::get_environment() const { return environment; } -void Camera3D::set_effects(const Ref<CameraEffects> &p_effects) { - effects = p_effects; - if (effects.is_valid()) { - RS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid()); +void Camera3D::set_attributes(const Ref<CameraAttributes> &p_attributes) { + if (attributes.is_valid()) { + CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr()); + if (physical_attributes) { + attributes->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Camera3D::_attributes_changed)); + } + } + + attributes = p_attributes; + + if (attributes.is_valid()) { + CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr()); + if (physical_attributes) { + attributes->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Camera3D::_attributes_changed)); + _attributes_changed(); + } + + RS::get_singleton()->camera_set_camera_attributes(camera, attributes->get_rid()); } else { - RS::get_singleton()->camera_set_camera_effects(camera, RID()); + RS::get_singleton()->camera_set_camera_attributes(camera, RID()); } - _update_camera_mode(); + + notify_property_list_changed(); } -Ref<CameraEffects> Camera3D::get_effects() const { - return effects; +Ref<CameraAttributes> Camera3D::get_attributes() const { + return attributes; +} + +void Camera3D::_attributes_changed() { + CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr()); + ERR_FAIL_COND(!physical_attributes); + + fov = physical_attributes->get_fov(); + near = physical_attributes->get_near(); + far = physical_attributes->get_far(); + keep_aspect = KEEP_HEIGHT; + _update_camera_mode(); } void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) { @@ -479,8 +517,8 @@ void Camera3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera3D::get_cull_mask); ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera3D::set_environment); ClassDB::bind_method(D_METHOD("get_environment"), &Camera3D::get_environment); - ClassDB::bind_method(D_METHOD("set_effects", "env"), &Camera3D::set_effects); - ClassDB::bind_method(D_METHOD("get_effects"), &Camera3D::get_effects); + ClassDB::bind_method(D_METHOD("set_attributes", "env"), &Camera3D::set_attributes); + ClassDB::bind_method(D_METHOD("get_attributes"), &Camera3D::get_attributes); ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera3D::set_keep_aspect_mode); ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera3D::get_keep_aspect_mode); ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera3D::set_doppler_tracking); @@ -498,7 +536,7 @@ void Camera3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_effects", "get_effects"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_attributes", "get_attributes"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking"); diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index bba9b7d1e4..f150a23e27 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -33,7 +33,7 @@ #include "scene/3d/node_3d.h" #include "scene/3d/velocity_tracker_3d.h" -#include "scene/resources/camera_effects.h" +#include "scene/resources/camera_attributes.h" #include "scene/resources/environment.h" class Camera3D : public Node3D { @@ -64,11 +64,11 @@ private: ProjectionType mode = PROJECTION_PERSPECTIVE; - real_t fov = 0.0; + real_t fov = 75.0; real_t size = 1.0; Vector2 frustum_offset; - real_t near = 0.0; - real_t far = 0.0; + real_t near = 0.05; + real_t far = 4000.0; real_t v_offset = 0.0; real_t h_offset = 0.0; KeepAspect keep_aspect = KEEP_HEIGHT; @@ -81,7 +81,8 @@ private: uint32_t layers = 0xfffff; Ref<Environment> environment; - Ref<CameraEffects> effects; + Ref<CameraAttributes> attributes; + void _attributes_changed(); // void _camera_make_current(Node *p_camera); friend class Viewport; @@ -159,8 +160,8 @@ public: void set_environment(const Ref<Environment> &p_environment); Ref<Environment> get_environment() const; - void set_effects(const Ref<CameraEffects> &p_effects); - Ref<CameraEffects> get_effects() const; + void set_attributes(const Ref<CameraAttributes> &p_effects); + Ref<CameraAttributes> get_attributes() const; void set_keep_aspect_mode(KeepAspect p_aspect); KeepAspect get_keep_aspect_mode() const; diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 48eb2a66b1..f5e3e8b015 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -469,6 +469,8 @@ void CollisionObject3D::_bind_methods() { ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner); GDVIRTUAL_BIND(_input_event, "camera", "event", "position", "normal", "shape_idx"); + GDVIRTUAL_BIND(_mouse_enter); + GDVIRTUAL_BIND(_mouse_exit); ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "position"), PropertyInfo(Variant::VECTOR3, "normal"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("mouse_entered")); diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index 51c31da79f..c638be9d90 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -113,6 +113,8 @@ protected: bool is_only_update_transform_changes_enabled() const; GDVIRTUAL5(_input_event, Camera3D *, Ref<InputEvent>, Vector3, Vector3, int) + GDVIRTUAL0(_mouse_enter) + GDVIRTUAL0(_mouse_exit) public: void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 9dc61b35af..e14bb1aa94 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -739,17 +739,17 @@ void CPUParticles3D::_particles_process(double p_delta) { /*real_t tex_linear_velocity = 0; if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0); + tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->sample(0); }*/ real_t tex_angle = 0.0; if (curve_parameters[PARAM_ANGLE].is_valid()) { - tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv); + tex_angle = curve_parameters[PARAM_ANGLE]->sample(tv); } real_t tex_anim_offset = 0.0; if (curve_parameters[PARAM_ANGLE].is_valid()) { - tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(tv); + tex_anim_offset = curve_parameters[PARAM_ANGLE]->sample(tv); } p.seed = Math::rand(); @@ -907,53 +907,53 @@ void CPUParticles3D::_particles_process(double p_delta) { real_t tex_linear_velocity = 1.0; if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv); + tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->sample(tv); } real_t tex_orbit_velocity = 1.0; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { - tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv); + tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->sample(tv); } } real_t tex_angular_velocity = 1.0; if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) { - tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv); + tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->sample(tv); } real_t tex_linear_accel = 1.0; if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) { - tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv); + tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->sample(tv); } real_t tex_tangential_accel = 1.0; if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) { - tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv); + tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->sample(tv); } real_t tex_radial_accel = 1.0; if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) { - tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv); + tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->sample(tv); } real_t tex_damping = 1.0; if (curve_parameters[PARAM_DAMPING].is_valid()) { - tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv); + tex_damping = curve_parameters[PARAM_DAMPING]->sample(tv); } real_t tex_angle = 1.0; if (curve_parameters[PARAM_ANGLE].is_valid()) { - tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv); + tex_angle = curve_parameters[PARAM_ANGLE]->sample(tv); } real_t tex_anim_speed = 1.0; if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) { - tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv); + tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->sample(tv); } real_t tex_anim_offset = 1.0; if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) { - tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv); + tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->sample(tv); } Vector3 force = gravity; @@ -1016,23 +1016,23 @@ void CPUParticles3D::_particles_process(double p_delta) { Vector3 tex_scale = Vector3(1.0, 1.0, 1.0); if (split_scale) { if (scale_curve_x.is_valid()) { - tex_scale.x = scale_curve_x->interpolate(tv); + tex_scale.x = scale_curve_x->sample(tv); } else { tex_scale.x = 1.0; } if (scale_curve_y.is_valid()) { - tex_scale.y = scale_curve_y->interpolate(tv); + tex_scale.y = scale_curve_y->sample(tv); } else { tex_scale.y = 1.0; } if (scale_curve_z.is_valid()) { - tex_scale.z = scale_curve_z->interpolate(tv); + tex_scale.z = scale_curve_z->sample(tv); } else { tex_scale.z = 1.0; } } else { if (curve_parameters[PARAM_SCALE].is_valid()) { - float tmp_scale = curve_parameters[PARAM_SCALE]->interpolate(tv); + float tmp_scale = curve_parameters[PARAM_SCALE]->sample(tv); tex_scale.x = tmp_scale; tex_scale.y = tmp_scale; tex_scale.z = tmp_scale; @@ -1041,7 +1041,7 @@ void CPUParticles3D::_particles_process(double p_delta) { real_t tex_hue_variation = 0.0; if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) { - tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv); + tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->sample(tv); } real_t hue_rot_angle = (tex_hue_variation)*Math_TAU * Math::lerp(parameters_min[PARAM_HUE_VARIATION], parameters_max[PARAM_HUE_VARIATION], p.hue_rot_rand); diff --git a/scene/3d/fog_volume.cpp b/scene/3d/fog_volume.cpp index 319129603e..cfee7028d4 100644 --- a/scene/3d/fog_volume.cpp +++ b/scene/3d/fog_volume.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "fog_volume.h" +#include "scene/resources/environment.h" /////////////////////////// diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 40b8af7d63..d977874911 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -34,6 +34,7 @@ #include "scene/main/viewport.h" #include "scene/resources/theme.h" #include "scene/scene_string_names.h" +#include "scene/theme/theme_db.h" void Label3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &Label3D::set_horizontal_alignment); @@ -485,8 +486,9 @@ void Label3D::_shape() { case TextServer::AUTOWRAP_OFF: break; } - PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); + autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); float max_line_w = 0.0; for (int i = 0; i < line_breaks.size(); i = i + 2) { RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); @@ -734,13 +736,13 @@ Ref<Font> Label3D::_get_font_or_default() const { } // Check the project-defined Theme resource. - if (Theme::get_project_default().is_valid()) { + if (ThemeDB::get_singleton()->get_project_theme().is_valid()) { List<StringName> theme_types; - Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types); for (const StringName &E : theme_types) { - if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { - Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + Ref<Font> f = ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); if (f.is_valid()) { theme_font = f; theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed")); @@ -753,11 +755,11 @@ Ref<Font> Label3D::_get_font_or_default() const { // Lastly, fall back on the items defined in the default Theme, if they exist. { List<StringName> theme_types; - Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types); for (const StringName &E : theme_types) { - if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { - Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); if (f.is_valid()) { theme_font = f; theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed")); @@ -768,7 +770,7 @@ Ref<Font> Label3D::_get_font_or_default() const { } // If they don't exist, use any type to return the default/empty value. - Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); + Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); if (f.is_valid()) { theme_font = f; theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed")); diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 8d96d13f0c..e51f06e083 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -28,6 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "core/config/project_settings.h" + #include "light_3d.h" void Light3D::set_param(Param p_param, real_t p_value) { @@ -122,7 +124,14 @@ uint32_t Light3D::get_cull_mask() const { void Light3D::set_color(const Color &p_color) { color = p_color; - RS::get_singleton()->light_set_color(light, p_color); + + if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { + Color combined = color.srgb_to_linear(); + combined *= correlated_color.srgb_to_linear(); + RS::get_singleton()->light_set_color(light, combined.linear_to_srgb()); + } else { + RS::get_singleton()->light_set_color(light, color); + } // The gizmo color depends on the light color, so update it. update_gizmos(); } @@ -181,6 +190,56 @@ void Light3D::owner_changed_notify() { _update_visibility(); } +// Temperature expressed in Kelvins. Valid range 1000 - 15000 +// First converts to CIE 1960 then to sRGB +// As explained in the Filament documentation: https://google.github.io/filament/Filament.md.html#lighting/directlighting/lightsparameterization +Color _color_from_temperature(float p_temperature) { + float T2 = p_temperature * p_temperature; + float u = (0.860117757f + 1.54118254e-4f * p_temperature + 1.28641212e-7f * T2) / + (1.0f + 8.42420235e-4f * p_temperature + 7.08145163e-7f * T2); + float v = (0.317398726f + 4.22806245e-5f * p_temperature + 4.20481691e-8f * T2) / + (1.0f - 2.89741816e-5f * p_temperature + 1.61456053e-7f * T2); + + // Convert to xyY space. + float d = 1.0f / (2.0f * u - 8.0f * v + 4.0f); + float x = 3.0f * u * d; + float y = 2.0f * v * d; + + // Convert to XYZ space + const float a = 1.0 / MAX(y, 1e-5f); + Vector3 xyz = Vector3(x * a, 1.0, (1.0f - x - y) * a); + + // Convert from XYZ to sRGB(linear) + Vector3 linear = Vector3(3.2404542f * xyz.x - 1.5371385f * xyz.y - 0.4985314f * xyz.z, + -0.9692660f * xyz.x + 1.8760108f * xyz.y + 0.0415560f * xyz.z, + 0.0556434f * xyz.x - 0.2040259f * xyz.y + 1.0572252f * xyz.z); + linear /= MAX(1e-5f, linear[linear.max_axis_index()]); + // Normalize, clamp, and convert to sRGB. + return Color(linear.x, linear.y, linear.z).clamp().linear_to_srgb(); +} + +void Light3D::set_temperature(const float p_temperature) { + temperature = p_temperature; + if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { + return; + } + correlated_color = _color_from_temperature(temperature); + + Color combined = color.srgb_to_linear() * correlated_color.srgb_to_linear(); + + RS::get_singleton()->light_set_color(light, combined.linear_to_srgb()); + // The gizmo color depends on the light color, so update it. + update_gizmos(); +} + +Color Light3D::get_correlated_color() const { + return correlated_color; +} + +float Light3D::get_temperature() const { + return temperature; +} + void Light3D::_update_visibility() { if (!is_inside_tree()) { return; @@ -224,12 +283,18 @@ bool Light3D::is_editor_only() const { } void Light3D::_validate_property(PropertyInfo &p_property) const { - if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_fog_fade" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow")) { + if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow")) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (get_light_type() != RS::LIGHT_DIRECTIONAL && p_property.name == "light_angular_distance") { - // Angular distance is only used in DirectionalLight3D. + if (get_light_type() != RS::LIGHT_DIRECTIONAL && (p_property.name == "light_angular_distance" || p_property.name == "light_intensity_lux")) { + // Angular distance and Light Intensity Lux are only used in DirectionalLight3D. + p_property.usage = PROPERTY_USAGE_NONE; + } else if (get_light_type() == RS::LIGHT_DIRECTIONAL && p_property.name == "light_intensity_lumens") { + p_property.usage = PROPERTY_USAGE_NONE; + } + + if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units") && (p_property.name == "light_intensity_lumens" || p_property.name == "light_intensity_lux" || p_property.name == "light_temperature")) { p_property.usage = PROPERTY_USAGE_NONE; } @@ -278,10 +343,18 @@ void Light3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_projector", "projector"), &Light3D::set_projector); ClassDB::bind_method(D_METHOD("get_projector"), &Light3D::get_projector); + ClassDB::bind_method(D_METHOD("set_temperature", "temperature"), &Light3D::set_temperature); + ClassDB::bind_method(D_METHOD("get_temperature"), &Light3D::get_temperature); + ClassDB::bind_method(D_METHOD("get_correlated_color"), &Light3D::get_correlated_color); + ADD_GROUP("Light", "light_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_intensity_lumens", PROPERTY_HINT_RANGE, "0,100000.0,0.01,or_greater,suffix:lm"), "set_param", "get_param", PARAM_INTENSITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_intensity_lux", PROPERTY_HINT_RANGE, "0,150000.0,0.01,or_greater,suffix:lx"), "set_param", "get_param", PARAM_INTENSITY); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "light_temperature", PROPERTY_HINT_RANGE, "1000,15000.0,1.0,suffix:k"), "set_temperature", "get_temperature"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_volumetric_fog_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_VOLUMETRIC_FOG_ENERGY); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_projector", "get_projector"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_param", "get_param", PARAM_SIZE); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01,degrees"), "set_param", "get_param", PARAM_SIZE); @@ -296,7 +369,6 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_OPACITY); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR); @@ -313,6 +385,7 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_ENERGY); BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY); + BIND_ENUM_CONSTANT(PARAM_VOLUMETRIC_FOG_ENERGY); BIND_ENUM_CONSTANT(PARAM_SPECULAR); BIND_ENUM_CONSTANT(PARAM_RANGE); BIND_ENUM_CONSTANT(PARAM_SIZE); @@ -329,8 +402,8 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE); BIND_ENUM_CONSTANT(PARAM_SHADOW_OPACITY); BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR); - BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE); BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS); + BIND_ENUM_CONSTANT(PARAM_INTENSITY); BIND_ENUM_CONSTANT(PARAM_MAX); BIND_ENUM_CONSTANT(BAKE_DISABLED); @@ -363,6 +436,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) { set_param(PARAM_ENERGY, 1); set_param(PARAM_INDIRECT_ENERGY, 1); + set_param(PARAM_VOLUMETRIC_FOG_ENERGY, 1); set_param(PARAM_SPECULAR, 0.5); set_param(PARAM_RANGE, 5); set_param(PARAM_SIZE, 0); @@ -380,8 +454,10 @@ Light3D::Light3D(RenderingServer::LightType p_type) { set_param(PARAM_SHADOW_BIAS, 0.03); set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0); set_param(PARAM_TRANSMITTANCE_BIAS, 0.05); - set_param(PARAM_SHADOW_VOLUMETRIC_FOG_FADE, 0.1); set_param(PARAM_SHADOW_FADE_START, 1); + // For OmniLight3D and SpotLight3D, specified in Lumens. + set_param(PARAM_INTENSITY, 1000.0); + set_temperature(6500.0); // Nearly white. set_disable_scale(true); } @@ -487,6 +563,7 @@ DirectionalLight3D::DirectionalLight3D() : set_param(PARAM_SHADOW_FADE_START, 0.8); // Increase the default shadow bias to better suit most scenes. set_param(PARAM_SHADOW_BIAS, 0.1); + set_param(PARAM_INTENSITY, 100000.0); // Specified in Lux, approximate mid-day sun. set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); blend_splits = false; set_sky_mode(SKY_MODE_LIGHT_AND_SKY); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 035ba50e42..e43d6f0419 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -40,6 +40,7 @@ public: enum Param { PARAM_ENERGY = RS::LIGHT_PARAM_ENERGY, PARAM_INDIRECT_ENERGY = RS::LIGHT_PARAM_INDIRECT_ENERGY, + PARAM_VOLUMETRIC_FOG_ENERGY = RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY, PARAM_SPECULAR = RS::LIGHT_PARAM_SPECULAR, PARAM_RANGE = RS::LIGHT_PARAM_RANGE, PARAM_SIZE = RS::LIGHT_PARAM_SIZE, @@ -56,8 +57,8 @@ public: PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE, PARAM_SHADOW_OPACITY = RS::LIGHT_PARAM_SHADOW_OPACITY, PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR, - PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE, PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS, + PARAM_INTENSITY = RS::LIGHT_PARAM_INTENSITY, PARAM_MAX = RS::LIGHT_PARAM_MAX }; @@ -83,6 +84,8 @@ private: void _update_visibility(); BakeMode bake_mode = BAKE_DYNAMIC; Ref<Texture2D> projector; + Color correlated_color = Color(1.0, 1.0, 1.0); + float temperature = 6500.0; // bind helpers @@ -139,6 +142,10 @@ public: void set_projector(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_projector() const; + void set_temperature(const float p_temperature); + float get_temperature() const; + Color get_correlated_color() const; + virtual AABB get_aabb() const override; Light3D(); diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 7efda6db32..41a537f7cb 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -30,10 +30,14 @@ #include "lightmap_gi.h" +#include "core/config/project_settings.h" #include "core/io/config_file.h" #include "core/math/delaunay_3d.h" #include "lightmap_probe.h" #include "scene/3d/mesh_instance_3d.h" +#include "scene/resources/camera_attributes.h" +#include "scene/resources/environment.h" +#include "scene/resources/sky.h" void LightmapGIData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) { User user; @@ -207,7 +211,7 @@ bool LightmapGIData::is_using_spherical_harmonics() const { return uses_spherical_harmonics; } -void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { +void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure) { if (p_points.size()) { int pc = p_points.size(); ERR_FAIL_COND(pc * 9 != p_point_sh.size()); @@ -221,6 +225,8 @@ void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, con RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB()); RS::get_singleton()->lightmap_set_probe_interior(lightmap, false); } + RS::get_singleton()->lightmap_set_baked_exposure_normalization(lightmap, p_baked_exposure); + baked_exposure = p_baked_exposure; interior = p_interior; bounds = p_bounds; } @@ -249,6 +255,10 @@ bool LightmapGIData::is_interior() const { return interior; } +float LightmapGIData::get_baked_exposure() const { + return baked_exposure; +} + void LightmapGIData::_set_probe_data(const Dictionary &p_data) { ERR_FAIL_COND(!p_data.has("bounds")); ERR_FAIL_COND(!p_data.has("points")); @@ -256,7 +266,8 @@ void LightmapGIData::_set_probe_data(const Dictionary &p_data) { ERR_FAIL_COND(!p_data.has("bsp")); ERR_FAIL_COND(!p_data.has("sh")); ERR_FAIL_COND(!p_data.has("interior")); - set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]); + ERR_FAIL_COND(!p_data.has("baked_exposure")); + set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"], p_data["baked_exposure"]); } Dictionary LightmapGIData::_get_probe_data() const { @@ -267,6 +278,7 @@ Dictionary LightmapGIData::_get_probe_data() const { d["bsp"] = get_capture_bsp_tree(); d["sh"] = get_capture_sh(); d["interior"] = is_interior(); + d["baked_exposure"] = get_baked_exposure(); return d; } @@ -977,15 +989,21 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa Transform3D xf = lights_found[i].xform; Color linear_color = light->get_color().srgb_to_linear(); + float energy = light->get_param(Light3D::PARAM_ENERGY); + if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { + energy *= light->get_param(Light3D::PARAM_INTENSITY); + linear_color *= light->get_correlated_color().srgb_to_linear(); + } + if (Object::cast_to<DirectionalLight3D>(light)) { DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light); - lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR)); + lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy, l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR)); } else if (Object::cast_to<OmniLight3D>(light)) { OmniLight3D *l = Object::cast_to<OmniLight3D>(light); - lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR)); + lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, energy * (1.0 / (Math_PI * 4.0)), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR)); } else if (Object::cast_to<SpotLight3D>(light)) { SpotLight3D *l = Object::cast_to<SpotLight3D>(light); - lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR)); + lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy * (1.0 / Math_PI), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR)); } } for (int i = 0; i < probes_found.size(); i++) { @@ -1040,7 +1058,12 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa } } - Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud); + float exposure_normalization = 1.0; + if (camera_attributes.is_valid()) { + exposure_normalization = camera_attributes->calculate_exposure_normalization() * camera_attributes->get_exposure_multiplier(); + } + + Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud, exposure_normalization); if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) { return BAKE_ERROR_MESHES_INVALID; @@ -1214,7 +1237,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa /* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */ - data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array); + data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array, exposure_normalization); /* Compute a BSP tree of the simplices, so it's easy to find the exact one */ } @@ -1410,6 +1433,14 @@ LightmapGI::GenerateProbes LightmapGI::get_generate_probes() const { return gen_probes; } +void LightmapGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) { + camera_attributes = p_camera_attributes; +} + +Ref<CameraAttributes> LightmapGI::get_camera_attributes() const { + return camera_attributes; +} + void LightmapGI::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) { p_property.usage = PROPERTY_USAGE_NONE; @@ -1462,6 +1493,9 @@ void LightmapGI::_bind_methods() { ClassDB::bind_method(D_METHOD("set_directional", "directional"), &LightmapGI::set_directional); ClassDB::bind_method(D_METHOD("is_directional"), &LightmapGI::is_directional); + ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &LightmapGI::set_camera_attributes); + ClassDB::bind_method(D_METHOD("get_camera_attributes"), &LightmapGI::get_camera_attributes); + // ClassDB::bind_method(D_METHOD("bake", "from_node"), &LightmapGI::bake, DEFVAL(Variant())); ADD_GROUP("Tweaks", ""); @@ -1477,6 +1511,7 @@ void LightmapGI::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes"); ADD_GROUP("Gen Probes", "generate_probes_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes"); ADD_GROUP("Data", ""); diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index 87add9facc..0062a4a093 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -36,6 +36,9 @@ #include "scene/3d/lightmapper.h" #include "scene/3d/visual_instance_3d.h" +class Sky; +class CameraAttributes; + class LightmapGIData : public Resource { GDCLASS(LightmapGIData, Resource); RES_BASE_EXTENSION("lmbake") @@ -47,6 +50,7 @@ class LightmapGIData : public Resource { RID lightmap; AABB bounds; + float baked_exposure = 1.0; struct User { NodePath path; @@ -83,8 +87,9 @@ public: bool is_using_spherical_harmonics() const; bool is_interior() const; + float get_baked_exposure() const; - void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree); + void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure); PackedVector3Array get_capture_points() const; PackedColorArray get_capture_sh() const; PackedInt32Array get_capture_tetrahedra() const; @@ -147,6 +152,7 @@ private: float environment_custom_energy = 1.0; bool directional = false; GenerateProbes gen_probes = GENERATE_PROBES_DISABLED; + Ref<CameraAttributes> camera_attributes; Ref<LightmapGIData> light_data; @@ -260,6 +266,9 @@ public: void set_generate_probes(GenerateProbes p_generate_probes); GenerateProbes get_generate_probes() const; + void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes); + Ref<CameraAttributes> get_camera_attributes() const; + AABB get_aabb() const override; BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr); diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h index 9b973fd6bc..5b5c6cf53a 100644 --- a/scene/3d/lightmapper.h +++ b/scene/3d/lightmapper.h @@ -180,7 +180,7 @@ public: virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) = 0; virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) = 0; virtual void add_probe(const Vector3 &p_position) = 0; - virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr) = 0; + virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, float p_exposure_normalization = 1.0) = 0; virtual int get_bake_texture_count() const = 0; virtual Ref<Image> get_bake_texture(int p_index) const = 0; diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 31993f898d..a76f4dd0d5 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -115,8 +115,8 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) { if (mesh.is_valid()) { mesh->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance3D::_mesh_changed)); - _mesh_changed(); set_base(mesh->get_rid()); + _mesh_changed(); } else { blend_shape_tracks.clear(); blend_shape_properties.clear(); @@ -380,6 +380,13 @@ void MeshInstance3D::_mesh_changed() { } } + int surface_count = mesh->get_surface_count(); + for (int surface_index = 0; surface_index < surface_count; ++surface_index) { + if (surface_override_materials[surface_index].is_valid()) { + RS::get_singleton()->instance_set_surface_override_material(get_instance(), surface_index, surface_override_materials[surface_index]->get_rid()); + } + } + update_gizmos(); } diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index 7d79d9b4fd..3d23206e6b 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -198,17 +198,17 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { } } - Vector3 pos = c->interpolate_baked(progress, cubic); + Vector3 pos = c->sample_baked(progress, cubic); Transform3D t = get_transform(); // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used if (rotation_mode == ROTATION_ORIENTED) { - Vector3 forward = c->interpolate_baked(o_next, cubic) - pos; + Vector3 forward = c->sample_baked(o_next, cubic) - pos; // Try with the previous position if (forward.length_squared() < CMP_EPSILON2) { - forward = pos - c->interpolate_baked(o_prev, cubic); + forward = pos - c->sample_baked(o_prev, cubic); } if (forward.length_squared() < CMP_EPSILON2) { @@ -217,10 +217,10 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { forward.normalize(); } - Vector3 up = c->interpolate_baked_up_vector(progress, true); + Vector3 up = c->sample_baked_up_vector(progress, true); if (o_next < progress) { - Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); + Vector3 up1 = c->sample_baked_up_vector(o_next, true); Vector3 axis = up.cross(up1); if (axis.length_squared() < CMP_EPSILON2) { @@ -249,10 +249,10 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { t.origin = pos; if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree. real_t sample_distance = bi * 0.01; - Vector3 t_prev_pos_a = c->interpolate_baked(prev_offset - sample_distance, cubic); - Vector3 t_prev_pos_b = c->interpolate_baked(prev_offset + sample_distance, cubic); - Vector3 t_cur_pos_a = c->interpolate_baked(progress - sample_distance, cubic); - Vector3 t_cur_pos_b = c->interpolate_baked(progress + sample_distance, cubic); + Vector3 t_prev_pos_a = c->sample_baked(prev_offset - sample_distance, cubic); + Vector3 t_prev_pos_b = c->sample_baked(prev_offset + sample_distance, cubic); + Vector3 t_cur_pos_a = c->sample_baked(progress - sample_distance, cubic); + Vector3 t_cur_pos_b = c->sample_baked(progress + sample_distance, cubic); Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized(); Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized(); @@ -277,7 +277,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { } // do the additional tilting - real_t tilt_angle = c->interpolate_baked_tilt(progress); + real_t tilt_angle = c->sample_baked_tilt(progress); Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) { diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 1bc138704e..e04e1866db 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -315,9 +315,7 @@ void Skeleton3D::_notification(int p_what) { rs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i)); } } -#ifdef TOOLS_ENABLED emit_signal(SceneStringNames::get_singleton()->pose_updated); -#endif // TOOLS_ENABLED } break; #ifndef _3D_DISABLED @@ -603,18 +601,25 @@ void Skeleton3D::unparent_bone_and_rest(int p_bone) { int Skeleton3D::get_bone_parent(int p_bone) const { const int bone_size = bones.size(); ERR_FAIL_INDEX_V(p_bone, bone_size, -1); - + if (process_order_dirty) { + const_cast<Skeleton3D *>(this)->_update_process_order(); + } return bones[p_bone].parent; } -Vector<int> Skeleton3D::get_bone_children(int p_bone) { +Vector<int> Skeleton3D::get_bone_children(int p_bone) const { const int bone_size = bones.size(); ERR_FAIL_INDEX_V(p_bone, bone_size, Vector<int>()); + if (process_order_dirty) { + const_cast<Skeleton3D *>(this)->_update_process_order(); + } return bones[p_bone].child_bones; } -Vector<int> Skeleton3D::get_parentless_bones() { - _update_process_order(); +Vector<int> Skeleton3D::get_parentless_bones() const { + if (process_order_dirty) { + const_cast<Skeleton3D *>(this)->_update_process_order(); + } return parentless_bones; } diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 79feadf44f..5e49dfa1f4 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -191,11 +191,8 @@ public: void unparent_bone_and_rest(int p_bone); - Vector<int> get_bone_children(int p_bone); - void set_bone_children(int p_bone, Vector<int> p_children); - void add_bone_child(int p_bone, int p_child); - void remove_bone_child(int p_bone, int p_child); - Vector<int> get_parentless_bones(); + Vector<int> get_bone_children(int p_bone) const; + Vector<int> get_parentless_bones() const; int get_bone_count() const; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 669c3eb7fd..4515277dc3 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -1174,7 +1174,7 @@ void AnimatedSprite3D::_res_changed() { _queue_update(); } -void AnimatedSprite3D::_set_playing(bool p_playing) { +void AnimatedSprite3D::set_playing(bool p_playing) { if (playing == p_playing) { return; } @@ -1183,7 +1183,7 @@ void AnimatedSprite3D::_set_playing(bool p_playing) { set_process_internal(playing); } -bool AnimatedSprite3D::_is_playing() const { +bool AnimatedSprite3D::is_playing() const { return playing; } @@ -1191,15 +1191,11 @@ void AnimatedSprite3D::play(const StringName &p_animation) { if (p_animation) { set_animation(p_animation); } - _set_playing(true); + set_playing(true); } void AnimatedSprite3D::stop() { - _set_playing(false); -} - -bool AnimatedSprite3D::is_playing() const { - return playing; + set_playing(false); } void AnimatedSprite3D::_reset_timeout() { @@ -1262,12 +1258,11 @@ void AnimatedSprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_animation", "animation"), &AnimatedSprite3D::set_animation); ClassDB::bind_method(D_METHOD("get_animation"), &AnimatedSprite3D::get_animation); - ClassDB::bind_method(D_METHOD("_set_playing", "playing"), &AnimatedSprite3D::_set_playing); - ClassDB::bind_method(D_METHOD("_is_playing"), &AnimatedSprite3D::_is_playing); + ClassDB::bind_method(D_METHOD("set_playing", "playing"), &AnimatedSprite3D::set_playing); + ClassDB::bind_method(D_METHOD("is_playing"), &AnimatedSprite3D::is_playing); ClassDB::bind_method(D_METHOD("play", "anim"), &AnimatedSprite3D::play, DEFVAL(StringName())); ClassDB::bind_method(D_METHOD("stop"), &AnimatedSprite3D::stop); - ClassDB::bind_method(D_METHOD("is_playing"), &AnimatedSprite3D::is_playing); ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite3D::set_frame); ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame); @@ -1280,7 +1275,7 @@ void AnimatedSprite3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "set_playing", "is_playing"); } AnimatedSprite3D::AnimatedSprite3D() { diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 03688cf787..84244a2476 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -219,8 +219,6 @@ class AnimatedSprite3D : public SpriteBase3D { void _res_changed(); void _reset_timeout(); - void _set_playing(bool p_playing); - bool _is_playing() const; RID last_shader; RID last_texture; @@ -237,6 +235,8 @@ public: void play(const StringName &p_animation = StringName()); void stop(); + + void set_playing(bool p_playing); bool is_playing() const; void set_animation(const StringName &p_animation); diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index ae231026a7..c97af087bf 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -30,8 +30,10 @@ #include "voxel_gi.h" +#include "core/core_string_names.h" #include "mesh_instance_3d.h" #include "multimesh_instance_3d.h" +#include "scene/resources/camera_attributes.h" #include "voxelizer.h" void VoxelGIData::_set_data(const Dictionary &p_data) { @@ -281,6 +283,14 @@ Vector3 VoxelGI::get_extents() const { return extents; } +void VoxelGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) { + camera_attributes = p_camera_attributes; +} + +Ref<CameraAttributes> VoxelGI::get_camera_attributes() const { + return camera_attributes; +} + void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { @@ -370,9 +380,14 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { p_from_node = p_from_node ? p_from_node : get_parent(); ERR_FAIL_NULL(p_from_node); + float exposure_normalization = 1.0; + if (camera_attributes.is_valid()) { + exposure_normalization = camera_attributes->calculate_exposure_normalization() * camera_attributes->get_exposure_multiplier(); + } + Voxelizer baker; - baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0)); + baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0), exposure_normalization); List<PlotMesh> mesh_list; @@ -428,6 +443,8 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { Vector<uint8_t> df = baker.get_sdf_3d_image(); + RS::get_singleton()->voxel_gi_set_baked_exposure_normalization(probe_data->get_rid(), exposure_normalization); + probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count()); set_probe_data(probe_data); @@ -472,12 +489,16 @@ void VoxelGI::_bind_methods() { ClassDB::bind_method(D_METHOD("set_extents", "extents"), &VoxelGI::set_extents); ClassDB::bind_method(D_METHOD("get_extents"), &VoxelGI::get_extents); + ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &VoxelGI::set_camera_attributes); + ClassDB::bind_method(D_METHOD("get_camera_attributes"), &VoxelGI::get_camera_attributes); + ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &VoxelGI::bake, DEFVAL(Variant()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("debug_bake"), &VoxelGI::_debug_bake); ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_NONE, "suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "VoxelGIData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data"); BIND_ENUM_CONSTANT(SUBDIV_64); diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h index 6d173dea87..b31ae4cd95 100644 --- a/scene/3d/voxel_gi.h +++ b/scene/3d/voxel_gi.h @@ -33,6 +33,8 @@ #include "scene/3d/visual_instance_3d.h" +class CameraAttributes; + class VoxelGIData : public Resource { GDCLASS(VoxelGIData, Resource); @@ -117,6 +119,7 @@ private: Subdiv subdiv = SUBDIV_128; Vector3 extents = Vector3(10, 10, 10); + Ref<CameraAttributes> camera_attributes; struct PlotMesh { Ref<Material> override_material; @@ -144,6 +147,10 @@ public: void set_extents(const Vector3 &p_extents); Vector3 get_extents() const; + + void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes); + Ref<CameraAttributes> get_camera_attributes() const; + Vector3i get_estimated_cell_size() const; void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false); diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index 9380d1cf32..6daa9e0aec 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -30,6 +30,8 @@ #include "voxelizer.h" +#include "core/config/project_settings.h" + static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) { if (p_pos.is_equal_approx(p_vtx[0])) { r_uv = p_uv[0]; @@ -348,7 +350,10 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION); Color emission_col = mat->get_emission(); - float emission_energy = mat->get_emission_energy(); + float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization; + if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { + emission_energy *= mat->get_emission_intensity(); + } Ref<Image> img_emission; @@ -608,10 +613,11 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { } } -void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) { +void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds, float p_exposure_normalization) { sorted = false; original_bounds = p_bounds; cell_subdiv = p_subdiv; + exposure_normalization = p_exposure_normalization; bake_cells.resize(1); material_cache.clear(); diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h index 68bce768b7..f5bb9af107 100644 --- a/scene/3d/voxelizer.h +++ b/scene/3d/voxelizer.h @@ -87,6 +87,7 @@ private: }; HashMap<Ref<Material>, MaterialCache> material_cache; + float exposure_normalization = 1.0; AABB original_bounds; AABB po2_bounds; int axis_cell_size[3] = {}; @@ -111,7 +112,7 @@ private: void _sort(); public: - void begin_bake(int p_subdiv, const AABB &p_bounds); + void begin_bake(int p_subdiv, const AABB &p_bounds, float p_exposure_normalization); void plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material); void end_bake(); diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index fe9d9ae4dd..ae7d79e8b0 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -42,9 +42,9 @@ void WorldEnvironment::_notification(int p_what) { _update_current_environment(); } - if (camera_effects.is_valid()) { - add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); - _update_current_camera_effects(); + if (camera_attributes.is_valid()) { + add_to_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_camera_attributes(); } } break; @@ -55,9 +55,9 @@ void WorldEnvironment::_notification(int p_what) { _update_current_environment(); } - if (camera_effects.is_valid()) { - remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); - _update_current_camera_effects(); + if (camera_attributes.is_valid()) { + remove_from_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_camera_attributes(); } } break; } @@ -74,15 +74,15 @@ void WorldEnvironment::_update_current_environment() { get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } -void WorldEnvironment::_update_current_camera_effects() { - WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()))); +void WorldEnvironment::_update_current_camera_attributes() { + WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()))); if (first) { - get_viewport()->find_world_3d()->set_camera_effects(first->camera_effects); + get_viewport()->find_world_3d()->set_camera_attributes(first->camera_attributes); } else { - get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>()); + get_viewport()->find_world_3d()->set_camera_attributes(Ref<CameraAttributes>()); } - get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) { @@ -110,36 +110,36 @@ Ref<Environment> WorldEnvironment::get_environment() const { return environment; } -void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) { - if (camera_effects == p_camera_effects) { +void WorldEnvironment::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) { + if (camera_attributes == p_camera_attributes) { return; } - if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) { - remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + if (is_inside_tree() && camera_attributes.is_valid() && get_viewport()->find_world_3d()->get_camera_attributes() == camera_attributes) { + remove_from_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); } - camera_effects = p_camera_effects; - if (is_inside_tree() && camera_effects.is_valid()) { - add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + camera_attributes = p_camera_attributes; + if (is_inside_tree() && camera_attributes.is_valid()) { + add_to_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); } if (is_inside_tree()) { - _update_current_camera_effects(); + _update_current_camera_attributes(); } else { update_configuration_warnings(); } } -Ref<CameraEffects> WorldEnvironment::get_camera_effects() const { - return camera_effects; +Ref<CameraAttributes> WorldEnvironment::get_camera_attributes() const { + return camera_attributes; } TypedArray<String> WorldEnvironment::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); - if (!environment.is_valid() && !camera_effects.is_valid()) { - warnings.push_back(RTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Effects\" property to contain a CameraEffects resource, or both.")); + if (!environment.is_valid() && !camera_attributes.is_valid()) { + warnings.push_back(RTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Attributes\" property to contain a CameraAttributes resource, or both.")); } if (!is_inside_tree()) { @@ -150,7 +150,7 @@ TypedArray<String> WorldEnvironment::get_configuration_warnings() const { warnings.push_back(("Only the first Environment has an effect in a scene (or set of instantiated scenes).")); } - if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() != camera_effects) { + if (camera_attributes.is_valid() && get_viewport()->find_world_3d()->get_camera_attributes() != camera_attributes) { warnings.push_back(RTR("Only one WorldEnvironment is allowed per scene (or set of instantiated scenes).")); } @@ -162,9 +162,9 @@ void WorldEnvironment::_bind_methods() { ClassDB::bind_method(D_METHOD("get_environment"), &WorldEnvironment::get_environment); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); - ClassDB::bind_method(D_METHOD("set_camera_effects", "env"), &WorldEnvironment::set_camera_effects); - ClassDB::bind_method(D_METHOD("get_camera_effects"), &WorldEnvironment::get_camera_effects); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects"); + ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &WorldEnvironment::set_camera_attributes); + ClassDB::bind_method(D_METHOD("get_camera_attributes"), &WorldEnvironment::get_camera_attributes); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes"); } WorldEnvironment::WorldEnvironment() { diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index 9955aa72a8..07f243c750 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -32,17 +32,17 @@ #define WORLD_ENVIRONMENT_H #include "scene/main/node.h" -#include "scene/resources/camera_effects.h" +#include "scene/resources/camera_attributes.h" #include "scene/resources/environment.h" class WorldEnvironment : public Node { GDCLASS(WorldEnvironment, Node); Ref<Environment> environment; - Ref<CameraEffects> camera_effects; + Ref<CameraAttributes> camera_attributes; void _update_current_environment(); - void _update_current_camera_effects(); + void _update_current_camera_attributes(); protected: void _notification(int p_what); @@ -52,8 +52,8 @@ public: void set_environment(const Ref<Environment> &p_environment); Ref<Environment> get_environment() const; - void set_camera_effects(const Ref<CameraEffects> &p_camera_effects); - Ref<CameraEffects> get_camera_effects() const; + void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes); + Ref<CameraAttributes> get_camera_attributes() const; TypedArray<String> get_configuration_warnings() const override; |