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/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 ++- 5 files changed, 159 insertions(+), 53 deletions(-) (limited to 'intern/cycles/kernel/svm') 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