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. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to