diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2021-03-19 14:07:23 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2021-03-19 23:11:06 +0300 |
commit | 884f934a853f7043a7e5a6ea380d560c858a78b7 (patch) | |
tree | 14c4441579169bcc50de145d24dbff5ab206200a /source/blender/draw/engines/eevee/eevee_lights.c | |
parent | fb3e5b7f986e7215c6488c2b93db8559e84cfb98 (diff) |
EEVEE: Lights: Add Volume and diffuse light power slider
This adds 2 new sliders for light objects that modulates the diffuse
light and the volume light intensities.
This also changes the way volume light is computed using point lamp
representation. We use "Point Light Attenuation Without Singularity"
from Cem Yuksel instead of the usual inverse square law.
Diffstat (limited to 'source/blender/draw/engines/eevee/eevee_lights.c')
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_lights.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index b773049f6f7..146dbc8fc28 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -50,7 +50,7 @@ static float light_attenuation_radius_get(const Light *la, float light_threshold /* Compute max light power. */ float power = max_fff(la->r, la->g, la->b); power *= fabsf(la->energy / 100.0f); - power *= max_ff(1.0f, la->spec_fac); + 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))); @@ -75,6 +75,8 @@ static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, const else { evli->sizey = max_ff(0.003f, la->area_size * scale[1] * 0.5f); } + /* For volume point lighting. */ + evli->radius = max_ff(0.001f, hypotf(evli->sizex, evli->sizey)); } else if (la->type == LA_SUN) { evli->radius = max_ff(0.001f, tanf(min_ff(la->sun_angle, DEG2RADF(179.9f)) / 2.0f)); @@ -103,8 +105,8 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) /* for point lights (a.k.a radius == 0.0) */ // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */ } - else { - power = 1.0f / (evli->radius * evli->radius * M_PI); /* 1/(r²*Pi) */ + else { /* LA_SUN */ + power = 1.0f / (evli->radius * evli->radius * M_PI); /* Make illumination power closer to cycles for bigger radii. Cycles uses a cos^3 term that we * cannot reproduce so we account for that by scaling the light power. This function is the * result of a rough manual fitting. */ @@ -113,11 +115,30 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) return power; } +static float light_shape_power_volume_get(const Light *la, float area_power) +{ + /* Volume light is evaluated as point lights. Remove the shape power. */ + float power = 1.0f / area_power; + /* Make illumination power constant */ + if (la->type == LA_AREA) { + /* Match cycles. Empirical fit... must correspond to some constant. */ + power *= 0.0792f * M_PI; + } + else if (ELEM(la->type, LA_SPOT, LA_LOCAL)) { + /* Match cycles. Empirical fit... must correspond to some constant. */ + power *= 0.0792f; + } + else { /* LA_SUN */ + /* Nothing to do. */ + } + return power; +} + /* Update buffer with light data */ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) { - Light *la = (Light *)ob->data; - float mat[4][4], scale[3], power, att_radius; + const Light *la = (Light *)ob->data; + float mat[4][4], scale[3], att_radius; const DRWContextState *draw_ctx = DRW_context_state_get(); const float light_threshold = draw_ctx->scene->eevee.light_threshold; @@ -128,7 +149,9 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) /* Color */ copy_v3_v3(evli->color, &la->r); + evli->diff = la->diff_fac; evli->spec = la->spec_fac; + evli->volume = la->volume_fac; /* Influence Radius */ att_radius = light_attenuation_radius_get(la, light_threshold); @@ -163,8 +186,10 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) evli->light_type = LAMPTYPE_AREA_ELLIPSE; } - power = light_shape_power_get(la, evli); - mul_v3_fl(evli->color, power * la->energy); + float shape_power = light_shape_power_get(la, evli); + mul_v3_fl(evli->color, shape_power * la->energy); + + evli->volume *= light_shape_power_volume_get(la, shape_power); /* No shadow by default */ evli->shadow_id = -1.0f; |