Commit: 4c291b1191d09d564f6a57f8f6f8bd0210ceafcb Author: YimingWu Date: Fri Apr 8 22:08:31 2022 +0800 Branches: lineart-shadow https://developer.blender.org/rB4c291b1191d09d564f6a57f8f6f8bd0210ceafcb
LineArt: Lit/shade filtering logic corrected. Intersection lines won't work at the moment. =================================================================== M source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h M source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c =================================================================== diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h index 463846fb9fc..b9e05e3639c 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h +++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h @@ -87,6 +87,9 @@ typedef struct LineartElementLinkNode { void *object_ref; eLineArtElementNodeFlag flags; + /* For edge element link nodes, used for shadow edge matching. */ + int obindex; + /** Per object value, always set, if not enabled by #ObjectLineArt, then it's set to global. */ float crease_threshold; } LineartElementLinkNode; @@ -100,6 +103,11 @@ typedef struct LineartEdgeSegment { /* Used to filter line art occlusion edges */ unsigned char material_mask_bits; + + /* Only used to mark "lit/shade" for now, But reserverd bits for material info. + * TODO(Yiming): Transfer material masks from shadow results + * onto here so then we can even filter transparent shadows. */ + unsigned char shadow_mask_bits; } LineartEdgeSegment; typedef struct LineartShadowSegmentContainer { @@ -305,6 +313,11 @@ typedef struct LineartRenderBuffer { * calculation is finished. */ LineartStaticMemPool *shadow_data_pool; + /* Storing shadow edge eln, array, and cuts for shadow information, so it's avaliable when line + * art runs the second time for occlusion. Either a reference to LineartCache::shadow_data_pool + * (shadow stage) or a reference to LineartRenderBuffer::render_data_pool (final stage). */ + LineartStaticMemPool *edge_data_pool; + /* Render status */ double view_vector[3]; double view_vector_secondary[3]; /* For shadow. */ @@ -417,8 +430,10 @@ typedef struct LineartCache { /** A copy of rb->Chains after calculation is done, then we can destroy rb. */ ListBase chains; - /** Shadow segments to be included into occlusion calculation in the second run of line art. */ - ListBase shadow_edges; + + /** Shadow-computed feature lines from original meshes to be matched with the second load of + * meshes thus providing lit/shade info in the second run of line art. */ + ListBase shadow_elns; /** Cache only contains edge types specified in this variable. */ uint16_t rb_edge_types; @@ -472,8 +487,8 @@ typedef struct LineartRenderTaskInfo { #define LRT_OBINDEX_SHIFT 20 #define LRT_OBINDEX_LOWER 0x0fffff /* Lower 20 bits. */ #define LRT_EDGE_IDENTIFIER(obi, e) \ - ((((obi->obindex << LRT_OBINDEX_SHIFT) | (e->v1->index & LRT_OBINDEX_LOWER)) << 32) | \ - ((obi->obindex << LRT_OBINDEX_SHIFT) | (e->v2->index & LRT_OBINDEX_LOWER))) + (((uint64_t)((obi->obindex << 0) | (e->v1->index & LRT_OBINDEX_LOWER)) << 32) | \ + ((obi->obindex << 0) | (e->v2->index & LRT_OBINDEX_LOWER))) typedef struct LineartObjectInfo { struct LineartObjectInfo *next; @@ -515,6 +530,7 @@ typedef struct LineartObjectLoadTaskInfo { LineartObjectInfo *pending; /* Used to spread the load across several threads. This can not overflow. */ uint64_t total_faces; + ListBase *shadow_elns; } LineartObjectLoadTaskInfo; /** diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index cf11c1dea1a..821e137985e 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -162,7 +162,7 @@ static LineartEdgeSegment *lineart_give_segment(LineartRenderBuffer *rb) BLI_spin_unlock(&rb->lock_cuts); /* Otherwise allocate some new memory. */ - return (LineartEdgeSegment *)lineart_mem_acquire_thread(&rb->render_data_pool, + return (LineartEdgeSegment *)lineart_mem_acquire_thread(rb->edge_data_pool, sizeof(LineartEdgeSegment)); } @@ -174,7 +174,8 @@ static void lineart_edge_cut(LineartRenderBuffer *rb, double start, double end, uchar material_mask_bits, - uchar mat_occlusion) + uchar mat_occlusion, + uchar shadow_bits) { LineartEdgeSegment *es, *ies, *next_es, *prev_es; LineartEdgeSegment *cut_start_before = 0, *cut_end_before = 0; @@ -311,6 +312,8 @@ static void lineart_edge_cut(LineartRenderBuffer *rb, for (es = ns; es && es != ns2; es = es->next) { es->occlusion += mat_occlusion; es->material_mask_bits |= material_mask_bits; + /* Currently only register lit/shade, see LineartEdgeSegment::shadow_mask_bits for details. */ + es->shadow_mask_bits |= shadow_bits; } /* Reduce adjacent cutting points of the same level, which saves memory. */ @@ -432,7 +435,7 @@ static void lineart_occlusion_single_line(LineartRenderBuffer *rb, LineartEdge * rb->shift_y, &l, &r)) { - lineart_edge_cut(rb, e, l, r, tri->base.material_mask_bits, tri->base.mat_occlusion); + lineart_edge_cut(rb, e, l, r, tri->base.material_mask_bits, tri->base.mat_occlusion, 0); 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. */ @@ -733,12 +736,10 @@ static LineartElementLinkNode *lineart_memory_get_edge_space(LineartRenderBuffer { LineartElementLinkNode *eln; - LineartEdge *render_edges = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartEdge) * 64); + LineartEdge *render_edges = lineart_mem_acquire(rb->edge_data_pool, sizeof(LineartEdge) * 64); - eln = lineart_list_append_pointer_pool_sized(&rb->line_buffer_pointers, - &rb->render_data_pool, - render_edges, - sizeof(LineartElementLinkNode)); + eln = lineart_list_append_pointer_pool_sized( + &rb->line_buffer_pointers, rb->edge_data_pool, render_edges, sizeof(LineartElementLinkNode)); eln->element_count = 64; eln->crease_threshold = rb->crease_threshold; eln->flags |= LRT_ELEMENT_IS_ADDITIONAL; @@ -1475,12 +1476,21 @@ static void lineart_mvert_transform_task(void *__restrict userdata, v->index = i; } -static int lineart_edge_type_duplication_count(char eflag) +static const int LRT_MESH_EDGE_TYPES[] = { + LRT_EDGE_FLAG_EDGE_MARK, + LRT_EDGE_FLAG_CONTOUR, + LRT_EDGE_FLAG_CREASE, + LRT_EDGE_FLAG_MATERIAL, + LRT_EDGE_FLAG_LOOSE, + LRT_EDGE_FLAG_CONTOUR_SECONDARY, +}; + +static int lineart_edge_type_duplication_count(int eflag) { int count = 0; /* See eLineartEdgeFlag for details. */ for (int i = 0; i < 6; i++) { - if (eflag & (1 << i)) { + if (eflag & LRT_MESH_EDGE_TYPES[i]) { count++; } } @@ -1618,6 +1628,7 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata, } if (rb->use_contour_secondary) { + view_vector = vv; if (rb->cam_is_persp_secondary) { sub_v3_v3v3_db(view_vector, vert->gloc, rb->camera_pos_secondary); } @@ -1629,9 +1640,7 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata, dot_2 = dot_v3v3_db(view_vector, tri2->gn); if ((result = dot_1 * dot_2) <= 0 && (dot_1 + dot_2)) { - /* Note: we only allow one contour type for now, either it's from light camera or it's from - * viewing camera, hence directly assign. */ - edge_flag_result = LRT_EDGE_FLAG_CONTOUR_SECONDARY; + edge_flag_result |= LRT_EDGE_FLAG_CONTOUR_SECONDARY; } } @@ -2112,8 +2121,49 @@ static void lineart_load_tri_reduce(const void *__restrict UNUSED(userdata), BLI_edgehash_free(data_reduce->edge_hash, NULL); } +static LineartElementLinkNode *lineart_find_matching_eln(ListBase *shadow_elns, int obindex) +{ + LISTBASE_FOREACH (LineartElementLinkNode *, eln, shadow_elns) { + if (eln->obindex == obindex) { + return eln; + } + } + return NULL; +} + +static LineartEdge *lineart_find_matching_edge(LineartElementLinkNode *shadow_eln, + uint64_t edge_identifier) +{ + LineartEdge *elist = (LineartEdge *)shadow_eln->pointer; + for (int i = 0; i < shadow_eln->element_count; i++) { + if (elist[i].from_shadow == (LineartEdge *)edge_identifier) { + return &elist[i]; + } + } + return NULL; +} + +static void lineart_register_shadow_cuts(LineartRenderBuffer *rb, + LineartEdge *e, + LineartEdge *shadow_edge) +{ + LISTBASE_FOREACH (LineartEdgeSegment *, es, &shadow_edge->segments) { + if (es->occlusion != 0) { + /* Convert to view space cutting points. */ + double la1 = es->at; + double la2 = es->next ? es->next->at : 1.0f; + la1 = la1 * e->v2->fbcoord[3] / + (e->v1->fbcoord[3] - la1 * (e->v1->fbcoord[3] - e->v2->fbcoord[3])); + la2 = la2 * e->v2->fbcoord[3] / + (e->v1->fbcoord[3] - la2 * (e->v1->fbcoord[3] - e->v2->fbcoord[3])); + lineart_edge_cut(rb, e, la1, la2, 0, 10, es->occlusion != 0); + } + } +} + static void lineart_geometry_object_load_no_bmesh(LineartObjectInfo *ob_info, - LineartRenderBuffer *re_buf) + LineartRenderBuffer *re_buf, + ListBase *shadow_elns) { LineartElementLinkNode *elem_link_node; LineartVert *la_v_arr; @@ -2392,18 +2442,24 @@ static void lineart_geometry_object_load_no_bmesh(LineartObjectInfo *ob_info, BLI_edgehash_free(edge_hash, NULL); } - la_edge_arr = lineart_mem_acquire_thread(&re_buf->render_data_pool, + la_edge_arr = lineart_mem_acquire_thread(re_buf->edge_data_pool, sizeof(LineartEdge) * allocate_la_e); - la_seg_arr = lineart_mem_acquire_thread(& @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs