[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