From e2613e4051d501c8b553d781cb63d06735968f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 20 Apr 2018 18:18:33 +0200 Subject: Eevee: Add Velocity pass. This pass create a velocity buffer which is basically a 2D motion vector texture. This is not yet used for rendering but will be usefull for motion blur and temporal reprojection. --- source/blender/draw/CMakeLists.txt | 1 + source/blender/draw/engines/eevee/eevee_effects.c | 77 ++++++++++++++++++++-- source/blender/draw/engines/eevee/eevee_engine.c | 3 + source/blender/draw/engines/eevee/eevee_private.h | 7 ++ .../shaders/effect_velocity_resolve_frag.glsl | 19 ++++++ 5 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index d8143fef771..22106c55bda 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -174,6 +174,7 @@ data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_velocity_resolve_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_mist_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC) diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 719ff879e8e..14924345d3e 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -27,6 +27,10 @@ #include "DRW_render.h" +#include "BKE_global.h" /* for G.debug_value */ + +#include "BLI_string_utils.h" + #include "eevee_private.h" #include "GPU_texture.h" #include "GPU_extensions.h" @@ -46,6 +50,9 @@ static struct { struct GPUShader *downsample_sh; struct GPUShader *downsample_cube_sh; + /* Velocity Resolve */ + struct GPUShader *velocity_resolve_sh; + /* Theses are just references, not actually allocated */ struct GPUTexture *depth_src; struct GPUTexture *color_src; @@ -54,6 +61,10 @@ static struct { float cube_texel_size; } e_data = {NULL}; /* Engine data */ +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_effect_velocity_resolve_frag_glsl[]; extern char datatoc_effect_minmaxz_frag_glsl[]; extern char datatoc_effect_downsample_frag_glsl[]; extern char datatoc_effect_downsample_cube_frag_glsl[]; @@ -62,6 +73,16 @@ extern char datatoc_lightprobe_geom_glsl[]; static void eevee_create_shader_downsample(void) { + char *frag_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_effect_velocity_resolve_frag_glsl); + + e_data.velocity_resolve_sh = DRW_shader_create_fullscreen(frag_str, NULL); + + MEM_freeN(frag_str); + e_data.downsample_sh = DRW_shader_create_fullscreen(datatoc_effect_downsample_frag_glsl, NULL); e_data.downsample_cube_sh = DRW_shader_create( datatoc_lightprobe_vert_glsl, @@ -110,6 +131,8 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object ViewLayer *view_layer = draw_ctx->view_layer; const float *viewport_size = DRW_viewport_size_get(); + int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + /* Shaders */ if (!e_data.downsample_sh) { eevee_create_shader_downsample(); @@ -122,6 +145,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object effects = stl->effects; 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_bloom_init(sldata, vedata); effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera); @@ -163,9 +187,9 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object /** * MinMax Pyramid */ - int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - size[0] = max_ii(size[0] / 2, 1); - size[1] = max_ii(size[1] / 2, 1); + int size[2]; + size[0] = max_ii(size_fs[0] / 2, 1); + size[1] = max_ii(size_fs[1] / 2, 1); if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { /* Intel gpu seems to have problem rendering to only depth format */ @@ -197,8 +221,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object * Normal buffer for deferred passes. */ if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) { - int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - effects->ssr_normal_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], DRW_TEX_RG_16, &draw_engine_eevee_type); @@ -208,6 +230,26 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object effects->ssr_normal_input = NULL; } + /** + * Motion vector buffer for correct TAA / motion blur. + */ + if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { + /* TODO use RG16_UNORM */ + effects->velocity_tx = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], DRW_TEX_RG_32, + &draw_engine_eevee_type); + + /* TODO output objects velocity during the mainpass. */ + // GPU_framebuffer_texture_attach(fbl->main_fb, effects->velocity_tx, 1, 0); + + GPU_framebuffer_ensure_config(&fbl->velocity_resolve_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->velocity_tx) + }); + } + else { + effects->velocity_tx = NULL; + } + /** * Setup double buffer so we can access last frame as it was before post processes. */ @@ -235,6 +277,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; int downsample_write = DRW_STATE_WRITE_DEPTH; /* Intel gpu seems to have problem rendering to only depth format. @@ -291,6 +335,17 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); } + + if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { + /* This pass compute camera motions to the non moving objects. */ + psl->velocity_resolve = DRW_pass_create("Velocity Resolve", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.velocity_resolve_sh, psl->velocity_resolve); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv); + DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat); + DRW_shgroup_call_add(grp, quad, NULL); + } } #if 0 /* Not required for now */ @@ -401,11 +456,21 @@ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, i void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) { + EEVEE_PassList *psl = vedata->psl; EEVEE_TextureList *txl = vedata->txl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; + /* First resolve the velocity. */ + if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { + DRW_viewport_matrix_get(effects->velocity_curr_persinv, DRW_MAT_PERSINV); + + GPU_framebuffer_bind(fbl->velocity_resolve_fb); + DRW_draw_pass(psl->velocity_resolve); + } + DRW_viewport_matrix_get(effects->velocity_past_persmat, DRW_MAT_PERS); + /* only once per frame after the first post process */ effects->swap_double_buffer = ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0); @@ -448,6 +513,8 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) void EEVEE_effects_free(void) { + DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.downsample_sh); DRW_SHADER_FREE_SAFE(e_data.downsample_cube_sh); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 276f23c7cf7..3dd7d98842b 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -333,6 +333,9 @@ static void eevee_draw_background(void *vedata) case 8: if (effects->sss_data) DRW_transform_to_display(effects->sss_data); break; + case 9: + if (effects->velocity_tx) DRW_transform_to_display(effects->velocity_tx); + break; default: break; } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index f0ba458dcc8..07624100ea7 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -184,6 +184,7 @@ typedef struct EEVEE_PassList { struct DRWPass *sss_accum_ps; struct DRWPass *color_downsample_ps; struct DRWPass *color_downsample_cube_ps; + struct DRWPass *velocity_resolve; struct DRWPass *taa_resolve; /* HiZ */ @@ -235,6 +236,7 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *refract_fb; struct GPUFrameBuffer *mist_accum_fb; struct GPUFrameBuffer *ao_accum_fb; + struct GPUFrameBuffer *velocity_resolve_fb; struct GPUFrameBuffer *update_noise_fb; @@ -480,6 +482,7 @@ typedef enum EEVEE_EffectsFlag { EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */ EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */ EFFECT_SSS = (1 << 11), + EFFECT_VELOCITY_BUFFER = (1 << 12), /* Not really an effect but a feature */ } EEVEE_EffectsFlag; typedef struct EEVEE_EffectsInfo { @@ -522,6 +525,10 @@ typedef struct EEVEE_EffectsInfo { float current_ndc_to_world[4][4]; float past_world_to_ndc[4][4]; int motion_blur_samples; + /* Velocity Pass */ + float velocity_curr_persinv[4][4]; + float velocity_past_persmat[4][4]; + struct GPUTexture *velocity_tx; /* Texture from pool */ /* Depth Of Field */ float dof_near_far[2]; float dof_params[3]; diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl new file mode 100644 index 00000000000..9c118277212 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl @@ -0,0 +1,19 @@ + +uniform mat4 currPersinv; +uniform mat4 pastPersmat; + +out vec2 outData; + +void main() +{ + /* Extract pixel motion vector from camera movement. */ + ivec2 texel = ivec2(gl_FragCoord.xy); + vec2 uv = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0).xy); + + float depth = texelFetch(depthBuffer, texel, 0).r; + + vec3 world_position = project_point(currPersinv, vec3(uv, depth) * 2.0 - 1.0); + vec2 uv_history = project_point(pastPersmat, world_position).xy * 0.5 + 0.5; + + outData = uv - uv_history; +} -- cgit v1.2.3