diff --git a/doc/classes/Light.xml b/doc/classes/Light.xml
index 8c4ffa9ca639..6b36416c23fd 100644
--- a/doc/classes/Light.xml
+++ b/doc/classes/Light.xml
@@ -54,6 +54,9 @@
If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows.
+
+ The size of the light in Godot units. Only considered in baked lightmaps and only if [member light_bake_mode] is set to [constant BAKE_ALL]. Increasing this value will make the shadows appear blurrier. This can be used to simulate area lights to an extent.
+
The intensity of the specular blob in objects affected by the light. At [code]0[/code], the light becomes a pure diffuse light. When not baking emission, this can be used to avoid unrealistic reflections when placing lights above an emissive surface.
@@ -80,46 +83,49 @@
Constant for accessing [member light_indirect_energy].
-
+
+ Constant for accessing [member light_size].
+
+
Constant for accessing [member light_specular].
-
+
Constant for accessing [member OmniLight.omni_range] or [member SpotLight.spot_range].
-
+
Constant for accessing [member OmniLight.omni_attenuation] or [member SpotLight.spot_attenuation].
-
+
Constant for accessing [member SpotLight.spot_angle].
-
+
Constant for accessing [member SpotLight.spot_angle_attenuation].
-
+
Constant for accessing [member shadow_contact].
-
+
Constant for accessing [member DirectionalLight.directional_shadow_max_distance].
-
+
Constant for accessing [member DirectionalLight.directional_shadow_split_1].
-
+
Constant for accessing [member DirectionalLight.directional_shadow_split_2].
-
+
Constant for accessing [member DirectionalLight.directional_shadow_split_3].
-
+
Constant for accessing [member DirectionalLight.directional_shadow_normal_bias].
-
+
Constant for accessing [member shadow_bias].
-
+
Constant for accessing [member DirectionalLight.directional_shadow_bias_split_scale].
-
+
Represents the size of the [enum Param] enum.
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 1f063f4371bd..8ec4baf8f101 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -4534,46 +4534,52 @@
The light's energy.
-
+
+ Secondary multiplier used with indirect light (light bounces).
+
+
+ The light's size, currently only used for soft shadows in baked lightmaps.
+
+
The light's influence on specularity.
-
+
The light's range.
-
+
The light's attenuation.
-
+
The spotlight's angle.
-
+
The spotlight's attenuation.
-
+
Scales the shadow color.
-
+
Max distance that shadows will be rendered.
-
+
Proportion of shadow atlas occupied by the first split.
-
+
Proportion of shadow atlas occupied by the second split.
-
+
Proportion of shadow atlas occupied by the third split. The fourth split occupies the rest.
-
+
Normal bias used to offset shadow lookup by object normal. Can be used to fix self-shadowing artifacts.
-
+
Bias the shadow lookup to fix self-shadowing artifacts.
-
+
Increases bias on further splits to fix self-shadowing that only occurs far away from the camera.
-
+
Represents the size of the [enum LightParam] enum.
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index cab7e9caa0c5..0776902b1e5b 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -3756,6 +3756,7 @@ RID RasterizerStorageGLES2::light_create(VS::LightType p_type) {
light->param[VS::LIGHT_PARAM_ENERGY] = 1.0;
light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+ light->param[VS::LIGHT_PARAM_SIZE] = 0.0;
light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
light->param[VS::LIGHT_PARAM_RANGE] = 1.0;
light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 2c28c62daa57..9762b48b25c1 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -5261,6 +5261,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) {
light->param[VS::LIGHT_PARAM_ENERGY] = 1.0;
light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+ light->param[VS::LIGHT_PARAM_SIZE] = 0.0;
light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
light->param[VS::LIGHT_PARAM_RANGE] = 1.0;
light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
diff --git a/modules/lightmapper_cpu/lightmapper_cpu.cpp b/modules/lightmapper_cpu/lightmapper_cpu.cpp
index 3ee8695b4dab..28a9e6edc8e0 100644
--- a/modules/lightmapper_cpu/lightmapper_cpu.cpp
+++ b/modules/lightmapper_cpu/lightmapper_cpu.cpp
@@ -685,78 +685,126 @@ void LightmapperCPU::_plot_triangle(const Vector2 *p_vertices, const Vector3 *p_
}
}
+_ALWAYS_INLINE_ float uniform_rand() {
+ /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
+ static thread_local uint32_t state = Math::rand();
+ state ^= state << 13;
+ state ^= state >> 17;
+ state ^= state << 5;
+ /* implicit conversion from 'unsigned int' to 'float' changes value from 4294967295 to 4294967296 */
+ return float(state) / float(UINT32_MAX);
+}
+
void LightmapperCPU::_compute_direct_light(uint32_t p_idx, void *r_lightmap) {
LightmapTexel *lightmap = (LightmapTexel *)r_lightmap;
for (unsigned int i = 0; i < lights.size(); ++i) {
const Light &light = lights[i];
Vector3 normal = lightmap[p_idx].normal;
Vector3 position = lightmap[p_idx].pos;
- Vector3 final_energy;
Color c = light.color;
Vector3 light_energy = Vector3(c.r, c.g, c.b) * light.energy;
- if (light.type == LIGHT_TYPE_OMNI) {
- Vector3 light_direction = (position - light.position).normalized();
- if (normal.dot(light_direction) >= 0.0) {
- continue;
- }
- float dist = position.distance_to(light.position);
+ Vector3 light_to_point = light.direction;
+ if (light.type == LIGHT_TYPE_OMNI || light.type == LIGHT_TYPE_SPOT) {
+ light_to_point = (position - light.position).normalized();
+ }
- if (dist <= light.range) {
- LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_direction, parameters.bias, dist - parameters.bias);
- if (raycaster->intersect(ray)) {
- continue;
- }
- float att = powf(1.0 - dist / light.range, light.attenuation);
- final_energy = light_energy * att * MAX(0, normal.dot(-light_direction));
- }
+ if (normal.dot(light_to_point) >= 0.0) {
+ continue;
}
- if (light.type == LIGHT_TYPE_SPOT) {
- Vector3 light_direction = (position - light.position).normalized();
- if (normal.dot(light_direction) >= 0.0) {
+ float dist;
+ float attenuation;
+ float soft_shadowing_disk_size;
+
+ if (light.type == LIGHT_TYPE_OMNI || light.type == LIGHT_TYPE_SPOT) {
+ dist = position.distance_to(light.position);
+ if (dist > light.range) {
continue;
}
+ soft_shadowing_disk_size = light.size / dist;
- float angle = Math::acos(light.direction.dot(light_direction));
+ if (light.type == LIGHT_TYPE_OMNI) {
+ attenuation = powf(1.0 - dist / light.range, light.attenuation);
+ } else /* (light.type == LIGHT_TYPE_SPOT) */ {
+ float angle = Math::acos(light.direction.dot(light_to_point));
- if (angle > light.spot_angle) {
- continue;
- }
+ if (angle > light.spot_angle) {
+ continue;
+ }
- float dist = position.distance_to(light.position);
- if (dist > light.range) {
- continue;
+ float normalized_dist = dist * (1.0f / MAX(0.001f, light.range));
+ float norm_light_attenuation = Math::pow(MAX(1.0f - normalized_dist, 0.001f), light.attenuation);
+
+ float spot_cutoff = Math::cos(light.spot_angle);
+ float scos = MAX(light_to_point.dot(light.direction), spot_cutoff);
+ float spot_rim = (1.0f - scos) / (1.0f - spot_cutoff);
+ attenuation = norm_light_attenuation * (1.0f - pow(MAX(spot_rim, 0.001f), light.spot_attenuation));
}
+ } else /*if (light.type == LIGHT_TYPE_DIRECTIONAL)*/ {
+ dist = INFINITY;
+ attenuation = 1.0f;
+ soft_shadowing_disk_size = light.size;
+ }
- LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_direction, parameters.bias, dist);
- if (raycaster->intersect(ray)) {
- continue;
+ float penumbra = 0.0f;
+ if (light.size > 0.0) {
+ Vector3 light_to_point_tan;
+ Vector3 light_to_point_bitan;
+
+ if (light.type == LIGHT_TYPE_OMNI || light.type == LIGHT_TYPE_SPOT) {
+ light_to_point = (position - light.position).normalized();
+ Vector3 aux = light_to_point.y < 0.777 ? Vector3(0, 1, 0) : Vector3(1, 0, 0);
+ light_to_point_tan = light_to_point.cross(aux).normalized();
+ light_to_point_bitan = light_to_point.cross(light_to_point_tan).normalized();
+ } else /*if (light.type == LIGHT_TYPE_DIRECTIONAL)*/ {
+ Vector3 aux = light_to_point.y < 0.777 ? Vector3(0, 1, 0) : Vector3(1, 0, 0);
+ light_to_point_tan = light_to_point.cross(aux).normalized();
+ light_to_point_bitan = light_to_point.cross(light_to_point_tan).normalized();
}
- float normalized_dist = dist * (1.0f / MAX(0.001f, light.range));
- float norm_light_attenuation = Math::pow(MAX(1.0f - normalized_dist, 0.001f), light.attenuation);
+ const static int shadowing_rays_check_penumbra_denom = 2;
+ int shadowing_ray_count = parameters.samples;
+
+ int hits = 0;
+ Vector3 light_disk_to_point = light_to_point;
+ for (int j = 0; j < shadowing_ray_count; j++) {
+ // Optimization:
+ // Once already casted an important proportion of rays, if all are hits or misses,
+ // assume we're not in the penumbra so we can infer the rest would have the same result
+ if (j == shadowing_ray_count / shadowing_rays_check_penumbra_denom) {
+ if (hits == j) {
+ // Assume totally lit
+ hits = shadowing_ray_count;
+ break;
+ } else if (hits == 0) {
+ // Assume totally dark
+ hits = 0;
+ break;
+ }
+ }
- float spot_cutoff = Math::cos(light.spot_angle);
- float scos = MAX(light_direction.dot(light.direction), spot_cutoff);
- float spot_rim = (1.0f - scos) / (1.0f - spot_cutoff);
- norm_light_attenuation *= 1.0f - pow(MAX(spot_rim, 0.001f), light.spot_attenuation);
- final_energy = light_energy * norm_light_attenuation * MAX(0, normal.dot(-light_direction));
- }
+ float r = uniform_rand();
+ float a = uniform_rand() * Math_TAU;
+ Vector2 disk_sample = (r * Vector2(Math::cos(a), Math::sin(a))) * soft_shadowing_disk_size;
+ light_disk_to_point = (light_to_point + disk_sample.x * light_to_point_tan + disk_sample.y * light_to_point_bitan).normalized();
- if (light.type == LIGHT_TYPE_DIRECTIONAL) {
- if (normal.dot(light.direction) >= 0.0) {
- continue;
- }
+ LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_disk_to_point, parameters.bias, dist);
+ if (raycaster->intersect(ray)) {
+ continue;
+ }
- LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position + normal * parameters.bias, -light.direction, parameters.bias);
- if (raycaster->intersect(ray)) {
- continue;
+ hits++;
+ }
+ penumbra = (float)hits / shadowing_ray_count;
+ } else {
+ LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_to_point, parameters.bias, dist);
+ if (!raycaster->intersect(ray)) {
+ penumbra = 1.0f;
}
-
- final_energy = light_energy * MAX(0, normal.dot(-light.direction));
}
+ Vector3 final_energy = attenuation * penumbra * light_energy * MAX(0, normal.dot(-light_to_point));
lightmap[p_idx].direct_light += final_energy * light.indirect_multiplier;
if (light.bake_direct) {
lightmap[p_idx].output_light += final_energy;
@@ -764,16 +812,6 @@ void LightmapperCPU::_compute_direct_light(uint32_t p_idx, void *r_lightmap) {
}
}
-_ALWAYS_INLINE_ float uniform_rand() {
- /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
- static thread_local uint32_t state = Math::rand();
- state ^= state << 13;
- state ^= state >> 17;
- state ^= state << 5;
- /* implicit conversion from 'unsigned int' to 'float' changes value from 4294967295 to 4294967296 */
- return float(state) / float(UINT32_MAX);
-}
-
void LightmapperCPU::_compute_indirect_light(uint32_t p_idx, void *r_lightmap) {
LightmapTexel *lightmap = (LightmapTexel *)r_lightmap;
LightmapTexel &texel = lightmap[p_idx];
@@ -1583,7 +1621,7 @@ void LightmapperCPU::add_mesh(const MeshData &p_mesh, Vector2i p_size) {
mesh_instances.push_back(mi);
}
-void LightmapperCPU::add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier) {
+void LightmapperCPU::add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size) {
Light l;
l.type = LIGHT_TYPE_DIRECTIONAL;
l.direction = p_direction;
@@ -1591,10 +1629,11 @@ void LightmapperCPU::add_directional_light(bool p_bake_direct, const Vector3 &p_
l.energy = p_energy;
l.indirect_multiplier = p_indirect_multiplier;
l.bake_direct = p_bake_direct;
+ l.size = p_size;
lights.push_back(l);
}
-void LightmapperCPU::add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation) {
+void LightmapperCPU::add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size) {
Light l;
l.type = LIGHT_TYPE_OMNI;
l.position = p_position;
@@ -1604,10 +1643,11 @@ void LightmapperCPU::add_omni_light(bool p_bake_direct, const Vector3 &p_positio
l.energy = p_energy;
l.indirect_multiplier = p_indirect_multiplier;
l.bake_direct = p_bake_direct;
+ l.size = p_size;
lights.push_back(l);
}
-void LightmapperCPU::add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation) {
+void LightmapperCPU::add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) {
Light l;
l.type = LIGHT_TYPE_SPOT;
l.position = p_position;
@@ -1620,6 +1660,7 @@ void LightmapperCPU::add_spot_light(bool p_bake_direct, const Vector3 &p_positio
l.energy = p_energy;
l.indirect_multiplier = p_indirect_multiplier;
l.bake_direct = p_bake_direct;
+ l.size = p_size;
lights.push_back(l);
}
diff --git a/modules/lightmapper_cpu/lightmapper_cpu.h b/modules/lightmapper_cpu/lightmapper_cpu.h
index 6fca658b04aa..503a09c13445 100644
--- a/modules/lightmapper_cpu/lightmapper_cpu.h
+++ b/modules/lightmapper_cpu/lightmapper_cpu.h
@@ -62,6 +62,7 @@ class LightmapperCPU : public Lightmapper {
float attenuation;
float spot_angle;
float spot_attenuation;
+ float size;
bool bake_direct;
};
@@ -165,9 +166,9 @@ class LightmapperCPU : public Lightmapper {
virtual void add_albedo_texture(Ref p_texture);
virtual void add_emission_texture(Ref p_texture);
virtual void add_mesh(const MeshData &p_mesh, Vector2i p_size);
- virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier);
- virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation);
- virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation);
+ virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size);
+ virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size);
+ virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size);
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, BakeStepFunc p_substep_function = nullptr);
int get_bake_texture_count() const;
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 099bbcda6361..23584ec501a0 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -746,13 +746,13 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_data_sa
if (Object::cast_to(light)) {
DirectionalLight *l = Object::cast_to(light);
- lightmapper->add_directional_light(light->get_bake_mode() == Light::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY));
+ lightmapper->add_directional_light(light->get_bake_mode() == Light::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_SIZE));
} else if (Object::cast_to(light)) {
OmniLight *l = Object::cast_to(light);
- lightmapper->add_omni_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION));
+ lightmapper->add_omni_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SIZE));
} else if (Object::cast_to(light)) {
SpotLight *l = Object::cast_to(light);
- lightmapper->add_spot_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SPOT_ANGLE), l->get_param(Light::PARAM_SPOT_ATTENUATION));
+ lightmapper->add_spot_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SPOT_ANGLE), l->get_param(Light::PARAM_SPOT_ATTENUATION), l->get_param(Light::PARAM_SIZE));
}
}
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 78785545acf0..b295ab2cba7d 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -141,6 +141,7 @@ PoolVector Light::get_faces(uint32_t p_usage_flags) const {
void Light::set_bake_mode(BakeMode p_mode) {
bake_mode = p_mode;
VS::get_singleton()->light_set_bake_mode(light, VS::LightBakeMode(bake_mode));
+ _change_notify();
}
Light::BakeMode Light::get_bake_mode() const {
@@ -196,6 +197,10 @@ void Light::_validate_property(PropertyInfo &property) const {
if (VisualServer::get_singleton()->is_low_end() && property.name == "shadow_contact") {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
+
+ if (bake_mode != BAKE_ALL && property.name == "light_size") {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
}
void Light::_bind_methods() {
@@ -230,6 +235,7 @@ void Light::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_size", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode");
@@ -246,6 +252,7 @@ void Light::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_ENERGY);
BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY);
+ BIND_ENUM_CONSTANT(PARAM_SIZE);
BIND_ENUM_CONSTANT(PARAM_SPECULAR);
BIND_ENUM_CONSTANT(PARAM_RANGE);
BIND_ENUM_CONSTANT(PARAM_ATTENUATION);
@@ -295,6 +302,7 @@ Light::Light(VisualServer::LightType p_type) {
set_param(PARAM_ENERGY, 1);
set_param(PARAM_INDIRECT_ENERGY, 1);
+ set_param(PARAM_SIZE, 0);
set_param(PARAM_SPECULAR, 0.5);
set_param(PARAM_RANGE, 5);
set_param(PARAM_ATTENUATION, 1);
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 2a1e277dfea0..244a544d66be 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -43,6 +43,7 @@ class Light : public VisualInstance {
enum Param {
PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY,
PARAM_INDIRECT_ENERGY = VS::LIGHT_PARAM_INDIRECT_ENERGY,
+ PARAM_SIZE = VS::LIGHT_PARAM_SIZE,
PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR,
PARAM_RANGE = VS::LIGHT_PARAM_RANGE,
PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION,
diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h
index b1346ca8c3fe..1ca81ab9765c 100644
--- a/scene/3d/lightmapper.h
+++ b/scene/3d/lightmapper.h
@@ -176,9 +176,9 @@ class Lightmapper : public Reference {
virtual void add_albedo_texture(Ref p_texture) = 0;
virtual void add_emission_texture(Ref p_texture) = 0;
virtual void add_mesh(const MeshData &p_mesh, Vector2i p_size) = 0;
- virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier) = 0;
- virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation) = 0;
- virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation) = 0;
+ virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size) = 0;
+ virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size) = 0;
+ virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) = 0;
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, BakeStepFunc p_substep_function = nullptr) = 0;
virtual int get_bake_texture_count() const = 0;
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 00146a7e3d5a..e347215fe709 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -2002,6 +2002,8 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_SPOT);
BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SIZE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 73f64303bd54..eff6a713dc78 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -411,6 +411,7 @@ class VisualServer : public Object {
LIGHT_PARAM_ENERGY,
LIGHT_PARAM_INDIRECT_ENERGY,
+ LIGHT_PARAM_SIZE,
LIGHT_PARAM_SPECULAR,
LIGHT_PARAM_RANGE,
LIGHT_PARAM_ATTENUATION,