From 0a0f737f91dcbf280143c826780afe30dae811c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 19 Mar 2021 12:52:35 +0100 Subject: EEVEE: Volumetrics: Add special attenuation volume for lights This makes volume lights more efficient if they have lower power. --- source/blender/draw/engines/eevee/eevee_lights.c | 26 ++++++++++++---------- .../draw/engines/eevee/shaders/lights_lib.glsl | 4 ++++ .../eevee/shaders/volumetric_scatter_frag.glsl | 13 ++++++++--- 3 files changed, 28 insertions(+), 15 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 146dbc8fc28..63d1cb7adc8 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -41,20 +41,16 @@ void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]) r_mat[3][3] = 1.0f; } -static float light_attenuation_radius_get(const Light *la, float light_threshold) +static float light_attenuation_radius_get(const Light *la, + float light_threshold, + float light_power) { if (la->mode & LA_CUSTOM_ATTENUATION) { return la->att_dist; } - - /* Compute max light power. */ - float power = max_fff(la->r, la->g, la->b); - power *= fabsf(la->energy / 100.0f); - power *= max_fff(la->diff_fac, la->spec_fac, la->volume_fac); /* Compute the distance (using the inverse square law) * at which the light power reaches the light_threshold. */ - float distance = sqrtf(max_ff(1e-16, power / max_ff(1e-16, light_threshold))); - return distance; + return sqrtf(max_ff(1e-16, light_power / max_ff(1e-16, light_threshold))); } static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, const float scale[3]) @@ -138,7 +134,7 @@ static float light_shape_power_volume_get(const Light *la, float area_power) static void eevee_light_setup(Object *ob, EEVEE_Light *evli) { const Light *la = (Light *)ob->data; - float mat[4][4], scale[3], att_radius; + float mat[4][4], scale[3]; const DRWContextState *draw_ctx = DRW_context_state_get(); const float light_threshold = draw_ctx->scene->eevee.light_threshold; @@ -153,10 +149,16 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) evli->spec = la->spec_fac; evli->volume = la->volume_fac; - /* Influence Radius */ - att_radius = light_attenuation_radius_get(la, light_threshold); + float max_power = max_fff(la->r, la->g, la->b) * fabsf(la->energy / 100.0f); + float surface_max_power = max_ff(evli->diff, evli->spec) * max_power; + float volume_max_power = evli->volume * max_power; + + /* Influence Radii. */ + float att_radius = light_attenuation_radius_get(la, light_threshold, surface_max_power); + float att_radius_volume = light_attenuation_radius_get(la, light_threshold, volume_max_power); /* Take the inverse square of this distance. */ - evli->invsqrdist = 1.0 / max_ff(1e-4f, att_radius * att_radius); + evli->invsqrdist = 1.0f / max_ff(1e-4f, square_f(att_radius)); + evli->invsqrdist_volume = 1.0f / max_ff(1e-4f, square_f(att_radius_volume)); /* Vectors */ normalize_m4_m4_ex(mat, ob->obmat, scale); diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl index d2daa5a1092..0c26c8d1ff1 100644 --- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -251,7 +251,11 @@ float light_attenuation(LightData ld, vec4 l_vector) vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } if (ld.l_type != SUN) { +#ifdef VOLUME_LIGHTING + vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence_volume); +#else vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence); +#endif } return vis; } diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl index f75108babe6..dc755aeab8b 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl @@ -40,18 +40,25 @@ void main() #ifdef VOLUME_LIGHTING /* Lights */ for (int i = 0; i < MAX_LIGHT && i < laNumLight; i++) { - LightData ld = lights_data[i]; + if (ld.l_volume == 0.0) { + continue; + } + vec4 l_vector; l_vector.xyz = light_volume_light_vector(ld, P); l_vector.w = length(l_vector.xyz); - float Vis = light_visibility(ld, P, l_vector); + float vis = light_visibility(ld, P, l_vector); + + if (vis < 1e-4) { + continue; + } vec3 Li = light_volume(ld, l_vector) * light_volume_shadow(ld, P, l_vector, volumeExtinction); - outScattering.rgb += Li * Vis * s_scattering * + outScattering.rgb += Li * vis * s_scattering * phase_function(-V, l_vector.xyz / l_vector.w, s_anisotropy); } #endif -- cgit v1.2.3