diff options
5 files changed, 26 insertions, 11 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index dff69bcdd52..cba86d058ea 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -243,11 +243,27 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) linfo->num_light++; } -void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata)) +void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_LightsInfo *linfo = sldata->lights; sldata->common_data.la_num_light = linfo->num_light; + /* Clamp volume lights power. */ + float upper_bound = vedata->stl->effects->volume_light_clamp; + for (int i = 0; i < linfo->num_light; i++) { + EEVEE_Light *evli = linfo->light_data + i; + + float power = max_fff(UNPACK3(evli->color)) * evli->volume; + if (power > 0.0f && evli->light_type != LA_SUN) { + /* The limit of the power attenuation function when the distance to the light goes to 0 is + * 2 / r² where r is the light radius. We need to find the right radius that emits at most + * the volume light upper bound. Inverting the function we get: */ + float min_radius = 1.0f / sqrtf(0.5f * upper_bound / power); + /* Square it here to avoid a multiplication inside the shader. */ + evli->volume_radius = square_f(max_ff(min_radius, evli->radius)); + } + } + GPU_uniformbuf_update(sldata->light_ubo, &linfo->light_data); } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index cbaf55809c6..bc04fe024fc 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -489,7 +489,7 @@ typedef struct EEVEE_Light { float rightvec[3], sizex; float upvec[3], sizey; float forwardvec[3], light_type; - float diff, spec, volume, _pad0[1]; + float diff, spec, volume, volume_radius; } EEVEE_Light; /* Special type for elliptic area lights, matches lamps_lib.glsl */ @@ -717,6 +717,7 @@ typedef struct EEVEE_EffectsInfo { struct GPUTexture *sss_stencil; /* Volumetrics */ int volume_current_sample; + float volume_light_clamp; struct GPUTexture *volume_scatter; struct GPUTexture *volume_transmit; /* SSR */ diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 136737f7d8b..aee260a542e 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -184,9 +184,7 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) float integration_start = scene_eval->eevee.volumetric_start; float integration_end = scene_eval->eevee.volumetric_end; - /* TODO(fclem) Use clamp to modulate the light radius for - * volume lighting and avoid very bright highlights. */ - // common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp; + effects->volume_light_clamp = scene_eval->eevee.volumetric_light_clamp; common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples; if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) { common_data->vol_shadow_steps = 0; @@ -218,10 +216,9 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } /* Disable clamp if equal to 0. */ - /* TODO(fclem) Re-implement */ - // if (common_data->vol_light_clamp == 0.0) { - // common_data->vol_light_clamp = FLT_MAX; - // } + if (effects->volume_light_clamp == 0.0) { + effects->volume_light_clamp = FLT_MAX; + } common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0; common_data->vol_use_soft_shadows = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_SOFT) != 0; diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl index 0c26c8d1ff1..2f1fd0ce5f8 100644 --- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -19,7 +19,7 @@ struct LightData { vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */ vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */ vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Light Type */ - vec4 diff_spec_volume; /* xyz: Diffuse/Spec/Volume power, w: unused. */ + vec4 diff_spec_volume; /* xyz: Diffuse/Spec/Volume power, w: radius for volumetric. */ }; /* convenience aliases */ @@ -27,6 +27,7 @@ struct LightData { #define l_diff diff_spec_volume.x #define l_spec diff_spec_volume.y #define l_volume diff_spec_volume.z +#define l_volume_radius diff_spec_volume.w #define l_position position_influence.xyz #define l_influence position_influence.w #define l_influence_volume color_influence_volume.w diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl index 11fd3418a72..788e621c3c1 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl @@ -73,7 +73,7 @@ vec3 light_volume(LightData ld, vec4 l_vector) **/ float d = l_vector.w; float d_sqr = sqr(d); - float r_sqr = sqr(ld.l_radius); + float r_sqr = ld.l_volume_radius; /* Using reformulation that has better numerical percision. */ power = 2.0 / (d_sqr + r_sqr + d * sqrt(d_sqr + r_sqr)); |