diff options
Diffstat (limited to 'source/blender/draw')
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_draw_utils.c | 49 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_engine.c | 104 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_engine.h | 3 |
3 files changed, 136 insertions, 20 deletions
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 9a78c24ca19..7df28bb9730 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -1453,6 +1453,12 @@ void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps) MEM_SAFE_FREE(uv); } +/* Check if stencil is required */ +static bool gpencil_is_stencil_required(MaterialGPencilStyle *gp_style) +{ + return (bool)(gp_style->stroke_style == GP_STYLE_STROKE_STYLE_SOLID); +} + /* draw stroke in drawing buffer */ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, @@ -1515,6 +1521,15 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, false, 1.0f, (const int *)stl->storage->shade_render); + + if (gpencil_is_stencil_required(gp_style)) { + DRW_shgroup_stencil_mask(stl->g_data->shgrps_drawing_stroke, 0x01); + } + else { + /* Disable stencil for this type */ + DRW_shgroup_state_disable(stl->g_data->shgrps_drawing_stroke, + DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); + } } else { stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create( @@ -1530,6 +1545,9 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, false, 1.0f, (const int *)stl->storage->shade_render); + /* Disable stencil for this type */ + DRW_shgroup_state_disable(stl->g_data->shgrps_drawing_stroke, + DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); } /* use unit matrix because the buffer is in screen space and does not need conversion */ @@ -1555,6 +1573,9 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, } stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(e_data->gpencil_drawing_fill_sh, psl->drawing_pass); + /* Disable stencil for this type */ + DRW_shgroup_state_disable(stl->g_data->shgrps_drawing_stroke, + DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); stl->g_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd); DRW_shgroup_call(stl->g_data->shgrps_drawing_fill, stl->g_data->batch_buffer_fill, NULL); @@ -1644,11 +1665,17 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, int start_edit = 0; int start_edlin = 0; + uint stencil_id = 1; for (int i = 0; i < cache->grp_used; i++) { elm = &cache->grp_cache[i]; array_elm = &cache_ob->shgrp_array[idx]; const float scale = cache_ob->scale; + /* Limit stencil id */ + if (stencil_id > 255) { + stencil_id = 1; + } + /* save last group when change */ if (gpl_prev == NULL) { gpl_prev = elm->gpl; @@ -1702,6 +1729,18 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, } stl->storage->shgroup_id++; start_stroke = elm->vertex_idx; + + /* set stencil mask id */ + if (gpencil_is_stencil_required(gp_style)) { + DRW_shgroup_stencil_mask(shgrp, stencil_id); + stencil_id++; + } + else { + /* Disable stencil for this type */ + DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); + /* set stencil mask id as not used */ + DRW_shgroup_stencil_mask(shgrp, 0x0); + } break; } case eGpencilBatchGroupType_Point: { @@ -1725,6 +1764,11 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, } stl->storage->shgroup_id++; start_point = elm->vertex_idx; + + /* Disable stencil for this type */ + DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); + /* set stencil mask id as not used */ + DRW_shgroup_stencil_mask(shgrp, 0x0); break; } case eGpencilBatchGroupType_Fill: { @@ -1745,6 +1789,11 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, } stl->storage->shgroup_id++; start_fill = elm->vertex_idx; + + /* Disable stencil for this type */ + DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); + /* set stencil mask id as not used */ + DRW_shgroup_stencil_mask(shgrp, 0x0); break; } case eGpencilBatchGroupType_Edit: { diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index fbff680e3f5..f736034a887 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -88,7 +88,7 @@ void DRW_gpencil_multisample_ensure(GPENCIL_Data *vedata, int rect_w, int rect_h } if (txl->multisample_depth == NULL) { txl->multisample_depth = GPU_texture_create_2d_multisample( - rect_w, rect_h, GPU_DEPTH_COMPONENT24, NULL, samples, NULL); + rect_w, rect_h, GPU_DEPTH24_STENCIL8, NULL, samples, NULL); } GPU_framebuffer_ensure_config(&fbl->multisample_fb, {GPU_ATTACHMENT_TEXTURE(txl->multisample_depth), @@ -121,7 +121,7 @@ static void GPENCIL_create_framebuffers(void *vedata) if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_BASIC) { /* temp textures for ping-pong buffers */ stl->g_data->temp_depth_tx_a = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type); stl->g_data->temp_color_tx_a = DRW_texture_pool_query_2d( size[0], size[1], fb_format, &draw_engine_gpencil_type); GPU_framebuffer_ensure_config(&fbl->temp_fb_a, @@ -131,7 +131,7 @@ static void GPENCIL_create_framebuffers(void *vedata) }); stl->g_data->temp_depth_tx_b = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type); stl->g_data->temp_color_tx_b = DRW_texture_pool_query_2d( size[0], size[1], fb_format, &draw_engine_gpencil_type); GPU_framebuffer_ensure_config(&fbl->temp_fb_b, @@ -142,7 +142,7 @@ static void GPENCIL_create_framebuffers(void *vedata) /* used for FX effects and Layer blending */ stl->g_data->temp_depth_tx_fx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type); stl->g_data->temp_color_tx_fx = DRW_texture_pool_query_2d( size[0], size[1], fb_format, &draw_engine_gpencil_type); GPU_framebuffer_ensure_config(&fbl->temp_fb_fx, @@ -358,12 +358,14 @@ void GPENCIL_cache_init(void *vedata) /* Stroke pass 2D */ psl->stroke_pass_2d = DRW_pass_create("GPencil Stroke Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA); + DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA | + DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); stl->storage->shgroup_id = 0; /* Stroke pass 3D */ psl->stroke_pass_3d = DRW_pass_create("GPencil Stroke Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA); + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA | + DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); stl->storage->shgroup_id = 0; /* edit pass */ @@ -462,7 +464,8 @@ void GPENCIL_cache_init(void *vedata) */ psl->drawing_pass = DRW_pass_create("GPencil Drawing Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA | - DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | + DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); /* full screen pass to combine the result with default framebuffer */ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); @@ -756,7 +759,7 @@ static void gpencil_prepare_fast_drawing(GPENCIL_StorageList *stl, GPU_framebuffer_bind(fbl->background_fb); /* clean only in first loop cycle */ if (stl->g_data->session_flag & GP_DRW_PAINT_IDLE) { - GPU_framebuffer_clear_color_depth(fbl->background_fb, clearcol, 1.0f); + GPU_framebuffer_clear_color_depth_stencil(fbl->background_fb, clearcol, 1.0f, 0x0); stl->g_data->session_flag = GP_DRW_PAINT_FILLING; } /* repeat pass to fill temp texture */ @@ -822,16 +825,80 @@ static void gpencil_draw_pass_range(GPENCIL_FramebufferList *fbl, return; } - /* previews don't use AA */ - if ((!stl->storage->is_mat_preview) && (multi)) { + const bool do_antialiasing = ((!stl->storage->is_mat_preview) && (multi)); + + DRWShadingGroup *shgrp = init_shgrp; + DRWShadingGroup *from_shgrp = init_shgrp; + DRWShadingGroup *to_shgrp = init_shgrp; + int stencil_tot = 0; + bool do_last = true; + + if (do_antialiasing) { MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); } - DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d, - init_shgrp, - end_shgrp); + /* Loop all shading groups to separate by stencil groups. */ + while ((shgrp) && (shgrp != end_shgrp)) { + do_last = true; + /* Count number of groups using stencil. */ + if (DRW_shgroup_stencil_mask_get(shgrp) != 0) { + stencil_tot++; + } + + /* Draw stencil group and clear stencil bit. This is required because the number of + * shading groups can be greater than the limit of 255 stencil values. + * Only count as stencil if the shading group has an stencil value assigned. This reduces + * the number of clears because Dots, Fills and some Line strokes don't need stencil. + */ + if (stencil_tot == 255) { + DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : + psl->stroke_pass_2d, + from_shgrp, + to_shgrp); + /* Clear Stencil and prepare for next group. */ + if (do_antialiasing) { + GPU_framebuffer_clear_stencil(fbl->multisample_fb, 0x0); + } + else { + GPU_framebuffer_clear_stencil(fb, 0x0); + } + + /* Set new init group and reset. */ + do_last = false; + + shgrp = DRW_shgroup_get_next(shgrp); + if (shgrp) { + from_shgrp = to_shgrp = shgrp; + stencil_tot = 0; + if (shgrp != end_shgrp) { + continue; + } + else { + do_last = true; + break; + } + } + else { + /* No more groups. */ + break; + } + } + + /* Still below stencil group limit. */ + shgrp = DRW_shgroup_get_next(shgrp); + if (shgrp) { + to_shgrp = shgrp; + } + } + + /* Draw last pending groups. */ + if (do_last) { + DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d, + from_shgrp, + to_shgrp); + } - if ((!stl->storage->is_mat_preview) && (multi)) { + if (do_antialiasing) { MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl); } } @@ -965,8 +1032,7 @@ void GPENCIL_draw_scene(void *ved) init_shgrp = NULL; /* Render stroke in separated framebuffer */ GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); - + GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_a, clearcol, 1.0f, 0x0); /* Stroke Pass: * draw only a subset that usually starts with a fill and ends with stroke */ @@ -995,13 +1061,13 @@ void GPENCIL_draw_scene(void *ved) end_shgrp = array_elm->end_shgrp; GPU_framebuffer_bind(fbl->temp_fb_fx); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_fx, clearcol, 1.0f, 0x0); gpencil_draw_pass_range( fbl, stl, psl, txl, fbl->temp_fb_fx, ob, gpd, init_shgrp, end_shgrp, is_last); /* Blend A texture and FX texture */ GPU_framebuffer_bind(fbl->temp_fb_b); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_b, clearcol, 1.0f, 0x0); stl->storage->blend_mode = array_elm->mode; stl->storage->clamp_layer = (int)array_elm->clamp_layer; stl->storage->tonemapping = DRW_state_do_color_management() ? 0 : 1; @@ -1013,7 +1079,7 @@ void GPENCIL_draw_scene(void *ved) stl->g_data->input_color_tx = stl->g_data->temp_color_tx_b; GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_a, clearcol, 1.0f, 0x0); DRW_draw_pass(psl->mix_pass_noblend); /* prepare next group */ diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index fa8745f3db9..957acb8c780 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -514,7 +514,8 @@ void GPENCIL_render_to_image(void *vedata, if ((lvl > 0) && (fbl->multisample_fb != NULL) && (DRW_state_is_fbo())) { \ DRW_stats_query_start("GP Multisample Blit"); \ GPU_framebuffer_bind(fbl->multisample_fb); \ - GPU_framebuffer_clear_color_depth(fbl->multisample_fb, (const float[4]){0.0f}, 1.0f); \ + GPU_framebuffer_clear_color_depth_stencil( \ + fbl->multisample_fb, (const float[4]){0.0f}, 1.0f, 0x0); \ DRW_stats_query_end(); \ } \ } \ |