[Bf-blender-cvs] [516e000aa97] blender2.8: Eevee: Add Light Threshold value

Clément Foucault noreply at git.blender.org
Thu Nov 15 18:17:34 CET 2018


Commit: 516e000aa9762c6b19c64ce46e5dd458cd04a1fb
Author: Clément Foucault
Date:   Thu Nov 15 14:44:45 2018 +0100
Branches: blender2.8
https://developer.blender.org/rB516e000aa9762c6b19c64ce46e5dd458cd04a1fb

Eevee: Add Light Threshold value

This is an important change. Starting from now, all lights have a finite
influence radius (similar to the old sphere option for BI).

In order to avoid costly setup time, this distance is first computed
automatically based on a light threshold. The distance is computed
at the light origin and using the inverse square falloff. The setting
can be found inside the render settings panel > shadow tab.

This light threshold does not take the light shape into account an may not
suit every case. That's why we provide a per lamp override where you can
just set the cutt off distance (Light Properties Panel > Light >
Custom Distance).

The influence distance is also used as shadow far clip distance.

This influence distance does not concerns sun lights that still have a
far clip distance.

---

This change is important because it makes it possible to cull lights
an improve performance drastically in the future.

===================================================================

M	release/scripts/startup/bl_ui/properties_data_light.py
M	release/scripts/startup/bl_ui/properties_render.py
M	source/blender/blenkernel/intern/lamp.c
M	source/blender/blenkernel/intern/scene.c
M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/draw/engines/eevee/eevee_lights.c
M	source/blender/draw/engines/eevee/eevee_private.h
M	source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
M	source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
M	source/blender/makesdna/DNA_lamp_types.h
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_lamp.c
M	source/blender/makesrna/intern/rna_scene.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_data_light.py b/release/scripts/startup/bl_ui/properties_data_light.py
index 8aa70d1e05f..7d21ecb99b3 100644
--- a/release/scripts/startup/bl_ui/properties_data_light.py
+++ b/release/scripts/startup/bl_ui/properties_data_light.py
@@ -105,6 +105,36 @@ class DATA_PT_EEVEE_light(DataButtonsPanel, Panel):
                 sub.prop(light, "size_y", text="Y")
 
 
+class DATA_PT_EEVEE_light_distance(DataButtonsPanel, Panel):
+    bl_label = "Custom Distance"
+    bl_parent_id = "DATA_PT_EEVEE_light"
+    bl_options = {'DEFAULT_CLOSED'}
+    COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+    @classmethod
+    def poll(cls, context):
+        light = context.light
+        engine = context.engine
+
+        return (light and light.type != 'SUN') and (engine in cls.COMPAT_ENGINES)
+
+    def draw_header(self, context):
+        light = context.light
+
+        layout = self.layout
+        layout.active = light.use_shadow
+        layout.prop(light, "use_custom_distance", text="")
+
+    def draw(self, context):
+        layout = self.layout
+        light = context.light
+        layout.use_property_split = True
+
+        col = layout.column()
+
+        col.prop(light, "cutoff_distance", text="Distance")
+
+
 class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel):
     bl_label = "Shadow"
     bl_options = {'DEFAULT_CLOSED'}
@@ -131,7 +161,8 @@ class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel):
         col = layout.column()
         sub = col.column(align=True)
         sub.prop(light, "shadow_buffer_clip_start", text="Clip Start")
-        sub.prop(light, "shadow_buffer_clip_end", text="End")
+        if light.type == 'SUN':
+            sub.prop(light, "shadow_buffer_clip_end", text="End")
 
         col.prop(light, "shadow_buffer_soft", text="Softness")
 
