Merge pull request #41308 from JFonS/fix_spotlight_attenuation

Invert spotlight angle attenuation
This commit is contained in:
Rémi Verschelde 2021-02-07 20:33:14 +01:00 committed by GitHub
commit ce332859e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 54 additions and 44 deletions

View file

@ -93,8 +93,8 @@ void LightmapperRD::add_spot_light(bool p_static, const Vector3 &p_position, con
l.direction[2] = p_direction.z;
l.range = p_range;
l.attenuation = p_attenuation;
l.spot_angle = Math::deg2rad(p_spot_angle);
l.spot_attenuation = p_spot_attenuation;
l.cos_spot_angle = Math::cos(Math::deg2rad(p_spot_angle));
l.inv_spot_attenuation = 1.0f / p_spot_attenuation;
l.color[0] = p_color.r;
l.color[1] = p_color.g;
l.color[2] = p_color.b;

View file

@ -54,8 +54,8 @@ class LightmapperRD : public Lightmapper {
float size;
float range;
float attenuation;
float spot_angle;
float spot_attenuation;
float cos_spot_angle;
float inv_spot_attenuation;
uint32_t static_bake;
uint32_t pad[3];

View file

@ -56,8 +56,8 @@ struct Light {
float range;
float attenuation;
float spot_angle;
float spot_attenuation;
float cos_spot_angle;
float inv_spot_attenuation;
bool static_bake;
uint pad[3];

View file

@ -313,13 +313,16 @@ void main() {
if (lights.data[i].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(position - light_pos);
float angle = acos(dot(rel, lights.data[i].direction));
if (angle > lights.data[i].spot_angle) {
float cos_spot_angle = lights.data[i].cos_spot_angle;
float cos_angle = dot(rel, lights.data[i].direction);
if (cos_angle < cos_spot_angle) {
continue; //invisible, dont try
}
float d = clamp(angle / lights.data[i].spot_angle, 0, 1);
attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation);
float scos = max(cos_angle, cos_spot_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
attenuation *= 1.0 - pow(spot_rim, lights.data[i].inv_spot_attenuation);
}
}

View file

@ -1611,8 +1611,8 @@ void RendererSceneRenderRD::_pre_process_gi(RID p_render_buffers, const Transfor
lights[idx].has_shadow = storage->light_has_shadow(li->light);
lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE));
lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@ -4539,8 +4539,8 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
l.color[1] = color.g;
l.color[2] = color.b;
l.spot_angle_radians = Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE));
l.spot_attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
l.cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
l.inv_spot_attenuation = 1.0f / storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
Transform xform = light_instance_get_base_transform(light_instance);
@ -6491,9 +6491,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.size = size;
light_data.cone_attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
light_data.inv_spot_attenuation = 1.0f / storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
light_data.cone_angle = Math::cos(Math::deg2rad(spot_angle));
light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle));
light_data.mask = storage->light_get_cull_mask(base);
@ -8094,8 +8094,8 @@ void RendererSceneRenderRD::_render_sdfgi_static_lights(RID p_render_buffers, ui
lights[idx].has_shadow = storage->light_has_shadow(li->light);
lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE));
lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}

View file

@ -406,10 +406,10 @@ private:
float attenuation;
float color[3];
float spot_angle_radians;
float cos_spot_angle;
float position[3];
float spot_attenuation;
float inv_spot_attenuation;
float direction[3];
uint32_t has_shadow;
@ -1146,8 +1146,8 @@ private:
float attenuation;
uint32_t type;
float spot_angle;
float spot_attenuation;
float cos_spot_angle;
float inv_spot_attenuation;
float radius;
float shadow_color[4];
@ -1362,8 +1362,8 @@ private:
float color[3];
float attenuation;
float cone_attenuation;
float cone_angle;
float inv_spot_attenuation;
float cos_spot_angle;
float specular_amount;
uint32_t shadow_enabled;

View file

@ -51,10 +51,10 @@ struct Light {
float attenuation;
vec3 color;
float spot_angle_radians;
float cos_spot_angle;
vec3 position;
float spot_attenuation;
float inv_spot_attenuation;
vec3 direction;
bool has_shadow;
@ -233,13 +233,15 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel, lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
float cos_spot_angle = lights.data[light].cos_spot_angle;
float cos_angle = dot(rel, lights.data[light].direction);
if (cos_angle < cos_spot_angle) {
return false;
}
float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
float scos = max(cos_angle, cos_spot_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation);
}
}

View file

@ -43,10 +43,10 @@ struct Light {
float attenuation;
vec3 color;
float spot_angle_radians;
float cos_spot_angle;
vec3 position;
float spot_attenuation;
float inv_spot_attenuation;
vec3 direction;
bool has_shadow;
@ -146,13 +146,15 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel, lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
float cos_spot_angle = lights.data[light].cos_spot_angle;
float cos_angle = dot(rel, lights.data[light].direction);
if (cos_angle < cos_spot_angle) {
return false;
}
float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
float scos = max(cos_angle, cos_spot_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
attenuation *= 1.0 - pow(spot_rim, lights.data[light].inv_spot_attenuation);
}
}

View file

@ -67,8 +67,8 @@ struct Light {
float attenuation;
uint type;
float spot_angle;
float spot_attenuation;
float cos_spot_angle;
float inv_spot_attenuation;
float radius;
vec4 shadow_color;
@ -266,13 +266,16 @@ void main() {
rel_vec.y /= params.y_mult;
attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);
float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction));
if (angle > lights.data[i].spot_angle) {
attenuation = 0.0;
} else {
float d = clamp(angle / lights.data[i].spot_angle, 0, 1);
attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation);
float cos_spot_angle = lights.data[i].cos_spot_angle;
float cos_angle = dot(-direction, lights.data[i].direction);
if (cos_angle < cos_spot_angle) {
continue;
}
float scos = max(cos_angle, cos_spot_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
attenuation *= 1.0 - pow(spot_rim, lights.data[i].inv_spot_attenuation);
} break;
}