[Bf-blender-cvs] [0b9c5184ef0] lineart-shadow: Merge branch 'temp-lineart-contained' into lineart-shadow
YimingWu
noreply at git.blender.org
Fri Apr 22 11:20:29 CEST 2022
Commit: 0b9c5184ef083bf733e444f40da1cbe974a66a2f
Author: YimingWu
Date: Fri Apr 22 16:46:18 2022 +0800
Branches: lineart-shadow
https://developer.blender.org/rB0b9c5184ef083bf733e444f40da1cbe974a66a2f
Merge branch 'temp-lineart-contained' into lineart-shadow
===================================================================
===================================================================
diff --cc source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index c69746040ce,ac3cdc43235..88021ed0eeb
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@@ -169,12 -127,11 +169,10 @@@ typedef enum eLineArtVertFlags
} eLineArtVertFlags;
typedef struct LineartEdge {
- /** We only need link node kind of list here. */
- struct LineartEdge *next;
struct LineartVert *v1, *v2;
- /** These two variables are also used to specify original edge and segment during 3rd stage
- * reprojection, So we can easily find out the line which results come from. */
struct LineartTriangle *t1, *t2;
+
ListBase segments;
char min_occ;
diff --cc source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index f5c410e9593,d0f5086a822..249af318d32
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@@ -5294,1016 -5098,6 +5296,1016 @@@ static LineartBoundingArea *lineart_bou
return 0;
}
+static LineartShadowSegment *lineart_give_shadow_segment(LineartRenderBuffer *rb)
+{
+ BLI_spin_lock(&rb->lock_cuts);
+
+ /* See if there is any already allocated memory we can reuse. */
+ if (rb->wasted_shadow_cuts.first) {
+ LineartShadowSegment *es = (LineartShadowSegment *)BLI_pophead(&rb->wasted_shadow_cuts);
+ BLI_spin_unlock(&rb->lock_cuts);
+ memset(es, 0, sizeof(LineartShadowSegment));
+ return (LineartShadowSegment *)es;
+ }
+ BLI_spin_unlock(&rb->lock_cuts);
+
+ /* Otherwise allocate some new memory. */
+ return (LineartShadowSegment *)lineart_mem_acquire_thread(&rb->render_data_pool,
+ sizeof(LineartShadowSegment));
+}
+
+static void lineart_shadow_segment_slice_get(double *fbl,
+ double *fbr,
+ double *gl,
+ double *gr,
+ double at,
+ double at_l,
+ double at_r,
+ double *r_fb,
+ double *r_g)
+{
+ double real_at = ((at_r - at_l) == 0) ? 0 : ((at - at_l) / (at_r - at_l));
+ double ga = fbl[3] * real_at / (fbr[3] * (1.0f - real_at) + fbl[3] * real_at);
+ interp_v3_v3v3_db(r_fb, fbl, fbr, real_at);
+ r_fb[3] = interpd(fbr[3], fbl[3], ga);
+ interp_v3_v3v3_db(r_g, gl, gr, ga);
+}
+
+/* Returns true when a new cut is needed in the middle, otherwise `*r_new_xxx` are not touched. */
+static bool lineart_do_closest_segment(bool is_persp,
+ double *s1fbl,
+ double *s1fbr,
+ double *s2fbl,
+ double *s2fbr,
+ double *s1gl,
+ double *s1gr,
+ double *s2gl,
+ double *s2gr,
+ double *r_fbl,
+ double *r_fbr,
+ double *r_gl,
+ double *r_gr,
+ double *r_new_in_the_middle,
+ double *r_new_in_the_middle_global,
+ double *r_new_at,
+ bool *is_side_2r,
+ bool *use_new_ref)
+{
+ int side = 0;
+ int zid = is_persp ? 3 : 2;
+ /* Always use the closest point to the light camera. */
+ if (s1fbl[zid] >= s2fbl[zid]) {
+ copy_v4_v4_db(r_fbl, s2fbl);
+ copy_v3_v3_db(r_gl, s2gl);
+ side++;
+ }
+ if (s1fbr[zid] >= s2fbr[zid]) {
+ copy_v4_v4_db(r_fbr, s2fbr);
+ copy_v3_v3_db(r_gr, s2gr);
+ *is_side_2r = true;
+ side++;
+ }
+ if (s1fbl[zid] <= s2fbl[zid]) {
+ copy_v4_v4_db(r_fbl, s1fbl);
+ copy_v3_v3_db(r_gl, s1gl);
+ side--;
+ }
+ if (s1fbr[zid] <= s2fbr[zid]) {
+ copy_v4_v4_db(r_fbr, s1fbr);
+ copy_v3_v3_db(r_gr, s1gr);
+ *is_side_2r = false;
+ side--;
+ }
+
+ /* No need to cut in the middle, because one segment completely overlaps the other. */
+ if (side) {
+ if (side > 0) {
+ *is_side_2r = true;
+ *use_new_ref = true;
+ }
+ else if (side < 0) {
+ *is_side_2r = false;
+ *use_new_ref = false;
+ }
+ return false;
+ }
+
+ /* Else there must be an intersection point in the middle. Use "w" value to linearly plot the
+ * position and get image space "at" position. */
+ double dl = s1fbl[zid] - s2fbl[zid];
+ double dr = s1fbr[zid] - s2fbr[zid];
+ double ga = ratiod(dl, dr, 0);
+ *r_new_at = is_persp ? s2fbr[3] * ga / (s2fbl[3] * (1.0f - ga) + s2fbr[3] * ga) : ga;
+ interp_v3_v3v3_db(r_new_in_the_middle, s2fbl, s2fbr, *r_new_at);
+ r_new_in_the_middle[3] = interpd(s2fbr[3], s2fbl[3], ga);
+ interp_v3_v3v3_db(r_new_in_the_middle_global, s1gl, s1gr, ga);
+ *use_new_ref = true;
+
+ return true;
+}
+
+static void lineart_shadow_create_container_array(LineartRenderBuffer *rb,
+ bool transform_edge_cuts)
+{
+#define DISCARD_NONSENSE_SEGMENTS \
+ if (es->occlusion != 0 || \
+ (es->next && LRT_DOUBLE_CLOSE_ENOUGH(es->at, ((LineartEdgeSegment *)es->next)->at))) { \
+ LRT_ITER_ALL_LINES_NEXT; \
+ continue; \
+ }
+
+ /* Count and allocate at once to save time. */
+ int segment_count = 0;
+ LRT_ITER_ALL_LINES_BEGIN
+ {
+ /* Only contour and loose edges can actually cast shadows. */
+ if (!(e->flags &
+ (LRT_EDGE_FLAG_CONTOUR | LRT_EDGE_FLAG_LOOSE | LRT_EDGE_FLAG_LIGHT_CONTOUR))) {
+ continue;
+ }
+ if (e->flags == LRT_EDGE_FLAG_LIGHT_CONTOUR) {
+ /* Only reproject light contours that also doubles as a view contour. */
+ LineartEdge *orig_e = (LineartEdge *)e->t1;
+ if (!orig_e->t2) {
+ e->flags |= LRT_EDGE_FLAG_CONTOUR;
+ }
+ else {
+ double vv[3];
+ double *view_vector = vv;
+ double dot_1 = 0, dot_2 = 0;
+ double result;
+
+ if (rb->cam_is_persp) {
+ sub_v3_v3v3_db(view_vector, orig_e->v1->gloc, rb->camera_pos);
+ }
+ else {
+ view_vector = rb->view_vector;
+ }
+
+ dot_1 = dot_v3v3_db(view_vector, orig_e->t1->gn);
+ dot_2 = dot_v3v3_db(view_vector, orig_e->t2->gn);
+
+ if ((result = dot_1 * dot_2) <= 0 && (dot_1 + dot_2)) {
+ e->flags |= LRT_EDGE_FLAG_CONTOUR;
+ }
+ }
+ if (!(e->flags & LRT_EDGE_FLAG_CONTOUR)) {
+ continue;
+ }
+ }
+ LISTBASE_FOREACH (LineartEdgeSegment *, es, &e->segments) {
+ DISCARD_NONSENSE_SEGMENTS
+ segment_count++;
+ }
+ }
+ LRT_ITER_ALL_LINES_END
+
+ LineartShadowSegmentContainer *ssc = lineart_mem_acquire(
+ &rb->render_data_pool, sizeof(LineartShadowSegmentContainer) * segment_count);
+ LineartShadowSegment *ss = lineart_mem_acquire(&rb->render_data_pool,
+ sizeof(LineartShadowSegment) * segment_count * 2);
+
+ int i = 0;
+ LRT_ITER_ALL_LINES_BEGIN
+ {
+ if (!(e->flags & (LRT_EDGE_FLAG_CONTOUR | LRT_EDGE_FLAG_LOOSE))) {
+ continue;
+ }
+ LISTBASE_FOREACH (LineartEdgeSegment *, es, &e->segments) {
+ DISCARD_NONSENSE_SEGMENTS
+
+ double next_at = es->next ? ((LineartEdgeSegment *)es->next)->at : 1.0f;
+ /* Get correct XYZ and W coordinates. */
+ interp_v3_v3v3_db(ssc[i].fbc1, e->v1->fbcoord, e->v2->fbcoord, es->at);
+ interp_v3_v3v3_db(ssc[i].fbc2, e->v1->fbcoord, e->v2->fbcoord, next_at);
+
+ /* Global coord for light-shadow separation line (occlusion-corrected light contour). */
+ double ga1 = e->v1->fbcoord[3] * es->at /
+ (es->at * e->v1->fbcoord[3] + (1 - es->at) * e->v2->fbcoord[3]);
+ double ga2 = e->v1->fbcoord[3] * next_at /
+ (next_at * e->v1->fbcoord[3] + (1 - next_at) * e->v2->fbcoord[3]);
+ interp_v3_v3v3_db(ssc[i].g1, e->v1->gloc, e->v2->gloc, ga1);
+ interp_v3_v3v3_db(ssc[i].g2, e->v1->gloc, e->v2->gloc, ga2);
+
+ /* Assign an absurdly big W for initial distance so when triangles show up to catch the
+ * shadow, their w must certainlly be smaller than this value so the shadow catches
+ * successfully. */
+ ssc[i].fbc1[3] = 1e30;
+ ssc[i].fbc2[3] = 1e30;
+ ssc[i].fbc1[2] = 1e30;
+ ssc[i].fbc2[2] = 1e30;
+
+ /* Assign to the first segment's right and the last segment's left position */
+ copy_v4_v4_db(ss[i * 2].fbc2, ssc[i].fbc1);
+ copy_v4_v4_db(ss[i * 2 + 1].fbc1, ssc[i].fbc2);
+ ss[i * 2].at = 0.0f;
+ ss[i * 2 + 1].at = 1.0f;
+ BLI_addtail(&ssc[i].shadow_segments, &ss[i * 2]);
+ BLI_addtail(&ssc[i].shadow_segments, &ss[i * 2 + 1]);
+
+ if (e->flags & LRT_EDGE_FLAG_LIGHT_CONTOUR) {
+ ssc[i].e_ref = e->t1;
+ ssc[i].e_ref_light_contour = e;
+ /* Restore original edge flag. */
+ e->flags &= (~LRT_EDGE_FLAG_CONTOUR);
+ }
+ else {
+ ssc[i].e_ref = e;
+ }
+
+ ssc[i].es_ref = es;
+ BLI_addtail(&rb->shadow_containers, &ssc[i]);
+
+ i++;
+ }
+ }
+ LRT_ITER_ALL_LINES_END
+
+ if (transform_edge_cuts) {
+ LRT_ITER_ALL_LINES_BEGIN
+ {
+ /* Transform the cutting position to global space for regular feature lines. */
+ LISTBASE_FOREACH (LineartEdgeSegment *, es, &e->segments) {
+ es->at = e->v1->fbcoord[3] * es->at /
+ (es->at * e->v1->fbcoord[3] + (1 - es->at) * e->v2->fbcoord[3]);
+ }
+ }
+ LRT_ITER_ALL_LINES_END
+ }
+
+ if (G.debug_value == 4000) {
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list