Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c39
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lights_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl51
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl2
7 files changed, 69 insertions, 41 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;
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index e98ba4136ed..ca10e01e3f5 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -484,11 +484,12 @@ typedef struct EEVEE_RenderPassData {
/* ************ LIGHT UBO ************* */
typedef struct EEVEE_Light {
float position[3], invsqrdist;
- float color[3], spec;
+ float color[3], invsqrdist_volume;
float spotsize, spotblend, radius, shadow_id;
float rightvec[3], sizex;
float upvec[3], sizey;
float forwardvec[3], light_type;
+ float diff, spec, volume, _pad0[1];
} EEVEE_Light;
/* Special type for elliptic area lights, matches lamps_lib.glsl */
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
index c5996f5160a..4f9791ac95f 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
@@ -45,7 +45,8 @@ void closure_Diffuse_light_eval(ClosureInputDiffuse cl_in,
float radiance = light_diffuse(light.data, cl_in.N, cl_common.V, light.L);
/* TODO(fclem) We could try to shadow lights that are shadowless with the ambient_occlusion
* factor here. */
- cl_out.radiance += light.data.l_color * (light.vis * light.contact_shadow * radiance);
+ cl_out.radiance += light.data.l_color *
+ (light.data.l_diff * light.vis * light.contact_shadow * radiance);
}
void closure_Diffuse_grid_eval(ClosureInputDiffuse cl_in,
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
index 66c467af29b..183219c9088 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
@@ -32,7 +32,7 @@ void closure_Translucent_light_eval(ClosureInputTranslucent cl_in,
inout ClosureOutputTranslucent cl_out)
{
float radiance = light_diffuse(light.data, cl_in.N, cl_common.V, light.L);
- cl_out.radiance += light.data.l_color * (light.vis * radiance);
+ cl_out.radiance += light.data.l_color * (light.data.l_diff * light.vis * radiance);
}
void closure_Translucent_grid_eval(ClosureInputTranslucent cl_in,
diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
index 87934027361..d2daa5a1092 100644
--- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
@@ -14,18 +14,22 @@
struct LightData {
vec4 position_influence; /* w : InfluenceRadius (inversed and squared) */
- vec4 color_spec; /* w : Spec Intensity */
+ vec4 color_influence_volume; /* w : InfluenceRadius but for Volume power */
vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */
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. */
};
/* convenience aliases */
-#define l_color color_spec.rgb
-#define l_spec color_spec.a
+#define l_color color_influence_volume.rgb
+#define l_diff diff_spec_volume.x
+#define l_spec diff_spec_volume.y
+#define l_volume diff_spec_volume.z
#define l_position position_influence.xyz
#define l_influence position_influence.w
+#define l_influence_volume color_influence_volume.w
#define l_sizex rightvec_sizex.w
#define l_sizey upvec_sizey.w
#define l_right rightvec_sizex.xyz
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
index b1e3a40e8d2..5b747d66e4d 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -64,38 +64,35 @@ float phase_function(vec3 v, vec3 l, float g)
vec3 light_volume(LightData ld, vec4 l_vector)
{
- float power;
- /* TODO : Area lighting ? */
- /* XXX : Removing Area Power. */
- /* TODO : put this out of the shader. */
- /* See eevee_light_setup(). */
- if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) {
- power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
- if (ld.l_type == AREA_ELLIPSE) {
- power *= M_PI * 0.25;
+ float power = 1.0;
+ if (ld.l_type != SUN) {
+ /**
+ * Using "Point Light Attenuation Without Singularity" from Cem Yuksel
+ * http://www.cemyuksel.com/research/pointlightattenuation/pointlightattenuation.pdf
+ * http://www.cemyuksel.com/research/pointlightattenuation/
+ **/
+ float d = l_vector.w;
+ float d_sqr = sqr(d);
+ float r_sqr = sqr(ld.l_radius);
+ /* Using reformulation that has better numerical percision. */
+ power = 2.0 / (d_sqr + r_sqr + d * sqrt(d_sqr + r_sqr));
+
+ if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) {
+ /* Modulate by light plane orientation / solid angle. */
+ power *= saturate(dot(-ld.l_forward, l_vector.xyz / l_vector.w));
}
- power *= 20.0 *
- max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
}
- else if (ld.l_type == SUN) {
- power = ld.l_radius * ld.l_radius * M_PI; /* Removing area light power*/
- power /= 1.0f + (ld.l_radius * ld.l_radius * 0.5f);
- power *= M_PI * 0.5; /* Matching cycles. */
+ return ld.l_color * ld.l_volume * power;
+}
+
+vec3 light_volume_light_vector(LightData ld, vec3 P)
+{
+ if (ld.l_type == SUN) {
+ return -ld.l_forward;
}
else {
- power = (4.0 * ld.l_radius * ld.l_radius) * (1.0 / 10.0);
- power *= M_2PI; /* Matching cycles with point light. */
+ return ld.l_position - P;
}
-
- power /= (l_vector.w * l_vector.w);
-
- /* OPTI: find a better way than calculating this on the fly */
- float lum = dot(ld.l_color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
- vec3 tint = (lum > 0.0) ? ld.l_color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
-
- lum = min(lum * power, volLightClamp);
-
- return tint * lum;
}
#define VOLUMETRIC_SHADOW_MAX_STEP 128.0
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 e72bf8b9150..f75108babe6 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
@@ -44,7 +44,7 @@ void main()
LightData ld = lights_data[i];
vec4 l_vector;
- l_vector.xyz = (ld.l_type == SUN) ? -ld.l_forward : ld.l_position - P;
+ l_vector.xyz = light_volume_light_vector(ld, P);
l_vector.w = length(l_vector.xyz);
float Vis = light_visibility(ld, P, l_vector);