LineArt: Occlusion effectiveness support

This patch adds a function where you can specify occlusion effectiveness from 0 to 255 layers per face for a given mesh material.

Reviewed By: Sebastian Parborg (zeddb)

Ref D11308
This commit is contained in:
YimingWu 2021-06-28 22:26:23 +08:00
parent 9c6a382f95
commit cf21ba37ef
11 changed files with 157 additions and 113 deletions

View File

@ -291,12 +291,18 @@ class MATERIAL_PT_lineart(MaterialButtonsPanel, Panel):
mat = context.material
lineart = mat.lineart
layout.prop(lineart, "use_transparency")
layout.prop(lineart, "use_material_mask")
row = layout.row(align=True, heading="Masks")
row.active = lineart.use_transparency
row.active = lineart.use_material_mask
for i in range(8):
row.prop(lineart, "use_transparency_mask", text=str(i), index=i, toggle=True)
row.prop(lineart, "use_material_mask_bits", text=str(i), index=i, toggle=True)
row = layout.row(align=True, heading="Custom Occlusion")
row.prop(lineart, "use_mat_occlusion", text="")
sub = row.row(align=False)
sub.active = lineart.use_mat_occlusion
sub.prop(lineart, "mat_occlusion", slider=True, text="Levels")
classes = (

View File

@ -101,8 +101,8 @@ static void generate_strokes_actual(
lmd->use_multiple_levels ? lmd->level_end : lmd->level_start,
lmd->target_material ? BKE_gpencil_object_material_index_get(ob, lmd->target_material) : 0,
lmd->edge_types,
lmd->transparency_flags,
lmd->transparency_mask,
lmd->material_mask_flags,
lmd->material_mask_bits,
lmd->thickness,
lmd->opacity,
lmd->source_vertex_group,
@ -411,7 +411,7 @@ static void occlusion_panel_draw(const bContext *UNUSED(C), Panel *panel)
}
}
static void transparency_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
static void material_mask_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
@ -419,10 +419,10 @@ static void transparency_panel_draw_header(const bContext *UNUSED(C), Panel *pan
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
uiLayoutSetEnabled(layout, !is_baked);
uiItemR(layout, ptr, "use_transparency", 0, IFACE_("Transparency"), ICON_NONE);
uiItemR(layout, ptr, "use_material_mask", 0, IFACE_("Material Mask"), ICON_NONE);
}
static void transparency_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void material_mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
@ -432,21 +432,21 @@ static void transparency_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
uiLayoutSetEnabled(layout, RNA_boolean_get(ptr, "use_transparency"));
uiLayoutSetEnabled(layout, RNA_boolean_get(ptr, "use_material_mask"));
uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetPropDecorate(row, false);
uiLayout *sub = uiLayoutRowWithHeading(row, true, IFACE_("Masks"));
char text[2] = "0";
PropertyRNA *prop = RNA_struct_find_property(ptr, "use_transparency_mask");
PropertyRNA *prop = RNA_struct_find_property(ptr, "use_material_mask_bits");
for (int i = 0; i < 8; i++, text[0]++) {
uiItemFullR(sub, ptr, prop, i, 0, UI_ITEM_R_TOGGLE, text, ICON_NONE);
}
uiItemL(row, "", ICON_BLANK1); /* Space for decorator. */
uiLayout *col = uiLayoutColumn(layout, true);
uiItemR(col, ptr, "use_transparency_match", 0, IFACE_("Match All Masks"), ICON_NONE);
uiItemR(col, ptr, "use_material_mask_match", 0, IFACE_("Match All Masks"), ICON_NONE);
}
static void face_mark_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
@ -606,10 +606,10 @@ static void panelRegister(ARegionType *region_type)
PanelType *occlusion_panel = gpencil_modifier_subpanel_register(
region_type, "occlusion", "Occlusion", NULL, occlusion_panel_draw, panel_type);
gpencil_modifier_subpanel_register(region_type,
"transparency",
"material_mask",
"",
transparency_panel_draw_header,
transparency_panel_draw,
material_mask_panel_draw_header,
material_mask_panel_draw,
occlusion_panel);
gpencil_modifier_subpanel_register(
region_type, "face_mark", "", face_mark_panel_draw_header, face_mark_panel_draw, panel_type);

