Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-03-03 18:45:26 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-03-03 19:35:30 +0300
commitbd6567b262225e0eb5e392bc257c55e43a585ded (patch)
treeea0b2329e338ee5ccce6e2529d0554285bde03ff
parent91dfe40ef07a174d73cf06b497f1e35b9772bcf0 (diff)
Workbench: Refactor: Antialiasingtmp-workbench-rewrite
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl14
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl14
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl11
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c4
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_aa.c337
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c4
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h28
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c53
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);
}