@@ -281,6 +312,7 @@ classes = (
     DATA_PT_preview,
     DATA_PT_light,
     DATA_PT_EEVEE_light,
+    DATA_PT_EEVEE_light_distance,
     DATA_PT_EEVEE_shadow,
     DATA_PT_EEVEE_shadow_contact,
     DATA_PT_EEVEE_shadow_cascaded_shadow_map,
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index bbb1a067dd7..61804bae9d8 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -390,6 +390,7 @@ class RENDER_PT_eevee_shadows(RenderButtonsPanel, Panel):
         col.prop(props, "shadow_cascade_size", text="Cascade Size")
         col.prop(props, "use_shadow_high_bitdepth")
         col.prop(props, "use_soft_shadows")
+        col.prop(props, "light_threshold")
 
 
 class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel):
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index a2571c8cee5..8768810ccff 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -89,6 +89,7 @@ void BKE_lamp_init(Lamp *la)
 	la->contact_spread = 0.2f;
 	la->contact_thickness = 0.2f;
 	la->spec_fac = 1.0f;
+	la->att_dist = 40.0f;
 
 	curvemapping_initialize(la->curfalloff);
 }
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index af27103b07e..ee30179e632 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -915,6 +915,7 @@ void BKE_scene_init(Scene *sce)
 	sce->eevee.shadow_cascade_size = 1024;
 
 	sce->eevee.light_cache = NULL;
+	sce->eevee.light_threshold = 0.01f;
 
 	sce->eevee.overscan = 3.0f;
 
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 9521c05f7f0..1871aea86a4 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -2265,6 +2265,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
 			}
 		}
 