View File

@ -53,7 +53,8 @@ typedef struct LineartTriangle {
double gn[3];
/* Material flag is removed to save space. */
unsigned char transparency_mask;
unsigned char material_mask_bits;
unsigned char mat_occlusion;
unsigned char flags; /* #eLineartTriangleFlags */
/**
@ -101,13 +102,8 @@ typedef struct LineartEdgeSegment {
/** Occlusion level after "at" point */
unsigned char occlusion;
/**
* For determining lines behind a glass window material.
* the size of this variable should also be dynamically decided, 1 byte to 8 byte,
* allows 8 to 64 materials for "transparent mask". 1 byte (8 materials) should be
* enough for most cases.
*/
unsigned char transparency_mask;
/* Used to filter line art occlusion edges */
unsigned char material_mask_bits;
} LineartEdgeSegment;
typedef struct LineartVert {
@ -177,7 +173,7 @@ typedef struct LineartEdgeChain {
/** Chain now only contains one type of segments */
int type;
unsigned char transparency_mask;
unsigned char material_mask_bits;
struct Object *object_ref;
} LineartEdgeChain;
@ -191,7 +187,7 @@ typedef struct LineartEdgeChainItem {
float normal[3];
unsigned char line_type;
char occlusion;
unsigned char transparency_mask;
unsigned char material_mask_bits;
size_t index;
} LineartEdgeChainItem;
@ -616,8 +612,8 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
int level_end,
int mat_nr,
short edge_types,
unsigned char transparency_flags,
unsigned char transparency_mask,
unsigned char material_mask_flags,
unsigned char material_mask_bits,
short thickness,
float opacity,
const char *source_vgname,

View File

@ -103,7 +103,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
float *normal,
char type,
int level,
unsigned char transparency_mask,
unsigned char material_mask_bits,
size_t index)
{
LineartEdgeChainItem *eci;
@ -115,7 +115,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
LineartEdgeChainItem *old_rlci = ec->chain.last;
old_rlci->line_type = type;
old_rlci->occlusion = level;
old_rlci->transparency_mask = transparency_mask;
old_rlci->material_mask_bits = material_mask_bits;
return old_rlci;
}
@ -127,7 +127,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
copy_v3_v3(eci->normal, normal);
eci->line_type = type & LRT_EDGE_FLAG_ALL_TYPE;
eci->occlusion = level;
eci->transparency_mask = transparency_mask;
eci->material_mask_bits = material_mask_bits;
BLI_addtail(&ec->chain, eci);
return eci;
@ -140,7 +140,7 @@ static LineartEdgeChainItem *lineart_chain_prepend_point(LineartRenderBuffer *rb
float *normal,
char type,
int level,
unsigned char transparency_mask,
unsigned char material_mask_bits,
size_t index)
{
LineartEdgeChainItem *eci;
@ -157,7 +157,7 @@ static LineartEdgeChainItem *lineart_chain_prepend_point(LineartRenderBuffer *rb
copy_v3_v3(eci->normal, normal);
eci->line_type = type & LRT_EDGE_FLAG_ALL_TYPE;
eci->occlusion = level;
eci->transparency_mask = transparency_mask;
eci->material_mask_bits = material_mask_bits;
BLI_addhead(&ec->chain, eci);
return eci;
@ -228,7 +228,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
N,
e->flags,
es->occlusion,
es->transparency_mask,
es->material_mask_bits,
e->v1_obindex);
while (ba && (new_e = lineart_line_get_connected(ba, new_vt, &new_vt, e->flags))) {
new_e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED;
@ -263,16 +263,16 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
N,
new_e->flags,
es->occlusion,
es->transparency_mask,
es->material_mask_bits,
new_e->v1_obindex);
last_occlusion = es->occlusion;
last_transparency = es->transparency_mask;
last_transparency = es->material_mask_bits;
}
}
else if (new_vt == new_e->v2) {
es = new_e->segments.first;
last_occlusion = es->occlusion;
last_transparency = es->transparency_mask;
last_transparency = es->material_mask_bits;
es = es->next;
for (; es; es = es->next) {
double gpos[3], lpos[3];
@ -291,7 +291,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
last_transparency,
new_e->v2_obindex);
last_occlusion = es->occlusion;
last_transparency = es->transparency_mask;
last_transparency = es->material_mask_bits;
}
VERT_COORD_TO_FLOAT(new_e->v2);
lineart_chain_prepend_point(rb,
@ -326,7 +326,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
* of the line. */
es = e->segments.first;
last_occlusion = ((LineartEdgeSegment *)es)->occlusion;
last_transparency = ((LineartEdgeSegment *)es)->transparency_mask;
last_transparency = ((LineartEdgeSegment *)es)->material_mask_bits;
for (es = es->next; es; es = es->next) {
double gpos[3], lpos[3];
double *lfb = e->v1->fbcoord, *rfb = e->v2->fbcoord;
@ -341,10 +341,10 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
N,
e->flags,
es->occlusion,
es->transparency_mask,
es->material_mask_bits,
e->v1_obindex);
last_occlusion = es->occlusion;
last_transparency = es->transparency_mask;
last_transparency = es->material_mask_bits;
}
VERT_COORD_TO_FLOAT(e->v2)
lineart_chain_append_point(rb,
@ -385,10 +385,10 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
if (new_vt == new_e->v1) {
es = new_e->segments.last;
last_occlusion = es->occlusion;
last_transparency = es->transparency_mask;
last_transparency = es->material_mask_bits;
/* Fix leading vertex occlusion. */
eci->occlusion = last_occlusion;
eci->transparency_mask = last_transparency;
eci->material_mask_bits = last_transparency;
for (es = new_e->segments.last; es; es = es->prev) {
double gpos[3], lpos[3];
double *lfb = new_e->v1->fbcoord, *rfb = new_e->v2->fbcoord;
@ -396,7 +396,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at);
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
last_occlusion = es->prev ? es->prev->occlusion : last_occlusion;
last_transparency = es->prev ? es->prev->transparency_mask : last_transparency;
last_transparency = es->prev ? es->prev->material_mask_bits : last_transparency;
POS_TO_FLOAT(lpos, gpos)
lineart_chain_append_point(rb,
ec,
@ -412,9 +412,9 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
else if (new_vt == new_e->v2) {
es = new_e->segments.first;
last_occlusion = es->occlusion;
last_transparency = es->transparency_mask;
last_transparency = es->material_mask_bits;
eci->occlusion = last_occlusion;
eci->transparency_mask = last_transparency;
eci->material_mask_bits = last_transparency;
es = es->next;
for (; es; es = es->next) {
double gpos[3], lpos[3];
@ -430,10 +430,10 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
N,
new_e->flags,
es->occlusion,
es->transparency_mask,
es->material_mask_bits,
new_e->v2_obindex);
last_occlusion = es->occlusion;
last_transparency = es->transparency_mask;
last_transparency = es->material_mask_bits;
}
VERT_COORD_TO_FLOAT(new_e->v2)
lineart_chain_append_point(rb,
@ -574,12 +574,12 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
BLI_addtail(&rb->chains, ec);
LineartEdgeChainItem *first_rlci = (LineartEdgeChainItem *)ec->chain.first;
int fixed_occ = first_rlci->occlusion;
unsigned char fixed_mask = first_rlci->transparency_mask;
unsigned char fixed_mask = first_rlci->material_mask_bits;
ec->level = fixed_occ;
ec->transparency_mask = fixed_mask;
ec->material_mask_bits = fixed_mask;
for (eci = first_rlci->next; eci; eci = next_rlci) {
next_rlci = eci->next;
if (eci->occlusion != fixed_occ || eci->transparency_mask != fixed_mask) {
if (eci->occlusion != fixed_occ || eci->material_mask_bits != fixed_mask) {
if (next_rlci) {
if (lineart_point_overlapping(next_rlci, eci->pos[0], eci->pos[1], 1e-5)) {
continue;
@ -589,7 +589,7 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
/* Set the same occlusion level for the end vertex, so when further connection is needed
* the backwards occlusion info is also correct. */
eci->occlusion = fixed_occ;
eci->transparency_mask = fixed_mask;
eci->material_mask_bits = fixed_mask;
/* No need to split at the last point anyway. */
break;
}
@ -614,9 +614,9 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
new_rlc->type = ec->type;
ec = new_rlc;
fixed_occ = eci->occlusion;
fixed_mask = eci->transparency_mask;
fixed_mask = eci->material_mask_bits;
ec->level = fixed_occ;
ec->transparency_mask = fixed_mask;
ec->material_mask_bits = fixed_mask;
}
}
}
@ -683,7 +683,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
LineartEdgeChain *ec,
LineartEdgeChainItem *eci,
int occlusion,
unsigned char transparency_mask,
unsigned char material_mask_bits,
float dist,
float *result_new_len,
LineartBoundingArea *caller_ba)
@ -712,7 +712,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
continue;
}
if (cre->ec == ec || (!cre->ec->chain.first) || (cre->ec->level != occlusion) ||
(cre->ec->transparency_mask != transparency_mask)) {
(cre->ec->material_mask_bits != material_mask_bits)) {
continue;
}
if (!rb->fuzzy_everything) {
@ -749,7 +749,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
LISTBASE_FOREACH (LinkData *, ld, list) { \
LineartBoundingArea *sba = (LineartBoundingArea *)ld->data; \
adjacent_closest = lineart_chain_get_closest_cre( \
rb, sba, ec, eci, occlusion, transparency_mask, dist, &adjacent_new_len, ba); \
rb, sba, ec, eci, occlusion, material_mask_bits, dist, &adjacent_new_len, ba); \
if (adjacent_new_len < dist) { \
dist = adjacent_new_len; \
closest_cre = adjacent_closest; \
@ -782,7 +782,7 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
float dist = rb->chaining_image_threshold;
float dist_l, dist_r;
int occlusion, reverse_main;
unsigned char transparency_mask;
unsigned char material_mask_bits;
ListBase swap = {0};
if (rb->chaining_image_threshold < 0.0001) {
@ -806,16 +806,16 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
}
occlusion = ec->level;
transparency_mask = ec->transparency_mask;
material_mask_bits = ec->material_mask_bits;
rlci_l = ec->chain.first;
rlci_r = ec->chain.last;
while ((ba_l = lineart_bounding_area_get_end_point(rb, rlci_l)) &&
(ba_r = lineart_bounding_area_get_end_point(rb, rlci_r))) {
closest_cre_l = lineart_chain_get_closest_cre(
rb, ba_l, ec, rlci_l, occlusion, transparency_mask, dist, &dist_l, NULL);
rb, ba_l, ec, rlci_l, occlusion, material_mask_bits, dist, &dist_l, NULL);
closest_cre_r = lineart_chain_get_closest_cre(
rb, ba_r, ec, rlci_r, occlusion, transparency_mask, dist, &dist_r, NULL);
rb, ba_r, ec, rlci_r, occlusion, material_mask_bits, dist, &dist_r, NULL);
if (closest_cre_l && closest_cre_r) {
if (dist_l < dist_r) {
closest_cre = closest_cre_l;
@ -949,12 +949,12 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
eci->normal,
eci->line_type,
ec->level,
eci->transparency_mask,
eci->material_mask_bits,
eci->index);
new_rlc->object_ref = ec->object_ref;
new_rlc->type = ec->type;
new_rlc->level = ec->level;
new_rlc->transparency_mask = ec->transparency_mask;
new_rlc->material_mask_bits = ec->material_mask_bits;
ec = new_rlc;
}
}

View File

@ -146,8 +146,12 @@ static LineartEdgeSegment *lineart_give_segment(LineartRenderBuffer *rb)
/**
* Cuts the edge in image space and mark occlusion level for each segment.
*/
static void lineart_edge_cut(
LineartRenderBuffer *rb, LineartEdge *e, double start, double end, uchar transparency_mask)
static void lineart_edge_cut(LineartRenderBuffer *rb,
LineartEdge *e,
double start,
double end,
uchar material_mask_bits,
uchar mat_occlusion)
{
LineartEdgeSegment *es, *ies, *next_es, *prev_es;
LineartEdgeSegment *cut_start_before = 0, *cut_end_before = 0;
@ -240,7 +244,7 @@ static void lineart_edge_cut(
/* Insert cutting points for when a new cut is needed. */
ies = cut_start_before->prev ? cut_start_before->prev : NULL;
ns->occlusion = ies ? ies->occlusion : 0;
ns->transparency_mask = ies->transparency_mask;
ns->material_mask_bits = ies->material_mask_bits;
BLI_insertlinkbefore(&e->segments, cut_start_before, ns);
}
/* Otherwise we already found a existing cutting point, no need to insert a new one. */
@ -250,7 +254,7 @@ static void lineart_edge_cut(
* append the new cut to the end. */
ies = e->segments.last;
ns->occlusion = ies->occlusion;
ns->transparency_mask = ies->transparency_mask;
ns->material_mask_bits = ies->material_mask_bits;
BLI_addtail(&e->segments, ns);
}
if (cut_end_before) {
@ -258,14 +262,14 @@ static void lineart_edge_cut(
if (cut_end_before != ns2) {
ies = cut_end_before->prev ? cut_end_before->prev : NULL;
ns2->occlusion = ies ? ies->occlusion : 0;
ns2->transparency_mask = ies ? ies->transparency_mask : 0;
ns2->material_mask_bits = ies ? ies->material_mask_bits : 0;
BLI_insertlinkbefore(&e->segments, cut_end_before, ns2);
}
}
else {
ies = e->segments.last;
ns2->occlusion = ies->occlusion;
ns2->transparency_mask = ies->transparency_mask;
ns2->material_mask_bits = ies->material_mask_bits;
BLI_addtail(&e->segments, ns2);
}
@ -282,8 +286,8 @@ static void lineart_edge_cut(
/* Register 1 level of occlusion for all touched segments. */
for (es = ns; es && es != ns2; es = es->next) {
es->occlusion++;
es->transparency_mask |= transparency_mask;
es->occlusion += mat_occlusion;
es->material_mask_bits |= material_mask_bits;
}
/* Reduce adjacent cutting points of the same level, which saves memory. */
@ -293,7 +297,7 @@ static void lineart_edge_cut(
next_es = es->next;
if (prev_es && prev_es->occlusion == es->occlusion &&
prev_es->transparency_mask == es->transparency_mask) {
prev_es->material_mask_bits == es->material_mask_bits) {
BLI_remlink(&e->segments, es);
/* This puts the node back to the render buffer, if more cut happens, these unused nodes get
* picked first. */
@ -373,7 +377,11 @@ static void lineart_occlusion_single_line(LineartRenderBuffer *rb, LineartEdge *
tri = (LineartTriangleThread *)nba->linked_triangles[i];
/* If we are already testing the line in this thread, then don't do it. */
if (tri->testing_e[thread_id] == e || (tri->base.flags & LRT_TRIANGLE_INTERSECTION_ONLY) ||
lineart_occlusion_is_adjacent_intersection(e, (LineartTriangle *)tri)) {
/* Ignore this triangle if an intersection line directly comes from it, */
lineart_occlusion_is_adjacent_intersection(e, (LineartTriangle *)tri) ||
/* Or if this triangle isn't effectively occluding anything nor it's providing a
material flag. */
((!tri->base.mat_occlusion) && (!tri->base.material_mask_bits))) {
continue;
}
tri->testing_e[thread_id] = e;
@ -389,7 +397,7 @@ static void lineart_occlusion_single_line(LineartRenderBuffer *rb, LineartEdge *
rb->shift_y,
&l,
&r)) {
lineart_edge_cut(rb, e, l, r, tri->base.transparency_mask);
lineart_edge_cut(rb, e, l, r, tri->base.material_mask_bits, tri->base.mat_occlusion);
if (e->min_occ > rb->max_occlusion_level) {
/* No need to calculate any longer on this line because no level more than set value is
* going to show up in the rendered result. */
@ -726,7 +734,7 @@ static void lineart_triangle_post(LineartTriangle *tri, LineartTriangle *orig)
/* Just re-assign normal and set cull flag. */
copy_v3_v3_db(tri->gn, orig->gn);
tri->flags = LRT_CULL_GENERATED;
tri->transparency_mask = orig->transparency_mask;
tri->material_mask_bits = orig->material_mask_bits;
}
static void lineart_triangle_set_cull_flag(LineartTriangle *tri, uchar flag)
@ -1782,11 +1790,15 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
loop = loop->next;
tri->v[2] = &orv[BM_elem_index_get(loop->v)];
/* Transparency bit assignment. */
/* Material mask bits and occlusion effectiveness assignment. */
Material *mat = BKE_object_material_get(orig_ob, f->mat_nr + 1);
tri->transparency_mask = ((mat && (mat->lineart.flags & LRT_MATERIAL_TRANSPARENCY_ENABLED)) ?
mat->lineart.transparency_mask :
0);
tri->material_mask_bits |= ((mat && (mat->lineart.flags & LRT_MATERIAL_MASK_ENABLED)) ?
mat->lineart.material_mask_bits :
0);
tri->mat_occlusion |= ((mat &&
(mat->lineart.flags & LRT_MATERIAL_CUSTOM_OCCLUSION_EFFECTIVENESS)) ?
mat->lineart.mat_occlusion :
1);
double gn[3];
copy_v3db_v3fl(gn, f->no);
@ -4172,8 +4184,8 @@ static void lineart_gpencil_generate(LineartCache *cache,
Object *source_object,
Collection *source_collection,
int types,
uchar transparency_flags,
uchar transparency_mask,
uchar material_mask_flags,
uchar material_mask_bits,
short thickness,
float opacity,
const char *source_vgname,
@ -4229,14 +4241,14 @@ static void lineart_gpencil_generate(LineartCache *cache,
continue;
}
}
if (transparency_flags & LRT_GPENCIL_TRANSPARENCY_ENABLE) {
if (transparency_flags & LRT_GPENCIL_TRANSPARENCY_MATCH) {
if (ec->transparency_mask != transparency_mask) {
if (material_mask_flags & LRT_GPENCIL_MATERIAL_MASK_ENABLE) {
if (material_mask_flags & LRT_GPENCIL_MATERIAL_MASK_MATCH) {
if (ec->material_mask_bits != material_mask_bits) {
continue;
}
}
else {
if (!(ec->transparency_mask & transparency_mask)) {
if (!(ec->material_mask_bits & material_mask_bits)) {
continue;
}
}
@ -4335,8 +4347,8 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
int level_end,
int mat_nr,
short edge_types,
uchar transparency_flags,
uchar transparency_mask,
uchar material_mask_flags,
uchar material_mask_bits,
short thickness,
float opacity,
const char *source_vgname,
@ -4384,8 +4396,8 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
source_object,
source_collection,
use_types,
transparency_flags,
transparency_mask,
material_mask_flags,
material_mask_bits,
thickness,
opacity,
source_vgname,

View File

@ -143,8 +143,8 @@ static bool bake_strokes(Object *ob,
lmd->use_multiple_levels ? lmd->level_end : lmd->level_start,
lmd->target_material ? BKE_gpencil_object_material_index_get(ob, lmd->target_material) : 0,
lmd->edge_types,
lmd->transparency_flags,
lmd->transparency_mask,
lmd->material_mask_flags,
lmd->material_mask_bits,
lmd->thickness,
lmd->opacity,
lmd->source_vertex_group,

View File

@ -883,11 +883,11 @@ typedef enum eLineArtGPencilModifierFlags {
LRT_GPENCIL_USE_CACHE = (1 << 4),
} eLineArtGPencilModifierFlags;
typedef enum eLineartGpencilTransparencyFlags {
LRT_GPENCIL_TRANSPARENCY_ENABLE = (1 << 0),
/** Set to true means using "and" instead of "or" logic on mask bits. */
LRT_GPENCIL_TRANSPARENCY_MATCH = (1 << 1),
} eLineartGpencilTransparencyFlags;
typedef enum eLineartGpencilMaterialMaskFlags {
LRT_GPENCIL_MATERIAL_MASK_ENABLE = (1 << 0),
/** When set, material mask bit comparisons are done with bit wise "AND" instead of "OR". */
LRT_GPENCIL_MATERIAL_MASK_MATCH = (1 << 1),
} eLineartGpencilMaterialMaskFlags;
struct LineartCache;
@ -918,8 +918,8 @@ typedef struct LineartGpencilModifierData {
float opacity;
short thickness;
unsigned char transparency_flags; /* eLineartGpencilTransparencyFlags */
unsigned char transparency_mask;
unsigned char material_mask_flags; /* eLineartGpencilMaterialMaskFlags */
unsigned char material_mask_bits;
/** `0..1` range for cosine angle */
float crease_threshold;

View File

@ -146,13 +146,21 @@ typedef enum eMaterialGPencilStyle_Mode {
} eMaterialGPencilStyle_Mode;
typedef struct MaterialLineArt {
int flags; /* eMaterialLineArtFlags */
unsigned char transparency_mask;
unsigned char _pad[3];
/* eMaterialLineArtFlags */
int flags;
/* Used to filter line art occlusion edges */
unsigned char material_mask_bits;
/** Maximum 255 levels of equavalent occlusion. */
unsigned char mat_occlusion;
unsigned char _pad[2];
} MaterialLineArt;
typedef enum eMaterialLineArtFlags {
LRT_MATERIAL_TRANSPARENCY_ENABLED = (1 << 0),
LRT_MATERIAL_MASK_ENABLED = (1 << 0),
LRT_MATERIAL_CUSTOM_OCCLUSION_EFFECTIVENESS = (1 << 1),
} eMaterialLineArtFlags;
typedef struct Material {

View File

@ -134,3 +134,6 @@ DNA_STRUCT_RENAME_ELEM(RigidBodyWorld, steps_per_second, substeps_per_frame)
* global_areas. See D9442. */
DNA_STRUCT_RENAME_ELEM(wmWindow, global_area_map, global_areas)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, material_mask_flags)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits)
DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits)

View File

@ -2997,20 +2997,22 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_transparency", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transparency_flags", LRT_GPENCIL_TRANSPARENCY_ENABLE);
prop = RNA_def_property(srna, "use_material_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, NULL, "material_mask_flags", LRT_GPENCIL_MATERIAL_MASK_ENABLE);
RNA_def_property_ui_text(
prop, "Use Transparency", "Use transparency mask from this material in line art");
prop, "Use Material Mask", "Use material masks to filter out occluded strokes");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_transparency_match", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transparency_flags", LRT_GPENCIL_TRANSPARENCY_MATCH);
prop = RNA_def_property(srna, "use_material_mask_match", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, NULL, "material_mask_flags", LRT_GPENCIL_MATERIAL_MASK_MATCH);
RNA_def_property_ui_text(
prop, "Match Transparency", "Require matching all transparency masks instead of just one");
prop, "Match Masks", "Require matching all material masks instead of just one");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_transparency_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transparency_mask", 1);
prop = RNA_def_property(srna, "use_material_mask_bits", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "material_mask_bits", 1);
RNA_def_property_array(prop, 8);
RNA_def_property_ui_text(prop, "Mask", "");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");

View File

@ -688,19 +688,36 @@ static void rna_def_material_lineart(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MaterialLineArt");
RNA_def_struct_ui_text(srna, "Material Line Art", "");
prop = RNA_def_property(srna, "use_transparency", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "use_material_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LRT_MATERIAL_TRANSPARENCY_ENABLED);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LRT_MATERIAL_MASK_ENABLED);
RNA_def_property_ui_text(
prop, "Use Transparency", "Use transparency mask from this material in line art");
prop, "Use Material Mask", "Use material masks to filter out occluded strokes");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialLineArt_update");
prop = RNA_def_property(srna, "use_transparency_mask", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "use_material_mask_bits", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_boolean_sdna(prop, NULL, "transparency_mask", 1);
RNA_def_property_boolean_sdna(prop, NULL, "material_mask_bits", 1);
RNA_def_property_array(prop, 8);
RNA_def_property_ui_text(prop, "Mask", "");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialLineArt_update");
prop = RNA_def_property(srna, "use_mat_occlusion", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LRT_MATERIAL_CUSTOM_OCCLUSION_EFFECTIVENESS);
RNA_def_property_ui_text(prop,
"Custom Occlusion Effectiveness",
"Use custom occlusion effectiveness for this material");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialLineArt_update");
prop = RNA_def_property(srna, "mat_occlusion", PROP_INT, PROP_NONE);
RNA_def_property_int_default(prop, 1);
RNA_def_property_ui_range(prop, 0.0f, 5.0f, 1.0f, 1);
RNA_def_property_ui_text(
prop,
"Effectiveness",
"Faces with this material will behave as if it has set number of layers in occlusion");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialLineArt_update");
}
void RNA_def_material(BlenderRNA *brna)