LineArt: Option to keep contour when using face mark filtering.

When enabled, it will keep contour around the object instead of hide them by rule of face mark,
so the object can always have full contour while filtering out some of the feature lines inside certain regions.

Reviewed By: Antonio Vazquez (antoniov), Aleš Jelovčan (frogstomp)

Differential Revision: https://developer.blender.org/D13847
This commit is contained in:
YimingWu 2022-01-22 16:57:25 +08:00
parent 579e8ebe79
commit dde997086c
Notes: blender-bot 2023-02-13 18:10:37 +01:00
Referenced by issue #87739, Line Art further improvement list
6 changed files with 40 additions and 12 deletions

View File

@ -581,6 +581,7 @@ static void face_mark_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(layout, ptr, "use_face_mark_invert", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_face_mark_boundaries", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_face_mark_keep_contour", 0, NULL, ICON_NONE);
}
static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)

View File

@ -305,6 +305,7 @@ typedef struct LineartRenderBuffer {
bool filter_face_mark;
bool filter_face_mark_invert;
bool filter_face_mark_boundaries;
bool filter_face_mark_keep_contour;
bool force_crease;
bool sharp_as_crease;

View File

@ -1493,6 +1493,7 @@ static uint16_t lineart_identify_feature_line(LineartRenderBuffer *rb,
FreestyleEdge *fel, *fer;
bool face_mark_filtered = false;
uint16_t edge_flag_result = 0;
bool only_contour = false;
if (use_freestyle_face && rb->filter_face_mark) {
fel = CustomData_bmesh_get(&bm_if_freestyle->pdata, ll->f->head.data, CD_FREESTYLE_FACE);
@ -1517,7 +1518,12 @@ static uint16_t lineart_identify_feature_line(LineartRenderBuffer *rb,
face_mark_filtered = !face_mark_filtered;
}
if (!face_mark_filtered) {
return 0;
if (rb->filter_face_mark_keep_contour) {
only_contour = true;
}
else {
return 0;
}
}
}
@ -1577,6 +1583,12 @@ static uint16_t lineart_identify_feature_line(LineartRenderBuffer *rb,
edge_flag_result |= LRT_EDGE_FLAG_CONTOUR;
}
/* For when face mark filtering decided that we discard the face but keep_contour option is on.
* so we still have correct full contour around the object. */
if (only_contour) {
return edge_flag_result;
}
if (rb->use_crease) {
if (rb->sharp_as_crease && !BM_elem_flag_test(e, BM_ELEM_SMOOTH)) {
edge_flag_result |= LRT_EDGE_FLAG_CREASE;
@ -1902,7 +1914,8 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
bm);
if (eflag) {
/* Only allocate for feature lines (instead of all lines) to save memory.
* If allow duplicated edges, one edge gets added multiple times if it has multiple types. */
* If allow duplicated edges, one edge gets added multiple times if it has multiple types.
*/
allocate_la_e += rb->allow_duplicated_types ? lineart_edge_type_duplication_count(eflag) : 1;
}
/* Here we just use bm's flag for when loading actual lines, then we don't need to call
@ -2096,8 +2109,8 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4],
}
bool cond[6] = {true, true, true, true, true, true};
/* Because for a point to be inside clip space, it must satisfy `-Wc <= XYCc <= Wc`, here if all
* verts falls to the same side of the clip space border, we know it's outside view. */
/* Because for a point to be inside clip space, it must satisfy `-Wc <= XYCc <= Wc`, here if
* all verts falls to the same side of the clip space border, we know it's outside view. */
for (int i = 0; i < 8; i++) {
cond[0] &= (co[i][0] < -co[i][3]);
cond[1] &= (co[i][0] > co[i][3]);
@ -2172,7 +2185,8 @@ static void lineart_main_load_geometries(
int thread_count = rb->thread_count;
/* This memory is in render buffer memory pool. so we don't need to free those after loading. */
/* This memory is in render buffer memory pool. so we don't need to free those after loading.
*/
LineartObjectLoadTaskInfo *olti = lineart_mem_acquire(
&rb->render_data_pool, sizeof(LineartObjectLoadTaskInfo) * thread_count);
@ -2455,8 +2469,9 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
dot_f = dot_v3v3_db(Cv, tri->gn);
/* NOTE(Yiming): When we don't use `dot_f==0` here, it's theoretically possible that _some_
* faces in perspective mode would get erroneously caught in this condition where they really are
* legit faces that would produce occlusion, but haven't encountered those yet in my test files.
* faces in perspective mode would get erroneously caught in this condition where they really
* are legit faces that would produce occlusion, but haven't encountered those yet in my test
* files.
*/
if (fabs(dot_f) < FLT_EPSILON) {
return false;
@ -2523,8 +2538,9 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
return false; \
}
/* Determine the pair of edges that the line has crossed. The "|" symbol in the comment indicates
* triangle boundary. DBL_TRIANGLE_LIM is needed to for floating point precision tolerance. */
/* Determine the pair of edges that the line has crossed. The "|" symbol in the comment
* indicates triangle boundary. DBL_TRIANGLE_LIM is needed to for floating point precision
* tolerance. */
if (st_l == 2) {
/* Left side is in the triangle. */
@ -3206,6 +3222,8 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
rb->filter_face_mark = (lmd->calculation_flags & LRT_FILTER_FACE_MARK) != 0;
rb->filter_face_mark_boundaries = (lmd->calculation_flags & LRT_FILTER_FACE_MARK_BOUNDARIES) !=
0;
rb->filter_face_mark_keep_contour = (lmd->calculation_flags &
LRT_FILTER_FACE_MARK_KEEP_CONTOUR) != 0;
rb->chain_data_pool = &lc->chain_data_pool;
@ -4282,8 +4300,8 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
if (rb->chain_smooth_tolerance > FLT_EPSILON) {
/* Keeping UI range of 0-1 for ease of read while scaling down the actual value for best
* effective range in image-space (Coordinate only goes from -1 to 1). This value is somewhat
* arbitrary, but works best for the moment. */
* effective range in image-space (Coordinate only goes from -1 to 1). This value is
* somewhat arbitrary, but works best for the moment. */
MOD_lineart_smooth_chains(rb, rb->chain_smooth_tolerance / 50);
}

View File

@ -315,7 +315,8 @@
.opacity = 1.0f, \
.flags = LRT_GPENCIL_MATCH_OUTPUT_VGROUP, \
.crease_threshold = DEG2RAD(140.0f), \
.calculation_flags = LRT_ALLOW_DUPLI_OBJECTS | LRT_ALLOW_CLIPPING_BOUNDARIES | LRT_USE_CREASE_ON_SHARP_EDGES, \
.calculation_flags = LRT_ALLOW_DUPLI_OBJECTS | LRT_ALLOW_CLIPPING_BOUNDARIES | \
LRT_USE_CREASE_ON_SHARP_EDGES | LRT_FILTER_FACE_MARK_KEEP_CONTOUR, \
.angle_splitting_threshold = DEG2RAD(60.0f), \
.chaining_image_threshold = 0.001f, \
.chain_smooth_tolerance = 0.2f,\

View File

@ -50,6 +50,7 @@ typedef enum eLineartMainFlags {
LRT_USE_CREASE_ON_SMOOTH_SURFACES = (1 << 15),
LRT_USE_CREASE_ON_SHARP_EDGES = (1 << 16),
LRT_USE_CUSTOM_CAMERA = (1 << 17),
LRT_FILTER_FACE_MARK_KEEP_CONTOUR = (1 << 18),
LRT_USE_BACK_FACE_CULLING = (1 << 19),
LRT_USE_IMAGE_BOUNDARY_TRIMMING = (1 << 20),
LRT_CHAIN_PRESERVE_DETAILS = (1 << 22),

View File

@ -3211,6 +3211,12 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
prop, "Boundaries", "Filter feature lines based on face mark boundaries");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_face_mark_keep_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, NULL, "calculation_flags", LRT_FILTER_FACE_MARK_KEEP_CONTOUR);
RNA_def_property_ui_text(prop, "Keep Contour", "Preserve contour lines while filtering");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "chaining_image_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_ui_text(
prop,