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.
This commit is contained in:
parent
736632ee7e
commit
385ee5c70b
131 changed files with 2692 additions and 1283 deletions
|
|
@ -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", "");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue