summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
authorclayjohn <claynjohn@gmail.com>2022-07-31 16:20:24 -0700
committerclayjohn <claynjohn@gmail.com>2022-08-31 12:14:46 -0700
commit385ee5c70b110fc4e6a47c847428bfe3da89e18e (patch)
tree79a98b11b042372e99ed209f033dd721f5a74e14 /scene/3d
parent736632ee7ed00a3474448cfd227f696f82905ac7 (diff)
Implement Physical Light Units as an optional setting.
This allows light sources to be specified in physical light units in addition to the regular energy multiplier. In order to avoid loss of precision at high values, brightness values are premultiplied by an exposure normalization value. In support of Physical Light Units this PR also renames CameraEffects to CameraAttributes.
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/camera_3d.cpp60
-rw-r--r--scene/3d/camera_3d.h15
-rw-r--r--scene/3d/fog_volume.cpp1
-rw-r--r--scene/3d/light_3d.cpp83
-rw-r--r--scene/3d/light_3d.h7
-rw-r--r--scene/3d/lightmap_gi.cpp49
-rw-r--r--scene/3d/lightmap_gi.h11
-rw-r--r--scene/3d/lightmapper.h2
-rw-r--r--scene/3d/voxel_gi.cpp23
-rw-r--r--scene/3d/voxel_gi.h7
-rw-r--r--scene/3d/voxelizer.cpp10
-rw-r--r--scene/3d/voxelizer.h3
-rw-r--r--scene/3d/world_environment.cpp54
-rw-r--r--scene/3d/world_environment.h10
14 files changed, 269 insertions, 66 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/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/light_3d.cpp b/scene/3d/light_3d.cpp
index 66f4fa2bcc..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;
@@ -228,8 +287,14 @@ void Light3D::_validate_property(PropertyInfo &p_property) const {
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,7 +343,14 @@ 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);
@@ -331,6 +403,7 @@ void Light3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_OPACITY);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
+ BIND_ENUM_CONSTANT(PARAM_INTENSITY);
BIND_ENUM_CONSTANT(PARAM_MAX);
BIND_ENUM_CONSTANT(BAKE_DISABLED);
@@ -382,6 +455,9 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
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 0792f21c6e..e43d6f0419 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -58,6 +58,7 @@ public:
PARAM_SHADOW_OPACITY = RS::LIGHT_PARAM_SHADOW_OPACITY,
PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
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/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;