diff options
Diffstat (limited to 'source/blender/draw/engines/gpencil/gpencil_engine.c')
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_engine.c | 124 |
1 files changed, 113 insertions, 11 deletions
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 7be06d501f1..a80ad133d09 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -64,6 +64,7 @@ extern char datatoc_gpencil_paper_frag_glsl[]; extern char datatoc_gpencil_edit_point_vert_glsl[]; extern char datatoc_gpencil_edit_point_geom_glsl[]; extern char datatoc_gpencil_edit_point_frag_glsl[]; +extern char datatoc_gpencil_blend_frag_glsl[]; /* *********** STATIC *********** */ static GPENCIL_e_data e_data = {NULL}; /* Engine data */ @@ -221,6 +222,11 @@ static void GPENCIL_create_shaders(void) e_data.gpencil_simple_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_simple_mix_frag_glsl, NULL); } + /* blend */ + if (!e_data.gpencil_blend_fullscreen_sh) { + e_data.gpencil_blend_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_blend_frag_glsl, NULL); + } + /* shaders for use when drawing */ if (!e_data.gpencil_background_sh) { e_data.gpencil_background_sh = DRW_shader_create_fullscreen(datatoc_gpencil_background_frag_glsl, NULL); @@ -266,6 +272,7 @@ static void GPENCIL_engine_free(void) DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_blend_fullscreen_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh); @@ -371,6 +378,7 @@ void GPENCIL_cache_init(void *vedata) stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing); stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing); stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing); + stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing); /* save pixsize */ stl->storage->pixsize = DRW_viewport_pixelsize_get(); @@ -485,6 +493,20 @@ void GPENCIL_cache_init(void *vedata) stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass); } + /* blend layers pass */ + psl->blend_pass = DRW_pass_create( + "GPencil Blend Layers Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh, psl->blend_pass); + DRW_shgroup_call_add(blend_shgrp, quad, NULL); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &e_data.temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &e_data.temp_depth_tx_a); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &e_data.temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendDepth", &e_data.temp_depth_tx_fx); + DRW_shgroup_uniform_int(blend_shgrp, "mode", &stl->storage->blend_mode, 1); + DRW_shgroup_uniform_int(blend_shgrp, "clamp_layer", &stl->storage->clamp_layer, 1); + DRW_shgroup_uniform_float(blend_shgrp, "blend_opacity", &stl->storage->blend_opacity, 1); + /* create effects passes */ if (!stl->storage->simplify_fx) { GPENCIL_create_fx_passes(psl); @@ -639,12 +661,40 @@ static void gpencil_free_obj_runtime(GPENCIL_StorageList *stl) tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; bGPdata *gpd = cache_ob->gpd; gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; + + /* free shgrp array */ + cache_ob->tot_layers = 0; + MEM_SAFE_FREE(cache_ob->shgrp_array); } /* free the cache itself */ MEM_SAFE_FREE(stl->g_data->gp_object_cache); } +static void gpencil_draw_pass_range( + GPENCIL_FramebufferList *fbl, GPENCIL_StorageList *stl, + GPENCIL_PassList *psl, GPENCIL_TextureList *txl, + GPUFrameBuffer *fb, + DRWShadingGroup *init_shgrp, DRWShadingGroup *end_shgrp, bool multi) +{ + if (init_shgrp == NULL) { + return; + } + + /* previews don't use AA */ + if ((!stl->storage->is_mat_preview) && (multi)) { + MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); + } + + DRW_draw_pass_subset( + psl->stroke_pass, init_shgrp, end_shgrp); + + if ((!stl->storage->is_mat_preview) && (multi)) { + MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl); + } + +} + /* draw scene */ void GPENCIL_draw_scene(void *ved) { @@ -657,6 +707,10 @@ void GPENCIL_draw_scene(void *ved) GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl; tGPencilObjectCache *cache_ob; + tGPencilObjectCache_shgrp *array_elm = NULL; + DRWShadingGroup *init_shgrp = NULL; + DRWShadingGroup *end_shgrp = NULL; + const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -712,7 +766,7 @@ void GPENCIL_draw_scene(void *ved) for (int i = 0; i < stl->g_data->gp_cache_used; i++) { cache_ob = &stl->g_data->gp_object_cache[i]; bGPdata *gpd = cache_ob->gpd; - + 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); @@ -720,19 +774,67 @@ void GPENCIL_draw_scene(void *ved) /* Stroke Pass: * draw only a subset that usually starts with a fill and ends with stroke */ - if (cache_ob->init_grp) { - /* previews don't use AA */ - if (!stl->storage->is_mat_preview) { - MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); - } + bool use_blend = false; + if (cache_ob->tot_layers > 0) { + for (int e = 0; e < cache_ob->tot_layers; e++) { + bool is_last = e == cache_ob->tot_layers - 1 ? true : false; + array_elm = &cache_ob->shgrp_array[e]; + + if (((array_elm->mode == eGplBlendMode_Normal) && + (!use_blend) && (!array_elm->clamp_layer)) || + ( e == 0)) + { + if (init_shgrp == NULL) { + init_shgrp = array_elm->init_shgrp; + } + end_shgrp = array_elm->end_shgrp; + } + else { + use_blend = true; + /* draw pending groups */ + gpencil_draw_pass_range( + fbl, stl, psl, txl, fbl->temp_fb_a, + init_shgrp, end_shgrp, is_last); + + /* draw current group in separated texture */ + init_shgrp = array_elm->init_shgrp; + 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); + gpencil_draw_pass_range( + fbl, stl, psl, txl, fbl->temp_fb_fx, + 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); + stl->storage->blend_mode = array_elm->mode; + stl->storage->clamp_layer = (int)array_elm->clamp_layer; + stl->storage->blend_opacity = array_elm->blend_opacity; + DRW_draw_pass(psl->blend_pass); + + /* Copy B texture to A texture to follow loop */ + e_data.input_depth_tx = e_data.temp_depth_tx_b; + e_data.input_color_tx = e_data.temp_color_tx_b; + + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + DRW_draw_pass(psl->mix_pass_noblend); + + /* prepare next group */ + init_shgrp = NULL; + } - DRW_draw_pass_subset( - psl->stroke_pass, cache_ob->init_grp, cache_ob->end_grp); - - if (!stl->storage->is_mat_preview) { - MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fbl->temp_fb_a, txl); } + /* last group */ + gpencil_draw_pass_range( + fbl, stl, psl, txl, fbl->temp_fb_a, + init_shgrp, end_shgrp, + true); } + /* Current buffer drawing */ if ((!is_render) && (cache_ob->is_dup_ob == false)) { DRW_draw_pass(psl->drawing_pass); |