[Bf-blender-cvs] [439b40e601f] master: EEVEE: Motion Blur: Add accumulation motion blur for better precision

Clément Foucault noreply at git.blender.org
Tue Jun 23 14:04:48 CEST 2020


Commit: 439b40e601f8cdae9a12fc3f503e9e6acdd596d5
Author: Clément Foucault
Date:   Tue Jun 23 13:59:55 2020 +0200
Branches: master
https://developer.blender.org/rB439b40e601f8cdae9a12fc3f503e9e6acdd596d5

EEVEE: Motion Blur: Add accumulation motion blur for better precision

This revisit the render pipeline to support time slicing for better motion
blur.

We support accumulation with or without the Post-process motion blur.

If using the post-process, we reuse last step next motion data to avoid
another scene reevaluation.

This also adds support for hair motion blur which is handled in a similar
way as mesh motion blur.

The total number of samples is distributed evenly accross all timesteps to
avoid sampling weighting issues. For this reason, the sample count is
(internally) rounded up to the next multiple of the step count.

Only FX Motion BLur: {F8632258}

FX Motion Blur + 4 time steps: {F8632260}

FX Motion Blur + 32 time steps: {F8632261}

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D8079

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

M	release/scripts/startup/bl_ui/properties_render.py
M	source/blender/blenloader/intern/versioning_290.c
M	source/blender/draw/engines/eevee/eevee_data.c
M	source/blender/draw/engines/eevee/eevee_effects.c
M	source/blender/draw/engines/eevee/eevee_engine.c
M	source/blender/draw/engines/eevee/eevee_lightcache.c
M	source/blender/draw/engines/eevee/eevee_materials.c
M	source/blender/draw/engines/eevee/eevee_motion_blur.c
M	source/blender/draw/engines/eevee/eevee_private.h
M	source/blender/draw/engines/eevee/eevee_render.c
M	source/blender/draw/engines/eevee/eevee_subsurface.c
M	source/blender/draw/engines/eevee/eevee_temporal_sampling.c
M	source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl
M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_common.h
M	source/blender/draw/intern/draw_hair.c
M	source/blender/draw/intern/draw_manager.c
M	source/blender/makesdna/DNA_scene_defaults.h
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_scene.c

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

diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 70d4e3c275d..fcaa715cfd8 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -176,6 +176,7 @@ class RENDER_PT_eevee_motion_blur(RenderButtonsPanel, Panel):
         col.prop(props, "motion_blur_shutter")
         col.prop(props, "motion_blur_depth_scale")
         col.prop(props, "motion_blur_max")
+        col.prop(props, "motion_blur_steps", text="Steps")
 
 
 class RENDER_PT_eevee_depth_of_field(RenderButtonsPanel, Panel):
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 843bf4c98d9..c1bbb4a6fff 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -291,6 +291,12 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
       }
     }
 
+    if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "int", "motion_blur_steps")) {
+      LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+        scene->eevee.motion_blur_steps = 1;
+      }
+    }
+
     /* Transition to saving expansion for all of a constraint's subpanels. */
     if (!DNA_struct_elem_find(fd->filesdna, "bConstraint", "short", "ui_expand_flag")) {
       for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 5ca24d296c5..a4aa0e10198 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -41,8 +41,19 @@
 static void eevee_motion_blur_mesh_data_free(void *val)
 {
   EEVEE_GeometryMotionData *geom_mb = (EEVEE_GeometryMotionData *)val;
-  for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
-    GPU_VERTBUF_DISCARD_SAFE(geom_mb->vbo[i]);
+  switch (geom_mb->type) {
+    case EEVEE_HAIR_GEOM_MOTION_DATA:
+      for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
+        GPU_VERTBUF_DISCARD_SAFE(geom_mb->hair_pos[i]);
+        DRW_TEXTURE_FREE_SAFE(geom_mb->hair_pos_tx[i]);
+      }
+      break;
+
+    case EEVEE_MESH_GEOM_MOTION_DATA:
+      for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
+        GPU_VERTBUF_DISCARD_SAFE(geom_mb->vbo[i]);
+      }
+      break;
   }
   MEM_freeN(val);
 }
@@ -103,14 +114,17 @@ void EEVEE_motion_blur_data_free(EEVEE_MotionBlurData *mb)
   }
 }
 
-EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb, Object *ob)
+EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb,
+                                                          Object *ob,
+                                                          bool hair)
 {
   if (mb->object == NULL) {
     return NULL;
   }
 
   EEVEE_ObjectKey key, *key_p;
-  key.ob = ob;
+  /* Small hack to avoid another comparisson. */
+  key.ob = (Object *)((char *)ob + hair);
   DupliObject *dup = DRW_object_get_dupli(ob);
   if (dup) {
     key.parent = DRW_object_get_dupli_parent(ob);
@@ -133,7 +147,9 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *
   return ob_step;
 }
 
-EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, Object *ob)
+EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb,
+                                                              Object *ob,
+                                                              bool hair)
 {
   if (mb->geom == NULL) {
     return NULL;
@@ -142,10 +158,12 @@ EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurDa
   /* Use original data as key to ensure matching accross update. */
   Object *ob_orig = DEG_get_original_object(ob);
 
-  EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, ob_orig->data);
+  void *key = (char *)ob_orig->data + hair;
+  EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, key);
   if (geom_step == NULL) {
     geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
-    BLI_ghash_insert(mb->geom, ob_orig->data, geom_step);
+    geom_step->type = (hair) ? EEVEE_HAIR_GEOM_MOTION_DATA : EEVEE_MESH_GEOM_MOTION_DATA;
+    BLI_ghash_insert(mb->geom, key, geom_step);
   }
 
   return geom_step;
