Invert spotlight angle attenuation

Inverted the spotlight angle attenuation so a higher value results in
a dimmer light, this makes it more consistent with the distance
attenuation.

Also changed the way spotlighs are computed in SDFGI
and GIPorbes and GPU lightmapper, now it matches the falloff used in the scene rendering
code.
This commit is contained in:
jfons 2021-02-06 21:39:08 +01:00
parent 7bb7a3c4a7
commit 99e1ce0690
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;
}