[Bf-blender-cvs] [f59b1179c5b] blender2.8: Eevee: Tag shadow maps to update only when necessary.

Clément Foucault noreply at git.blender.org
Thu Jun 1 23:55:17 CEST 2017


Commit: f59b1179c5b368179fd78a2ad999161ad4f071b9
Author: Clément Foucault
Date:   Thu Jun 1 18:20:44 2017 +0200
Branches: blender2.8
https://developer.blender.org/rBf59b1179c5b368179fd78a2ad999161ad4f071b9

Eevee: Tag shadow maps to update only when necessary.

Shadow maps are now only updated if one shadow casting object inside it's shadow bounds has been updated.

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

M	source/blender/draw/engines/eevee/eevee_engine.c
M	source/blender/draw/engines/eevee/eevee_lights.c
M	source/blender/draw/engines/eevee/eevee_private.h

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

diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index cd3819b88e1..3e2b47819d7 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -441,6 +441,17 @@ static void EEVEE_cache_init(void *vedata)
 	EEVEE_effects_cache_init(vedata);
 }
 
+EEVEE_ObjectEngineData *EEVEE_get_object_engine_data(Object *ob)
+{
+	EEVEE_ObjectEngineData **oedata = (EEVEE_ObjectEngineData **)DRW_object_engine_data_get(ob, &draw_engine_eevee_type, NULL);
+
+	if (*oedata == NULL) {
+		*oedata = MEM_callocN(sizeof(**oedata), "EEVEE_ObjectEngineData");
+	}
+
+	return *oedata;
+}
+
 static void EEVEE_cache_populate(void *vedata, Object *ob)
 {
 	EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
@@ -565,6 +576,9 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
 
 		if (cast_shadow) {
 			EEVEE_lights_cache_shcaster_add(sldata, psl, geom, ob->obmat);
+			BLI_addtail(&sldata->shadow_casters, BLI_genericNodeN(ob));
+			EEVEE_ObjectEngineData *oedata = EEVEE_get_object_engine_data(ob);
+			oedata->need_update = ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0);
 		}
 	}
 	else if (ob->type == OB_LAMP) {
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 4c992fca8e0..9dd87cc11f3 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -25,6 +25,8 @@
 
 #include "DRW_render.h"
 
+#include "BKE_object.h"
+
 #include "eevee_engine.h"
 #include "eevee_private.h"
 
@@ -47,6 +49,12 @@ typedef struct EEVEE_ShadowCascadeData {
 	float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
 } EEVEE_ShadowCascadeData;
 
+typedef struct ShadowCaster {
+	struct ShadowCaster *next, *prev;
+	void *ob;
+	bool prune;
+} ShadowCaster;
+
 static struct {
 	struct GPUShader *shadow_sh;
 	struct GPUShader *shadow_store_sh;
@@ -61,6 +69,25 @@ extern char datatoc_shadow_store_frag_glsl[];
 
 /* *********** FUNCTIONS *********** */
 
+static void eevee_lamp_engine_data_free(void *storage)
+{
+	EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)storage;
+	MEM_SAFE_FREE(led->storage);
+	BLI_freelistN(&led->shadow_caster_list);
+}
+
+static EEVEE_LampEngineData *eevee_get_lamp_engine_data(Object *ob)
+{
+	EEVEE_LampEngineData **ledata = (EEVEE_LampEngineData **)DRW_object_engine_data_get(ob, &draw_engine_eevee_type, &eevee_lamp_engine_data_free);
+
+	if (*ledata == NULL) {
+		*ledata = MEM_callocN(sizeof(**ledata), "EEVEE_LampEngineData");
+		(*ledata)->need_update = true;
+	}
+
+	return *ledata;
+}
+
 void EEVEE_lights_init(EEVEE_SceneLayerData *sldata)
 {
 	const unsigned int shadow_ubo_size = sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
@@ -109,6 +136,9 @@ void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 	{
 		psl->shadow_cascade_pass = DRW_pass_create("Shadow Cascade Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 	}
+
+	/* Reset shadow casters list */
+	BLI_freelistN(&sldata->shadow_casters);
 }
 
 void EEVEE_lights_cache_add(EEVEE_SceneLayerData *sldata, Object *ob)
@@ -122,37 +152,43 @@ void EEVEE_lights_cache_add(EEVEE_SceneLayerData *sldata, Object *ob)
 	}
 	else {
 		Lamp *la = (Lamp *)ob->data;
-		EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
+		EEVEE_LampEngineData *led = eevee_get_lamp_engine_data(ob);
+
+		if ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0) {
+			led->need_update = true;
+		}
 
-		DRW_lamp_engine_data_free((void *)led);
+		MEM_SAFE_FREE(led->storage);
 
 #if 1 /* TODO Waiting for notified refresh. only on scene change. Else too much perf cost. */
 		if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
 			if (la->type == LA_SUN && linfo->num_cascade < MAX_SHADOW_CASCADE) {
 #if 0 /* TODO filter cascaded shadow map */
-				led->sto = MEM_mallocN(sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData");
-				((EEVEE_ShadowCascadeData *)led->sto)->shadow_id = linfo->num_cascade;
+				led->storage = MEM_mallocN(sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData");
+				((EEVEE_ShadowCascadeData *)led->storage)->shadow_id = linfo->num_cascade;
 				linfo->shadow_cascade_ref[linfo->num_cascade] = ob;
 				linfo->num_cascade++;
 #endif
 			}
 			else if ((la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA)
 			          && linfo->num_cube < MAX_SHADOW_CUBE) {
-				led->sto = MEM_mallocN(sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData");
-				((EEVEE_ShadowCubeData *)led->sto)->shadow_id = linfo->num_cube;
+				led->storage = MEM_mallocN(sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData");
+				((EEVEE_ShadowCubeData *)led->storage)->shadow_id = linfo->num_cube;
 				linfo->shadow_cube_ref[linfo->num_cube] = ob;
 				linfo->num_cube++;
 			}
+
 		}
 #else
 		UNUSED_VARS(la);
 #endif
-		if (!led->sto) {
-			led->sto = MEM_mallocN(sizeof(EEVEE_LightData), "EEVEE_LightData");
-			((EEVEE_LightData *)led->sto)->shadow_id = -1;
+		/* Default light without shadows */
+		if (!led->storage) {
+			led->storage = MEM_mallocN(sizeof(EEVEE_LightData), "EEVEE_LightData");
+			((EEVEE_LightData *)led->storage)->shadow_id = -1;
 		}
 
-		((EEVEE_LightData *)led->sto)->light_id = linfo->num_light;
+		((EEVEE_LightData *)led->storage)->light_id = linfo->num_light;
 		linfo->light_ref[linfo->num_light] = ob;
 		linfo->num_light++;
 	}
@@ -180,14 +216,13 @@ void EEVEE_lights_cache_finish(EEVEE_SceneLayerData *sldata)
 {
 	EEVEE_LampsInfo *linfo = sldata->lamps;
 
-	/* Step 4 Update Lamp UBOs */
-	EEVEE_lights_update(sldata);
 
-	/* Step 5 Setup enough layers */
-	/* Free textures if number mismatch */
+	/* Setup enough layers. */
+	/* Free textures if number mismatch. */
 	if (linfo->num_cube != linfo->cache_num_cube) {
 		DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cube_pool);
 		linfo->cache_num_cube = linfo->num_cube;
+		linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE;
 	}
 	if (linfo->num_map != linfo->cache_num_map) {
 		DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_map_pool);
@@ -245,13 +280,16 @@ void EEVEE_lights_cache_finish(EEVEE_SceneLayerData *sldata)
 
 	DRWFboTexture tex_cascade = {&sldata->shadow_depth_cascade_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE};
 	DRW_framebuffer_init(&sldata->shadow_cascade_fb, &draw_engine_eevee_type, 512, 512, &tex_cascade, 1);
+
+	/* Update Lamps UBOs. */
+	EEVEE_lights_update(sldata);
 }
 
 /* Update buffer with lamp data */
 static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
 {
 	/* TODO only update if data changes */
-	EEVEE_LightData *evld = led->sto;
+	EEVEE_LightData *evld = led->storage;
 	EEVEE_Light *evli = linfo->light_data + evld->light_id;
 	Lamp *la = (Lamp *)ob->data;
 	float mat[4][4], scale[3], power;
@@ -326,7 +364,7 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
 {
 	float projmat[4][4];
 
-	EEVEE_ShadowCubeData *evsmp = (EEVEE_ShadowCubeData *)led->sto;
+	EEVEE_ShadowCubeData *evsmp = (EEVEE_ShadowCubeData *)led->storage;
 	EEVEE_Light *evli = linfo->light_data + evsmp->light_id;
 	EEVEE_ShadowCube *evsh = linfo->shadow_cube_data + evsmp->shadow_id;
 	Lamp *la = (Lamp *)ob->data;
@@ -352,7 +390,7 @@ static void eevee_shadow_map_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_Lam
 {
 	float viewmat[4][4], projmat[4][4];
 
-	EEVEE_ShadowMapData *evsmp = (EEVEE_ShadowMapData *)led->sto;
+	EEVEE_ShadowMapData *evsmp = (EEVEE_ShadowMapData *)led->storage;
 	EEVEE_Light *evli = linfo->light_data + evsmp->light_id;
 	EEVEE_ShadowMap *evsh = linfo->shadow_map_data + evsmp->shadow_id;
 	Lamp *la = (Lamp *)ob->data;
@@ -435,7 +473,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
 	int cascade_ct = MAX_CASCADE_NUM;
 	float shadow_res = 512.0f; /* TODO parameter */
 
-	EEVEE_ShadowCascadeData *evscp = (EEVEE_ShadowCascadeData *)led->sto;
+	EEVEE_ShadowCascadeData *evscp = (EEVEE_ShadowCascadeData *)led->storage;
 	EEVEE_Light *evli = linfo->light_data + evscp->light_id;
 	EEVEE_ShadowCascade *evsh = linfo->shadow_cascade_data + evscp->shadow_id;
 	Lamp *la = (Lamp *)ob->data;
@@ -546,29 +584,135 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
 	evli->shadowid = (float)(MAX_SHADOW_CUBE + MAX_SHADOW_MAP + evscp->shadow_id);
 }
 
+/* Used for checking if object is inside the shadow volume. */
+static bool cube_bbox_intersect(const float cube_center[3], float cube_half_dim, const BoundBox *bb, float (*obmat)[4])
+{
+	float min[3], max[4], tmp[4][4];
+	unit_m4(tmp);
+	translate_m4(tmp, -cube_center[0], -cube_center[1], -cube_center[2]);
+	mul_m4_m4m4(tmp, tmp, obmat);
+
+	/* Just simple AABB intersection test in world space. */
+	INIT_MINMAX(min, max);
+	for (int i = 0; i < 8; ++i) {
+		float vec[3];
+		copy_v3_v3(vec, bb->vec[i]);
+		mul_m4_v3(tmp, vec);
+		minmax_v3v3_v3(min, max, vec);
+	}
+
+    if (MAX3(max[0], max[1], max[2]) < -cube_half_dim) return false;
+    if (MIN3(min[0], min[1], min[2]) >  cube_half_dim) return false;
+
+	return true;
+}
+
+static ShadowCaster *search_object_in_list(ListBase *list, Object *ob)
+{
+	for (ShadowCaster *ldata = list->first; ldata; ldata = ldata->next) {
+		if (ldata->ob == ob)
+			return ldata;
+	}
+
+	return NULL;
+}
+
+static void delete_pruned_shadowcaster(EEVEE_LampEngineData *led)
+{
+	ShadowCaster *next;
+	for (ShadowCaster *ldata = led->shadow_caster_list.first; ldata; ldata = next) {
+		next = ldata->next;
+		if (ldata->prune == true) {
+			BLI_freelinkN(&led->shadow_caster_list, ldata);
+		}
+	}
+}
+
+static void light_tag_shadow_update(Object *lamp, Object *ob)
+{
+	Lamp *la = lamp->data;
+	EEVEE_LampEngineData *led = eevee_get_lamp_engine_data(lamp);
+
+	bool is_inside_range = cube_bbox_intersect(lamp->obmat[3], la->clipend, BKE_object_boundbox_get(ob), ob->obmat);
+	ShadowCaster *ldata = search_object_in_list(&led->shadow_caster_list, ob);
+
+	if (is_inside_range) {
+		if (ldata == NULL) {
+			/* Object was not a shadow caster previously but is now. Add it. */
+			ldata = MEM_callocN(siz

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list