From a2ba7910ba1f07817d80e261022a6693183660be Mon Sep 17 00:00:00 2001 From: JFonS Date: Mon, 5 Jul 2021 15:55:52 +0200 Subject: [PATCH] Add soft shadows to the CPU lightmapper Adds the "light_size" property to Lights. It's only considered in baked lightmaps for soft shadowing purposes. --- doc/classes/Light.xml | 34 ++-- doc/classes/VisualServer.xml | 34 ++-- drivers/gles2/rasterizer_storage_gles2.cpp | 1 + drivers/gles3/rasterizer_storage_gles3.cpp | 1 + modules/lightmapper_cpu/lightmapper_cpu.cpp | 205 ++++++++++++-------- modules/lightmapper_cpu/lightmapper_cpu.h | 7 +- scene/3d/baked_lightmap.cpp | 6 +- scene/3d/light.cpp | 8 + scene/3d/light.h | 1 + scene/3d/lightmapper.h | 6 +- servers/visual_server.cpp | 2 + servers/visual_server.h | 1 + 12 files changed, 187 insertions(+), 119 deletions(-) diff --git a/doc/classes/Light.xml b/doc/classes/Light.xml index 8c4ffa9ca63..6b36416c23f 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 1f063f4371b..8ec4baf8f10 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 cab7e9caa0c..0776902b1e5 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 2c28c62daa5..9762b48b25c 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 3ee8695b4da..28a9e6edc8e 100644 --- a/modules/lightmapper_cpu/lightmapper_cpu.cpp +++ b/modules/lightmapper_cpu/lightmapper_cpu.cpp @@ -685,85 +685,6 @@ void LightmapperCPU::_plot_triangle(const Vector2 *p_vertices, const Vector3 *p_ } } -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); - - 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 (light.type == LIGHT_TYPE_SPOT) { - Vector3 light_direction = (position - light.position).normalized(); - if (normal.dot(light_direction) >= 0.0) { - continue; - } - - float angle = Math::acos(light.direction.dot(light_direction)); - - if (angle > light.spot_angle) { - continue; - } - - float dist = position.distance_to(light.position); - if (dist > light.range) { - continue; - } - - LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_direction, parameters.bias, dist); - if (raycaster->intersect(ray)) { - 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_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)); - } - - if (light.type == LIGHT_TYPE_DIRECTIONAL) { - if (normal.dot(light.direction) >= 0.0) { - continue; - } - - LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position + normal * parameters.bias, -light.direction, parameters.bias); - if (raycaster->intersect(ray)) { - continue; - } - - final_energy = light_energy * MAX(0, normal.dot(-light.direction)); - } - - lightmap[p_idx].direct_light += final_energy * light.indirect_multiplier; - if (light.bake_direct) { - lightmap[p_idx].output_light += final_energy; - } - } -} - _ALWAYS_INLINE_ float uniform_rand() { /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */ static thread_local uint32_t state = Math::rand(); @@ -774,6 +695,123 @@ _ALWAYS_INLINE_ float uniform_rand() { 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; + Color c = light.color; + Vector3 light_energy = Vector3(c.r, c.g, c.b) * light.energy; + + 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 (normal.dot(light_to_point) >= 0.0) { + continue; + } + + 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; + + 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; + } + + 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; + } + + 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(); + } + + 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 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(); + + LightmapRaycaster::Ray ray = LightmapRaycaster::Ray(position, -light_disk_to_point, parameters.bias, dist); + 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; + } + } + + 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; + } + } +} + 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 6fca658b04a..503a09c1344 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 @@ public: 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 099bbcda636..23584ec501a 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 78785545acf..b295ab2cba7 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 2a1e277dfea..244a544d66b 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -43,6 +43,7 @@ public: 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 b1346ca8c3f..1ca81ab9765 100644 --- a/scene/3d/lightmapper.h +++ b/scene/3d/lightmapper.h @@ -176,9 +176,9 @@ public: 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 00146a7e3d5..e347215fe70 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 73f64303bd5..eff6a713dc7 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -411,6 +411,7 @@ public: LIGHT_PARAM_ENERGY, LIGHT_PARAM_INDIRECT_ENERGY, + LIGHT_PARAM_SIZE, LIGHT_PARAM_SPECULAR, LIGHT_PARAM_RANGE, LIGHT_PARAM_ATTENUATION,