GPencil: Fading based on distance to reference object in Opacity and Thickness modifiers

This patch allows you to dynamically control stroke's opacity and thickness using an object for distance reference in the modifier. Fading range is adjustable, and it is compatible with current curve/vertex group selection.

Reviewed By: #grease_pencil, antoniov, mendio

Maniphest Tasks: T82177, T80194

Differential Revision: https://developer.blender.org/D9091
This commit is contained in:
YimingWu 2021-04-28 16:46:46 +02:00 committed by Antonio Vazquez
parent 67a52c8a40
commit f8f7c0ca6d
Notes: blender-bot 2023-02-14 07:25:51 +01:00
Referenced by issue #82177, Grease pencil fading settings for Thickness and Opacity
Referenced by issue #80194, LineArt: New module to generate lines over meshes using grease pencil as target
7 changed files with 233 additions and 4 deletions

View File

@ -203,6 +203,21 @@ void gpencil_modifier_curve_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiTemplateCurveMapping(layout, ptr, "curve", 0, false, false, false, false);
}
void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel)
{
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiLayout *layout = panel->layout;
uiLayoutSetPropSep(layout, true);
bool fading_enabled = RNA_boolean_get(ptr, "use_fading");
uiItemR(layout, ptr, "object", 0, NULL, ICON_CUBE);
uiLayout *sub = uiLayoutColumn(layout, true);
uiItemR(sub, ptr, "fading_start", 0, NULL, ICON_NONE);
uiItemR(sub, ptr, "fading_end", 0, IFACE_("End"), ICON_NONE);
uiItemR(layout, ptr, "fading_end_factor", 0, NULL, ICON_NONE);
}
/**
* Draw modifier error message.
*/

View File

@ -37,6 +37,8 @@ void gpencil_modifier_masking_panel_draw(Panel *panel, bool use_material, bool u
void gpencil_modifier_curve_header_draw(const bContext *C, Panel *panel);
void gpencil_modifier_curve_panel_draw(const bContext *C, Panel *panel);
void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel);
void gpencil_modifier_panel_end(struct uiLayout *layout, PointerRNA *ptr);
struct PointerRNA *gpencil_modifier_panel_get_property_pointers(struct Panel *panel,

View File

@ -47,6 +47,8 @@
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
#include "UI_resources.h"
@ -84,6 +86,39 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
static float give_opacity_fading_factor(OpacityGpencilModifierData *mmd,
Object *ob_this,
float *pos,
bool apply_obmat)
{
float factor_depth = 1;
if (((mmd->flag & GP_OPACITY_FADING) == 0) || ((mmd->object) == NULL)) {
return factor_depth;
}
float gvert[3];
if (apply_obmat) {
mul_v3_m4v3(gvert, ob_this->obmat, pos);
}
float dist = len_v3v3(mmd->object->obmat[3], gvert);
float fading_max = MAX2(mmd->fading_start, mmd->fading_end);
float fading_min = MIN2(mmd->fading_start, mmd->fading_end);
/* Better with ratiof() function from line art. */
if (dist > fading_max) {
factor_depth = 0;
}
else if (dist <= fading_max && dist > fading_min) {
factor_depth = (fading_max - dist) / (fading_max - fading_min);
}
else {
factor_depth = 1;
}
return factor_depth;
}
/* opacity strokes */
static void deformStroke(GpencilModifierData *md,
Depsgraph *UNUSED(depsgraph),
@ -138,6 +173,9 @@ static void deformStroke(GpencilModifierData *md,
factor_curve *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
}
float factor_depth = give_opacity_fading_factor(mmd, ob, &pt->x, true);
factor_curve = interpf(factor_curve, mmd->fading_end_factor, factor_depth);
if (def_nr < 0) {
if (mmd->flag & GP_OPACITY_NORMALIZE) {
pt->strength = factor_curve;
@ -167,6 +205,10 @@ static void deformStroke(GpencilModifierData *md,
/* Fill using opacity factor. */
if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
gps->fill_opacity_fac = mmd->factor;
float factor_depth = give_opacity_fading_factor(mmd, ob, ob->obmat[3], true);
gps->fill_opacity_fac = interpf(mmd->factor, mmd->fading_end_factor, factor_depth);
CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f);
}
}
@ -201,6 +243,18 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(GpencilModifierData *md,
const ModifierUpdateDepsgraphContext *ctx,
const int UNUSED(mode))
{
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
if (mmd->object != NULL) {
DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier");
}
DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier");
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@ -228,6 +282,20 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
gpencil_modifier_panel_end(layout, ptr);
}
static void fading_header_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE);
}
static void fading_panel_draw(const bContext *C, Panel *panel)
{
gpencil_modifier_fading_draw(C, panel);
}
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
@ -266,6 +334,9 @@ static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Opacity, panel_draw);
gpencil_modifier_subpanel_register(
region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type);
PanelType *mask_panel_type = gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
@ -289,7 +360,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
/* initData */ initData,
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ NULL,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,

View File

