Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-06-23 14:59:55 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-06-23 15:04:41 +0300
commit439b40e601f8cdae9a12fc3f503e9e6acdd596d5 (patch)
tree9a485ec18d1c9dd030ffdfe9309193adc96dc515 /source/blender/draw/engines/eevee/eevee_engine.c
parentcc3e808ab47887c002faaa8a28318a2b4f47e02a (diff)
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
Diffstat (limited to 'source/blender/draw/engines/eevee/eevee_engine.c')
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c138
1 files changed, 93 insertions, 45 deletions
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, depsgraph, EEVEE_render_cache);
- DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache);
EEVEE_motion_blur_cache_finish(vedata);
- /* Reset passlist. This is safe as they are stored into managed memory chunks. */
- memset(ved->psl, 0, sizeof(*ved->psl));
- /* Fix memleak */
- BLI_ghash_free(ved->stl->g_data->material_hash, NULL, NULL);
- ved->stl->g_data->material_hash = NULL;
+ EEVEE_materials_cache_finish(sldata, vedata);
+ eevee_render_reset_passes(vedata);
}
+ /* Current motion step. */
{
- EEVEE_motion_blur_step_set(ved, MB_NEXT);
- RE_engine_frame_set(engine, floorf(end_time), fractf(end_time));
+ if (do_motion_blur) {
+ EEVEE_motion_blur_step_set(ved, MB_CURR);
+ RE_engine_frame_set(engine, floorf(time_curr), fractf(time_curr));
+ }
+
+ EEVEE_render_view_sync(vedata, engine, depsgraph);
+ EEVEE_render_cache_init(sldata, vedata);
- EEVEE_render_init(vedata, engine, draw_ctx->depsgraph);
+ DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
- DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache);
EEVEE_motion_blur_cache_finish(vedata);
- /* Reset passlist. This is safe as they are stored into managed memory chunks. */
- memset(ved->psl, 0, sizeof(*ved->psl));
- /* Fix memleak */
- BLI_ghash_free(ved->stl->g_data->material_hash, NULL, NULL);
- ved->stl->g_data->material_hash = NULL;
+ EEVEE_volumes_cache_finish(sldata, vedata);
+ EEVEE_materials_cache_finish(sldata, 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);
}
- /* Current frame. */
- EEVEE_motion_blur_step_set(ved, MB_CURR);
- RE_engine_frame_set(engine, time, 0.0f);
- }
+ /* Actual drawing. */
+ {
+ if (i == 0) {
+ EEVEE_renderpasses_output_init(
+ sldata, vedata, g_data->render_tot_samples * time_steps_tot);
+ }
- if (!EEVEE_render_init(vedata, engine, draw_ctx->depsgraph)) {
- return;
+ EEVEE_temporal_sampling_create_view(vedata);
+ EEVEE_render_draw(vedata, engine, render_layer, rect);
+
+ DRW_cache_restart();
+ }
}
+ EEVEE_volumes_free_smoke_textures();
+ EEVEE_motion_blur_data_free(&ved->stl->effects->motion_blur);
+
if (RE_engine_test_break(engine)) {
return;
}
- DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache);
-
- EEVEE_motion_blur_cache_finish(vedata);
+ EEVEE_render_read_result(vedata, engine, render_layer, rect);
- /* Actually do the rendering. */
- EEVEE_render_draw(vedata, engine, render_layer, rect);
-
- EEVEE_volumes_free_smoke_textures();
- EEVEE_motion_blur_data_free(&ved->stl->effects->motion_blur);
+ /* Restore original viewport size. */
+ DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]});
}
static void eevee_engine_free(void)