diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2018-06-25 10:06:39 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2018-06-26 17:35:47 +0300 |
commit | cf8a0597693de8fbf3dccf607d81e6e1f2c0d2aa (patch) | |
tree | eea2c1b0fbe0313d196e41ace1cd42b9ade50469 /source/blender/draw | |
parent | c07f2bc89196ea449a2875634eb85efa45733fb5 (diff) |
Workbench: Tempural Anti Aliasing
- FXAA is now also done in the workbench_forward engine.
- User can enable TAA8 in the userpref by setting their max
viewport AA to TAA8. FXAA will still be used when navigating
Diffstat (limited to 'source/blender/draw')
9 files changed, 433 insertions, 41 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 2f268663186..a68ccc0da93 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -111,6 +111,8 @@ set(SRC engines/workbench/workbench_data.c engines/workbench/workbench_engine.c engines/workbench/workbench_deferred.c + engines/workbench/workbench_effect_fxaa.c + engines/workbench/workbench_effect_taa.c engines/workbench/workbench_forward.c engines/workbench/workbench_materials.c engines/workbench/workbench_studiolight.c @@ -209,6 +211,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_common_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_data_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_effect_fxaa_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_effect_taa_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_composite_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_depth_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl SRC) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl new file mode 100644 index 00000000000..d962ffedf1f --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl @@ -0,0 +1,15 @@ +uniform sampler2D historyBuffer; +uniform sampler2D colorBuffer; + +out vec4 colorOutput; + +uniform float mixFactor; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + + vec4 history_buffer = texelFetch(historyBuffer, texel, 0); + vec4 color_buffer = texelFetch(colorBuffer, texel, 0); + colorOutput = mix(history_buffer, color_buffer, mixFactor); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/workbench/solid_mode.c b/source/blender/draw/engines/workbench/solid_mode.c index 1e49d1ae573..a3a42e10c8e 100644 --- a/source/blender/draw/engines/workbench/solid_mode.c +++ b/source/blender/draw/engines/workbench/solid_mode.c @@ -76,6 +76,12 @@ static void workbench_solid_engine_free(void) workbench_deferred_engine_free(); } +static void workbench_solid_view_update(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_taa_view_updated(data); +} + static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data); DrawEngineType draw_engine_workbench_solid = { @@ -89,7 +95,7 @@ DrawEngineType draw_engine_workbench_solid = { &workbench_solid_cache_finish, &workbench_solid_draw_background, &workbench_solid_draw_scene, - NULL, + &workbench_solid_view_update, NULL, NULL, }; diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index d544e7614ab..a72f3a673b5 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -5,6 +5,12 @@ #include "UI_resources.h" +void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info) +{ + effect_info->jitter_index = 0; + effect_info->view_updated = true; +} + void workbench_private_data_init(WORKBENCH_PrivateData *wpd) { const DRWContextState *draw_ctx = DRW_context_state_get(); diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 4fe3e92f10c..96ed345ed45 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -65,7 +65,6 @@ static struct { struct GPUShader *shadow_pass_manifold_sh; struct GPUShader *shadow_caps_sh; struct GPUShader *shadow_caps_manifold_sh; - struct GPUShader *effect_fxaa_sh; struct GPUTexture *object_id_tx; /* ref only, not alloced */ struct GPUTexture *color_buffer_tx; /* ref only, not alloced */ @@ -85,8 +84,6 @@ static struct { } e_data = {{NULL}}; /* Shaders */ -extern char datatoc_common_fxaa_lib_glsl[]; -extern char datatoc_common_fullscreen_vert_glsl[]; extern char datatoc_common_hair_lib_glsl[]; extern char datatoc_workbench_prepass_vert_glsl[]; @@ -103,7 +100,6 @@ extern char datatoc_workbench_background_lib_glsl[]; extern char datatoc_workbench_cavity_lib_glsl[]; extern char datatoc_workbench_common_lib_glsl[]; extern char datatoc_workbench_data_lib_glsl[]; -extern char datatoc_workbench_effect_fxaa_frag_glsl[]; extern char datatoc_workbench_object_outline_lib_glsl[]; extern char datatoc_workbench_world_light_lib_glsl[]; @@ -219,7 +215,7 @@ static void select_deferred_shaders(WORKBENCH_PrivateData *wpd) static float *create_disk_samples(int num_samples) { /* vec4 to ensure memory alignment. */ - float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * num_samples, "concentric_tex"); + float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * num_samples, __func__); const float num_samples_inv = 1.0f / num_samples; for (int i = 0; i < num_samples; i++) { @@ -272,9 +268,19 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) { WORKBENCH_FramebufferList *fbl = vedata->fbl; WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_TextureList *txl = vedata->txl; WORKBENCH_PassList *psl = vedata->psl; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + if (!stl->effects) { + stl->effects = MEM_mallocN(sizeof(*stl->effects), __func__); + workbench_effect_info_init(stl->effects); + } + if (!e_data.next_object_id) { memset(e_data.prepass_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); @@ -322,17 +328,10 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) e_data.cavity_sh = DRW_shader_create_fullscreen(cavity_frag, NULL); MEM_freeN(cavity_frag); - e_data.effect_fxaa_sh = DRW_shader_create_with_lib( - datatoc_common_fullscreen_vert_glsl, NULL, - datatoc_workbench_effect_fxaa_frag_glsl, - datatoc_common_fxaa_lib_glsl, - NULL); } + workbench_fxaa_engine_init(); + workbench_taa_engine_init(vedata); - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } WORKBENCH_PrivateData *wpd = stl->g_data; workbench_private_data_init(wpd); @@ -424,15 +423,20 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) } { - psl->effect_fxaa_pass = DRW_pass_create("Effect FXAA", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_fxaa_sh, psl->effect_fxaa_pass); - DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.effect_buffer_tx); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + if (TAA_ENABLED(wpd)) { + psl->effect_aa_pass = workbench_taa_create_pass(txl, stl->effects, fbl, &e_data.composite_buffer_tx); + } + else if (FXAA_ENABLED(wpd)) { + psl->effect_aa_pass = workbench_fxaa_create_pass(&e_data.effect_buffer_tx); + stl->effects->jitter_index = 0; + } + else { + psl->effect_aa_pass = NULL; + } } } -void workbench_deferred_engine_free() +void workbench_deferred_engine_free(void) { for (int index = 0; index < MAX_SHADERS; index++) { DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[index]); @@ -449,7 +453,8 @@ void workbench_deferred_engine_free() DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh); DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_fxaa_sh); + workbench_fxaa_engine_free(); + workbench_taa_engine_free(); } static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp) @@ -834,7 +839,14 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_FramebufferList *fbl = vedata->fbl; WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_EffectInfo *effect_info = stl->effects; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + const bool taa_enabled = TAA_ENABLED(wpd); + + if (taa_enabled) + { + workbench_taa_draw_scene_start(effect_info); + } /* clear in background */ GPU_framebuffer_bind(fbl->prepass_fb); @@ -870,21 +882,14 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) DRW_draw_pass(psl->composite_pass); } - if (FXAA_ENABLED(wpd)) { - GPU_framebuffer_bind(fbl->effect_fb); - DRW_transform_to_display(e_data.composite_buffer_tx); - - /* TODO: when rendering the fxaa pass should be done in display space - Currently we do not support rendering in the workbench - */ - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->effect_fxaa_pass); - } - else { - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_transform_to_display(e_data.composite_buffer_tx); + GPUTexture *final_color_tx = e_data.composite_buffer_tx; + if (taa_enabled) + { + workbench_taa_draw_pass(effect_info, psl->effect_aa_pass); + final_color_tx = effect_info->final_color_tx; + workbench_taa_draw_scene_end(vedata); } - + workbench_fxaa_draw_pass(wpd, fbl->effect_fb, final_color_tx, psl->effect_aa_pass); workbench_private_data_free(wpd); } diff --git a/source/blender/draw/engines/workbench/workbench_effect_fxaa.c b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c new file mode 100644 index 00000000000..2746a4f14f8 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c @@ -0,0 +1,80 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_effect_fxaa.c + * \ingroup draw_engine + */ +#include "workbench_private.h" + +/* *********** STATIC *********** */ +static struct { + struct GPUShader *effect_fxaa_sh; +} e_data = {NULL}; + +/* Shaders */ +extern char datatoc_common_fxaa_lib_glsl[]; +extern char datatoc_common_fullscreen_vert_glsl[]; +extern char datatoc_workbench_effect_fxaa_frag_glsl[]; + +/* *********** Functions *********** */ +void workbench_fxaa_engine_init(void) +{ + if (e_data.effect_fxaa_sh == NULL) + { + e_data.effect_fxaa_sh = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, NULL, + datatoc_workbench_effect_fxaa_frag_glsl, + datatoc_common_fxaa_lib_glsl, + NULL); + } +} + +DRWPass *workbench_fxaa_create_pass(GPUTexture **color_buffer_tx) +{ + DRWPass *pass = DRW_pass_create("Effect FXAA", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_fxaa_sh, pass); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + return pass; +} + +void workbench_fxaa_draw_pass(WORKBENCH_PrivateData *wpd, GPUFrameBuffer *fb, GPUTexture *tx, DRWPass *effect_aa_pass) +{ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + if (FXAA_ENABLED(wpd)) { + GPU_framebuffer_bind(fb); + DRW_transform_to_display(tx); + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(effect_aa_pass); + } + else { + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_transform_to_display(tx); + } + +} + +void workbench_fxaa_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.effect_fxaa_sh); +} + diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c new file mode 100644 index 00000000000..deebac05096 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c @@ -0,0 +1,207 @@ + +#include "workbench_private.h" + +static struct { + struct GPUShader *effect_taa_sh; + +} e_data = {NULL}; + +extern char datatoc_workbench_effect_taa_frag_glsl[]; + +/* + * Sub-sample positions for TAA8 + * first sample needs to be at 0.0f, 0.0f + * as that sample depicts the z-buffer + */ +static const float SAMPLE_LOCS_8[8][2] = { + { 0.125f-0.125f, 0.375f-0.375f}, + {-0.625f-0.125f, -0.625f-0.375f}, + { 0.875f-0.125f, 0.875f-0.375f}, + {-0.875f-0.125f, 0.125f-0.375f}, + { 0.625f-0.125f, -0.125f-0.375f}, + {-0.375f-0.125f, 0.625f-0.375f}, + { 0.375f-0.125f, -0.875f-0.375f}, + {-0.125f-0.125f, -0.375f-0.375f}, +}; + +void workbench_taa_engine_init(WORKBENCH_Data *vedata) +{ + WORKBENCH_EffectInfo *effect_info = vedata->stl->effects; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + + if (e_data.effect_taa_sh == NULL) + { + e_data.effect_taa_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_taa_frag_glsl, NULL); + } + + /* reset complete drawing when navigating. */ + if (effect_info->jitter_index != 0) + { + if (rv3d && rv3d->rflag & RV3D_NAVIGATING) + { + effect_info->jitter_index = 0; + } + } + + if (effect_info->view_updated) + { + effect_info->jitter_index = 0; + effect_info->view_updated = false; + } + + { + float view[4][4]; + float win[4][4]; + DRW_viewport_matrix_get(view, DRW_MAT_VIEW); + DRW_viewport_matrix_get(win, DRW_MAT_WIN); + mul_m4_m4m4(effect_info->curr_mat, view, win); + if(!equals_m4m4(effect_info->curr_mat, effect_info->last_mat)){ + effect_info->jitter_index = 0; + } + } +} + +void workbench_taa_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.effect_taa_sh); +} + + +DRWPass *workbench_taa_create_pass(WORKBENCH_TextureList *txl, WORKBENCH_EffectInfo *effect_info, WORKBENCH_FramebufferList *fbl, GPUTexture **color_buffer_tx) +{ + /* + * jitter_index is not updated yet. This will be done in during draw phase. + * so for now it is inversed. + */ + int previous_jitter_index = effect_info->jitter_index; + bool previous_jitter_even = (previous_jitter_index & 1) == 0; + + { + DRW_texture_ensure_fullscreen_2D(&txl->history_buffer1_tx, GPU_RGBA16F, 0); + DRW_texture_ensure_fullscreen_2D(&txl->history_buffer2_tx, GPU_RGBA16F, 0); + DRW_texture_ensure_fullscreen_2D(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0); + } + + { + GPU_framebuffer_ensure_config(&fbl->effect_taa_even_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->history_buffer1_tx), + }); + GPU_framebuffer_ensure_config(&fbl->effect_taa_uneven_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->history_buffer2_tx), + }); + GPU_framebuffer_ensure_config(&fbl->depth_buffer_fb, { + GPU_ATTACHMENT_TEXTURE(txl->depth_buffer_tx), + }); + } + + + DRWPass *pass = DRW_pass_create("Effect TAA", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_taa_sh, pass); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); + if (previous_jitter_even) { + DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->history_buffer2_tx); + } + else { + DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->history_buffer1_tx); + } + + DRW_shgroup_uniform_float(grp, "mixFactor", &effect_info->taa_mix_factor, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + + if (previous_jitter_even) + { + effect_info->final_color_tx = txl->history_buffer1_tx; + effect_info->final_color_fb = fbl->effect_taa_even_fb; + } + else { + effect_info->final_color_tx = txl->history_buffer2_tx; + effect_info->final_color_fb = fbl->effect_taa_uneven_fb; + } + return pass; +} + +void workbench_taa_draw_scene_start(WORKBENCH_EffectInfo *effect_info) +{ + const float *viewport_size = DRW_viewport_size_get(); + const int samples = 8; + float mix_factor; + + mix_factor = 1.0f / (effect_info->jitter_index + 1); + + const int bitmask = samples - 1; + const int jitter_index = effect_info->jitter_index; + const float *transform_offset = SAMPLE_LOCS_8[jitter_index]; + effect_info->jitter_index = (jitter_index + 1) & bitmask; + + /* construct new matrices from transform delta */ + float viewmat[4][4]; + float persmat[4][4]; + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_get(effect_info->override_winmat, DRW_MAT_WIN); + + window_translate_m4( + effect_info->override_winmat, persmat, + transform_offset[0] / viewport_size[0], + transform_offset[1] / viewport_size[1]); + + mul_m4_m4m4(effect_info->override_persmat, effect_info->override_winmat, viewmat); + invert_m4_m4(effect_info->override_persinv, effect_info->override_persmat); + invert_m4_m4(effect_info->override_wininv, effect_info->override_winmat); + + DRW_viewport_matrix_override_set(effect_info->override_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(effect_info->override_persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(effect_info->override_winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(effect_info->override_wininv, DRW_MAT_WININV); + + /* weight the mix factor by the jitter index */ + effect_info->taa_mix_factor = mix_factor; +} + +void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata) +{ + /* + * If first frame than the offset is 0.0 and its depth is the depth buffer to use + * for the rest of the draw engines. We store it in a persistent buffer. + * + * If it is not the first frame we copy the persistent buffer back to the + * default depth buffer + */ + const WORKBENCH_StorageList *stl = vedata->stl; + const WORKBENCH_EffectInfo *effect_info = stl->effects; + const WORKBENCH_FramebufferList *fbl = vedata->fbl; + const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + if (effect_info->jitter_index == 1) + { + GPU_framebuffer_blit(dfbl->depth_only_fb, 0, fbl->depth_buffer_fb, 0, GPU_DEPTH_BIT); + } + else { + GPU_framebuffer_blit(fbl->depth_buffer_fb, 0, dfbl->depth_only_fb, 0, GPU_DEPTH_BIT); + } + + + + DRW_viewport_matrix_override_unset_all(); +} + +void workbench_taa_draw_pass(WORKBENCH_EffectInfo *effect_info, DRWPass *pass) +{ + GPU_framebuffer_bind(effect_info->final_color_fb); + DRW_draw_pass(pass); + + copy_m4_m4(effect_info->last_mat, effect_info->curr_mat); + if (effect_info->jitter_index != 0) + { + DRW_viewport_request_redraw(); + } +} + +void workbench_taa_view_updated(WORKBENCH_Data *vedata) +{ + WORKBENCH_EffectInfo *effect_info = vedata->stl->effects; + effect_info->view_updated = true; +} diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 9f23cd5b43b..dd57bec05f6 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -58,12 +58,15 @@ static struct { struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *effect_buffer_tx; /* ref only, not alloced */ + int next_object_id; float normal_world_matrix[3][3]; } e_data = {{NULL}}; /* Shaders */ extern char datatoc_common_hair_lib_glsl[]; + extern char datatoc_workbench_forward_composite_frag_glsl[]; extern char datatoc_workbench_forward_depth_frag_glsl[]; extern char datatoc_workbench_forward_transparent_accum_frag_glsl[]; @@ -259,6 +262,10 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) /* Alloc transient pointers */ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); } + if (!stl->effects) { + stl->effects = MEM_mallocN(sizeof(*stl->effects), __func__); + workbench_effect_info_init(stl->effects); + } WORKBENCH_PrivateData *wpd = stl->g_data; workbench_private_data_init(wpd); float light_direction[3]; @@ -280,6 +287,8 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) forward_vert, NULL, forward_depth_frag, defines_hair); + workbench_fxaa_engine_init(); + e_data.checker_depth_sh = DRW_shader_create_fullscreen( datatoc_workbench_checkerboard_depth_frag_glsl, NULL); MEM_freeN(forward_vert); @@ -300,6 +309,8 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent); e_data.composite_buffer_tx = DRW_texture_pool_query_2D( size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_workbench_transparent); + e_data.effect_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); GPU_framebuffer_ensure_config(&fbl->object_outline_fb, { GPU_ATTACHMENT_TEXTURE(dtxl->depth), @@ -316,6 +327,10 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), }); + GPU_framebuffer_ensure_config(&fbl->effect_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.effect_buffer_tx), + }); /* Transparency Accum */ { @@ -342,6 +357,11 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } + + { + psl->effect_aa_pass = workbench_fxaa_create_pass(&e_data.effect_buffer_tx); + } + /* Checker Depth */ { int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS; @@ -361,6 +381,8 @@ void workbench_forward_engine_free() DRW_SHADER_FREE_SAFE(e_data.object_outline_sh); DRW_SHADER_FREE_SAFE(e_data.object_outline_hair_sh); DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh); + + workbench_fxaa_engine_free(); } void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata)) @@ -585,9 +607,9 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata) DRW_draw_pass(psl->composite_pass); /* Color correct */ - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_transform_to_display(e_data.composite_buffer_tx); + workbench_fxaa_draw_pass(wpd, fbl->effect_fb, e_data.composite_buffer_tx, psl->effect_aa_pass); + /* Apply checker pattern */ GPU_framebuffer_bind(dfbl->depth_only_fb); DRW_draw_pass(psl->checker_depth_pass); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 57cfd6b4718..404ec50fd97 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -50,7 +50,12 @@ #define STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd) (MATCAP_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL)) #define CAVITY_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_CAVITY) #define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW) -#define FXAA_ENABLED(wpd) (wpd->user_preferences->gpu_viewport_antialias & USER_AA_FXAA && (!DRW_state_is_opengl_render())) + +#define IS_NAVIGATING(wpd) (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING) +#define FXAA_ENABLED(wpd) ((!DRW_state_is_opengl_render()) && ((wpd->user_preferences->gpu_viewport_antialias == USER_AA_FXAA) || (ELEM(wpd->user_preferences->gpu_viewport_antialias, USER_AA_TAA8) && IS_NAVIGATING(wpd)))) +#define TAA8_ENABLED(wpd) (ELEM(wpd->user_preferences->gpu_viewport_antialias, USER_AA_TAA8) && (!DRW_state_is_opengl_render()) && (!IS_NAVIGATING(wpd))) +#define TAA_ENABLED(wpd) (TAA8_ENABLED(wpd)) + #define SPECULAR_HIGHLIGHT_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd))) #define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) #define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd)) @@ -64,7 +69,11 @@ typedef struct WORKBENCH_FramebufferList { struct GPUFrameBuffer *prepass_fb; struct GPUFrameBuffer *cavity_fb; struct GPUFrameBuffer *composite_fb; + struct GPUFrameBuffer *effect_fb; + struct GPUFrameBuffer *effect_taa_even_fb; + struct GPUFrameBuffer *effect_taa_uneven_fb; + struct GPUFrameBuffer *depth_buffer_fb; /* Forward render buffers */ struct GPUFrameBuffer *object_outline_fb; @@ -72,8 +81,15 @@ typedef struct WORKBENCH_FramebufferList { struct GPUFrameBuffer *transparent_revealage_fb; } WORKBENCH_FramebufferList; +typedef struct WORKBENCH_TextureList { + struct GPUTexture *history_buffer1_tx; + struct GPUTexture *history_buffer2_tx; + struct GPUTexture *depth_buffer_tx; +} WORKBENCH_TextureList; + typedef struct WORKBENCH_StorageList { struct WORKBENCH_PrivateData *g_data; + struct WORKBENCH_EffectInfo *effects; } WORKBENCH_StorageList; typedef struct WORKBENCH_PassList { @@ -89,7 +105,7 @@ typedef struct WORKBENCH_PassList { struct DRWPass *shadow_depth_fail_caps_mani_pass; struct DRWPass *composite_pass; struct DRWPass *composite_shadow_pass; - struct DRWPass *effect_fxaa_pass; + struct DRWPass *effect_aa_pass; /* forward rendering */ struct DRWPass *transparent_accum_pass; @@ -101,7 +117,7 @@ typedef struct WORKBENCH_PassList { typedef struct WORKBENCH_Data { void *engine_type; WORKBENCH_FramebufferList *fbl; - DRWViewportEmptyList *txl; + WORKBENCH_TextureList *txl; WORKBENCH_PassList *psl; WORKBENCH_StorageList *stl; } WORKBENCH_Data; @@ -171,6 +187,22 @@ typedef struct WORKBENCH_PrivateData { float ssao_settings[4]; } WORKBENCH_PrivateData; /* Transient data */ +typedef struct WORKBENCH_EffectInfo { + float override_persmat[4][4]; + float override_persinv[4][4]; + float override_winmat[4][4]; + float override_wininv[4][4]; + float last_mat[4][4]; + float curr_mat[4][4]; + int jitter_index; + float taa_mix_factor; + bool view_updated; + + /* The TX that holds the last color data */ + struct GPUTexture *final_color_tx; + struct GPUFrameBuffer *final_color_fb; +} WORKBENCH_EffectInfo; + typedef struct WORKBENCH_MaterialData { /* Solid color */ WORKBENCH_UBO_Material material_data; @@ -228,6 +260,21 @@ void workbench_forward_cache_init(WORKBENCH_Data *vedata); void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob); void workbench_forward_cache_finish(WORKBENCH_Data *vedata); +/* workbench_effect_fxaa.c */ +void workbench_fxaa_engine_init(void); +void workbench_fxaa_engine_free(void); +DRWPass *workbench_fxaa_create_pass(GPUTexture **color_buffer_tx); +void workbench_fxaa_draw_pass(WORKBENCH_PrivateData *wpd, GPUFrameBuffer *fb, GPUTexture *tx, DRWPass *effect_aa_pass); + +/* workbench_effect_taa.c */ +void workbench_taa_engine_init(WORKBENCH_Data *vedata); +void workbench_taa_engine_free(void); +DRWPass *workbench_taa_create_pass(WORKBENCH_TextureList *txl, WORKBENCH_EffectInfo *effect_info, WORKBENCH_FramebufferList *fbl, GPUTexture **color_buffer_tx); +void workbench_taa_draw_pass(WORKBENCH_EffectInfo *effect_info, /*WORKBENCH_PrivateData *wpd, , GPUFrameBuffer *fb, GPUTexture *tx, */DRWPass *effect_aa_pass); +void workbench_taa_draw_scene_start(WORKBENCH_EffectInfo *effect_info); +void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata); +void workbench_taa_view_updated(WORKBENCH_Data *vedata); + /* workbench_materials.c */ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima); char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); @@ -245,6 +292,7 @@ float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); /* workbench_data.c */ +void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info); void workbench_private_data_init(WORKBENCH_PrivateData *wpd); void workbench_private_data_free(WORKBENCH_PrivateData *wpd); void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float light_direction[3]); |