Change the light attenuation formulas.
-Much better looking, physically based. -Almost negligible extra cost.
This commit is contained in:
parent
6e23ab4fa2
commit
446618cf94
5 changed files with 58 additions and 14 deletions
|
@ -249,6 +249,15 @@ float quick_hash(vec2 pos) {
|
|||
return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237);
|
||||
}
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_LIGHT_PROBES
|
||||
int probe_index = int(gl_GlobalInvocationID.x);
|
||||
|
@ -300,7 +309,7 @@ void main() {
|
|||
|
||||
d /= lights.data[i].range;
|
||||
|
||||
attenuation = pow(max(1.0 - d, 0.0), lights.data[i].attenuation);
|
||||
attenuation = get_omni_attenuation(d, 1.0 / lights.data[i].range, lights.data[i].attenuation);
|
||||
|
||||
if (lights.data[i].type == LIGHT_TYPE_SPOT) {
|
||||
vec3 rel = normalize(position - light_pos);
|
||||
|
|
|
@ -208,6 +208,15 @@ float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
|
|||
return occlusion; //max(0.0,distance);
|
||||
}
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
|
||||
bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) {
|
||||
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
|
||||
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
|
||||
|
@ -220,7 +229,7 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
|
|||
return false;
|
||||
}
|
||||
|
||||
attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
|
||||
attenuation = get_omni_attenuation(distance, 1.0 / lights.data[light].radius, lights.data[light].attenuation);
|
||||
|
||||
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
|
||||
vec3 rel = normalize(pos - light_pos);
|
||||
|
|
|
@ -891,6 +891,15 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
|
|||
|
||||
#endif //USE_NO_SHADOWS
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
|
||||
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
|
@ -916,9 +925,8 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||
vec3 light_rel_vec = lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float normalized_distance = light_length * lights.data[idx].inv_radius;
|
||||
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
|
||||
float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
|
||||
float omni_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, attenuation_energy.x);
|
||||
float light_attenuation = omni_attenuation;
|
||||
vec3 shadow_attenuation = vec3(1.0);
|
||||
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
|
||||
|
@ -1205,9 +1213,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
inout vec3 specular_light) {
|
||||
vec3 light_rel_vec = lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float normalized_distance = light_length * lights.data[idx].inv_radius;
|
||||
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
|
||||
float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x);
|
||||
float spot_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, attenuation_energy.x);
|
||||
vec3 spot_dir = lights.data[idx].direction;
|
||||
vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle);
|
||||
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
|
||||
|
|
|
@ -112,6 +112,15 @@ vec2 octahedron_encode(vec3 n) {
|
|||
return n.xy;
|
||||
}
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
|
||||
void main() {
|
||||
uint voxel_index = uint(gl_GlobalInvocationID.x);
|
||||
|
||||
|
@ -184,14 +193,15 @@ void main() {
|
|||
direction = normalize(rel_vec);
|
||||
light_distance = length(rel_vec);
|
||||
rel_vec.y /= params.y_mult;
|
||||
attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
|
||||
attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);
|
||||
|
||||
} break;
|
||||
case LIGHT_TYPE_SPOT: {
|
||||
vec3 rel_vec = lights.data[i].position - position;
|
||||
direction = normalize(rel_vec);
|
||||
light_distance = length(rel_vec);
|
||||
rel_vec.y /= params.y_mult;
|
||||
attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
|
||||
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) {
|
||||
|
|
|
@ -169,6 +169,15 @@ vec3 hash3f(uvec3 x) {
|
|||
return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));
|
||||
}
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
|
||||
|
||||
|
@ -270,14 +279,14 @@ void main() {
|
|||
uint light_index = cluster_data.indices[omni_light_pointer + i];
|
||||
|
||||
vec3 light_pos = lights.data[i].position;
|
||||
float d = distance(lights.data[i].position, view_pos) * lights.data[i].inv_radius;
|
||||
float d = distance(lights.data[i].position, view_pos);
|
||||
vec3 shadow_attenuation = vec3(1.0);
|
||||
|
||||
if (d < 1.0) {
|
||||
if (d * lights.data[i].inv_radius < 1.0) {
|
||||
vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);
|
||||
vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular);
|
||||
|
||||
float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x);
|
||||
float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);
|
||||
|
||||
vec3 light = attenuation_energy.y * color_specular.rgb / M_PI;
|
||||
|
||||
|
@ -326,14 +335,14 @@ void main() {
|
|||
|
||||
vec3 light_pos = lights.data[i].position;
|
||||
vec3 light_rel_vec = lights.data[i].position - view_pos;
|
||||
float d = length(light_rel_vec) * lights.data[i].inv_radius;
|
||||
float d = length(light_rel_vec);
|
||||
vec3 shadow_attenuation = vec3(1.0);
|
||||
|
||||
if (d < 1.0) {
|
||||
if (d * lights.data[i].inv_radius < 1.0) {
|
||||
vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);
|
||||
vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular);
|
||||
|
||||
float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x);
|
||||
float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);
|
||||
|
||||
vec3 spot_dir = lights.data[i].direction;
|
||||
vec2 spot_att_angle = unpackHalf2x16(lights.data[i].cone_attenuation_angle);
|
||||
|
|
Loading…
Reference in a new issue