Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/engines/gpencil/gpencil_antialiasing.c
| Show All 11 Lines | |||||
| * You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
| * along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
| * | * | ||||
| * Copyright 2019, Blender Foundation. | * Copyright 2019, Blender Foundation. | ||||
| */ | */ | ||||
| /** \file | /** \file | ||||
| * \ingroup draw | * \ingroup draw_engine | ||||
| * | |||||
| * Anti-Aliasing: | |||||
| * | |||||
| * We use SMAA (Smart Morphological Anti-Aliasing) as a fast antialiasing solution. | |||||
| * | |||||
| * If the viewport stays static, the engine ask for multiple redraw and will progressively | |||||
| * converge to a much more accurate image without aliasing. | |||||
| * We call this one TAA (Temporal Anti-Aliasing). | |||||
| * | |||||
| * This is done using an accumulation buffer and a final pass that will output the final color | |||||
| * to the scene buffer. We softly blend between SMAA and TAA to avoid really harsh transitions. | |||||
| */ | */ | ||||
| #include "DRW_render.h" | #include "DRW_render.h" | ||||
| #include "gpencil_engine.h" | #include "BLI_jitter_2d.h" | ||||
| #include "smaa_textures.h" | #include "smaa_textures.h" | ||||
| void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata) | #include "gpencil_engine.h" | ||||
| #define NUM_JITTER_SAMPLES 11 | |||||
| static struct { | |||||
| bool init; | |||||
| float jitter[NUM_JITTER_SAMPLES][2]; | |||||
| } e_data = {false}; | |||||
| static void gpencil_taa_jitter_init_order(float (*table)[2], int num) | |||||
| { | |||||
| 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_f(table[index][0]) + square_f(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); | |||||
| } | |||||
| /* swap center sample to the start of the table */ | |||||
| if (closest_index != 0) { | |||||
| swap_v2_v2(table[0], table[closest_index]); | |||||
| } | |||||
| /* Sort list based on farthest 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_f(table[i][0] - table[j][0]) + | |||||
| square_f(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 gpencil_taa_jitter_init(void) | |||||
| { | |||||
| if (e_data.init == false) { | |||||
| e_data.init = true; | |||||
| gpencil_taa_jitter_init_order(e_data.jitter, NUM_JITTER_SAMPLES); | |||||
| } | |||||
| } | |||||
| int GPENCIL_antialiasing_sample_count_get(GPENCIL_PrivateData *pd) | |||||
| { | |||||
| if (pd->is_navigating || pd->is_playback) { | |||||
| /* Only draw using SMAA. */ | |||||
| return 1; | |||||
| } | |||||
| return NUM_JITTER_SAMPLES; | |||||
| } | |||||
| void GPENCIL_antialiasing_view_updated(GPENCIL_Data *vedata) | |||||
| { | |||||
| GPENCIL_StorageList *stl = vedata->stl; | |||||
| if (stl && stl->pd) { | |||||
| stl->pd->view_updated = true; | |||||
| } | |||||
| } | |||||
| /* This function checks if the overlay engine should need center in front depth's. | |||||
| * When that is the case the in front depth are stored and restored. Otherwise it | |||||
| * will be filled with the current sample data. */ | |||||
| static bool gpencil_in_front_history_needed(GPENCIL_Data *vedata) | |||||
| { | |||||
| GPENCIL_StorageList *stl = vedata->stl; | |||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | |||||
| const View3D *v3d = draw_ctx->v3d; | |||||
| if (!v3d || (v3d->flag2 & V3D_HIDE_OVERLAYS)) { | |||||
| return false; | |||||
| } | |||||
| if (stl->pd->is_playback) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| void GPENCIL_antialiasing_engine_init(struct GPENCIL_Data *vedata) | |||||
| { | { | ||||
| GPENCIL_PrivateData *pd = vedata->stl->pd; | |||||
| GPENCIL_FramebufferList *fbl = vedata->fbl; | GPENCIL_FramebufferList *fbl = vedata->fbl; | ||||
| GPENCIL_TextureList *txl = vedata->txl; | GPENCIL_TextureList *txl = vedata->txl; | ||||
| GPENCIL_PassList *psl = vedata->psl; | GPENCIL_PrivateData *pd = vedata->stl->pd; | ||||
| DRWShadingGroup *grp; | DrawEngineType *owner = (DrawEngineType *)&GPENCIL_antialiasing_engine_init; | ||||
| const float *size = DRW_viewport_size_get(); | pd->view = NULL; | ||||
| const float *sizeinv = DRW_viewport_invert_size_get(); | |||||
| const float metrics[4] = {sizeinv[0], sizeinv[1], size[0], size[1]}; | |||||
| if (pd->simplify_antialias) { | /* Reset complete drawing when navigating or during viewport playback or when | ||||
| /* No AA fallback. */ | * leaving one of those states. In case of multires modifier the navigation | ||||
| DRW_PASS_CREATE(psl->smaa_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM); | * mesh differs from the viewport mesh, so we need to be sure to restart. */ | ||||
| if (pd->taa_sample != 0) { | |||||
| if (pd->is_navigating || pd->is_playback) { | |||||
| pd->taa_sample = 0; | |||||
| pd->reset_next_sample = true; | |||||
| } | |||||
| else if (pd->reset_next_sample) { | |||||
| pd->taa_sample = 0; | |||||
| pd->reset_next_sample = false; | |||||
| } | |||||
| } | |||||
| GPUShader *sh = GPENCIL_shader_antialiasing(2); | /* Reset the TAA when we have already draw a sample, but the sample count differs from previous | ||||
| grp = DRW_shgroup_create(sh, psl->smaa_resolve_ps); | * time. This removes render artifacts when the viewport anti-aliasing in the user preferences is | ||||
| DRW_shgroup_uniform_texture(grp, "blendTex", pd->color_tx); | * set to a lower value. */ | ||||
| DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx); | if (pd->taa_sample_len != pd->taa_sample_len_previous) { | ||||
| DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx); | pd->taa_sample = 0; | ||||
| DRW_shgroup_uniform_bool_copy(grp, "doAntiAliasing", false); | pd->taa_sample_len_previous = pd->taa_sample_len; | ||||
| DRW_shgroup_uniform_bool_copy(grp, "onlyAlpha", pd->draw_wireframe); | } | ||||
| DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); | |||||
| DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | if (pd->view_updated) { | ||||
| return; | pd->taa_sample = 0; | ||||
| pd->view_updated = false; | |||||
| } | |||||
| if (pd->taa_sample_len > 0 && pd->valid_history == false) { | |||||
| pd->taa_sample = 0; | |||||
| } | |||||
| { | |||||
| float persmat[4][4]; | |||||
| DRW_view_persmat_get(NULL, persmat, false); | |||||
| if (!equals_m4m4(persmat, pd->last_mat)) { | |||||
| copy_m4_m4(pd->last_mat, persmat); | |||||
| pd->taa_sample = 0; | |||||
| } | |||||
| } | |||||
| if (pd->taa_sample_len > 0) { | |||||
| gpencil_taa_jitter_init(); | |||||
| DRW_texture_ensure_fullscreen_2d(&txl->history_buffer_tx, GPU_RGBA16F, DRW_TEX_FILTER); | |||||
| DRW_texture_ensure_fullscreen_2d(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0); | |||||
| const bool in_front_history = gpencil_in_front_history_needed(vedata); | |||||
| if (in_front_history) { | |||||
| DRW_texture_ensure_fullscreen_2d(&txl->depth_buffer_in_front_tx, GPU_DEPTH24_STENCIL8, 0); | |||||
| } | |||||
| else { | |||||
| DRW_TEXTURE_FREE_SAFE(txl->depth_buffer_in_front_tx); | |||||
| } | |||||
| pd->smaa_edge_tx = DRW_texture_pool_query_fullscreen(GPU_RG8, owner); | |||||
| pd->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), | |||||
| }); | |||||
| if (in_front_history) { | |||||
| GPU_framebuffer_ensure_config(&fbl->antialiasing_in_front_fb, | |||||
| { | |||||
| GPU_ATTACHMENT_TEXTURE(txl->depth_buffer_in_front_tx), | |||||
| }); | |||||
| } | } | ||||
| GPU_framebuffer_ensure_config(&fbl->smaa_edge_fb, | |||||
| { | |||||
| GPU_ATTACHMENT_NONE, | |||||
| GPU_ATTACHMENT_TEXTURE(pd->smaa_edge_tx), | |||||
| }); | |||||
| GPU_framebuffer_ensure_config(&fbl->smaa_weight_fb, | |||||
| { | |||||
| GPU_ATTACHMENT_NONE, | |||||
| GPU_ATTACHMENT_TEXTURE(pd->smaa_weight_tx), | |||||
| }); | |||||
| /* TODO could be shared for all viewports. */ | |||||
| if (txl->smaa_search_tx == NULL) { | if (txl->smaa_search_tx == NULL) { | ||||
| txl->smaa_search_tx = GPU_texture_create_2d( | txl->smaa_search_tx = GPU_texture_create_2d( | ||||
| "smaa_search", SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 1, GPU_R8, NULL); | "smaa_search", SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 1, GPU_R8, NULL); | ||||
| GPU_texture_update(txl->smaa_search_tx, GPU_DATA_UNSIGNED_BYTE, searchTexBytes); | GPU_texture_update(txl->smaa_search_tx, GPU_DATA_UNSIGNED_BYTE, searchTexBytes); | ||||
| txl->smaa_area_tx = GPU_texture_create_2d( | txl->smaa_area_tx = GPU_texture_create_2d( | ||||
| "smaa_area", AREATEX_WIDTH, AREATEX_HEIGHT, 1, GPU_RG8, NULL); | "smaa_area", AREATEX_WIDTH, AREATEX_HEIGHT, 1, GPU_RG8, NULL); | ||||
| GPU_texture_update(txl->smaa_area_tx, GPU_DATA_UNSIGNED_BYTE, areaTexBytes); | GPU_texture_update(txl->smaa_area_tx, GPU_DATA_UNSIGNED_BYTE, areaTexBytes); | ||||
| GPU_texture_filter_mode(txl->smaa_search_tx, true); | GPU_texture_filter_mode(txl->smaa_search_tx, true); | ||||
| GPU_texture_filter_mode(txl->smaa_area_tx, true); | GPU_texture_filter_mode(txl->smaa_area_tx, true); | ||||
| } | } | ||||
| } | |||||
| else { | |||||
| /* Cleanup */ | |||||
| DRW_TEXTURE_FREE_SAFE(txl->history_buffer_tx); | |||||
| DRW_TEXTURE_FREE_SAFE(txl->depth_buffer_tx); | |||||
| DRW_TEXTURE_FREE_SAFE(txl->depth_buffer_in_front_tx); | |||||
| DRW_TEXTURE_FREE_SAFE(txl->smaa_search_tx); | |||||
| DRW_TEXTURE_FREE_SAFE(txl->smaa_area_tx); | |||||
| } | |||||
| } | |||||
| static float filter_blackman_harris(float x, const float width) | |||||
| { | { | ||||
| pd->smaa_edge_tx = DRW_texture_pool_query_2d( | if (x > width * 0.5f) { | ||||
| size[0], size[1], GPU_RG8, &draw_engine_gpencil_type); | return 0.0f; | ||||
| pd->smaa_weight_tx = DRW_texture_pool_query_2d( | } | ||||
| size[0], size[1], GPU_RGBA8, &draw_engine_gpencil_type); | x = 2.0f * M_PI * clamp_f((x / width + 0.5f), 0.0f, 1.0f); | ||||
| return 0.35875f - 0.48829f * cosf(x) + 0.14128f * cosf(2.0f * x) - 0.01168f * cosf(3.0f * x); | |||||
| } | |||||
| GPU_framebuffer_ensure_config(&fbl->smaa_edge_fb, | /* Compute weights for the 3x3 neighborhood using a 1.5px filter. */ | ||||
| static void gpencil_antialiasing_weights_get(const float offset[2], | |||||
| float r_weights[9], | |||||
| float *r_weight_sum) | |||||
| { | { | ||||
| GPU_ATTACHMENT_NONE, | /* NOTE: If filter width is bigger than 2.0f, then we need to sample more neighborhood. */ | ||||
| GPU_ATTACHMENT_TEXTURE(pd->smaa_edge_tx), | const float filter_width = 2.0f; | ||||
| }); | *r_weight_sum = 0.0f; | ||||
| int i = 0; | |||||
| for (int x = -1; x <= 1; x++) { | |||||
| for (int y = -1; y <= 1; y++, i++) { | |||||
| float sample_co[2] = {x, y}; | |||||
| add_v2_v2(sample_co, offset); | |||||
| float r = len_v2(sample_co); | |||||
| /* fclem: is radial distance ok here? */ | |||||
| float weight = filter_blackman_harris(r, filter_width); | |||||
| *r_weight_sum += weight; | |||||
| r_weights[i] = weight; | |||||
| } | |||||
| } | |||||
| } | |||||
| GPU_framebuffer_ensure_config(&fbl->smaa_weight_fb, | void GPENCIL_antialiasing_cache_finish(GPENCIL_Data *vedata) | ||||
| { | { | ||||
| GPU_ATTACHMENT_NONE, | GPENCIL_TextureList *txl = vedata->txl; | ||||
| GPU_ATTACHMENT_TEXTURE(pd->smaa_weight_tx), | GPENCIL_PrivateData *pd = vedata->stl->pd; | ||||
| }); | GPENCIL_PassList *psl = vedata->psl; | ||||
| DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); | |||||
| DRWShadingGroup *grp = NULL; | |||||
| if (pd->taa_sample_len == 0) { | |||||
| return; | |||||
| } | } | ||||
| { | { | ||||
| DRW_PASS_CREATE(psl->aa_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL); | |||||
| DRW_PASS_INSTANCE_CREATE(psl->aa_accum_replace_ps, psl->aa_accum_ps, DRW_STATE_WRITE_COLOR); | |||||
| GPUShader *shader = GPENCIL_shader_antialiasing_accumulation_get(); | |||||
| grp = DRW_shgroup_create(shader, psl->aa_accum_ps); | |||||
| DRW_shgroup_uniform_texture_ex(grp, "colorBuffer", dtxl->color, GPU_SAMPLER_DEFAULT); | |||||
| DRW_shgroup_uniform_float(grp, "samplesWeights", pd->taa_weights, 9); | |||||
| DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | |||||
| } | |||||
| const float *size = DRW_viewport_size_get(); | |||||
| const float *sizeinv = DRW_viewport_invert_size_get(); | |||||
| const float metrics[4] = {sizeinv[0], sizeinv[1], size[0], size[1]}; | |||||
| { | |||||
| /* Stage 1: Edge detection. */ | /* Stage 1: Edge detection. */ | ||||
| DRW_PASS_CREATE(psl->smaa_edge_ps, DRW_STATE_WRITE_COLOR); | DRW_PASS_CREATE(psl->aa_edge_ps, DRW_STATE_WRITE_COLOR); | ||||
| GPUShader *sh = GPENCIL_shader_antialiasing(0); | GPUShader *sh = GPENCIL_shader_antialiasing(0); | ||||
| grp = DRW_shgroup_create(sh, psl->smaa_edge_ps); | grp = DRW_shgroup_create(sh, psl->aa_edge_ps); | ||||
| DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx); | DRW_shgroup_uniform_texture(grp, "colorTex", txl->history_buffer_tx); | ||||
| DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx); | DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx); | ||||
| DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); | DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); | ||||
| DRW_shgroup_uniform_float_copy( | DRW_shgroup_uniform_float_copy( | ||||
| grp, "lumaWeight", pd->scene->grease_pencil_settings.smaa_threshold); | grp, "lumaWeight", pd->scene->grease_pencil_settings.smaa_threshold); | ||||
| DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0); | DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0); | ||||
| DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | ||||
| } | } | ||||
| { | { | ||||
| /* Stage 2: Blend Weight/Coord. */ | /* Stage 2: Blend Weight/Coord. */ | ||||
| DRW_PASS_CREATE(psl->smaa_weight_ps, DRW_STATE_WRITE_COLOR); | DRW_PASS_CREATE(psl->aa_weight_ps, DRW_STATE_WRITE_COLOR); | ||||
| GPUShader *sh = GPENCIL_shader_antialiasing(1); | GPUShader *sh = GPENCIL_shader_antialiasing(1); | ||||
| grp = DRW_shgroup_create(sh, psl->smaa_weight_ps); | grp = DRW_shgroup_create(sh, psl->aa_weight_ps); | ||||
| DRW_shgroup_uniform_texture(grp, "edgesTex", pd->smaa_edge_tx); | DRW_shgroup_uniform_texture(grp, "edgesTex", pd->smaa_edge_tx); | ||||
| DRW_shgroup_uniform_texture(grp, "areaTex", txl->smaa_area_tx); | DRW_shgroup_uniform_texture(grp, "areaTex", txl->smaa_area_tx); | ||||
| DRW_shgroup_uniform_texture(grp, "searchTex", txl->smaa_search_tx); | DRW_shgroup_uniform_texture(grp, "searchTex", txl->smaa_search_tx); | ||||
| DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); | 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_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0); | ||||
| DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | ||||
| } | } | ||||
| { | { | ||||
| /* Stage 3: Resolve. */ | /* Stage 3: Resolve. */ | ||||
| DRW_PASS_CREATE(psl->smaa_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM); | DRW_PASS_CREATE(psl->aa_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM); | ||||
| GPUShader *sh = GPENCIL_shader_antialiasing(2); | GPUShader *sh = GPENCIL_shader_antialiasing(2); | ||||
| grp = DRW_shgroup_create(sh, psl->smaa_resolve_ps); | grp = DRW_shgroup_create(sh, psl->aa_resolve_ps); | ||||
| DRW_shgroup_uniform_texture(grp, "blendTex", pd->smaa_weight_tx); | DRW_shgroup_uniform_texture(grp, "blendTex", pd->smaa_weight_tx); | ||||
| DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx); | DRW_shgroup_uniform_texture(grp, "colorTex", txl->history_buffer_tx); | ||||
| DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx); | DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx); | ||||
| DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); | |||||
| DRW_shgroup_uniform_float(grp, "mixFactor", &pd->smaa_mix_factor, 1); | |||||
| DRW_shgroup_uniform_bool_copy(grp, "doAntiAliasing", true); | DRW_shgroup_uniform_bool_copy(grp, "doAntiAliasing", true); | ||||
| DRW_shgroup_uniform_bool_copy(grp, "onlyAlpha", pd->draw_wireframe); | DRW_shgroup_uniform_bool_copy(grp, "onlyAlpha", pd->draw_wireframe); | ||||
| DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics); | DRW_shgroup_uniform_float(grp, "taaAccumulatedWeight", &pd->taa_weight_accum, 1); | ||||
| DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | DRW_shgroup_call_procedural_triangles(grp, NULL, 1); | ||||
| } | } | ||||
| } | } | ||||
| /* Return true if render is not cached. */ | |||||
| bool GPENCIL_antialiasing_setup(GPENCIL_Data *vedata) | |||||
| { | |||||
| GPENCIL_PrivateData *pd = vedata->stl->pd; | |||||
| if (pd->taa_sample_len == 0) { | |||||
| /* AA disabled. */ | |||||
| return true; | |||||
| } | |||||
| void GPENCIL_antialiasing_draw(struct GPENCIL_Data *vedata) | if (pd->taa_sample >= pd->taa_sample_len) { | ||||
| /* TAA accumulation has finish. Just copy the result back */ | |||||
| return false; | |||||
| } | |||||
| const float *viewport_size = DRW_viewport_size_get(); | |||||
| const DRWView *default_view = DRW_view_default_get(); | |||||
| float *transform_offset; | |||||
| transform_offset = e_data.jitter[min_ii(pd->taa_sample, NUM_JITTER_SAMPLES)]; | |||||
| gpencil_antialiasing_weights_get(transform_offset, pd->taa_weights, &pd->taa_weights_sum); | |||||
| /* construct new matrices from transform delta */ | |||||
| float winmat[4][4], viewmat[4][4], persmat[4][4]; | |||||
| DRW_view_winmat_get(default_view, winmat, false); | |||||
| DRW_view_viewmat_get(default_view, viewmat, false); | |||||
| DRW_view_persmat_get(default_view, persmat, false); | |||||
| window_translate_m4(winmat, | |||||
| persmat, | |||||
| transform_offset[0] / viewport_size[0], | |||||
| transform_offset[1] / viewport_size[1]); | |||||
| if (pd->view) { | |||||
| /* When rendering just update the view. This avoids recomputing the culling. */ | |||||
| DRW_view_update_sub(pd->view, viewmat, winmat); | |||||
| } | |||||
| else { | |||||
| /* TAA is not making a big change to the matrices. | |||||
| * Reuse the main view culling by creating a sub-view. */ | |||||
| pd->view = DRW_view_create_sub(default_view, viewmat, winmat); | |||||
| } | |||||
| DRW_view_set_active(pd->view); | |||||
| return true; | |||||
| } | |||||
| void GPENCIL_antialiasing_draw(GPENCIL_Data *vedata) | |||||
| { | { | ||||
| GPENCIL_FramebufferList *fbl = vedata->fbl; | |||||
| GPENCIL_PrivateData *pd = vedata->stl->pd; | GPENCIL_PrivateData *pd = vedata->stl->pd; | ||||
| GPENCIL_FramebufferList *fbl = vedata->fbl; | |||||
| GPENCIL_TextureList *txl = vedata->txl; | |||||
| GPENCIL_PassList *psl = vedata->psl; | GPENCIL_PassList *psl = vedata->psl; | ||||
| // DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); | |||||
| DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); | |||||
| if (!pd->simplify_antialias) { | if (pd->taa_sample_len == 0) { | ||||
| /* AA disabled. */ | |||||
| /* Just set sample to 1 to avoid rendering indefinitely. */ | |||||
| pd->taa_sample = 1; | |||||
| pd->valid_history = false; | |||||
| return; | |||||
| } | |||||
| /** | |||||
| * 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. | |||||
| */ | |||||
| const bool last_sample = pd->taa_sample + 1 == pd->taa_sample_len; | |||||
| const bool taa_finished = pd->taa_sample >= pd->taa_sample_len; | |||||
| if (pd->taa_sample == 0) { | |||||
| pd->taa_weight_accum = pd->taa_weights_sum; | |||||
| pd->valid_history = true; | |||||
| GPU_framebuffer_bind(fbl->antialiasing_fb); | |||||
| DRW_draw_pass(psl->aa_accum_replace_ps); | |||||
| /* 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. */ | |||||
| if (!pd->is_playback) { | |||||
| GPU_texture_copy(txl->depth_buffer_tx, dtxl->depth); | |||||
| } | |||||
| if (gpencil_in_front_history_needed(vedata)) { | |||||
| GPU_texture_copy(txl->depth_buffer_in_front_tx, dtxl->depth_in_front); | |||||
| } | |||||
| } | |||||
| else { | |||||
| if (!taa_finished) { | |||||
| /* Accumulate result to the TAA buffer. */ | |||||
| GPU_framebuffer_bind(fbl->antialiasing_fb); | |||||
| DRW_draw_pass(psl->aa_accum_ps); | |||||
| pd->taa_weight_accum += pd->taa_weights_sum; | |||||
| } | |||||
| /* Copy back the saved depth buffer for correct overlays. */ | |||||
| GPU_texture_copy(dtxl->depth, txl->depth_buffer_tx); | |||||
| if (gpencil_in_front_history_needed(vedata)) { | |||||
| GPU_texture_copy(dtxl->depth_in_front, txl->depth_buffer_in_front_tx); | |||||
| } | |||||
| } | |||||
| if (!DRW_state_is_image_render() || last_sample) { | |||||
| /* After a certain point SMAA is no longer necessary. */ | |||||
| pd->smaa_mix_factor = 1.0f - clamp_f(pd->taa_sample / 4.0f, 0.0f, 1.0f); | |||||
| if (pd->smaa_mix_factor > 0.0f) { | |||||
| GPU_framebuffer_bind(fbl->smaa_edge_fb); | GPU_framebuffer_bind(fbl->smaa_edge_fb); | ||||
| DRW_draw_pass(psl->smaa_edge_ps); | DRW_draw_pass(psl->aa_edge_ps); | ||||
| GPU_framebuffer_bind(fbl->smaa_weight_fb); | GPU_framebuffer_bind(fbl->smaa_weight_fb); | ||||
| DRW_draw_pass(psl->smaa_weight_ps); | DRW_draw_pass(psl->aa_weight_ps); | ||||
| } | } | ||||
| GPU_framebuffer_bind(pd->scene_fb); | GPU_framebuffer_bind(pd->scene_fb); | ||||
| DRW_draw_pass(psl->smaa_resolve_ps); | DRW_draw_pass(psl->aa_resolve_ps); | ||||
| } | |||||
| if (!taa_finished) { | |||||
| pd->taa_sample++; | |||||
| } | |||||
| if (!DRW_state_is_image_render() && pd->taa_sample < pd->taa_sample_len) { | |||||
| DRW_viewport_request_redraw(); | |||||
| } | |||||
| } | } | ||||