diff options
Diffstat (limited to 'source/blender/draw/engines/eevee/eevee_motion_blur.c')
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_motion_blur.c | 302 |
1 files changed, 242 insertions, 60 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index b90d575b80c..586ee780f1d 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -25,6 +25,7 @@ #include "DRW_render.h" #include "BLI_rand.h" +#include "BLI_string_utils.h" #include "BKE_animsys.h" #include "BKE_camera.h" @@ -34,6 +35,8 @@ #include "DNA_anim_types.h" #include "DNA_camera_types.h" #include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_particle_types.h" #include "DNA_screen_types.h" #include "ED_screen.h" @@ -49,6 +52,7 @@ static struct { /* Motion Blur */ struct GPUShader *motion_blur_sh; struct GPUShader *motion_blur_object_sh; + struct GPUShader *motion_blur_hair_sh; struct GPUShader *velocity_tiles_sh; struct GPUShader *velocity_tiles_expand_sh; } e_data = {NULL}; /* Engine data */ @@ -57,6 +61,7 @@ extern char datatoc_effect_velocity_tile_frag_glsl[]; extern char datatoc_effect_motion_blur_frag_glsl[]; extern char datatoc_object_motion_frag_glsl[]; extern char datatoc_object_motion_vert_glsl[]; +extern char datatoc_common_hair_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; #define EEVEE_VELOCITY_TILE_SIZE 32 @@ -79,9 +84,14 @@ static void eevee_create_shader_motion_blur(void) datatoc_effect_velocity_tile_frag_glsl, "#define TILE_EXPANSION\n" "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n"); + + char *vert = BLI_string_joinN(datatoc_common_hair_lib_glsl, datatoc_object_motion_vert_glsl); + e_data.motion_blur_hair_sh = DRW_shader_create_with_lib( + vert, NULL, datatoc_object_motion_frag_glsl, datatoc_common_view_lib_glsl, "#define HAIR\n"); + MEM_freeN(vert); } -int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera) +int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) { EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; @@ -95,7 +105,9 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda return 0; } - if (scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED) { + effects->motion_blur_max = max_ii(0, scene->eevee.motion_blur_max); + + if ((effects->motion_blur_max > 0) && (scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED)) { if (!e_data.motion_blur_sh) { eevee_create_shader_motion_blur(); } @@ -107,17 +119,6 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda DRW_view_persmat_get(NULL, effects->motion_blur.camera[mb_step].persinv, true); } - if (camera != NULL) { - Camera *cam = camera->data; - effects->motion_blur_near_far[0] = cam->clip_start; - effects->motion_blur_near_far[1] = cam->clip_end; - } - else { - /* Not supported yet. */ - BLI_assert(0); - } - - effects->motion_blur_max = max_ii(0, scene->eevee.motion_blur_max); const float *fs_size = DRW_viewport_size_get(); int tx_size[2] = {1 + ((int)fs_size[0] / EEVEE_VELOCITY_TILE_SIZE), 1 + ((int)fs_size[1] / EEVEE_VELOCITY_TILE_SIZE)}; @@ -146,13 +147,23 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda void EEVEE_motion_blur_step_set(EEVEE_Data *vedata, int step) { BLI_assert(step < 3); - /* Meh, code duplication. Could be avoided if render init would not contain cache init. */ - if (vedata->stl->effects == NULL) { - vedata->stl->effects = MEM_callocN(sizeof(*vedata->stl->effects), __func__); - } vedata->stl->effects->motion_blur_step = step; } +static void eevee_motion_blur_sync_camera(EEVEE_Data *vedata) +{ + EEVEE_EffectsInfo *effects = vedata->stl->effects; + if (DRW_state_is_scene_render()) { + int mb_step = effects->motion_blur_step; + DRW_view_viewmat_get(NULL, effects->motion_blur.camera[mb_step].viewmat, false); + DRW_view_persmat_get(NULL, effects->motion_blur.camera[mb_step].persmat, false); + DRW_view_persmat_get(NULL, effects->motion_blur.camera[mb_step].persinv, true); + } + + effects->motion_blur_near_far[0] = fabsf(DRW_view_near_distance_get(NULL)); + effects->motion_blur_near_far[1] = fabsf(DRW_view_far_distance_get(NULL)); +} + void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; @@ -167,6 +178,9 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat const float *fs_size = DRW_viewport_size_get(); int tx_size[2] = {GPU_texture_width(effects->velocity_tiles_tx), GPU_texture_height(effects->velocity_tiles_tx)}; + + eevee_motion_blur_sync_camera(vedata); + DRWShadingGroup *grp; { DRW_PASS_CREATE(psl->velocity_tiles_x, DRW_STATE_WRITE_COLOR); @@ -230,6 +244,15 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat DRW_shgroup_uniform_mat4(grp, "prevViewProjMatrix", mb_data->camera[MB_PREV].persmat); DRW_shgroup_uniform_mat4(grp, "currViewProjMatrix", mb_data->camera[MB_CURR].persmat); DRW_shgroup_uniform_mat4(grp, "nextViewProjMatrix", mb_data->camera[MB_NEXT].persmat); + + DRW_PASS_CREATE(psl->velocity_hair, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + + mb_data->hair_grp = grp = DRW_shgroup_create(e_data.motion_blur_hair_sh, psl->velocity_hair); + DRW_shgroup_uniform_mat4(grp, "prevViewProjMatrix", mb_data->camera[MB_PREV].persmat); + DRW_shgroup_uniform_mat4(grp, "currViewProjMatrix", mb_data->camera[MB_CURR].persmat); + DRW_shgroup_uniform_mat4(grp, "nextViewProjMatrix", mb_data->camera[MB_NEXT].persmat); + + DRW_pass_link(psl->velocity_object, psl->velocity_hair); } EEVEE_motion_blur_data_init(mb_data); @@ -237,6 +260,59 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat else { psl->motion_blur = NULL; psl->velocity_object = NULL; + psl->velocity_hair = NULL; + } +} + +void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + Object *ob, + ParticleSystem *psys, + ModifierData *md) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DRWShadingGroup *grp = NULL; + + if (!DRW_state_is_scene_render() || psl->velocity_hair == NULL) { + return; + } + + /* For now we assume hair objects are always moving. */ + EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get( + &effects->motion_blur, ob, true); + + if (mb_data) { + int mb_step = effects->motion_blur_step; + /* Store transform */ + DRW_hair_duplimat_get(ob, psys, md, mb_data->obmat[mb_step]); + + EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get( + &effects->motion_blur, ob, true); + + if (mb_step == MB_CURR) { + /* Fill missing matrices if the object was hidden in previous or next frame. */ + if (is_zero_m4(mb_data->obmat[MB_PREV])) { + copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_CURR]); + } + if (is_zero_m4(mb_data->obmat[MB_NEXT])) { + copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]); + } + + grp = DRW_shgroup_hair_create_sub(ob, psys, md, effects->motion_blur.hair_grp); + DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]); + DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]); + DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]); + DRW_shgroup_uniform_texture(grp, "prvBuffer", mb_geom->hair_pos_tx[MB_PREV]); + DRW_shgroup_uniform_texture(grp, "nxtBuffer", mb_geom->hair_pos_tx[MB_NEXT]); + DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1); + } + else { + /* Store vertex position buffer. */ + mb_geom->hair_pos[mb_step] = DRW_hair_pos_buffer_get(ob, psys, md); + mb_geom->use_deform = true; + } } } @@ -262,15 +338,16 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), return; } - EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(&effects->motion_blur, ob); + EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get( + &effects->motion_blur, ob, false); if (mb_data) { int mb_step = effects->motion_blur_step; /* Store transform */ copy_m4_m4(mb_data->obmat[mb_step], ob->obmat); - EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(&effects->motion_blur, - ob); + EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get( + &effects->motion_blur, ob, false); if (mb_step == MB_CURR) { GPUBatch *batch = DRW_cache_object_surface_get(ob); @@ -295,6 +372,17 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), DRW_shgroup_call(grp, batch, ob); if (mb_geom->use_deform) { + EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob); + if (!oedata->geom_update) { + /* FIXME(fclem) There can be false positive where the actual mesh is not updated. + * This avoids a crash but removes the motion blur from some object. + * Maybe an issue with depsgraph tagging. */ + mb_geom->use_deform = false; + oedata->geom_update = false; + + GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]); + GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]); + } /* Keep to modify later (after init). */ mb_geom->batch = batch; } @@ -321,52 +409,151 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata) return; } + int mb_step = effects->motion_blur_step; + + if (mb_step != MB_CURR) { + /* Push instances attributes to the GPU. */ + DRW_render_instance_buffer_finish(); + + /* Need to be called after DRW_render_instance_buffer_finish() */ + /* Also we weed to have a correct fbo bound for DRW_hair_update */ + GPU_framebuffer_bind(vedata->fbl->main_fb); + DRW_hair_update(); + + DRW_cache_restart(); + } + 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 (!mb_geom->use_deform) { continue; } - if (mb_step == MB_CURR) { - /* Modify batch to have data from adjacent frames. */ - GPUBatch *batch = mb_geom->batch; - for (int i = 0; i < MB_CURR; i++) { - GPUVertBuf *vbo = mb_geom->vbo[i]; - 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[MB_PREV]); - GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]); - break; + switch (mb_geom->type) { + case EEVEE_HAIR_GEOM_MOTION_DATA: + if (mb_step == MB_CURR) { + /* TODO(fclem) Check if vertex count mismatch. */ + mb_geom->use_deform = true; + } + else { + mb_geom->hair_pos[mb_step] = GPU_vertbuf_duplicate(mb_geom->hair_pos[mb_step]); + + /* Create vbo immediately to bind to texture buffer. */ + GPU_vertbuf_use(mb_geom->hair_pos[mb_step]); + + mb_geom->hair_pos_tx[mb_step] = GPU_texture_create_from_vertbuf( + mb_geom->hair_pos[mb_step]); + } + break; + + case EEVEE_MESH_GEOM_MOTION_DATA: + if (mb_step == MB_CURR) { + /* Modify batch to have data from adjacent frames. */ + GPUBatch *batch = mb_geom->batch; + for (int i = 0; i < MB_CURR; i++) { + GPUVertBuf *vbo = mb_geom->vbo[i]; + if (vbo && batch) { + if (vbo->vertex_len != batch->verts[0]->vertex_len) { + /* Vertex count mismatch, disable deform motion blur. */ + mb_geom->use_deform = false; + } + + if (mb_geom->use_deform == false) { + GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]); + GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]); + break; + } + else { + /* Modify the batch to include the previous & next position. */ + if (i == MB_PREV) { + GPU_batch_vertbuf_add_ex(batch, vbo, true); + mb_geom->vbo[i] = NULL; + } + else { + /* This VBO can be reuse by next time step. Don't pass ownership. */ + GPU_batch_vertbuf_add_ex(batch, vbo, false); + } + } + } } - /* 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[i] = NULL; } - } + else { + GPUVertBuf *vbo = mb_geom->vbo[mb_step]; + /* If this assert fails, it means that different EEVEE_GeometryMotionDatas + * has been used for each motion blur step. */ + BLI_assert(vbo); + if (vbo) { + /* 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, (mb_step == MB_PREV) ? "prv" : "nxt"); + } + } + break; + + default: + BLI_assert(0); + break; } - else { - GPUVertBuf *vbo = mb_geom->vbo[mb_step]; - /* If this assert fails, it means that different EEVEE_GeometryMotionDatas - * has been used for each motion blur step. */ - BLI_assert(vbo); - if (vbo) { - /* 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, (mb_step == MB_PREV) ? "prv" : "nxt"); - } + } +} + +void EEVEE_motion_blur_swap_data(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + GHashIterator ghi; + + BLI_assert((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0); + + /* Camera Data. */ + effects->motion_blur.camera[MB_PREV] = effects->motion_blur.camera[MB_CURR]; + + /* Object Data. */ + for (BLI_ghashIterator_init(&ghi, effects->motion_blur.object); + BLI_ghashIterator_done(&ghi) == false; + BLI_ghashIterator_step(&ghi)) { + EEVEE_ObjectMotionData *mb_data = BLI_ghashIterator_getValue(&ghi); + + copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_NEXT]); + } + + /* Deformation Data. */ + 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); + + switch (mb_geom->type) { + case EEVEE_HAIR_GEOM_MOTION_DATA: + GPU_VERTBUF_DISCARD_SAFE(mb_geom->hair_pos[MB_PREV]); + DRW_TEXTURE_FREE_SAFE(mb_geom->hair_pos_tx[MB_PREV]); + mb_geom->hair_pos[MB_PREV] = mb_geom->hair_pos[MB_NEXT]; + mb_geom->hair_pos_tx[MB_PREV] = mb_geom->hair_pos_tx[MB_NEXT]; + break; + + case EEVEE_MESH_GEOM_MOTION_DATA: + GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]); + mb_geom->vbo[MB_PREV] = mb_geom->vbo[MB_NEXT]; + + if (mb_geom->vbo[MB_NEXT]) { + GPUVertBuf *vbo = mb_geom->vbo[MB_NEXT]; + int attrib_id = GPU_vertformat_attr_id_get(&vbo->format, "nxt"); + GPU_vertformat_attr_rename(&vbo->format, attrib_id, "prv"); + } + break; + + default: + BLI_assert(0); + break; } } } @@ -381,12 +568,6 @@ void EEVEE_motion_blur_draw(EEVEE_Data *vedata) /* Motion Blur */ if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) { - int sample = DRW_state_is_image_render() ? effects->taa_render_sample : - effects->taa_current_sample; - double r; - BLI_halton_1d(2, 0.0, sample - 1, &r); - effects->motion_blur_sample_offset = r; - /* Create velocity max tiles in 2 passes. One for each dimension. */ GPU_framebuffer_bind(fbl->velocity_tiles_fb[0]); DRW_draw_pass(psl->velocity_tiles_x); @@ -421,6 +602,7 @@ void EEVEE_motion_blur_free(void) { DRW_SHADER_FREE_SAFE(e_data.motion_blur_sh); DRW_SHADER_FREE_SAFE(e_data.motion_blur_object_sh); + DRW_SHADER_FREE_SAFE(e_data.motion_blur_hair_sh); DRW_SHADER_FREE_SAFE(e_data.velocity_tiles_sh); DRW_SHADER_FREE_SAFE(e_data.velocity_tiles_expand_sh); } |