[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