diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-03-03 18:45:26 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-03-03 19:35:30 +0300 |
commit | bd6567b262225e0eb5e392bc257c55e43a585ded (patch) | |
tree | ea0b2329e338ee5ccce6e2529d0554285bde03ff | |
parent | 91dfe40ef07a174d73cf06b497f1e35b9772bcf0 (diff) |
Workbench: Refactor: Antialiasingtmp-workbench-rewrite
11 files changed, 414 insertions, 61 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index a25dbcf4721..b48a5494782 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -260,6 +260,8 @@ data_to_c_simple(engines/workbench/shaders/workbench_effect_outline_frag.glsl SR data_to_c_simple(engines/workbench/shaders/workbench_effect_cavity_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_effect_dof_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_smaa_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_effect_smaa_vert.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) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl new file mode 100644 index 00000000000..95ca2c0c297 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl @@ -0,0 +1,14 @@ + +in vec4 uvcoordsvar; + +out vec4 FragColor; + +uniform sampler2D colorBuffer; +uniform vec2 invertedViewportSize; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + FragColor = FxaaPixelShader( + uvcoordsvar.st, colorBuffer, invertedViewportSize, 1.0, 0.166, 0.0833); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl new file mode 100644 index 00000000000..95ca2c0c297 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl @@ -0,0 +1,14 @@ + +in vec4 uvcoordsvar; + +out vec4 FragColor; + +uniform sampler2D colorBuffer; +uniform vec2 invertedViewportSize; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + FragColor = FxaaPixelShader( + uvcoordsvar.st, colorBuffer, invertedViewportSize, 1.0, 0.166, 0.0833); +} 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 index 5795268f794..b877c2c3f76 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl @@ -1,14 +1,11 @@ -uniform sampler2D historyBuffer; + uniform sampler2D colorBuffer; -out vec4 colorOutput; +in vec4 uvcoordsvar; -uniform float mixFactor; +out vec4 fragColor; void main() { - ivec2 texel = ivec2(gl_FragCoord.xy); - vec4 color_buffer = texelFetch(colorBuffer, texel, 0); - vec4 history_buffer = texelFetch(historyBuffer, texel, 0); - colorOutput = mix(history_buffer, color_buffer, mixFactor); + fragColor = texture(colorBuffer, uvcoordsvar.st); } diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index af65acddb53..d7b50a5c748 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -208,7 +208,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) wpd->sh_cfg = draw_ctx->sh_cfg; wpd->vldata = vldata; - wpd->taa_sample_len = workbench_taa_calculate_num_iterations(wpd); + wpd->taa_sample_len = workbench_aa_sample_count_get(wpd); wpd->world_ubo = vldata->world_ubo; diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index a0e03fd12cb..eb15460a9dd 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -577,7 +577,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) } { - workbench_aa_create_pass(vedata, &e_data.color_buffer_tx); + workbench_aa_cache_init(vedata); } { @@ -1375,7 +1375,7 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) } workbench_dof_draw_pass(vedata); - workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); + workbench_aa_draw_pass(vedata); } void workbench_deferred_draw_finish(WORKBENCH_Data *vedata) diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c index 482cb81917f..94deacf27d5 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_aa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright 2016, Blender Foundation. + * Copyright 2020, Blender Foundation. */ /** \file @@ -22,71 +22,318 @@ #include "ED_screen.h" -#include "draw_color_management.h" +#include "BLI_jitter_2d.h" + +#include "smaa_textures.h" #include "workbench_private.h" -void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx) +static struct { + bool init; + float jitter_5[5][2]; + float jitter_8[8][2]; + float jitter_11[11][2]; + float jitter_16[16][2]; + float jitter_32[32][2]; +} e_data = {false}; + +static void workbench_taa_jitter_init_order(float (*table)[2], int num) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_EffectInfo *effect_info = stl->effects; + BLI_jitter_init(table, num); + + /* find closest element to center */ + int closest_index = 0; + float closest_squared_distance = 1.0f; + + for (int index = 0; index < num; index++) { + const float squared_dist = SQUARE(table[index][0]) + SQUARE(table[index][1]); + if (squared_dist < closest_squared_distance) { + closest_squared_distance = squared_dist; + closest_index = index; + } + } + + /* move jitter table so that closest sample is in center */ + for (int index = 0; index < num; index++) { + sub_v2_v2(table[index], table[closest_index]); + mul_v2_fl(table[index], 2.0f); + } - if (workbench_is_taa_enabled(wpd)) { - psl->effect_aa_pass = workbench_taa_create_pass(vedata, tx); + /* swap center sample to the start of the table */ + if (closest_index != 0) { + swap_v2_v2(table[0], table[closest_index]); } - else if (workbench_is_fxaa_enabled(wpd)) { - psl->effect_aa_pass = workbench_fxaa_create_pass(tx); - effect_info->jitter_index = 0; + + /* sort list based on furtest distance with previous */ + for (int i = 0; i < num - 2; i++) { + float f_squared_dist = 0.0; + int f_index = i; + for (int j = i + 1; j < num; j++) { + const float squared_dist = SQUARE(table[i][0] - table[j][0]) + + SQUARE(table[i][1] - table[j][1]); + if (squared_dist > f_squared_dist) { + f_squared_dist = squared_dist; + f_index = j; + } + } + swap_v2_v2(table[i + 1], table[f_index]); + } +} + +static void workbench_taa_jitter_init(void) +{ + if (e_data.init == false) { + workbench_taa_jitter_init_order(e_data.jitter_5, 5); + workbench_taa_jitter_init_order(e_data.jitter_8, 8); + workbench_taa_jitter_init_order(e_data.jitter_11, 11); + workbench_taa_jitter_init_order(e_data.jitter_16, 16); + workbench_taa_jitter_init_order(e_data.jitter_32, 32); + } +} + +BLI_INLINE bool workbench_taa_enabled(WORKBENCH_PrivateData *wpd) +{ + if (DRW_state_is_image_render()) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (draw_ctx->v3d) { + return draw_ctx->scene->display.viewport_aa > SCE_DISPLAY_AA_FXAA; + } + else { + return draw_ctx->scene->display.render_aa > SCE_DISPLAY_AA_FXAA; + } + } + else { + return !(IS_NAVIGATING(wpd) || wpd->is_playback) && + wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA; + } +} + +int workbench_aa_sample_count_get(WORKBENCH_PrivateData *wpd) +{ + const Scene *scene = DRW_context_state_get()->scene; + if (workbench_taa_enabled(wpd)) { + if (DRW_state_is_image_render()) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (draw_ctx->v3d) { + return scene->display.viewport_aa; + } + else { + return scene->display.render_aa; + } + } + else { + return wpd->preferences->viewport_aa; + } + } + else { + /* when no TAA is disabled return 0 to render a single sample + * see `workbench_render.c` */ + return 0; + } +} + +void workbench_aa_engine_init(WORKBENCH_Data *vedata) +{ + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_TextureList *txl = vedata->txl; + WORKBENCH_PrivateData *wpd = vedata->stl->g_data; + DrawEngineType *owner = (DrawEngineType *)&workbench_aa_engine_init; + + if (wpd->taa_sample_len > 0) { + workbench_taa_jitter_init(); + + DRW_texture_ensure_fullscreen_2d(&txl->history_buffer_tx, GPU_RGBA16F, 0); + DRW_texture_ensure_fullscreen_2d(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0); + + wpd->smaa_edge_tx = DRW_texture_pool_query_fullscreen(GPU_RG8, owner); + wpd->smaa_weight_tx = DRW_texture_pool_query_fullscreen(GPU_RGBA8, owner); + + GPU_framebuffer_ensure_config(&fbl->antialiasing_fb, + { + GPU_ATTACHMENT_TEXTURE(txl->depth_buffer_tx), + GPU_ATTACHMENT_TEXTURE(txl->history_buffer_tx), + }); + + GPU_framebuffer_ensure_config(&fbl->smaa_edge_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->smaa_edge_tx), + }); + + GPU_framebuffer_ensure_config(&fbl->smaa_weight_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->smaa_weight_tx), + }); + + /* TODO could be shared for all viewports. */ + if (txl->smaa_search_tx == NULL) { + txl->smaa_search_tx = GPU_texture_create_nD(SEARCHTEX_WIDTH, + SEARCHTEX_HEIGHT, + 0, + 2, + searchTexBytes, + GPU_R8, + GPU_DATA_UNSIGNED_BYTE, + 0, + false, + NULL); + + txl->smaa_area_tx = GPU_texture_create_nD(AREATEX_WIDTH, + AREATEX_HEIGHT, + 0, + 2, + areaTexBytes, + GPU_RG8, + GPU_DATA_UNSIGNED_BYTE, + 0, + false, + NULL); + + GPU_texture_bind(txl->smaa_search_tx, 0); + GPU_texture_filter_mode(txl->smaa_search_tx, true); + GPU_texture_unbind(txl->smaa_search_tx); + + GPU_texture_bind(txl->smaa_area_tx, 0); + GPU_texture_filter_mode(txl->smaa_area_tx, true); + GPU_texture_unbind(txl->smaa_area_tx); + } } else { - psl->effect_aa_pass = NULL; - effect_info->jitter_index = 0; + /* Cleanup */ + DRW_TEXTURE_FREE_SAFE(txl->history_buffer_tx); + DRW_TEXTURE_FREE_SAFE(txl->depth_buffer_tx); + DRW_TEXTURE_FREE_SAFE(txl->smaa_search_tx); + DRW_TEXTURE_FREE_SAFE(txl->smaa_area_tx); } } -static void workspace_aa_draw_transform(GPUTexture *tx, WORKBENCH_PrivateData *UNUSED(wpd)) +void workbench_aa_cache_init(WORKBENCH_Data *vedata) { - DRW_transform_none(tx); + WORKBENCH_TextureList *txl = vedata->txl; + WORKBENCH_PrivateData *wpd = vedata->stl->g_data; + WORKBENCH_PassList *psl = vedata->psl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DRWShadingGroup *grp = NULL; + + if (wpd->taa_sample_len > 0) { + return; + } + + { + DRW_PASS_CREATE(psl->aa_accum_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL); + + GPUShader *shader = workbench_shader_antialiasing_accumulation_get(); + grp = DRW_shgroup_create(shader, psl->aa_accum_pass); + DRW_shgroup_uniform_texture(grp, "colorBuffer", dtxl->color); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } + + const float *size = DRW_viewport_size_get(); + const float *sizeinv = DRW_viewport_invert_size_get(); + float metrics[4] = {sizeinv[0], sizeinv[1], size[0], size[1]}; + + { + /* Stage 1: Edge detection. */ + DRW_PASS_CREATE(psl->aa_edge_pass, DRW_STATE_WRITE_COLOR); + + GPUShader *sh = workbench_shader_antialiasing_get(0); + grp = DRW_shgroup_create(sh, psl->aa_edge_pass); + DRW_shgroup_uniform_texture(grp, "colorTex", dtxl->color); + DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); + + DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } + { + /* Stage 2: Blend Weight/Coord. */ + DRW_PASS_CREATE(psl->aa_weight_pass, DRW_STATE_WRITE_COLOR); + + GPUShader *sh = workbench_shader_antialiasing_get(1); + grp = DRW_shgroup_create(sh, psl->aa_weight_pass); + DRW_shgroup_uniform_texture(grp, "edgesTex", wpd->smaa_edge_tx); + DRW_shgroup_uniform_texture(grp, "areaTex", txl->smaa_area_tx); + DRW_shgroup_uniform_texture(grp, "searchTex", txl->smaa_search_tx); + DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); + + DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } + { + /* Stage 3: Resolve. */ + DRW_PASS_CREATE(psl->aa_resolve_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM); + + GPUShader *sh = workbench_shader_antialiasing_get(2); + grp = DRW_shgroup_create(sh, psl->aa_resolve_pass); + DRW_shgroup_uniform_texture(grp, "blendTex", wpd->smaa_weight_tx); + DRW_shgroup_uniform_texture(grp, "colorTex", txl->history_buffer_tx); + DRW_shgroup_uniform_float(grp, "mixFactor", &wpd->smaa_mix_factor, 1); + DRW_shgroup_uniform_float_copy(grp, "invTaaSampleCount", wpd->taa_sample_inv); + DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); + + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } } -void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx) +void workbench_aa_draw_pass(WORKBENCH_Data *vedata) { WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_PrivateData *wpd = stl->g_data; WORKBENCH_FramebufferList *fbl = vedata->fbl; WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_EffectInfo *effect_info = stl->effects; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - if (workbench_is_fxaa_enabled(wpd)) { - GPU_framebuffer_bind(fbl->effect_fb); - workspace_aa_draw_transform(tx, wpd); - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->effect_aa_pass); - } - else if (workbench_is_taa_enabled(wpd)) { - /* - * when drawing the first TAA frame, we transform directly to the - * color_only_fb as the TAA shader is just performing a direct copy. - * the workbench_taa_draw_screen_end will fill the history buffer - * for the other iterations. - */ - if (effect_info->jitter_index == 1) { - GPU_framebuffer_bind(dfbl->color_only_fb); - workspace_aa_draw_transform(tx, wpd); - } - else { - GPU_framebuffer_bind(fbl->effect_fb); - workspace_aa_draw_transform(tx, wpd); - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->effect_aa_pass); - } - workbench_taa_draw_scene_end(vedata); + + if (wpd->taa_sample_len == 0) { + /* AA disabled. */ + return; } - else { - GPU_framebuffer_bind(dfbl->color_only_fb); - workspace_aa_draw_transform(tx, wpd); + + /* After a certain point SMAA is no longer necessary. */ + wpd->smaa_mix_factor = 1.0f - clamp_f(wpd->taa_sample / 4.0f, 0.0f, 1.0f); + wpd->taa_sample_inv = 1.0f / wpd->taa_sample; + + /** + * We always do SMAA on top of TAA accumulation, unless the number of samples of TAA is already + * high. This ensure a smoother transition. + * If TAA accumulation is finished, we only blit the result. + */ + + if (wpd->taa_sample == 1) { + /* In playback mode, we are sure the next redraw will not use the same viewmatrix. + * In this case no need to save the depth buffer. */ + eGPUFrameBufferBits bits = GPU_COLOR_BIT | (!wpd->is_playback ? GPU_DEPTH_BIT : 0); + GPU_framebuffer_blit(dfbl->default_fb, 0, fbl->antialiasing_fb, 0, bits); + } + else if (wpd->taa_sample < wpd->taa_sample_len) { + /* Accumulate result to the TAA buffer. */ + GPU_framebuffer_bind(fbl->antialiasing_fb); + DRW_draw_pass(psl->aa_accum_pass); + } + + if (wpd->taa_sample == wpd->taa_sample_len) { + /* TAA accumulation has finish. Just copy the result back */ + eGPUFrameBufferBits bits = GPU_COLOR_BIT | GPU_DEPTH_BIT; + GPU_framebuffer_blit(fbl->antialiasing_fb, 0, dfbl->default_fb, 0, bits); + return; + } + else if (wpd->taa_sample > 1) { + /* Copy back the saved depth buffer for correct overlays. */ + GPU_framebuffer_blit(fbl->antialiasing_fb, 0, dfbl->default_fb, 0, GPU_DEPTH_BIT); + } + + if (wpd->smaa_mix_factor > 0.0f) { + GPU_framebuffer_bind(fbl->smaa_edge_fb); + DRW_draw_pass(psl->aa_edge_pass); + + GPU_framebuffer_bind(fbl->smaa_weight_fb); + DRW_draw_pass(psl->aa_weight_pass); + } + + GPU_framebuffer_bind(dfbl->default_fb); + DRW_draw_pass(psl->aa_resolve_pass); + + if (!DRW_state_is_image_render() && wpd->taa_sample < wpd->taa_sample_len) { + DRW_viewport_request_redraw(); } } diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index cdb6c0e1423..6ea4c49d114 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -78,6 +78,7 @@ static void workbench_engine_init(void *ved) workbench_opaque_engine_init(vedata); workbench_transparent_engine_init(vedata); workbench_dof_engine_init(vedata); + workbench_aa_engine_init(vedata); // workbench_volume_engine_init(); // workbench_fxaa_engine_init(); // workbench_taa_engine_init(vedata); @@ -93,8 +94,9 @@ static void workbench_cache_init(void *ved) workbench_cavity_cache_init(vedata); workbench_outline_cache_init(vedata); workbench_dof_cache_init(vedata); + workbench_aa_cache_init(vedata); - // workbench_aa_create_pass(vedata); + // workbench_aa_cache_init(vedata); } /* TODO(fclem) DRW_cache_object_surface_material_get needs a refactor to allow passing NULL @@ -472,7 +474,7 @@ static void workbench_draw_scene(void *ved) workbench_dof_draw_pass(vedata); - /* TODO(fclem) antialias */ + workbench_aa_draw_pass(vedata); } static void workbench_engine_free(void) diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index d6afc4b35e7..64331ad6d58 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -428,7 +428,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) } { - workbench_aa_create_pass(vedata, &e_data.transparent_accum_tx); + workbench_aa_cache_init(vedata); } if (wpd->shading.type == OB_WIRE) { @@ -796,7 +796,7 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata) } /* Color correct and Anti aliasing */ - workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); + workbench_aa_draw_pass(vedata); } void workbench_forward_draw_finish(WORKBENCH_Data *vedata) diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 4016d0d58eb..ba82e63f465 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -118,6 +118,10 @@ typedef struct WORKBENCH_FramebufferList { struct GPUFrameBuffer *dof_blur1_fb; struct GPUFrameBuffer *dof_blur2_fb; + struct GPUFrameBuffer *antialiasing_fb; + struct GPUFrameBuffer *smaa_edge_fb; + struct GPUFrameBuffer *smaa_weight_fb; + /* Forward render buffers */ struct GPUFrameBuffer *object_outline_fb; struct GPUFrameBuffer *transparent_accum_fb; @@ -134,6 +138,8 @@ typedef struct WORKBENCH_TextureList { struct GPUTexture *history_buffer_tx; struct GPUTexture *depth_buffer_tx; struct GPUTexture *dummy_image_tx; + struct GPUTexture *smaa_search_tx; + struct GPUTexture *smaa_area_tx; } WORKBENCH_TextureList; typedef struct WORKBENCH_StorageList { @@ -179,6 +185,11 @@ typedef struct WORKBENCH_PassList { struct DRWPass *dof_resolve_ps; struct DRWPass *volume_pass; + struct DRWPass *aa_accum_pass; + struct DRWPass *aa_edge_pass; + struct DRWPass *aa_weight_pass; + struct DRWPass *aa_resolve_pass; + /* forward rendering */ struct DRWPass *transp_resolve_pass; struct DRWPass *transp_accum_pass; @@ -303,6 +314,14 @@ typedef struct WORKBENCH_PrivateData { int taa_sample_len; /** Current TAA sample index in [0..taa_sample_len[ range. */ int taa_sample; + /** Inverse of taa_sample to divide the accumulation buffer. */ + float taa_sample_inv; + + /* Smart Morphological Anti-Aliasing */ + struct GPUTexture *smaa_edge_tx; + struct GPUTexture *smaa_weight_tx; + /** Weight of the smaa pass. */ + float smaa_mix_factor; /* Opaque pipeline */ struct GPUTexture *object_id_tx; @@ -552,6 +571,9 @@ GPUShader *workbench_shader_shadow_fail_get(bool manifold, bool cap); GPUShader *workbench_shader_cavity_get(bool cavity, bool curvature); GPUShader *workbench_shader_outline_get(void); +GPUShader *workbench_shader_antialiasing_accumulation_get(void); +GPUShader *workbench_shader_antialiasing_get(int stage); + void workbench_shader_depth_of_field_get(GPUShader **prepare_sh, GPUShader **downsample_sh, GPUShader **blur1_sh, @@ -591,8 +613,10 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ int interp); /* workbench_effect_aa.c */ -void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx); -void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx); +int workbench_aa_sample_count_get(WORKBENCH_PrivateData *wpd); +void workbench_aa_engine_init(WORKBENCH_Data *vedata); +void workbench_aa_cache_init(WORKBENCH_Data *vedata); +void workbench_aa_draw_pass(WORKBENCH_Data *vedata); /* workbench_effect_fxaa.c */ void workbench_fxaa_engine_init(void); diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c index 4ee3cf02383..ec779469159 100644 --- a/source/blender/draw/engines/workbench/workbench_shader.c +++ b/source/blender/draw/engines/workbench/workbench_shader.c @@ -37,6 +37,9 @@ extern char datatoc_workbench_prepass_frag_glsl[]; extern char datatoc_workbench_effect_cavity_frag_glsl[]; extern char datatoc_workbench_effect_outline_frag_glsl[]; extern char datatoc_workbench_effect_dof_frag_glsl[]; +extern char datatoc_workbench_effect_taa_frag_glsl[]; +extern char datatoc_workbench_effect_smaa_frag_glsl[]; +extern char datatoc_workbench_effect_smaa_vert_glsl[]; extern char datatoc_workbench_composite_frag_glsl[]; @@ -88,6 +91,9 @@ static struct { struct GPUShader *dof_blur2_sh; struct GPUShader *dof_resolve_sh; + struct GPUShader *aa_accum_sh; + struct GPUShader *smaa_sh[2]; + struct DRWShaderLibrary *lib; } e_data = {{{{NULL}}}}; @@ -96,6 +102,7 @@ void workbench_shader_library_ensure(void) if (e_data.lib == NULL) { e_data.lib = DRW_shader_library_create(); + DRW_SHADER_LIB_ADD(e_data.lib, common_smaa_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); DRW_SHADER_LIB_ADD(e_data.lib, workbench_shader_interface_lib); @@ -370,6 +377,45 @@ void workbench_shader_depth_of_field_get(GPUShader **prepare_sh, *resolve_sh = e_data.dof_resolve_sh; } +GPUShader *workbench_shader_antialiasing_accumulation_get(void) +{ + if (e_data.aa_accum_sh == NULL) { + char *frag = DRW_shader_library_create_shader_string(e_data.lib, + datatoc_workbench_effect_taa_frag_glsl); + + e_data.aa_accum_sh = DRW_shader_create_fullscreen(frag, NULL); + + MEM_freeN(frag); + } + return e_data.aa_accum_sh; +} + +GPUShader *workbench_shader_antialiasing_get(int stage) +{ + if (e_data.smaa_sh[stage] == NULL) { + char *frag = DRW_shader_library_create_shader_string(e_data.lib, + datatoc_workbench_effect_smaa_frag_glsl); + + e_data.smaa_sh[stage] = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_workbench_shadow_vert_glsl, + NULL}, + .geom = (const char *[]){(cap) ? datatoc_workbench_shadow_caps_geom_glsl : + datatoc_workbench_shadow_geom_glsl, + NULL}, + .frag = (const char *[]){shadow_frag, NULL}, + .defs = (const char *[]){(depth_pass) ? "" : "#define SHADOW_FAIL\n", + (manifold) ? "" : "#define DOUBLE_MANIFOLD\n", + (manifold) ? "" : "#define DOUBLE_MANIFOLD\n", + NULL}, + }); + = DRW_shader_create_fullscreen(frag, NULL); + + MEM_freeN(frag); + } + return e_data.smaa_sh[stage]; +} + void workbench_shader_free(void) { for (int j = 0; j < sizeof(e_data.opaque_prepass_sh_cache) / sizeof(void *); j++) { @@ -396,6 +442,11 @@ void workbench_shader_free(void) struct GPUShader **sh_array = &e_data.cavity_sh[0][0]; DRW_SHADER_FREE_SAFE(sh_array[j]); } + for (int j = 0; j < sizeof(e_data.smaa_sh) / sizeof(void *); j++) { + struct GPUShader **sh_array = &e_data.smaa_sh[0]; + DRW_SHADER_FREE_SAFE(sh_array[j]); + } + DRW_SHADER_FREE_SAFE(e_data.oit_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.outline_sh); DRW_SHADER_FREE_SAFE(e_data.merge_infront_sh); @@ -406,5 +457,7 @@ void workbench_shader_free(void) DRW_SHADER_FREE_SAFE(e_data.dof_blur2_sh); DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.aa_accum_sh); + DRW_SHADER_LIB_FREE_SAFE(e_data.lib); } |