Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Broadfoot <gbroadfoot@hotmail.com>2012-12-28 18:21:30 +0400
committerStuart Broadfoot <gbroadfoot@hotmail.com>2012-12-28 18:21:30 +0400
commite9ba345c46c93a193193f01d4bfac714a666d384 (patch)
tree49df9d78dc9327de642779e300e1592e5d7b3a42 /intern/cycles/kernel
parent857df8065face58eff5556953cdf2dd72e09f2b6 (diff)
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.
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r--intern/cycles/kernel/kernel_bvh.h267
-rw-r--r--intern/cycles/kernel/kernel_emission.h12
-rw-r--r--intern/cycles/kernel/kernel_light.h64
-rw-r--r--intern/cycles/kernel/kernel_object.h50
-rw-r--r--intern/cycles/kernel/kernel_shader.h115
-rw-r--r--intern/cycles/kernel/kernel_textures.h5
-rw-r--r--intern/cycles/kernel/kernel_triangle.h176
-rw-r--r--intern/cycles/kernel/kernel_types.h34
-rw-r--r--intern/cycles/kernel/svm/svm.h6
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h144
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h38
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h14
-rw-r--r--intern/cycles/kernel/svm/svm_types.h10
13 files changed, 770 insertions, 165 deletions
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,