@@ -229,6 +247,8 @@ static void eevee_object_data_init(DrawData *dd)
 {
   EEVEE_ObjectEngineData *eevee_data = (EEVEE_ObjectEngineData *)dd;
   eevee_data->shadow_caster_id = -1;
+  eevee_data->need_update = false;
+  eevee_data->geom_update = false;
 }
 
 EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob)
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 6826b645971..8c48ae65d9b 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -153,7 +153,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
 
   effects->enabled_effects = 0;
   effects->enabled_effects |= (G.debug_value == 9) ? EFFECT_VELOCITY_BUFFER : 0;
-  effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata, camera);
+  effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata);
   effects->enabled_effects |= EEVEE_bloom_init(sldata, vedata);
   effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera);
   effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 93f66b0ab04..bdf00b7c568 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -167,6 +167,7 @@ static void eevee_cache_finish(void *vedata)
   EEVEE_lights_cache_finish(sldata, vedata);
   EEVEE_lightprobes_cache_finish(sldata, vedata);
 
+  EEVEE_subsurface_draw_init(sldata, vedata);
   EEVEE_effects_draw_init(sldata, vedata);
   EEVEE_volumes_draw_init(sldata, vedata);
 
@@ -381,6 +382,7 @@ static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
   EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
   if (oedata != NULL && oedata->dd.recalc != 0) {
     oedata->need_update = true;
+    oedata->geom_update = (oedata->dd.recalc & (ID_RECALC_GEOMETRY)) != 0;
     oedata->dd.recalc = 0;
   }
 }
@@ -400,7 +402,7 @@ static void eevee_id_world_update(void *vedata, World *wo)
   }
 }
 
-static void eevee_id_update(void *vedata, ID *id)
+void eevee_id_update(void *vedata, ID *id)
 {
   /* Handle updates based on ID type. */
   switch (GS(id->name)) {
@@ -416,6 +418,12 @@ static void eevee_id_update(void *vedata, ID *id)
   }
 }
 
+static void eevee_render_reset_passes(EEVEE_Data *vedata)
+{
+  /* Reset passlist. This is safe as they are stored into managed memory chunks. */
+  memset(vedata->psl, 0, sizeof(*vedata->psl));
+}
+
 static void eevee_render_to_image(void *vedata,
                                   RenderEngine *engine,
                                   struct RenderLayer *render_layer,
@@ -423,74 +431,114 @@ static void eevee_render_to_image(void *vedata,
 {
   EEVEE_Data *ved = (EEVEE_Data *)vedata;
   const DRWContextState *draw_ctx = DRW_context_state_get();
+  Depsgraph *depsgraph = draw_ctx->depsgraph;
+  Scene *scene = DEG_get_evaluated_scene(depsgraph);
+  EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+  const bool do_motion_blur = (scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED) != 0;
+  const bool do_motion_blur_fx = do_motion_blur && (scene->eevee.motion_blur_max > 0);
 
-  if (EEVEE_render_do_motion_blur(draw_ctx->depsgraph)) {
-    Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+  if (!EEVEE_render_init(vedata, engine, depsgraph)) {
+    return;
+  }
+  EEVEE_PrivateData *g_data = ved->stl->g_data;
+
+  int steps = max_ii(1, scene->eevee.motion_blur_steps);
+  int time_steps_tot = (do_motion_blur) ? steps : 1;
+  g_data->render_tot_samples = divide_ceil_u(scene->eevee.taa_render_samples, time_steps_tot);
+  /* Centered on frame for now. */
+  float time = CFRA - scene->eevee.motion_blur_shutter / 2.0f;
+  float time_step = scene->eevee.motion_blur_shutter / time_steps_tot;
+  for (int i = 0; i < time_steps_tot && !RE_engine_test_break(engine); i++) {
+    float time_prev = time;
+    float time_curr = time + time_step * 0.5f;
+    float time_next = time + time_step;
+    time += time_step;
+
+    /* Previous motion step. */
+    if (do_motion_blur_fx) {
+      if (i > 0) {
+        /* The previous step of this iteration N is exactly the next step of iteration N - 1.
+         * So we just swap the resources to avoid too much re-evaluation. */
+        EEVEE_motion_blur_swap_data(vedata);
+      }
+      else {
+        EEVEE_motion_blur_step_set(ved, MB_PREV);
+        RE_engine_frame_set(engine, floorf(time_prev), fractf(time_prev));
 
-    float shutter = scene->eevee.motion_blur_shutter * 0.5f;
-    float time = CFRA;
-    /* Centered on frame for now. */
-    float start_time = time - shutter;
-    float end_time = time + shutter;
+        EEVEE_render_view_sync(vedata, engine, depsgraph);
+        EEVEE_render_cache_init(sldata, vedata);
 
-    {
-      EEVEE_motion_blur_step_set(ved, MB_PREV);
-      RE_engine_frame_set(engine, floorf(start_time), fractf(start_time));
+        DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
 
-      if (!EEVEE_render_init(vedata, engine, draw_ctx->depsgraph)) {
-        return;
+        EEVEE_motion_blur_cache_finish(vedata);
+        EEVEE_materials_cache_finish(sldata, vedata);
+        eevee_render_reset_passes(vedata);
       }
+    }
 
-      if (RE_engine_test_break(engine)) {
-        return;
-      }
+    /* Next motion step. */
+    if (do_motion_blur_fx) {
+      EEVEE_motion_blur_step_set(ved, MB_NEXT);
+      RE_engine_frame_set(engine, floorf(time_next), fractf(time_next));
+
+      EEVEE_render_view_sync(vedata, engine, depsgraph);
+      EEVEE_render_cache_init(sldata, vedata);
+
+      DRW_render_object_iter(vedata, engine

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list