[Bf-blender-cvs] [85a93ce443d] lineart-shadow: LineArt: Shadow improvements.

YimingWu noreply at git.blender.org
Tue Jul 20 11:23:07 CEST 2021


Commit: 85a93ce443d21f35aebb378cbd811ab8643079cc
Author: YimingWu
Date:   Tue Jul 20 17:22:52 2021 +0800
Branches: lineart-shadow
https://developer.blender.org/rB85a93ce443d21f35aebb378cbd811ab8643079cc

LineArt: Shadow improvements.

===================================================================

M	source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
M	source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
M	source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
M	source/blender/makesdna/DNA_lineart_types.h

===================================================================

diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index bf227d454bb..a3d6c12d036 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -116,6 +116,7 @@ typedef struct LineartShadowSegmentContainer {
 
 enum eLineartShadowSegmentFlag {
   LRT_SHADOW_CASTED = 1,
+  LRT_SHADOW_FACING_LIGHT = 2,
 };
 
 typedef struct LineartShadowSegment {
@@ -400,6 +401,7 @@ typedef struct LineartCache {
 
 #define DBL_TRIANGLE_LIM 1e-8
 #define DBL_EDGE_LIM 1e-9
+#define DBL_SHADOW_LIM 1e-7
 
 #define LRT_MEMORY_POOL_1MB (1 << 20)
 
@@ -540,6 +542,9 @@ typedef struct LineartBoundingArea {
 
 #define LRT_DOUBLE_CLOSE_ENOUGH(a, b) (((a) + DBL_EDGE_LIM) >= (b) && ((a)-DBL_EDGE_LIM) <= (b))
 
+#define LRT_SHADOW_CLOSE_ENOUGH(a, b) \
+  (((a) + DBL_SHADOW_LIM) >= (b) && ((a)-DBL_SHADOW_LIM) <= (b))
+
 BLI_INLINE int lineart_LineIntersectTest2d(
     const double *a1, const double *a2, const double *b1, const double *b2, double *aRatio)
 {
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index e1fc1efa88f..ba6dd749fb0 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -815,7 +815,7 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
 
   while ((ec = BLI_pophead(&swap)) != NULL) {
     ec->next = ec->prev = NULL;
-    if (ec->picked) {
+    if (ec->picked || ec->chain.first == ec->chain.last) {
       continue;
     }
     BLI_addtail(&rb->chains, ec);
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 95aa6e6acc6..0933b7b073d 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -1690,6 +1690,7 @@ static void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e)
       lineart_prepend_edge_direct(&rb->light_contour.first, e);
       break;
     case LRT_EDGE_FLAG_PROJECTED_SHADOW:
+    case LRT_EDGE_FLAG_PROJECTED_SHADOW | LRT_EDGE_FLAG_SHADOW_FACING_LIGHT:
       lineart_prepend_edge_direct(&rb->shadow.first, e);
       break;
   }
@@ -2488,6 +2489,19 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
   dot_r = dot_v3v3_db(Rv, tri->gn);
   dot_f = dot_v3v3_db(Cv, tri->gn);
 
+  if (e->flags & LRT_EDGE_FLAG_PROJECTED_SHADOW && LRT_SHADOW_CLOSE_ENOUGH(dot_l, 0) &&
+      LRT_SHADOW_CLOSE_ENOUGH(dot_r, 0)) {
+    /* Currently unable to precisely determine if the edge is really from this triangle. */
+    /*if ((dot_f > 0 && (e->flags & LRT_EDGE_FLAG_SHADOW_FACING_LIGHT)) ||
+        (dot_f < 0 && (!(e->flags & LRT_EDGE_FLAG_SHADOW_FACING_LIGHT)))) {
+      *from = 0.0f;
+      *to = 1.0f;
+      return true;
+    }
+    */
+    return false;
+  }
+
   /* 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.
@@ -4367,7 +4381,8 @@ static void lineart_shadow_segment_slice_get(double *fbl,
 }
 
 /* Returns true when a new cut is needed in the middle, otherwise `*r_new_xxx` are not touched. */
-static bool lineart_do_closest_segment(double *s1fbl,
+static bool lineart_do_closest_segment(bool is_persp,
+                                       double *s1fbl,
                                        double *s1fbr,
                                        double *s2fbl,
                                        double *s2fbr,
@@ -4381,42 +4396,52 @@ static bool lineart_do_closest_segment(double *s1fbl,
                                        double *r_gr,
                                        double *r_new_in_the_middle,
                                        double *r_new_in_the_middle_global,
-                                       double *r_new_at)
+                                       double *r_new_at,
+                                       bool *is_side_2r)
 {
   int side = 0;
+  int zid = is_persp ? 3 : 2;
   /* Always use the closest point to the light camera. */
-  if (s1fbl[3] >= s2fbl[3]) {
+  if (s1fbl[zid] >= s2fbl[zid]) {
     copy_v4_v4_db(r_fbl, s2fbl);
     copy_v3_v3_db(r_gl, s2gl);
     side++;
   }
-  if (s1fbr[3] >= s2fbr[3]) {
+  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[3] <= s2fbl[3]) {
+  if (s1fbl[zid] < s2fbl[zid]) {
     copy_v4_v4_db(r_fbl, s1fbl);
     copy_v3_v3_db(r_gl, s1gl);
     side--;
   }
-  if (s1fbr[3] <= s2fbr[3]) {
+  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;
+    }
+    else if (side < 0) {
+      *is_side_2r = 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[3] - s2fbl[3];
-  double dr = s1fbr[3] - s2fbr[3];
+  double dl = s1fbl[zid] - s2fbl[zid];
+  double dr = s1fbr[zid] - s2fbr[zid];
   double ga = ratiod(dl, dr, 0);
-  *r_new_at = s2fbr[3] * ga / (s2fbl[3] * (1.0f - ga) + s2fbr[3] * ga);
+  *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);
@@ -4459,15 +4484,21 @@ static void lineart_shadow_create_container_array(LineartRenderBuffer *rb)
       /* 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);
-      double ga1 = e->v1->fbcoord[3] * es->at /
+
+      /* We don't need global coordinates of shadow contour, but if we need them for some reason,
+       * the following lines transform them correctly */
+      /* 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]);
+                   (next_at * e->v1->fbcoord[3] + (1 - next_at) * e->v2->fbcoord[3]); */
+
       /* 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);
@@ -4497,7 +4528,8 @@ static void lineart_shadow_edge_cut(LineartRenderBuffer *rb,
                                     double *start_gpos,
                                     double *end_gpos,
                                     double *start_fbc,
-                                    double *end_fbc)
+                                    double *end_fbc,
+                                    bool facing_light)
 {
   LineartShadowSegment *es, *ies;
   LineartShadowSegment *cut_start_after = e->shadow_segments.first,
@@ -4598,6 +4630,7 @@ static void lineart_shadow_edge_cut(LineartRenderBuffer *rb,
 
   double *s1fbl, *s1fbr, *s1gl, *s1gr;
   double tg1[3], tg2[3], tfbc1[4], tfbc2[4], mg1[3], mfbc1[4], mg2[3], mfbc2[4];
+  bool is_side_2r, has_middle = false;
   copy_v4_v4_db(tfbc1, start_fbc);
   copy_v3_v3_db(tg1, start_gpos);
 
@@ -4634,29 +4667,31 @@ static void lineart_shadow_edge_cut(LineartRenderBuffer *rb,
       }
     }
 
-    sl->flag |= LRT_SHADOW_CASTED;
-
     lineart_shadow_segment_slice_get(
         start_fbc, end_fbc, start_gpos, end_gpos, sr->at, start, end, tfbc2, tg2);
 
-    if (lineart_do_closest_segment(s1fbl,
-                                   s1fbr,
-                                   tfbc1,
-                                   tfbc2,
-                                   s1gl,
-                                   s1gr,
-                                   tg1,
-                                   tg2,
-                                   r_fbl,
-                                   r_fbr,
-                                   r_gl,
-                                   r_gr,
-                                   r_new_in_the_middle,
-                                   r_new_in_the_middle_global,
-                                   &r_new_at)) {
+    if ((has_middle = lineart_do_closest_segment(rb->cam_is_persp,
+                                                 s1fbl,
+                                                 s1fbr,
+                                                 tfbc1,
+                                                 tfbc2,
+                                                 s1gl,
+                                                 s1gr,
+                                                 tg1,
+                                                 tg2,
+                                                 r_fbl,
+                                                 r_fbr,
+                                                 r_gl,
+                                                 r_gr,
+                                                 r_new_in_the_middle,
+                                                 r_new_in_the_middle_global,
+                                                 &r_new_at,
+                                                 &is_side_2r))) {
       LineartShadowSegment *ss_middle 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list