+		if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "light_threshold")) {
+			for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+				scene->eevee.light_threshold = 0.01f;
+			}
+		}
+
+		if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "att_dist")) {
+			for (Lamp *la = bmain->lamp.first; la; la = la->id.next) {
+				la->att_dist = la->clipend;
+			}
+		}
+
 		if (!DNA_struct_elem_find(fd->filesdna, "Brush", "char", "weightpaint_tool")) {
 			/* Magic defines from old files (2.7x) */
 
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 5336e197d02..b946a49ea14 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -57,8 +57,9 @@ extern char datatoc_shadow_store_frag_glsl[];
 extern char datatoc_shadow_copy_frag_glsl[];
 extern char datatoc_concentric_samples_lib_glsl[];
 
-/* Prototype */
+/* Prototypes */
 static void eevee_light_setup(Object *ob, EEVEE_Light *evli);
+static float light_attenuation_radius_get(Lamp *la, float light_threshold);
 
 /* *********** LIGHT BITS *********** */
 static void lightbits_set_single(EEVEE_LightBits *bitf, uint idx, bool val)
@@ -337,6 +338,9 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
 {
 	EEVEE_LampsInfo *linfo = sldata->lamps;
 
+	const DRWContextState *draw_ctx = DRW_context_state_get();
+	const float threshold = draw_ctx->scene->eevee.light_threshold;
+
 	/* Step 1 find all lamps in the scene and setup them */
 	if (linfo->num_light >= MAX_LIGHT) {
 		printf("Too many lights in the scene !!!\n");
@@ -399,7 +403,7 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
 					/* Saving lamp bounds for later. */
 					BLI_assert(linfo->cpu_cube_len >= 0 && linfo->cpu_cube_len < MAX_LIGHT);
 					copy_v3_v3(linfo->shadow_bounds[linfo->cpu_cube_len].center, ob->obmat[3]);
-					linfo->shadow_bounds[linfo->cpu_cube_len].radius = la->clipend;
+					linfo->shadow_bounds[linfo->cpu_cube_len].radius = light_attenuation_radius_get(la, threshold);
 
 					EEVEE_ShadowCubeData *data = &led->data.scd;
 					/* Store indices. */
@@ -590,37 +594,25 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
 	EEVEE_lights_update(sldata, vedata);
 }
 
-/* Update buffer with lamp data */
-static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
+float light_attenuation_radius_get(Lamp *la, float light_threshold)
 {
-	Lamp *la = (Lamp *)ob->data;
-	float mat[4][4], scale[3], power;
-
-	/* Position */
-	copy_v3_v3(evli->position, ob->obmat[3]);
-
-	/* Color */
-	copy_v3_v3(evli->color, &la->r);
-
-	evli->spec = la->spec_fac;
-
-	/* Influence Radius */
-	evli->dist = la->dist;
-
-	/* Vectors */
-	normalize_m4_m4_ex(mat, ob->obmat, scale);
-	copy_v3_v3(evli->forwardvec, mat[2]);
-	normalize_v3(evli->forwardvec);
-	negate_v3(evli->forwardvec);
-
-	copy_v3_v3(evli->rightvec, mat[0]);
-	normalize_v3(evli->rightvec);
-
-	copy_v3_v3(evli->upvec, mat[1]);
-	normalize_v3(evli->upvec);
+	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);
+	power *= max_ff(1.0f, la->spec_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;
+}
 
-	/* Spot size & blend */
+static void light_shape_parameters_set(EEVEE_Light *evli, const Lamp *la, float scale[3])
+{
 	if (la->type == LA_SPOT) {
+		/* Spot size & blend */
 		evli->sizex = scale[0] / scale[2];
 		evli->sizey = scale[1] / scale[2];
 		evli->spotsize = cosf(la->spotsize * 0.5f);
@@ -639,16 +631,16 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
 	else {
 		evli->radius = max_ff(0.001f, la->area_size);
 	}
+}
 
-	/* Lamp Type */
-	evli->lamptype = (float)la->type;
-
+static float light_shape_power_get(const Lamp *la, const EEVEE_Light *evli)
+{
+	float power;
 	/* Make illumination power constant */
 	if (la->type == LA_AREA) {
 		power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */
 		        80.0f; /* XXX : Empirical, Fit cycles power */
 		if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) {
-			evli->lamptype = LAMPTYPE_AREA_ELLIPSE;
 			/* Scale power to account for the lower area of the ellipse compared to the surrounding rectangle. */
 			power *= 4.0f / M_PI;
 		}
@@ -664,8 +656,54 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
 		power = 1.0f / (evli->radius * evli->radius * M_PI); /* 1/(r²*Pi) */
 		/* Make illumation 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. */
-		power *= 1.0f + evli->radius * evli->radius * 0.5f;
+		power += 1.0f / (2.0f * M_PI); /* power *= 1 + r²/2 */
+	}
+	return power;
+}
+
+/* Update buffer with lamp data */
+static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
+{
+	Lamp *la = (Lamp *)ob->data;
+	float mat[4][4], scale[3], power, att_radius;
+
+	const DRWContextState *draw_ctx = DRW_context_state_get();
+	const float light_threshold = draw_ctx->scene->eevee.light_threshold;
+
+	/* Position */
+	copy_v3_v3(evli->position, ob->obmat[3]);
+
+	/* Color */
+	copy_v3_v3(evli->color, &la->r);
+
+	evli->spec = la->spec_fac;
+
+	/* Influence Radius */
+	att_radius = light_attenuation_radius_get(la, light_threshold);
+	/* Take the inverse square of this distance. */
+	evli->invsqrdist = 1.0 / max_ff(1e-4f, att_radius * att_radius);
+
+	/* Vectors */
+	normalize_m4_m4_ex(mat, ob->obmat, scale);
+	copy_v3_v3(evli->forwardvec, mat[2]);
+	normalize_v3(evli->forwardvec);
+	negate_v3(evli->forwardvec);
+
+	copy_v3_v3(evli->rightvec, mat[0]);
+	normalize_v3(evli->rightvec);
+
+	copy_v3_v3(evli->upvec, mat[1]);
+	normalize_v3(evli->upvec);
+
+	light_shape_parameters_set(evli, la, scale);
+
+	/* Lamp Type */
+	evli->lamptype = (float)la->type;
+	if ((la->type == LA_AREA) && ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) {
+		evli->lamptype = LAMPTYPE_AREA_ELLIP

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list