[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