diff options
9 files changed, 99 insertions, 46 deletions
diff --git a/release/scripts/startup/bl_ui/properties_material_gpencil.py b/release/scripts/startup/bl_ui/properties_material_gpencil.py index 5d10a2cef4a..a1af447d402 100644 --- a/release/scripts/startup/bl_ui/properties_material_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_material_gpencil.py @@ -70,6 +70,7 @@ class GPENCIL_UL_matslots(UIList): row.prop(ma, "name", text="", emboss=False, icon_value=icon) row = layout.row(align=True) + if gpcolor.ghost is True: icon = 'ONIONSKIN_OFF' else: @@ -168,6 +169,8 @@ class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel): if gpcolor.mode == 'LINE': col.prop(gpcolor, "use_overlap_strokes") + col.prop(gpcolor, "use_stroke_holdout") + class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel): bl_label = "Fill" @@ -222,6 +225,8 @@ class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel): col.prop(gpcolor, "texture_scale", text="Scale") col.prop(gpcolor, "texture_clamp", text="Clip Image") + col.prop(gpcolor, "use_fill_holdout") + class MATERIAL_PT_gpencil_preview(GPMaterialButtonsPanel, Panel): bl_label = "Preview" diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index 363794e1be3..c4997dace7e 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -58,6 +58,17 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob) tgp_ob->is_drawmode3d = (gpd->draw_mode == GP_DRAWMODE_3D) || pd->draw_depth_only; tgp_ob->object_scale = mat4_to_scale(ob->obmat); + /* Check if any material with holdout flag enabled. */ + tgp_ob->do_mat_holdout = false; + for (int i = 0; i < ob->totcol; i++) { + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, i + 1); + if ((gp_style->flag & GP_MATERIAL_IS_STROKE_HOLDOUT) || + ((gp_style->flag & GP_MATERIAL_IS_FILL_HOLDOUT))) { + tgp_ob->do_mat_holdout = true; + break; + } + } + /* Find the normal most likely to represent the gpObject. */ /* TODO: This does not work quite well if you use * strokes not aligned with the object axes. Maybe we could try to diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index 7faf426c4e0..89e47f88eec 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -237,6 +237,14 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje mat_data->flag |= GP_STROKE_OVERLAP; } + /* Material with holdout. */ + if (gp_style->flag & GP_MATERIAL_IS_STROKE_HOLDOUT) { + mat_data->flag |= GP_STROKE_HOLDOUT; + } + if (gp_style->flag & GP_MATERIAL_IS_FILL_HOLDOUT) { + mat_data->flag |= GP_FILL_HOLDOUT; + } + gp_style = gpencil_viewport_material_overrides(pd, ob, color_type, gp_style); /* Stroke Style */ diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 7a516b3dd6b..0922ab6552c 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -80,6 +80,8 @@ typedef struct gpMaterial { #define GP_STROKE_TEXTURE_STENCIL (1 << 4) #define GP_STROKE_TEXTURE_PREMUL (1 << 5) #define GP_STROKE_DOTS (1 << 6) +#define GP_STROKE_HOLDOUT (1 << 7) +#define GP_FILL_HOLDOUT (1 << 8) #define GP_FILL_TEXTURE_USE (1 << 10) #define GP_FILL_TEXTURE_PREMUL (1 << 11) #define GP_FILL_TEXTURE_CLIP (1 << 12) @@ -194,6 +196,10 @@ typedef struct GPENCIL_tObject { float plane_mat[4][4]; bool is_drawmode3d; + + /* Use Material Holdout. */ + bool do_mat_holdout; + } GPENCIL_tObject; /* *********** LISTS *********** */ diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index cf6e78f4702..bf146add19d 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -585,10 +585,6 @@ void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObjec bGPdata *gpd = (bGPdata *)ob->data; GPENCIL_FramebufferList *fbl = vedata->fbl; GPENCIL_PrivateData *pd = vedata->stl->pd; - /* If simplify enabled, nothing more to do. */ - if (pd->simplify_fx) { - return; - } /* These may not be allocated yet, use adress of future pointer. */ gpIterVfxData iter = { @@ -601,44 +597,46 @@ void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObjec .target_reveal_tx = &pd->reveal_layer_tx, .source_reveal_tx = &pd->reveal_object_tx, }; - - LISTBASE_FOREACH (ShaderFxData *, fx, &ob->shader_fx) { - if (effect_is_active(gpd, fx, pd->is_viewport)) { - switch (fx->type) { - case eShaderFxType_Blur: - gpencil_vfx_blur((BlurShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Colorize: - gpencil_vfx_colorize((ColorizeShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Flip: - gpencil_vfx_flip((FlipShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Pixel: - gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Rim: - gpencil_vfx_rim((RimShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Shadow: - gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Glow: - gpencil_vfx_glow((GlowShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Swirl: - gpencil_vfx_swirl((SwirlShaderFxData *)fx, ob, &iter); - break; - case eShaderFxType_Wave: - gpencil_vfx_wave((WaveShaderFxData *)fx, ob, &iter); - break; - default: - break; + /* If simplify enabled, nothing more to do. */ + if (!pd->simplify_fx) { + LISTBASE_FOREACH (ShaderFxData *, fx, &ob->shader_fx) { + if (effect_is_active(gpd, fx, pd->is_viewport)) { + switch (fx->type) { + case eShaderFxType_Blur: + gpencil_vfx_blur((BlurShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Colorize: + gpencil_vfx_colorize((ColorizeShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Flip: + gpencil_vfx_flip((FlipShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Pixel: + gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Rim: + gpencil_vfx_rim((RimShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Shadow: + gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Glow: + gpencil_vfx_glow((GlowShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Swirl: + gpencil_vfx_swirl((SwirlShaderFxData *)fx, ob, &iter); + break; + case eShaderFxType_Wave: + gpencil_vfx_wave((WaveShaderFxData *)fx, ob, &iter); + break; + default: + break; + } } } } - if (tgp_ob->vfx.first != NULL) { + if ((!pd->simplify_fx && tgp_ob->vfx.first != NULL) || tgp_ob->do_mat_holdout) { /* We need an extra pass to combine result to main buffer. */ iter.target_fb = &fbl->gpencil_fb; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index e1323f01d9e..5e930af7bd7 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -34,6 +34,8 @@ struct gpMaterial { #define GP_STROKE_TEXTURE_STENCIL (1 << 4) #define GP_STROKE_TEXTURE_PREMUL (1 << 5) #define GP_STROKE_DOTS (1 << 6) +#define GP_STROKE_HOLDOUT (1 << 7) +#define GP_FILL_HOLDOUT (1 << 8) #define GP_FILL_TEXTURE_USE (1 << 10) #define GP_FILL_TEXTURE_PREMUL (1 << 11) #define GP_FILL_TEXTURE_CLIP (1 << 12) @@ -44,7 +46,7 @@ struct gpMaterial { /* Multiline defines can crash blender with certain GPU drivers. */ /* clang-format off */ -#define GP_FILL_FLAGS (GP_FILL_TEXTURE_USE | GP_FILL_TEXTURE_PREMUL | GP_FILL_TEXTURE_CLIP | GP_FILL_GRADIENT_USE | GP_FILL_GRADIENT_RADIAL) +#define GP_FILL_FLAGS (GP_FILL_TEXTURE_USE | GP_FILL_TEXTURE_PREMUL | GP_FILL_TEXTURE_CLIP | GP_FILL_GRADIENT_USE | GP_FILL_GRADIENT_RADIAL | GP_FILL_HOLDOUT) /* clang-format on */ #define GP_FLAG_TEST(flag, val) (((flag) & (val)) != 0) diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl index d81c6f4fe0b..8cf457ee4dd 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl @@ -89,14 +89,21 @@ void main() fragColor *= stroke_round_cap_mask( strokePt1, strokePt2, strokeAspect, strokeThickness, strokeHardeness); - /* For compatibility with colored alpha buffer. - * Note that we are limited to mono-chromatic alpha blending here - * because of the blend equation and the limit of 1 color target - * when using custom color blending. */ - revealColor = vec4(0.0, 0.0, 0.0, fragColor.a); + /* Holdout materials. */ + if (GP_FLAG_TEST(matFlag, GP_STROKE_HOLDOUT | GP_FILL_HOLDOUT)) { + revealColor = fragColor.aaaa; + } + else { + /* NOT holdout materials. + * For compatibility with colored alpha buffer. + * Note that we are limited to mono-chromatic alpha blending here + * because of the blend equation and the limit of 1 color target + * when using custom color blending. */ + revealColor = vec4(0.0, 0.0, 0.0, fragColor.a); - if (fragColor.a < 0.001) { - discard; + if (fragColor.a < 0.001) { + discard; + } } vec2 fb_size = max(vec2(textureSize(gpSceneDepthTexture, 0).xy), diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 3d050805f12..355d3d6439b 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -128,6 +128,10 @@ typedef enum eMaterialGPencilStyle_Flag { GP_MATERIAL_STROKE_TEX_MIX = (1 << 11), /* disable stencil clipping (overlap) */ GP_MATERIAL_DISABLE_STENCIL = (1 << 12), + /* Material used as stroke masking. */ + GP_MATERIAL_IS_STROKE_HOLDOUT = (1 << 13), + /* Material used as fill masking. */ + GP_MATERIAL_IS_FILL_HOLDOUT = (1 << 14), } eMaterialGPencilStyle_Flag; typedef enum eMaterialGPencilStyle_Mode { diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 1004fc94d16..c358b61d24c 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -564,6 +564,18 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) prop, "Self Overlap", "Disable stencil and overlap self intersections with alpha materials"); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); + prop = RNA_def_property(srna, "use_stroke_holdout", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_IS_STROKE_HOLDOUT); + RNA_def_property_ui_text( + prop, "Holdout", "Remove the color from underneath strokes using current stroke as mask"); + RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); + + prop = RNA_def_property(srna, "use_fill_holdout", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_IS_FILL_HOLDOUT); + RNA_def_property_ui_text( + prop, "Holdout", "Remove the color from underneath strokes using current stroke as mask"); + RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); + prop = RNA_def_property(srna, "show_stroke", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_STROKE_SHOW); RNA_def_property_ui_text(prop, "Show Stroke", "Show stroke lines of this material"); |