[Bf-blender-cvs] [7b9a6f823bf] eevee-motionblur-object: EEVEE: Implement deformation motion blur

Clément Foucault noreply at git.blender.org
Tue Apr 14 19:09:14 CEST 2020


Commit: 7b9a6f823bf3c7c390724c3bf1e21ae1c5354b34
Author: Clément Foucault
Date:   Mon Apr 6 17:48:20 2020 +0200
Branches: eevee-motionblur-object
https://developer.blender.org/rB7b9a6f823bf3c7c390724c3bf1e21ae1c5354b34

EEVEE: Implement deformation motion blur

This adds deformation motion blur by saving the vertex buffers of the
previous frame.

We modify the surface batch to pass the vert position as new attributes.

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

M	source/blender/draw/engines/eevee/eevee_data.c
M	source/blender/draw/engines/eevee/eevee_engine.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/shaders/object_motion_vert.glsl

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

diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index e0fbd04833f..351a5123776 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -28,6 +28,10 @@
 
 #include "BKE_anim.h"
 
+#include "DEG_depsgraph_query.h"
+
+#include "GPU_vertex_buffer.h"
+
 #include "eevee_lightcache.h"
 #include "eevee_private.h"
 
@@ -35,6 +39,10 @@
 
 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]);
+  }
   MEM_freeN(val);
 }
 
@@ -124,6 +132,24 @@ 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)
+{
+  if (mb->geom == NULL) {
+    return NULL;
+  }
+
+  /* Use original data as key to ensure matching accross update. */
+  ID *id_orig = DEG_get_original_id(ob->data);
+
+  EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, id_orig);
+  if (geom_step == NULL) {
+    geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
+    BLI_ghash_insert(mb->geom, id_orig, geom_step);
+  }
+
+  return geom_step;
+}
+
 /* View Layer data. */
 
 void EEVEE_view_layer_data_free(void *storage)
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index e68c515e2d8..342e8641372 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -442,6 +442,8 @@ static void eevee_render_to_image(void *vedata,
 
     DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache);
 
+    EEVEE_motion_blur_cache_finish(vedata);
+
     RE_engine_frame_set(engine, time, 0.0f);
 
     /* Reset passlist. This is safe as they are stored into managed memory chunks. */
@@ -463,6 +465,8 @@ static void eevee_render_to_image(void *vedata,
 
   DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache);
 
+  EEVEE_motion_blur_cache_finish(vedata);
+
   /* Actually do the rendering. */
   EEVEE_render_draw(vedata, engine, render_layer, rect);
 
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index 13c9198d18f..2d215366447 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -41,6 +41,7 @@
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_query.h"
 
+#include "GPU_batch.h"
 #include "GPU_texture.h"
 #include "eevee_private.h"
 
@@ -221,21 +222,79 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
   EEVEE_EffectsInfo *effects = stl->effects;
   DRWShadingGroup *grp = NULL;
 
-  EEVEE_ObjectMotionData *mbdata = EEVEE_motion_blur_object_data_get(&effects->motion_blur, ob);
+  EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(&effects->motion_blur, ob);
 
-  if (mbdata) {
+  if (mb_data) {
+    int mb_step = effects->motion_blur_step;
     /* Store transform  */
-    copy_m4_m4(mbdata->obmat[effects->motion_blur_step], ob->obmat);
+    copy_m4_m4(mb_data->obmat[mb_step], ob->obmat);
 
-    struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
-    /* TODO(fclem) Copy pos vbo and store it in geometry motion steps. */
+    EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(&effects->motion_blur,
+                                                                            ob);
+
+    if (effects->motion_blur_step == MAX_MB_DATA_STEP - 1) {
+      GPUBatch *batch = DRW_cache_object_surface_get(ob);
+      if (batch == NULL || mb_geom->vbo[mb_step]) {
+        return;
+      }
 
-    if (geom && effects->motion_blur_step == MAX_MB_DATA_STEP - 1) {
       grp = DRW_shgroup_create(e_data.motion_blur_object_sh, psl->velocity_object);
-      DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mbdata->obmat[0]);
-      DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mbdata->obmat[1]);
+      DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[0]);
+      DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[1]);
+      DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1);
+
+      DRW_shgroup_call(grp, batch, ob);
+      /* Keep to modify later (after init). */
+      mb_geom->batch = batch;
+    }
+    else {
+      /* Store vertex position buffer. */
+      mb_geom->vbo[mb_step] = DRW_cache_object_pos_vertbuf_get(ob);
+      /* TODO(fclem) only limit deform motion blur to object that needs it. */
+      mb_geom->use_deform = true;
+    }
+  }
+}
 
