diff options
Diffstat (limited to 'intern/cycles/kernel/geom/geom_curve.h')
-rw-r--r-- | intern/cycles/kernel/geom/geom_curve.h | 153 |
1 files changed, 93 insertions, 60 deletions
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h index e57bcd894a6..e1d225436a6 100644 --- a/intern/cycles/kernel/geom/geom_curve.h +++ b/intern/cycles/kernel/geom/geom_curve.h @@ -125,6 +125,23 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd) return r*2.0f; } +/* Curve location for motion pass, linear interpolation between keys and + * ignoring radius because we do the same for the motion keys */ + +ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd) +{ + float4 curvedata = kernel_tex_fetch(__curves, sd->prim); + int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); + int k1 = k0 + 1; + + float4 P_curve[2]; + + P_curve[0]= kernel_tex_fetch(__curve_keys, k0); + P_curve[1]= kernel_tex_fetch(__curve_keys, k1); + + return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u); +} + /* Curve tangent normal */ ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd) @@ -152,48 +169,47 @@ ccl_device_inline void curvebounds(float *lower, float *upper, float *extremta, float halfdiscroot = (p2 * p2 - 3 * p3 * p1); float ta = -1.0f; float tb = -1.0f; + *extremta = -1.0f; *extremtb = -1.0f; *upper = p0; - *lower = p0 + p1 + p2 + p3; + *lower = (p0 + p1) + (p2 + p3); *extrema = *upper; *extremb = *lower; + if(*lower >= *upper) { *upper = *lower; *lower = p0; } if(halfdiscroot >= 0) { - halfdiscroot = sqrt(halfdiscroot); - ta = (-p2 - halfdiscroot) / (3 * p3); - tb = (-p2 + halfdiscroot) / (3 * p3); + float inv3p3 = (1.0f/3.0f)/p3; + halfdiscroot = sqrtf(halfdiscroot); + ta = (-p2 - halfdiscroot) * inv3p3; + tb = (-p2 + halfdiscroot) * inv3p3; } float t2; float t3; + if(ta > 0.0f && ta < 1.0f) { t2 = ta * ta; t3 = t2 * ta; *extremta = ta; *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0; - if(*extrema > *upper) { - *upper = *extrema; - } - if(*extrema < *lower) { - *lower = *extrema; - } + + *upper = fmaxf(*extrema, *upper); + *lower = fminf(*extrema, *lower); } + if(tb > 0.0f && tb < 1.0f) { t2 = tb * tb; t3 = t2 * tb; *extremtb = tb; *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0; - if(*extremb >= *upper) { - *upper = *extremb; - } - if(*extremb <= *lower) { - *lower = *extremb; - } + + *upper = fmaxf(*extremb, *upper); + *lower = fminf(*extremb, *lower); } } @@ -438,6 +454,8 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect * dP* is reversed if necessary.*/ float t = isect->t; float u = 0.0f; + float gd = 0.0f; + if(flags & CURVE_KN_RIBBONS) { float3 tg = (p_en - p_st); float w = tg.x * tg.x + tg.y * tg.y; @@ -481,10 +499,11 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect float d = sqrtf(p_curr.x * p_curr.x + p_curr.y * p_curr.y); float d0 = d - r_curr; float d1 = d + r_curr; + float inv_mw_extension = 1.0f/mw_extension; if (d0 >= 0) - coverage = (min(d1 / mw_extension, 1.0f) - min(d0 / mw_extension, 1.0f)) * 0.5f; + coverage = (min(d1 * inv_mw_extension, 1.0f) - min(d0 * inv_mw_extension, 1.0f)) * 0.5f; else // inside - coverage = (min(d1 / mw_extension, 1.0f) + min(-d0 / mw_extension, 1.0f)) * 0.5f; + coverage = (min(d1 * inv_mw_extension, 1.0f) + min(-d0 * inv_mw_extension, 1.0f)) * 0.5f; } if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) { @@ -494,12 +513,19 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect } t = p_curr.z; + + /* stochastic fade from minimum width */ + if(difl != 0.0f && lcg_state) { + if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage)) + return hit; + } } else { float l = len(p_en - p_st); /* minimum width extension */ float or1 = r1; float or2 = r2; + if(difl != 0.0f) { mw_extension = min(len(p_st - P) * difl, extmax); or1 = r1 < mw_extension ? mw_extension : r1; @@ -507,12 +533,14 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect or2 = r2 < mw_extension ? mw_extension : r2; } /* --- */ - float3 tg = (p_en - p_st) / l; - float gd = (or2 - or1) / l; + float invl = 1.0f/l; + float3 tg = (p_en - p_st) * invl; + gd = (or2 - or1) * invl; float difz = -dot(p_st,tg); float cyla = 1.0f - (tg.z * tg.z * (1 + gd*gd)); + float invcyla = 1.0f/cyla; float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + or1))); - float tcentre = -halfb/cyla; + float tcentre = -halfb*invcyla; float zcentre = difz + (tg.z * tcentre); float3 tdif = - p_st; tdif.z += tcentre; @@ -527,7 +555,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect } float rootd = sqrtf(td); - float correction = ((-tb - rootd)/(2*cyla)); + float correction = (-tb - rootd) * 0.5f * invcyla; t = tcentre + correction; float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1]; @@ -538,7 +566,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect dp_en *= -1; if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) { - correction = ((-tb + rootd)/(2*cyla)); + correction = (-tb + rootd) * 0.5f * invcyla; t = tcentre + correction; } @@ -548,22 +576,22 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect continue; } - float w = (zcentre + (tg.z * correction))/l; + float w = (zcentre + (tg.z * correction)) * invl; w = clamp((float)w, 0.0f, 1.0f); /* compute u on the curve segment */ u = i_st * (1 - w) + i_en * w; - r_curr = r1 + (r2 - r1) * w; - r_ext = or1 + (or2 - or1) * w; - coverage = r_curr/r_ext; - } - /* we found a new intersection */ + /* stochastic fade from minimum width */ + if(difl != 0.0f && lcg_state) { + r_curr = r1 + (r2 - r1) * w; + r_ext = or1 + (or2 - or1) * w; + coverage = r_curr/r_ext; - /* stochastic fade from minimum width */ - if(lcg_state && coverage != 1.0f) { - if(lcg_step_float(lcg_state) > coverage) - return hit; + if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage)) + return hit; + } } + /* we found a new intersection */ #ifdef __VISIBILITY_FLAG__ /* visibility flag test. we do it here under the assumption @@ -576,8 +604,8 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect isect->object = object; isect->type = type; isect->u = u; - isect->v = 0.0f; - /*isect->v = 1.0f - coverage; */ + isect->v = gd; + /*isect->transparency = 1.0f - coverage; */ isect->t = t; hit = true; } @@ -771,10 +799,10 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec } float z = zcentre + (dirz * correction); - bool backface = false; + // bool backface = false; if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) { - backface = true; + // backface = true; correction = ((-tb + rootd)/(2*a)); t = tcentre + correction; z = zcentre + (dirz * correction); @@ -812,13 +840,10 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec isect->object = object; isect->type = type; isect->u = z*invl; - isect->v = td/(4*a*a); - /*isect->v = 1.0f - adjradius;*/ + isect->v = gd; + /*isect->transparency = 1.0f - adjradius;*/ isect->t = t; - if(backface) - isect->u = -isect->u; - return true; } } @@ -901,35 +926,41 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve); } - float l = 1.0f; - tg = normalize_len(float4_to_float3(P_curve[2] - P_curve[1]), &l); - float r1 = P_curve[1].w; - float r2 = P_curve[2].w; - float gd = ((r2 - r1)/l); - - P = P + D*t; - float3 p[4]; p[0] = float4_to_float3(P_curve[0]); p[1] = float4_to_float3(P_curve[1]); p[2] = float4_to_float3(P_curve[2]); p[3] = float4_to_float3(P_curve[3]); + P = P + D*t; + #ifdef __UV__ sd->u = isect->u; sd->v = 0.0f; #endif - tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3])); - - if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) + if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) { + tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3])); sd->Ng = normalize(-(D - tg * (dot(tg, D)))); + } else { + /* direction from inside to surface of curve */ float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]); sd->Ng = normalize(P - p_curr); - sd->Ng = sd->Ng - gd * tg; - sd->Ng = normalize(sd->Ng); + + /* adjustment for changing radius */ + float gd = isect->v; + + if(gd != 0.0f) { + tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3])); + sd->Ng = sd->Ng - gd * tg; + sd->Ng = normalize(sd->Ng); + } } + + /* todo: sometimes the normal is still so that this is detected as + * backfacing even if cull backfaces is enabled */ + sd->N = sd->Ng; } else { @@ -945,9 +976,6 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con float l = 1.0f; tg = normalize_len(float4_to_float3(P_curve[1] - P_curve[0]), &l); - float r1 = P_curve[0].w; - float r2 = P_curve[1].w; - float gd = ((r2 - r1)/l); P = P + D*t; @@ -963,9 +991,14 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con sd->Ng = normalize(sd->Ng); } else { + float gd = isect->v; + + /* direction from inside to surface of curve */ sd->Ng = (dif - tg * sd->u * l) / (P_curve[0].w + sd->u * l * gd); + + /* adjustment for changing radius */ if (gd != 0.0f) { - sd->Ng = sd->Ng - gd * tg ; + sd->Ng = sd->Ng - gd * tg; sd->Ng = normalize(sd->Ng); } } @@ -980,7 +1013,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con #endif /*add fading parameter for minimum pixel width with transparency bsdf*/ - /*sd->curve_transparency = isect->v;*/ + /*sd->curve_transparency = isect->transparency;*/ /*sd->curve_radius = sd->u * gd * l + r1;*/ if(isect->object != OBJECT_NONE) { |