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.
This commit is contained in:
Clément Foucault 2018-04-20 18:18:33 +02:00
parent 358dfe6ac9
commit e2613e4051
5 changed files with 102 additions and 5 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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];

View File

@ -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;
}