@ -43,6 +43,8 @@
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
#include "UI_resources.h"
@ -128,6 +130,30 @@ static void deformStroke(GpencilModifierData *md,
}
float curvef = 1.0f;
float factor_depth = 1;
if (mmd->flag & GP_THICK_FADING) {
if (mmd->object) {
float gvert[3];
mul_v3_m4v3(gvert, ob->obmat, &pt->x);
float dist = len_v3v3(mmd->object->obmat[3], gvert);
float fading_max = MAX2(mmd->fading_start, mmd->fading_end);
float fading_min = MIN2(mmd->fading_start, mmd->fading_end);
/* Better with ratiof() function from line art. */
if (dist > fading_max) {
factor_depth = 0;
}
else if (dist <= fading_max && dist > fading_min) {
factor_depth = (fading_max - dist) / (fading_max - fading_min);
}
else {
factor_depth = 1;
}
}
}
if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) {
/* Normalize value to evaluate curve. */
float value = (float)i / (gps->totpoints - 1);
@ -144,6 +170,9 @@ static void deformStroke(GpencilModifierData *md,
weight *= curvef;
}
float fac_begin = mmd->flag & GP_THICK_NORMALIZE ? 1 : mmd->thickness_fac;
target *= interpf(fac_begin, mmd->fading_end_factor, factor_depth);
pt->pressure = interpf(target, pt->pressure, weight);
CLAMP_MIN(pt->pressure, 0.0f);
@ -171,6 +200,32 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(GpencilModifierData *md,
const ModifierUpdateDepsgraphContext *ctx,
const int UNUSED(mode))
{
ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
if (mmd->object != NULL) {
DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier");
}
DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier");
}
static void fading_header_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE);
}
static void fading_panel_draw(const bContext *C, Panel *panel)
{
gpencil_modifier_fading_draw(C, panel);
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@ -202,6 +257,8 @@ static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Thick, panel_draw);
gpencil_modifier_subpanel_register(
region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type);
PanelType *mask_panel_type = gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
gpencil_modifier_subpanel_register(region_type,
@ -229,7 +286,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = {
/* initData */ initData,
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ NULL,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,

View File

@ -184,6 +184,8 @@
.layer_pass = 0, \
.hardeness = 1.0f, \
.curve_intensity = NULL, \
.fading_end = 10.0f, \
.fading_end_factor = 0.2f, \
}
#define _DNA_DEFAULT_SimplifyGpencilModifierData \
@ -251,6 +253,8 @@
.thickness_fac = 1.0f, \
.thickness = 30, \
.layer_pass = 0, \
.fading_end = 10.0f, \
.fading_end_factor = 0.2f, \
}
#define _DNA_DEFAULT_TimeGpencilModifierData \

View File

@ -187,7 +187,12 @@ typedef struct ThickGpencilModifierData {
int thickness;
/** Custom index for passes. */
int layer_pass;
char _pad[4];
/** Start/end distances of the fading effect. */
float fading_start;
float fading_end;
float fading_end_factor;
/** Fading reference object */
struct Object *object;
struct CurveMapping *curve_thickness;
} ThickGpencilModifierData;
@ -199,6 +204,7 @@ typedef enum eThickGpencil_Flag {
GP_THICK_NORMALIZE = (1 << 4),
GP_THICK_INVERT_LAYERPASS = (1 << 5),
GP_THICK_INVERT_MATERIAL = (1 << 6),
GP_THICK_FADING = (1 << 7),
} eThickGpencil_Flag;
typedef struct TimeGpencilModifierData {
@ -291,9 +297,16 @@ typedef struct OpacityGpencilModifierData {
int flag;
/** Main Opacity factor. */
float factor;
/** Fading controlling object */
int _pad0;
struct Object *object;
/** Start/end distances of the fading effect. */
float fading_start;
float fading_end;
float fading_end_factor;
/** Modify stroke, fill or both. */
char modify_color;
char _pad[3];
char _pad1[3];
/** Custom index for passes. */
int layer_pass;
@ -309,6 +322,7 @@ typedef enum eOpacityGpencil_Flag {
GP_OPACITY_INVERT_MATERIAL = (1 << 5),
GP_OPACITY_CUSTOM_CURVE = (1 << 6),
GP_OPACITY_NORMALIZE = (1 << 7),
GP_OPACITY_FADING = (1 << 8),
} eOpacityGpencil_Flag;
typedef struct ArrayGpencilModifierData {

View File

@ -351,6 +351,8 @@ static void greasepencil_modifier_object_set(Object *self,
RNA_GP_MOD_OBJECT_SET(Armature, object, OB_ARMATURE);
RNA_GP_MOD_OBJECT_SET(Lattice, object, OB_LATTICE);
RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY);
RNA_GP_MOD_OBJECT_SET(Opacity, object, OB_EMPTY);
RNA_GP_MOD_OBJECT_SET(Thick, object, OB_EMPTY);
# undef RNA_GP_MOD_OBJECT_SET
@ -1116,6 +1118,38 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Thickness Factor", "Factor to multiply the thickness with");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_FADING);
RNA_def_property_ui_text(prop, "Fading", "Fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
/* Distance reference object */
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
RNA_def_property_pointer_funcs(prop, NULL, "rna_ThickGpencilModifier_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_start");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end_factor");
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3);
RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "pass_index");
RNA_def_property_range(prop, 0, 100);
@ -1625,6 +1659,38 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hardness", "Factor of stroke hardness");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_FADING);
RNA_def_property_ui_text(prop, "Fading", "Fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
/* Distance reference object */
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
RNA_def_property_pointer_funcs(prop, NULL, "rna_OpacityGpencilModifier_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_start");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end_factor");
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3);
RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "pass_index");
RNA_def_property_range(prop, 0, 100);