[Bf-blender-cvs] [10f2e39f480] greasepencil-refactor: GPencil: Refactor: New linked mask system
Clément Foucault
noreply at git.blender.org
Fri Feb 7 23:44:03 CET 2020
Commit: 10f2e39f4803ca4f1110f3866e7aae1ac29acc95
Author: Clément Foucault
Date: Fri Feb 7 23:43:36 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB10f2e39f4803ca4f1110f3866e7aae1ac29acc95
GPencil: Refactor: New linked mask system
The new system is more flexible and a bit simpler from the code side.
Each layer has a mask layer slot. If filled with a correct layer name,
the mask layer will be rendered again in a separate buffer. This buffer
will then be used in the blend pass to modulate the opacity of the layer.
This approach is not 100% equivalent to the standard layering in most 2D
applications if using varying alpha on a mask applied to multiple layers.
However this technique does support any ordering arrangement of the masks.
The layers used as mask can now still render normaly.
===================================================================
M source/blender/blenkernel/BKE_gpencil.h
M source/blender/blenkernel/intern/gpencil.c
M source/blender/draw/CMakeLists.txt
M source/blender/draw/engines/gpencil/gpencil_cache_utils.c
M source/blender/draw/engines/gpencil/gpencil_engine.c
M source/blender/draw/engines/gpencil/gpencil_engine.h
M source/blender/draw/engines/gpencil/gpencil_shader.c
M source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl
D source/blender/draw/engines/gpencil/shaders/gpencil_layer_mask_frag.glsl
===================================================================
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 495fe4eb7f6..f19af3cb1b7 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -179,6 +179,7 @@ struct bGPDframe *BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl,
struct bGPDframe *BKE_gpencil_layer_frame_find(struct bGPDlayer *gpl, int cframe);
bool BKE_gpencil_layer_frame_delete(struct bGPDlayer *gpl, struct bGPDframe *gpf);
+struct bGPDlayer *BKE_gpencil_layer_named_get(struct bGPdata *gpd, const char *name);
struct bGPDlayer *BKE_gpencil_layer_active_get(struct bGPdata *gpd);
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active);
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 2b58525396b..02cbbcc4060 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1002,6 +1002,14 @@ bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
return changed;
}
+bGPDlayer *BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
+{
+ if (name[0] == '\0') {
+ return NULL;
+ }
+ return BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info));
+}
+
/* get the active gp-layer for editing */
bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
{
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 5d11578fe19..46fce6341f0 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -283,7 +283,6 @@ data_to_c_simple(engines/gpencil/shaders/gpencil_antialiasing_vert.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_common_lib.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_composite_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_layer_blend_frag.glsl SRC)
-data_to_c_simple(engines/gpencil/shaders/gpencil_layer_mask_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_depth_merge_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_depth_merge_vert.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_vfx_frag.glsl SRC)
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index ae8ac611570..6b4e017c96b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -115,6 +115,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
const bool is_obact = ((pd->obact) && (pd->obact == ob));
const bool is_fade = ((pd->fade_layer_opacity > -1.0f) && (is_obact) &&
((gpl->flag & GP_LAYER_ACTIVE) == 0));
+ bool mask_invert = true; /* True because we invert the dummy texture red channel. */
/* Defines layer opacity. For active object depends of layer opacity factor, and
* for no active object, depends if the fade grease pencil objects option is enabled. */
@@ -127,28 +128,21 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
fade_layer_opacity = pd->fade_gp_object_opacity;
}
}
+
bGPdata *gpd = (bGPdata *)ob->data;
GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
+ tgp_layer->layer_id = BLI_findindex(&gpd->layers, gpl);
+ tgp_layer->mask_id = -1;
- const bool is_mask = (gpl->flag & GP_LAYER_USE_MASK) != 0;
- tgp_layer->is_mask = is_mask;
- tgp_layer->do_masked_clear = false;
-
- if (!is_mask) {
- tgp_layer->is_masked = false;
- for (bGPDlayer *gpl_m = gpl->next; gpl_m; gpl_m = gpl_m->next) {
- if (gpl_m->flag & GP_LAYER_USE_MASK) {
- if (gpl_m->flag & GP_LAYER_HIDE) {
- /* We don't mask but we dont try to mask with further layers. */
- }
- else {
- tgp_layer->is_masked = true;
- }
- break;
- }
- }
+ bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, gpl->mask_layer);
+ if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0)) {
+ mask_invert = (gpl->flag & GP_LAYER_MASK_INVERT) != 0;
+ tgp_layer->mask_id = BLI_findindex(&gpd->layers, gpl_mask);
+ pd->use_mask_fb = true;
}
+ const bool is_masked = tgp_layer->mask_id != -1;
+
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
if (GPENCIL_3D_DRAWMODE(ob, gpd) || pd->draw_depth_only) {
@@ -160,42 +154,13 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_GREATER;
}
- if (gpl->flag & GP_LAYER_USE_MASK) {
- state |= DRW_STATE_STENCIL_EQUAL;
- }
- else {
- state |= DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
- }
+ /* Always write stencil. Only used as optimization for blending. */
+ state |= DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
}
- if (is_mask) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_BLEND_MUL;
- tgp_layer->blend_ps = DRW_pass_create("GPencil Mask Layer", state);
-
- GPUShader *sh = GPENCIL_shader_layer_mask_get();
- DRWShadingGroup *grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
- DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true);
- DRW_shgroup_uniform_float_copy(grp, "maskOpacity", fade_layer_opacity);
- DRW_shgroup_uniform_bool_copy(grp, "maskInvert", gpl->flag & GP_LAYER_MASK_INVERT);
- DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_masked_tx);
- DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_masked_tx);
- DRW_shgroup_uniform_texture_ref(grp, "maskBuf", &pd->reveal_layer_tx);
- DRW_shgroup_stencil_mask(grp, 0xFF);
- DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
-
- /* We cannot do custom blending on MultiTarget framebuffers.
- * Workaround by doing 2 passes. */
- grp = DRW_shgroup_create_sub(grp);
- DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL);
- DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ADD_FULL);
- DRW_shgroup_uniform_int_copy(grp, "isFirstPass", false);
- DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
-
- pd->use_mask_fb = true;
- }
- else if ((gpl->blend_mode != eGplBlendMode_Regular) || (fade_layer_opacity < 1.0f)) {
+ if (is_masked || (gpl->blend_mode != eGplBlendMode_Regular) || (fade_layer_opacity < 1.0f)) {
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL;
switch (gpl->blend_mode) {
case eGplBlendMode_Regular:
@@ -227,6 +192,8 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
DRW_shgroup_uniform_float_copy(grp, "blendOpacity", fade_layer_opacity);
DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_layer_tx);
DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_layer_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "maskBuf", (is_masked) ? &pd->mask_tx : &pd->dummy_tx);
+ DRW_shgroup_uniform_bool_copy(grp, "maskInvert", mask_invert);
DRW_shgroup_stencil_mask(grp, 0xFF);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
@@ -248,3 +215,17 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
return tgp_layer;
}
+
+GPENCIL_tLayer *gpencil_layer_cache_get(GPENCIL_tObject *tgp_ob, int number)
+{
+ if (number >= 0) {
+ GPENCIL_tLayer *layer = tgp_ob->layers.first;
+ while (layer != NULL) {
+ if (layer->layer_id == number) {
+ return layer;
+ }
+ layer = layer->next;
+ }
+ }
+ return NULL;
+}
\ No newline at end of file
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 8736857c45c..437988c66c1 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -438,14 +438,9 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
(gpl == iter->pd->sbuffer_layer);
}
- GPENCIL_tLayer *tgp_layer_prev = iter->tgp_ob->layers.last;
GPENCIL_tLayer *tgp_layer = gpencil_layer_cache_add(iter->pd, iter->ob, gpl);
BLI_LINKS_APPEND(&iter->tgp_ob->layers, tgp_layer);
- if (tgp_layer->is_masked && (tgp_layer_prev == NULL || !tgp_layer_prev->is_masked)) {
- tgp_layer->do_masked_clear = true;
- }
-
gpencil_material_resources_get(iter->matpool, 0, NULL, NULL, &iter->ubo_mat);
const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D) || iter->pd->draw_depth_only;
@@ -784,17 +779,22 @@ void GPENCIL_cache_finish(void *ved)
}
if (pd->use_mask_fb) {
- /* We need to separate all the masked layer together in order to correctly mix them. */
- pd->color_masked_tx = DRW_texture_pool_query_2d(
- size[0], size[1], format, &draw_engine_gpencil_type);
- pd->reveal_masked_tx = DRW_texture_pool_query_2d(
- size[0], size[1], format, &draw_engine_gpencil_type);
-
- GPU_framebuffer_ensure_config(&fbl->masked_fb,
+ /* We need an extra depth to not disturb the normal drawing.
+ * The color_tx is needed for framebuffer cmpleteness. */
+ GPUTexture *color_tx, *depth_tx;
+ depth_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type);
+ color_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_R8, &draw_engine_gpencil_type);
+ /* Use high quality format for render. */
+ eGPUTextureFormat mask_format = pd->is_render ? GPU_R16 : GPU_R8;
+ pd->mask_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], mask_format, &draw_engine_gpencil_type);
+
+ GPU_framebuffer_ensure_config(&fbl->mask_fb,
{
- GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
- GPU_ATTACHMENT_TEXTURE(pd->color_masked_tx),
- GPU_ATTACHMENT_TEXTURE(pd->reveal_masked_tx)
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list