From e9ba345c46c93a193193f01d4bfac714a666d384 Mon Sep 17 00:00:00 2001 From: Stuart Broadfoot Date: Fri, 28 Dec 2012 14:21:30 +0000 Subject: New feature Patch [#33445] - Experimental Cycles Hair Rendering (CPU only) This patch allows hair data to be exported to cycles and introduces a new line segment primitive to render with. The UI appears under the particle tab and there is a new hair info node available. It is only available under the experimental feature set and for cpu rendering. --- intern/cycles/kernel/kernel_bvh.h | 267 ++++++++++++++++++++++++++++++- intern/cycles/kernel/kernel_emission.h | 12 +- intern/cycles/kernel/kernel_light.h | 64 +++++++- intern/cycles/kernel/kernel_object.h | 50 ++++++ intern/cycles/kernel/kernel_shader.h | 115 +++++++++---- intern/cycles/kernel/kernel_textures.h | 5 + intern/cycles/kernel/kernel_triangle.h | 176 +++++++++++--------- intern/cycles/kernel/kernel_types.h | 34 +++- intern/cycles/kernel/svm/svm.h | 6 + intern/cycles/kernel/svm/svm_attribute.h | 144 +++++++++++------ intern/cycles/kernel/svm/svm_geometry.h | 38 ++++- intern/cycles/kernel/svm/svm_tex_coord.h | 14 +- intern/cycles/kernel/svm/svm_types.h | 10 +- 13 files changed, 770 insertions(+), 165 deletions(-) (limited to 'intern/cycles/kernel') diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index 73e7fb0e5d6..15af35a05f8 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -205,6 +205,151 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise } } +#ifdef __HAIR__ +__device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, + float3 P, float3 idir, uint visibility, int object, int triAddr) +{ + /* curve Intersection check */ + + int flags = kernel_data.curve_kernel_data.curveflags; + + int prim = kernel_tex_fetch(__prim_index, triAddr); + float4 v00 = kernel_tex_fetch(__cur_segs, prim); + + int v1 = __float_as_int(v00.x); + int v2 = __float_as_int(v00.y); + + float4 P1 = kernel_tex_fetch(__cur_keys, v1); + float4 P2 = kernel_tex_fetch(__cur_keys, v2); + + float l = v00.w; + float r1 = P1.w; + float r2 = P2.w; + float mr = max(r1,r2); + float3 p1 = float4_to_float3(P1); + float3 p2 = float4_to_float3(P2); + float3 dif = P - p1; + float3 dir = 1.0f/idir; + + /* test bounding sphere intersection (introduce circular artifacts)*/ + /*float3 bvector = 0.5f * (p1 + p2) - P; + float bvectorl_sq = len_squared(bvector); + float dot_bv_dir = dot(bvector,dir); + float maxdist = l * 0.5f + mr; + if(bvectorl_sq - dot_bv_dir * dot_bv_dir > maxdist * maxdist) + return;*/ + + /* obtain parameters and test midpoint distance for suitable modes*/ + float3 tg = (p2 - p1) / l; + float gd = (r2 - r1) / l; + float dirz = dot(dir,tg); + float difz = dot(dif,tg); + + float a = 1.0f - (dirz*dirz*(1 + gd*gd)); + float halfb = (dot(dir,dif) - dirz*(difz + gd*(difz*gd + r1))); + + float tcentre = -halfb/a; + float zcentre = difz + (dirz * tcentre); + + if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE)) + return; + if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION)) + return; + + /* test minimum separation*/ + float3 cprod = cross(tg, dir); + float3 cprod2 = cross(tg, dif); + float cprodsq = len_squared(cprod); + float cprod2sq = len_squared(cprod2); + float distscaled = dot(cprod,dif); + + if(cprodsq == 0) + distscaled = cprod2sq; + else + distscaled = (distscaled*distscaled)/cprodsq; + + if(distscaled > mr*mr) + return; + + /* calculate true intersection*/ + float3 tdif = P - p1 + tcentre * dir; + float tdifz = dot(tdif,tg); + float tb = 2*(dot(dir,tdif) - dirz*(tdifz + gd*(tdifz*gd + r1))); + float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd; + float td = tb*tb - 4*a*tc; + + if (td<0) + return; + + float rootd = 0.0f; + float correction = 0.0f; + if(flags & CURVE_KN_ACCURATE) { + rootd = sqrtf(td); + correction = ((-tb - rootd)/(2*a)); + } + + float t = tcentre + correction; + + if(t < isect->t) { + + if(flags & CURVE_KN_INTERSECTCORRECTION) { + rootd = sqrtf(td); + correction = ((-tb - rootd)/(2*a)); + t = tcentre + correction; + } + + float z = zcentre + (dirz * correction); + bool backface = false; + + if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) { + backface = true; + correction = ((-tb + rootd)/(2*a)); + t = tcentre + correction; + z = zcentre + (dirz * correction); + } + + if(t > 0.0f && t < isect->t && z >= 0 && z <= l) { + + if (flags & CURVE_KN_ENCLOSEFILTER) { + + float enc_ratio = kernel_data.curve_kernel_data.encasing_ratio; + if((dot(P - p1, tg) > -r1 * enc_ratio) && (dot(P - p2, tg) < r2 * enc_ratio)) { + float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio)); + float c2 = dot(dif,dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio; + if(a2*c2 < 0.0f) + return; + } + } + + /*remove overlap - not functional yet*/ + /*if (flags & CURVE_KN_CURVEDATA) { + float3 tg1 = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0)); + float3 tg2 = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1)); + if((dot(P + t * dir - p1, tg1) < 0.0f) || (dot(P + t * dir - p2, tg2) > 0.0f)) + return; + }*/ + + #ifdef __VISIBILITY_FLAG__ + /* visibility flag test. we do it here under the assumption + * that most triangles are culled by node flags */ + if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility) + #endif + { + /* record intersection */ + isect->prim = triAddr; + isect->object = object; + isect->u = z/l; + isect->v = td/(4*a*a); + isect->t = t; + + if(backface) + isect->u = -isect->u; + } + } + } +} +#endif + __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) { /* traversal stack in CUDA thread-local memory */ @@ -281,10 +426,15 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint nodeAddr = traversalStack[stackPtr]; --stackPtr; - /* triangle intersection */ + /* primitive intersection */ while(primAddr < primAddr2) { - /* intersect ray against triangle */ - bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); + /* intersect ray against primitive */ +#ifdef __HAIR__ + if(kernel_tex_fetch(__prim_type, primAddr)) + bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr); + else +#endif + bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); /* shadow ray early termination */ if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0) @@ -401,10 +551,15 @@ __device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, con nodeAddr = traversalStack[stackPtr]; --stackPtr; - /* triangle intersection */ + /* primitive intersection */ while(primAddr < primAddr2) { - /* intersect ray against triangle */ - bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); + /* intersect ray against primitive */ +#ifdef __HAIR__ + if(kernel_tex_fetch(__prim_type, primAddr)) + bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr); + else +#endif + bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); /* shadow ray early termination */ if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0) @@ -545,5 +700,105 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co #endif } +#ifdef __HAIR__ +__device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float t) +{ + int flag = kernel_data.curve_kernel_data.curveflags; + float3 P = ray->P; + float3 D = ray->D; + + if(isect->object != ~0) { +#ifdef __OBJECT_MOTION__ + Transform tfm = sd->ob_itfm; +#else + Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); +#endif + + P = transform_point(&tfm, P); + D = transform_direction(&tfm, D*t); + D = normalize_len(D, &t); + } + + int prim = kernel_tex_fetch(__prim_index, isect->prim); + float4 v00 = kernel_tex_fetch(__cur_segs, prim); + + int v1 = __float_as_int(v00.x); + int v2 = __float_as_int(v00.y); + + float4 P1 = kernel_tex_fetch(__cur_keys, v1); + float4 P2 = kernel_tex_fetch(__cur_keys, v2); + float l = v00.w; + float r1 = P1.w; + float r2 = P2.w; + float3 tg = float4_to_float3(P2 - P1) / l; + float3 dif = P - float4_to_float3(P1) + t * D; + float gd = ((r2 - r1)/l); + + P = P + D*t; + + dif = P - float4_to_float3(P1); + + #ifdef __UV__ + sd->u = dot(dif,tg)/l; + sd->v = 0.0f; + #endif + + if (flag & CURVE_KN_TRUETANGENTGNORMAL) { + sd->Ng = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix)); + sd->Ng = normalize(sd->Ng); + if (flag & CURVE_KN_NORMALCORRECTION) + { + //sd->Ng = normalize(sd->Ng); + sd->Ng = sd->Ng - gd * tg; + sd->Ng = normalize(sd->Ng); + } + } + else { + sd->Ng = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd); + if (gd != 0.0f) { + sd->Ng = sd->Ng - gd * tg ; + sd->Ng = normalize(sd->Ng); + } + } + + sd->N = sd->Ng; + + if (flag & CURVE_KN_TANGENTGNORMAL && !(flag & CURVE_KN_TRUETANGENTGNORMAL)) { + sd->N = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix)); + sd->N = normalize(sd->N); + if (flag & CURVE_KN_NORMALCORRECTION) { + //sd->N = normalize(sd->N); + sd->N = sd->N - gd * tg; + sd->N = normalize(sd->N); + } + } + if (!(flag & CURVE_KN_TANGENTGNORMAL) && flag & CURVE_KN_TRUETANGENTGNORMAL) { + sd->N = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd); + if (gd != 0.0f) { + sd->N = sd->N - gd * tg ; + sd->N = normalize(sd->N); + } + } + + #ifdef __DPDU__ + /* dPdu/dPdv */ + sd->dPdu = tg; + sd->dPdv = cross(tg,sd->Ng); + #endif + + if(isect->object != ~0) { +#ifdef __OBJECT_MOTION__ + Transform tfm = sd->ob_tfm; +#else + Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); +#endif + + P = transform_point(&tfm, P); + } + + return P; +} +#endif + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index e56633c9358..adf7e8eca82 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -47,7 +47,13 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, else #endif { - shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time); +#ifdef __HAIR__ + if(ls->type == LIGHT_STRAND) + shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, ls->prim); + else +#endif + shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time); + ls->Ng = sd.Ng; /* no path flag, we're evaluating this for all closures. that's weak but @@ -150,7 +156,11 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in /* evaluate emissive closure */ float3 L = shader_emissive_eval(kg, sd); +#ifdef __HAIR__ + if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->curve_seg == ~0)) { +#else if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) { +#endif /* multiple importance sampling, get triangle light pdf, * and compute weight with respect to BSDF pdf */ float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t); diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 97ae2d3db87..0f74ab75dd4 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -326,6 +326,59 @@ __device float triangle_light_pdf(KernelGlobals *kg, return (t*t*kernel_data.integrator.pdf_triangles)/cos_pi; } +#ifdef __HAIR__ +/* Strand Light */ + +__device void curve_seg_light_sample(KernelGlobals *kg, int prim, int object, + float randu, float randv, float time, LightSample *ls) +{ + /* this strand code needs completion */ + float4 v00 = kernel_tex_fetch(__cur_segs, prim); + + int v1 = __float_as_int(v00.x); + int v2 = __float_as_int(v00.y); + float l = v00.w; + + float4 P1 = kernel_tex_fetch(__cur_keys, v1); + float4 P2 = kernel_tex_fetch(__cur_keys, v2); + float r1 = P1.w; + float r2 = P2.w; + float3 tg = float4_to_float3(P2 - P1) / l; + float3 xc = make_float3(tg.x * tg.z, tg.y * tg.z, -(tg.x * tg.x + tg.y * tg.y)); + if (dot(xc, xc) == 0.0f) + xc = make_float3(tg.x * tg.y, -(tg.x * tg.x + tg.z * tg.z), tg.z * tg.y); + xc = normalize(xc); + float3 yc = cross(tg, xc); + float gd = ((r2 - r1)/l); + + /* normal currently ignores gradient */ + ls->Ng = sinf(2 * M_PI_F * randv) * xc + cosf(2 * M_PI_F * randv) * yc; + ls->P = randu * l * tg + (gd * l + r1) * ls->Ng; + ls->object = object; + ls->prim = prim; + ls->t = 0.0f; + ls->type = LIGHT_STRAND; + ls->eval_fac = 1.0f; + ls->shader = __float_as_int(v00.z); + +#ifdef __INSTANCING__ + /* instance transform */ + if(ls->object >= 0) { +#ifdef __OBJECT_MOTION__ + Transform itfm; + Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm); +#else + Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM); + Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM); +#endif + + ls->P = transform_point(&tfm, ls->P); + ls->Ng = normalize(transform_direction(&tfm, ls->Ng)); + } +#endif +} +#endif + /* Light Distribution */ __device int light_distribution_sample(KernelGlobals *kg, float randt) @@ -365,10 +418,19 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra /* fetch light data */ float4 l = kernel_tex_fetch(__light_distribution, index); int prim = __float_as_int(l.y); +#ifdef __HAIR__ +/* currently use l.z to indicate is strand sample which isn't ideal */ + bool is_curve = __float_as_int(l.z) == 0.0f; +#endif if(prim >= 0) { int object = __float_as_int(l.w); - triangle_light_sample(kg, prim, object, randu, randv, time, ls); +#ifdef __HAIR__ + if (is_curve) + curve_seg_light_sample(kg, prim, object, randu, randv, time, ls); + else +#endif + triangle_light_sample(kg, prim, object, randu, randv, time, ls); } else { int point = -prim-1; diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 40aa4753daa..2260094aa70 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -288,5 +288,55 @@ __device float3 particle_angular_velocity(KernelGlobals *kg, int particle) return make_float3(f3.z, f3.w, f4.x); } +#ifdef __HAIR__ +/* Hair Info Node fns */ + +__device float hair_radius(KernelGlobals *kg, int prim, float u) +{ + float r = 0.0f; + + if (prim != -1) { + float4 v00 = kernel_tex_fetch(__cur_segs, prim); + + int v1 = __float_as_int(v00.x); + int v2 = __float_as_int(v00.y); + + float4 P1 = kernel_tex_fetch(__cur_keys, v1); + float4 P2 = kernel_tex_fetch(__cur_keys, v2); + r = (P2.w - P1.w) * u + P1.w; + } + + return r; +} + +__device float3 hair_tangent_normal(KernelGlobals *kg, ShaderData *sd) +{ + float3 tgN = make_float3(0.0f,0.0f,0.0f); + + if (sd->curve_seg != ~0) { + tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * kernel_data.curve_kernel_data.normalmix / len_squared(sd->dPdu))); + tgN = normalize(tgN); + /*if (kernel_data.curve_kernel_data.use_tangent_normal_correction) need to find suitable scaled gd for corrected normal + { + tgN = normalize(tgN - gd * sd->dPdu); + }*/ + } + + return tgN; +} + +__device float intercept(KernelGlobals *kg, int prim, int triAddr, float u) +{ + float t = 0.0f; + + if (prim != -1) { + float4 sd2 = kernel_tex_fetch(__tri_woop, triAddr*3+2); + t = (sd2.y - sd2.x) * u + sd2.x; + } + + return t; +} +#endif + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 47b4d02e5bf..36cd21c1b48 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -56,24 +56,9 @@ __device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderD __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { - /* fetch triangle data */ - int prim = kernel_tex_fetch(__prim_index, isect->prim); - float4 Ns = kernel_tex_fetch(__tri_normal, prim); - float3 Ng = make_float3(Ns.x, Ns.y, Ns.z); - int shader = __float_as_int(Ns.w); - - /* triangle */ #ifdef __INSTANCING__ sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object; #endif - sd->prim = prim; -#ifdef __UV__ - sd->u = isect->u; - sd->v = isect->v; -#endif - - sd->flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2); - sd->flag |= kernel_tex_fetch(__object_flag, sd->object); /* matrices and time */ #ifdef __OBJECT_MOTION__ @@ -81,23 +66,64 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, sd->time = ray->time; #endif - /* vectors */ - sd->P = bvh_triangle_refine(kg, sd, isect, ray); - sd->Ng = Ng; - sd->N = Ng; - sd->I = -ray->D; - sd->shader = shader; + sd->prim = kernel_tex_fetch(__prim_index, isect->prim); +#ifdef __HAIR__ + sd->curve_seg = ~0; +#endif sd->ray_length = isect->t; - /* smooth normal */ - if(sd->shader & SHADER_SMOOTH_NORMAL) - sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); +#ifdef __HAIR__ + if(kernel_tex_fetch(__prim_type, isect->prim)) { + /* Strand Shader setting*/ + float4 CurSeg = kernel_tex_fetch(__cur_segs, sd->prim); + sd->shader = __float_as_int(CurSeg.z); + + sd->curve_seg = sd->prim; + sd->prim = isect->prim; + + float tcorr = isect->t; + if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION) { + tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v); + sd->ray_length = tcorr; + } + sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr); + } + else { +#endif + /* fetch triangle data */ + float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim); + float3 Ng = make_float3(Ns.x, Ns.y, Ns.z); + sd->shader = __float_as_int(Ns.w); + +#ifdef __UV__ + sd->u = isect->u; + sd->v = isect->v; +#endif + + /* vectors */ + sd->P = bvh_triangle_refine(kg, sd, isect, ray); + sd->Ng = Ng; + sd->N = Ng; + + + /* smooth normal */ + if(sd->shader & SHADER_SMOOTH_NORMAL) + sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); #ifdef __DPDU__ - /* dPdu/dPdv */ - triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim); + /* dPdu/dPdv */ + triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim); #endif +#ifdef __HAIR__ + } +#endif + + sd->I = -ray->D; + + sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); + sd->flag |= kernel_tex_fetch(__object_flag, sd->object); + #ifdef __INSTANCING__ if(isect->object != ~0) { /* instance transform */ @@ -135,7 +161,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, const float3 P, const float3 Ng, const float3 I, - int shader, int object, int prim, float u, float v, float t, float time) + int shader, int object, int prim, float u, float v, float t, float time, int curve = ~0) { /* vectors */ sd->P = P; @@ -143,11 +169,15 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, sd->Ng = Ng; sd->I = I; sd->shader = shader; +#ifdef __HAIR__ + sd->curve_seg = curve; +#endif /* primitive */ #ifdef __INSTANCING__ sd->object = object; #endif + /* currently no access to bvh prim index for strand sd->prim - this will cause errors with needs fixing*/ sd->prim = prim; #ifdef __UV__ sd->u = u; @@ -183,8 +213,13 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, #endif /* smooth normal */ +#ifdef __HAIR__ + if(sd->shader & SHADER_SMOOTH_NORMAL && sd->curve_seg == ~0) { + sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); +#else if(sd->shader & SHADER_SMOOTH_NORMAL) { sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); +#endif #ifdef __INSTANCING__ if(instanced) @@ -194,10 +229,17 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, #ifdef __DPDU__ /* dPdu/dPdv */ +#ifdef __HAIR__ + if(sd->prim == ~0 || sd->curve_seg != ~0) { + sd->dPdu = make_float3(0.0f, 0.0f, 0.0f); + sd->dPdv = make_float3(0.0f, 0.0f, 0.0f); + } +#else if(sd->prim == ~0) { sd->dPdu = make_float3(0.0f, 0.0f, 0.0f); sd->dPdv = make_float3(0.0f, 0.0f, 0.0f); } +#endif else { triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim); @@ -279,6 +321,9 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData sd->object = ~0; #endif sd->prim = ~0; +#ifdef __HAIR__ + sd->curve_seg = ~0; +#endif #ifdef __UV__ sd->u = 0.0f; sd->v = 0.0f; @@ -732,8 +777,20 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, Shader __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect) { int prim = kernel_tex_fetch(__prim_index, isect->prim); - float4 Ns = kernel_tex_fetch(__tri_normal, prim); - int shader = __float_as_int(Ns.w); + int shader = 0; + +#ifdef __HAIR__ + if(!kernel_tex_fetch(__prim_type, isect->prim)) { +#endif + float4 Ns = kernel_tex_fetch(__tri_normal, prim); + shader = __float_as_int(Ns.w); +#ifdef __HAIR__ + } + else { + float4 str = kernel_tex_fetch(__cur_segs, prim); + shader = __float_as_int(str.z); + } +#endif int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2); return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0; diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 29f6b3f072c..0b6107b398e 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -27,6 +27,7 @@ /* bvh */ KERNEL_TEX(float4, texture_float4, __bvh_nodes) KERNEL_TEX(float4, texture_float4, __tri_woop) +KERNEL_TEX(uint, texture_uint, __prim_type) KERNEL_TEX(uint, texture_uint, __prim_visibility) KERNEL_TEX(uint, texture_uint, __prim_index) KERNEL_TEX(uint, texture_uint, __prim_object) @@ -42,6 +43,10 @@ KERNEL_TEX(float4, texture_float4, __tri_vnormal) KERNEL_TEX(float4, texture_float4, __tri_vindex) KERNEL_TEX(float4, texture_float4, __tri_verts) +/* curves */ +KERNEL_TEX(float4, texture_float4, __cur_segs) +KERNEL_TEX(float4, texture_float4, __cur_keys) + /* attributes */ KERNEL_TEX(uint4, texture_uint4, __attributes_map) KERNEL_TEX(float, texture_float, __attributes_float) diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index 570ae52d6c2..1f2618d3507 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -106,88 +106,107 @@ __device_inline void triangle_dPdudv(KernelGlobals *kg, float3 *dPdu, float3 *dP __device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) { - if(elem == ATTR_ELEMENT_FACE) { - if(dx) *dx = 0.0f; - if(dy) *dy = 0.0f; - - return kernel_tex_fetch(__attributes_float, offset + sd->prim); - } - else if(elem == ATTR_ELEMENT_VERTEX) { - float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); - - float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x)); - float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y)); - float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z)); - -#ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; -#endif - - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; - } - else if(elem == ATTR_ELEMENT_CORNER) { - int tri = offset + sd->prim*3; - float f0 = kernel_tex_fetch(__attributes_float, tri + 0); - float f1 = kernel_tex_fetch(__attributes_float, tri + 1); - float f2 = kernel_tex_fetch(__attributes_float, tri + 2); - -#ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; +#ifdef __HAIR__ + if(sd->curve_seg == ~0) { #endif - - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + if(elem == ATTR_ELEMENT_FACE) { + if(dx) *dx = 0.0f; + if(dy) *dy = 0.0f; + + return kernel_tex_fetch(__attributes_float, offset + sd->prim); + } + else if(elem == ATTR_ELEMENT_VERTEX) { + float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); + + float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x)); + float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y)); + float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z)); + + #ifdef __RAY_DIFFERENTIALS__ + if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; + if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + #endif + + return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + } + else if(elem == ATTR_ELEMENT_CORNER) { + int tri = offset + sd->prim*3; + float f0 = kernel_tex_fetch(__attributes_float, tri + 0); + float f1 = kernel_tex_fetch(__attributes_float, tri + 1); + float f2 = kernel_tex_fetch(__attributes_float, tri + 2); + + #ifdef __RAY_DIFFERENTIALS__ + if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; + if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + #endif + + return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + } + else { + if(dx) *dx = 0.0f; + if(dy) *dy = 0.0f; + + return 0.0f; + } +#ifdef __HAIR__ } else { - if(dx) *dx = 0.0f; - if(dy) *dy = 0.0f; - return 0.0f; } +#endif } __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) { - if(elem == ATTR_ELEMENT_FACE) { - if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); - if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - - return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim)); - } - else if(elem == ATTR_ELEMENT_VERTEX) { - float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); - - float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x))); - float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y))); - float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z))); - -#ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; +#ifdef __HAIR__ + if(sd->curve_seg == ~0) { #endif - - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; - } - else if(elem == ATTR_ELEMENT_CORNER) { - int tri = offset + sd->prim*3; - float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); - float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); - float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); - -#ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; -#endif - - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + if(elem == ATTR_ELEMENT_FACE) { + if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); + if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); + + return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim)); + } + else if(elem == ATTR_ELEMENT_VERTEX) { + float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); + + float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x))); + float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y))); + float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z))); + + #ifdef __RAY_DIFFERENTIALS__ + if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; + if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + #endif + + return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + } + else if(elem == ATTR_ELEMENT_CORNER) { + int tri = offset + sd->prim*3; + float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); + float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); + float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); + + #ifdef __RAY_DIFFERENTIALS__ + if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; + if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + #endif + + return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + } + else { + if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); + if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); + + return make_float3(0.0f, 0.0f, 0.0f); + } +#ifdef __HAIR__ } - else { - if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); - if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - + else + { return make_float3(0.0f, 0.0f, 0.0f); } +#endif } /* motion */ @@ -200,10 +219,16 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd) int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE); int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST); - if(offset_pre != ATTR_STD_NOT_FOUND) - motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL); - if(offset_post != ATTR_STD_NOT_FOUND) - motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL); +#ifdef __HAIR__ + if(sd->curve_seg == ~0) { +#endif + if(offset_pre != ATTR_STD_NOT_FOUND) + motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL); + if(offset_post != ATTR_STD_NOT_FOUND) + motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL); +#ifdef __HAIR__ + } +#endif /* object motion. note that depending on the mesh having motion vectors, this * transformation was set match the world/object space of motion_pre/post */ @@ -259,8 +284,13 @@ __device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd) { int offset_uv = find_attribute(kg, sd, ATTR_STD_UV); +#ifdef __HAIR__ + if(offset_uv == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0) + return make_float3(0.0f, 0.0f, 0.0f); +#else if(offset_uv == ATTR_STD_NOT_FOUND) return make_float3(0.0f, 0.0f, 0.0f); +#endif float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL); uv.z = 1.0f; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index d11b96503d9..d051006f165 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -47,6 +47,7 @@ CCL_NAMESPACE_BEGIN #define __OSL__ #endif #define __NON_PROGRESSIVE__ +#define __HAIR__ #endif #ifdef __KERNEL_CUDA__ @@ -116,7 +117,6 @@ CCL_NAMESPACE_BEGIN #define __ANISOTROPIC__ #define __OBJECT_MOTION__ #endif - //#define __SOBOL_FULL_SCREEN__ /* Shader Evaluation */ @@ -292,7 +292,8 @@ typedef enum LightType { LIGHT_BACKGROUND, LIGHT_AREA, LIGHT_AO, - LIGHT_SPOT + LIGHT_SPOT, + LIGHT_STRAND } LightType; /* Camera Type */ @@ -436,6 +437,11 @@ typedef struct ShaderData { /* primitive id if there is one, ~0 otherwise */ int prim; + +#ifdef __HAIR__ + /* strand id if there is one, -1 otherwise */ + int curve_seg; +#endif /* parametric coordinates * - barycentric weights for triangles */ float u, v; @@ -650,6 +656,29 @@ typedef struct KernelBVH { int pad2; } KernelBVH; +typedef enum CurveFlag { + /* runtime flags */ + CURVE_KN_BACKFACING = 1, /* backside of cylinder? */ + CURVE_KN_ENCLOSEFILTER = 2, /* don't consider strands surrounding start point? */ + CURVE_KN_CURVEDATA = 4, /* curve data available? */ + CURVE_KN_INTERPOLATE = 8, /* render as a curve? - not supported yet */ + CURVE_KN_ACCURATE = 16, /* use accurate intersections test? */ + CURVE_KN_INTERSECTCORRECTION = 32, /* correct for width after determing closest midpoint? */ + CURVE_KN_POSTINTERSECTCORRECTION = 64, /* correct for width after intersect? */ + CURVE_KN_NORMALCORRECTION = 128, /* correct tangent normal for slope? */ + CURVE_KN_TRUETANGENTGNORMAL = 256, /* use tangent normal for geometry? */ + CURVE_KN_TANGENTGNORMAL = 512, /* use tangent normal for shader? */ +} CurveFlag; + +typedef struct KernelCurves { + /* strand intersect and normal parameters - many can be changed to flags*/ + float normalmix; + float encasing_ratio; + int curveflags; + int pad; + +} KernelCurves; + typedef struct KernelData { KernelCamera cam; KernelFilm film; @@ -657,6 +686,7 @@ typedef struct KernelData { KernelSunSky sunsky; KernelIntegrator integrator; KernelBVH bvh; + KernelCurves curve_kernel_data; } KernelData; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index ec7978066c2..1f4857c0924 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -301,6 +301,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_PARTICLE_INFO: svm_node_particle_info(kg, sd, stack, node.y, node.z); break; +#ifdef __HAIR__ + case NODE_HAIR_INFO: + svm_node_hair_info(kg, sd, stack, node.y, node.z); + break; +#endif + #endif case NODE_CONVERT: svm_node_convert(sd, stack, node.y, node.z, node.w); diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index ed70a6dc423..4f9dc4af007 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -58,27 +58,45 @@ __device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uin svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset); - /* fetch and store attribute */ - if(type == NODE_ATTR_FLOAT) { - if(mesh_type == NODE_ATTR_FLOAT) { - float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL); - stack_store_float(stack, out_offset, f); - } +#ifdef __HAIR__ + if (sd->curve_seg != ~0) { + /*currently strand attributes aren't enabled - only exports stored uvs*/ + if(type == NODE_ATTR_FLOAT) + stack_store_float(stack, out_offset, 0.0f); else { - float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL); - stack_store_float(stack, out_offset, average(f)); + float4 sd2 = kernel_tex_fetch(__tri_woop, sd->prim*3+2); + float3 uv = make_float3(sd2.z,sd2.w,0.0f); + stack_store_float3(stack, out_offset, uv); } } - else { - if(mesh_type == NODE_ATTR_FLOAT3) { - float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL); - stack_store_float3(stack, out_offset, f); + else + { +#endif + + /* fetch and store attribute */ + if(type == NODE_ATTR_FLOAT) { + if(mesh_type == NODE_ATTR_FLOAT) { + float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL); + stack_store_float(stack, out_offset, f); + } + else { + float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL); + stack_store_float(stack, out_offset, average(f)); + } } else { - float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL); - stack_store_float3(stack, out_offset, make_float3(f, f, f)); + if(mesh_type == NODE_ATTR_FLOAT3) { + float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL); + stack_store_float3(stack, out_offset, f); + } + else { + float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL); + stack_store_float3(stack, out_offset, make_float3(f, f, f)); + } } +#ifdef __HAIR__ } +#endif } __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) @@ -91,30 +109,43 @@ __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *st svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset); /* fetch and store attribute */ - if(type == NODE_ATTR_FLOAT) { - if(mesh_type == NODE_ATTR_FLOAT) { - float dx; - float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL); - stack_store_float(stack, out_offset, f+dx); - } - else { - float3 dx; - float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL); - stack_store_float(stack, out_offset, average(f+dx)); - } +#ifdef __HAIR__ + if (sd->curve_seg != ~0) { + /*currently strand attributes aren't enabled*/ + if(type == NODE_ATTR_FLOAT) + stack_store_float(stack, out_offset, 0.0f); + else + stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f)); } else { - if(mesh_type == NODE_ATTR_FLOAT3) { - float3 dx; - float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL); - stack_store_float3(stack, out_offset, f+dx); +#endif + if(type == NODE_ATTR_FLOAT) { + if(mesh_type == NODE_ATTR_FLOAT) { + float dx; + float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL); + stack_store_float(stack, out_offset, f+dx); + } + else { + float3 dx; + float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL); + stack_store_float(stack, out_offset, average(f+dx)); + } } else { - float dx; - float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL); - stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx)); + if(mesh_type == NODE_ATTR_FLOAT3) { + float3 dx; + float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL); + stack_store_float3(stack, out_offset, f+dx); + } + else { + float dx; + float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL); + stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx)); + } } +#ifdef __HAIR__ } +#endif } __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) @@ -127,30 +158,43 @@ __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *st svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset); /* fetch and store attribute */ - if(type == NODE_ATTR_FLOAT) { - if(mesh_type == NODE_ATTR_FLOAT) { - float dy; - float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy); - stack_store_float(stack, out_offset, f+dy); - } - else { - float3 dy; - float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy); - stack_store_float(stack, out_offset, average(f+dy)); - } +#ifdef __HAIR__ + if (sd->curve_seg != ~0) { + /*currently strand attributes aren't enabled*/ + if(type == NODE_ATTR_FLOAT) + stack_store_float(stack, out_offset, 0.0f); + else + stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f)); } else { - if(mesh_type == NODE_ATTR_FLOAT3) { - float3 dy; - float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy); - stack_store_float3(stack, out_offset, f+dy); +#endif + if(type == NODE_ATTR_FLOAT) { + if(mesh_type == NODE_ATTR_FLOAT) { + float dy; + float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy); + stack_store_float(stack, out_offset, f+dy); + } + else { + float3 dy; + float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy); + stack_store_float(stack, out_offset, average(f+dy)); + } } else { - float dy; - float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy); - stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy)); + if(mesh_type == NODE_ATTR_FLOAT3) { + float3 dy; + float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy); + stack_store_float3(stack, out_offset, f+dy); + } + else { + float dy; + float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy); + stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy)); + } } +#ifdef __HAIR__ } +#endif } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index c4d03c1f948..e1b898e9b14 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -31,8 +31,11 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, case NODE_GEOM_T: { /* try to create spherical tangent from generated coordinates */ int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND; - +#ifdef __HAIR__ + if(attr_offset != ATTR_STD_NOT_FOUND && sd->curve_seg == ~0) { +#else if(attr_offset != ATTR_STD_NOT_FOUND) { +#endif data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); object_normal_transform(kg, sd, &data); @@ -160,5 +163,38 @@ __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *s } } +#ifdef __HAIR__ +/* Hair Info */ + +__device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) +{ + float data; + float3 data3; + + switch(type) { + case NODE_INFO_CURVE_IS_STRAND: { + data = !(sd->curve_seg == ~0); + stack_store_float(stack, out_offset, data); + break; + } + case NODE_INFO_CURVE_INTERCEPT: { + data = intercept(kg, sd->curve_seg, sd->prim, sd->u); + stack_store_float(stack, out_offset, data); + break; + } + case NODE_INFO_CURVE_THICKNESS: { + data = 2 * hair_radius(kg, sd->curve_seg, sd->u); + stack_store_float(stack, out_offset, data); + break; + } + case NODE_INFO_CURVE_TANGENT_NORMAL: { + data3 = hair_tangent_normal(kg, sd); + stack_store_float3(stack, out_offset, data3); + break; + } + } +} +#endif + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 9f2d3367420..5e7c92ba93c 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -242,7 +242,11 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac if(space == NODE_NORMAL_MAP_TANGENT) { /* tangent space */ - if(sd->object == ~0) { +#ifdef __HAIR__ + if(sd->object == ~0 || sd->curve_seg != ~0) { +#else + if(sd->object == ~0) { +#endif stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); return; } @@ -297,7 +301,11 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, /* UV map */ int attr_offset = find_attribute(kg, sd, node.z); +#ifdef __HAIR__ + if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0) +#else if(attr_offset == ATTR_STD_NOT_FOUND) +#endif tangent = make_float3(0.0f, 0.0f, 0.0f); else tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); @@ -307,7 +315,11 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, int attr_offset = find_attribute(kg, sd, node.z); float3 generated; +#ifdef __HAIR__ + if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0) +#else if(attr_offset == ATTR_STD_NOT_FOUND) +#endif generated = sd->P; else generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index e1a583625fc..57177eec48f 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -97,7 +97,8 @@ typedef enum NodeType { NODE_CLOSURE_SET_NORMAL, NODE_CLOSURE_AMBIENT_OCCLUSION, NODE_TANGENT, - NODE_NORMAL_MAP + NODE_NORMAL_MAP, + NODE_HAIR_INFO } NodeType; typedef enum NodeAttributeType { @@ -132,6 +133,13 @@ typedef enum NodeParticleInfo { NODE_INFO_PAR_ANGULAR_VELOCITY } NodeParticleInfo; +typedef enum NodeHairInfo { + NODE_INFO_CURVE_IS_STRAND, + NODE_INFO_CURVE_INTERCEPT, + NODE_INFO_CURVE_THICKNESS, + NODE_INFO_CURVE_TANGENT_NORMAL +} NodeHairInfo; + typedef enum NodeLightPath { NODE_LP_camera = 0, NODE_LP_shadow, -- cgit v1.2.3