-      DRW_shgroup_call(grp, geom, ob);
+void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
+{
+  EEVEE_StorageList *stl = vedata->stl;
+  EEVEE_EffectsInfo *effects = stl->effects;
+  GHashIterator ghi;
+  for (BLI_ghashIterator_init(&ghi, effects->motion_blur.geom);
+       BLI_ghashIterator_done(&ghi) == false;
+       BLI_ghashIterator_step(&ghi)) {
+    EEVEE_GeometryMotionData *mb_geom = BLI_ghashIterator_getValue(&ghi);
+
+    int mb_step = effects->motion_blur_step;
+
+    if (effects->motion_blur_step == MAX_MB_DATA_STEP - 1) {
+      /* Modify batch to have data from adjacent frames. */
+      GPUBatch *batch = mb_geom->batch;
+      GPUVertBuf *vbo = mb_geom->vbo[0];
+      if (vbo && batch) {
+        if (vbo->vertex_len != batch->verts[0]->vertex_len) {
+          /* Vertex count mismatch, disable deform motion blur. */
+          mb_geom->use_deform = false;
+          GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[0]);
+          return;
+        }
+        /* Modify the batch to include the previous position. */
+        GPU_batch_vertbuf_add_ex(batch, vbo, true);
+        /* TODO(fclem) keep the vbo around for next (sub)frames. */
+        /* Only do once. */
+        mb_geom->vbo[0] = NULL;
+      }
+    }
+    else {
+      GPUVertBuf *vbo = mb_geom->vbo[mb_step];
+      /* Use the vbo to perform the copy on the GPU. */
+      GPU_vertbuf_use(vbo);
+      /* Perform a copy to avoid loosing it after RE_engine_frame_set(). */
+      mb_geom->vbo[mb_step] = vbo = GPU_vertbuf_duplicate(vbo);
+      /* Find and replace "pos" attrib name. */
+      int attrib_id = GPU_vertformat_attr_id_get(&vbo->format, "pos");
+      GPU_vertformat_attr_rename(&vbo->format, attrib_id, "prv");
     }
   }
 }
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index d3f6eaecf28..62ee7965feb 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -576,8 +576,9 @@ typedef struct EEVEE_ObjectMotionData {
 } EEVEE_ObjectMotionData;
 
 typedef struct EEVEE_GeometryMotionData {
-  struct GPUBatch *batch;
-  struct GPUVertBuf *vbo[MAX_MB_DATA_STEP];
+  struct GPUBatch *batch;                       /* Batch for time = t. */
+  struct GPUVertBuf *vbo[MAX_MB_DATA_STEP - 1]; /* Vbo for time = t +/- step. */
+  int use_deform;                               /* To disable deform mb if vertcount mismatch. */
 } EEVEE_GeometryMotionData;
 
 /* ************ EFFECTS DATA ************* */
@@ -924,6 +925,8 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void);
 EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob);
 EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob);
 EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb, Object *ob);
+EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb,
+                                                              Object *ob);
 EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob);
 EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob);
 EEVEE_LightEngineData *EEVEE_light_data_get(Object *ob);
@@ -1164,6 +1167,7 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Obje
 void EEVEE_motion_blur_step_set(EEVEE_Data *vedata, int step);
 void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
 void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *ob);
+void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata);
 void EEVEE_motion_blur_draw(EEVEE_Data *vedata);
 void EEVEE_motion_blur_free(void);
 
diff --git a/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl b/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl
index 83f3925c34c..e8c59745cda 100644
--- a/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl
@@ -3,16 +3,17 @@ uniform mat4 currViewProjectionMatrix;
 uniform mat4 prevViewProjectionMatrix;
 uniform mat4 currModelMatrix;
 uniform mat4 prevModelMatrix;
+uniform bool useDeform;
 
 in vec3 pos;
-//  in vec3 pos_prev; /* TODO */
+in vec3 prv; /* Previous frame position. */
 
 out vec3 currWorldPos;
 out vec3 prevWorldPos;
 
 void main()
 {
-  prevWorldPos = (prevModelMatrix * vec4(pos, 1.0)).xyz;
+  prevWorldPos = (prevModelMatrix * vec4(useDeform ? prv : pos, 1.0)).xyz;
   currWorldPos = (currModelMatrix * vec4(pos, 1.0)).xyz;
   /* Use jittered projmatrix to be able to match exact sample depth (depth equal test).
    * Note that currModelMatrix needs to also be equal to ModelMatrix for the samples to match. */



More information about the Bf-blender-cvs mailing list