Cycles: Implement index output for hair node

This is like the only way to add variety to hair which is created
using simple children. Used here for the hair.

Maybe not ideal, but the time will show.
This commit is contained in:
Sergey Sharybin 2018-02-13 14:20:47 +01:00
parent d640ce40aa
commit 37f65e9dc4
8 changed files with 39 additions and 2 deletions

View File

@ -565,9 +565,12 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
return;
Attribute *attr_intercept = NULL;
Attribute *attr_index = NULL;
if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
if(mesh->need_attribute(scene, ATTR_STD_CURVE_INDEX))
attr_index = mesh->curve_attributes.add(ATTR_STD_CURVE_INDEX);
/* compute and reserve size of arrays */
for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
@ -612,12 +615,25 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
num_curve_keys++;
}
if(attr_index != NULL) {
attr_index->add(num_curves);
}
mesh->add_curve(num_keys, CData->psys_shader[sys]);
num_keys += num_curve_keys;
num_curves++;
}
}
if(attr_index != NULL) {
/* Normalize index to 0..1 range. */
float *curve_index = attr_index->data_float();
const float norm_factor = 1.0f / (float)num_curves;
for(int i = 0; i < num_curves; ++i) {
curve_index[i] *= norm_factor;
}
}
/* check allocation */
if((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
VLOG(1) << "Allocation failed, clearing data";

View File

@ -772,6 +772,7 @@ typedef enum AttributeStandard {
ATTR_STD_MOTION_VERTEX_NORMAL,
ATTR_STD_PARTICLE,
ATTR_STD_CURVE_INTERCEPT,
ATTR_STD_CURVE_INDEX,
ATTR_STD_PTEX_FACE_ID,
ATTR_STD_PTEX_UV,
ATTR_STD_VOLUME_DENSITY,

View File

@ -20,11 +20,13 @@ shader node_hair_info(
output float IsStrand = 0.0,
output float Intercept = 0.0,
output float Thickness = 0.0,
output normal TangentNormal = N)
output normal TangentNormal = N,
output float Index = 0)
{
getattribute("geom:is_curve", IsStrand);
getattribute("geom:curve_intercept", Intercept);
getattribute("geom:curve_thickness", Thickness);
getattribute("geom:curve_tangent_normal", TangentNormal);
getattribute("geom:curve_index", Index);
}

View File

@ -180,6 +180,8 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg,
}
case NODE_INFO_CURVE_INTERCEPT:
break; /* handled as attribute */
case NODE_INFO_CURVE_INDEX:
break; /* handled as attribute */
case NODE_INFO_CURVE_THICKNESS: {
data = curve_thickness(kg, sd);
stack_store_float(stack, out_offset, data);

View File

@ -176,7 +176,8 @@ typedef enum NodeHairInfo {
NODE_INFO_CURVE_THICKNESS,
/*fade for minimum hair width transpency*/
/*NODE_INFO_CURVE_FADE,*/
NODE_INFO_CURVE_TANGENT_NORMAL
NODE_INFO_CURVE_TANGENT_NORMAL,
NODE_INFO_CURVE_INDEX,
} NodeHairInfo;
typedef enum NodeLightPath {

View File

@ -267,6 +267,8 @@ const char *Attribute::standard_name(AttributeStandard std)
return "particle";
case ATTR_STD_CURVE_INTERCEPT:
return "curve_intercept";
case ATTR_STD_CURVE_INDEX:
return "curve_index";
case ATTR_STD_PTEX_FACE_ID:
return "ptex_face_id";
case ATTR_STD_PTEX_UV:
@ -451,6 +453,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_CURVE_INTERCEPT:
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
break;
case ATTR_STD_CURVE_INDEX:
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
break;
case ATTR_STD_GENERATED_TRANSFORM:
attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
break;

View File

@ -3572,6 +3572,7 @@ NODE_DEFINE(HairInfoNode)
#if 0 /*output for minimum hair width transparency - deactivated */
SOCKET_OUT_FLOAT(fade, "Fade");
#endif
SOCKET_OUT_FLOAT(index, "Index");
return type;
}
@ -3588,6 +3589,9 @@ void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
if(!intercept_out->links.empty())
attributes->add(ATTR_STD_CURVE_INTERCEPT);
if(!output("Index")->links.empty())
attributes->add(ATTR_STD_CURVE_INDEX);
}
ShaderNode::attributes(shader, attributes);
@ -3623,6 +3627,11 @@ void HairInfoNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
}*/
out = output("Index");
if(!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_INDEX);
compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
}
}
void HairInfoNode::compile(OSLCompiler& compiler)

View File

@ -33,6 +33,7 @@ static bNodeSocketTemplate outputs[] = {
{ SOCK_FLOAT, 0, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("Tangent Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
/*{ SOCK_FLOAT, 0, N_("Fade"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},*/
{ SOCK_FLOAT, 0, "Index" },
{ -1, 0, "" }
};