Pass dummy normal to elliptical hairs

This commit is contained in:
Weizhen Huang 2022-12-22 15:05:00 +01:00
parent 5e21a0909c
commit 8125657606
5 changed files with 74 additions and 103 deletions

View File

@ -272,10 +272,13 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
if (hair->num_curves())
return;
Attribute *attr_normal = NULL;
Attribute *attr_intercept = NULL;
Attribute *attr_length = NULL;
Attribute *attr_random = NULL;
if (hair->need_attribute(scene, ATTR_STD_VERTEX_NORMAL))
attr_normal = hair->attributes.add(ATTR_STD_VERTEX_NORMAL);
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT);
if (hair->need_attribute(scene, ATTR_STD_CURVE_LENGTH))
@ -325,6 +328,11 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
num_curve_keys++;
}
if (attr_normal != NULL) {
/* TODO: compute geometry normals. */
attr_normal->add(make_float3(1.0f, 0.0f, 0.0f));
}
if (attr_length != NULL) {
attr_length->add(CData->curve_length[curve]);
}
@ -881,10 +889,14 @@ static void export_hair_curves(Scene *scene,
int *curve_shader = hair->get_curve_shader().data();
/* Add requested attributes. */
float3 *attr_normal = NULL;
float *attr_intercept = NULL;
float *attr_length = NULL;
float *attr_random = NULL;
if (hair->need_attribute(scene, ATTR_STD_VERTEX_NORMAL)) {
attr_normal = hair->attributes.add(ATTR_STD_VERTEX_NORMAL)->data_float3();
}
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT)->data_float();
}
@ -912,6 +924,11 @@ static void export_hair_curves(Scene *scene,
const float3 co = get_float3(b_attr_position.data[point_offset].vector());
const float radius = b_attr_radius ? b_attr_radius->data[point_offset].value() : 0.005f;
if (attr_normal) {
/* TODO: compute geometry normals. */
attr_normal[point_offset] = make_float3(1.0f, 0.0f, 0.0f);
}
curve_keys[point_offset] = co;
curve_radius[point_offset] = radius;

View File

@ -17,13 +17,6 @@ typedef struct MicrofacetHairExtra {
float TRT;
float eccentricity;
float twist_rate;
float attr_descr_intercept;
float attr_descr_length;
float axis_rot;
float diffraction_weight;
float pad1, pad2, pad3;
/* Geometry data. */
float4 geom;
@ -73,15 +66,20 @@ ccl_device int bsdf_microfacet_hair_setup(ccl_private ShaderData *sd,
* the center, to grazing the other edge. This is the sine of the angle
* between sd->Ng and Z, as seen from the tangent X. */
/* TODO: we convert this value to a cosine later and discard the sign, so
* we could probably save some operations. */
float h = (sd->type & PRIMITIVE_CURVE_RIBBON) ? -sd->v : -dot(X, sd->Ng);
kernel_assert(fabsf(h) < 1.0f + 1e-4f);
kernel_assert(isfinite_safe(X));
kernel_assert(isfinite_safe(h));
bsdf->extra->geom = make_float4(X.x, X.y, X.z, h);
if (bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_GGX ||
bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN) {
/* Local frame is independent of the ray direction for elliptical hairs. */
bsdf->extra->geom.w = h;
}
else {
bsdf->extra->geom = make_float4(X.x, X.y, X.z, h);
}
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG | SD_BSDF_HAS_TRANSMISSION;
}
@ -1126,23 +1124,10 @@ ccl_device Spectrum bsdf_microfacet_hair_eval_elliptic(KernelGlobals kg,
{
/* get local wi(convention is reversed from other hair bcsdfs) */
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)sc;
const float3 X0 = float4_to_float3(bsdf->extra->geom);
const float3 Y = safe_normalize(sd->dPdu);
const float3 Z0 = safe_normalize(cross(X0, Y));
/* rotate (Z,X) around Y */
const float curve_parameter = bsdf->extra->attr_descr_intercept;
const float curve_length = bsdf->extra->attr_descr_length;
const float curve_twist_rate = bsdf->extra->twist_rate;
const float curve_twist_start = bsdf->extra->axis_rot;
const float twist_angle = M_2PI_F * (curve_twist_start +
curve_twist_rate * curve_parameter * curve_length);
const float sin_twist_angle = sinf(twist_angle);
const float cos_twist_angle = cosf(twist_angle);
const float3 Z = cos_twist_angle * Z0 + sin_twist_angle * X0;
const float3 X = -sin_twist_angle * Z0 + cos_twist_angle * X0;
const float3 X = float4_to_float3(bsdf->extra->geom);
float3 Y = sd->dPdu;
const float3 Z = safe_normalize(cross(X, Y));
Y = safe_normalize(cross(Z, X));
const float3 wi = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
const float3 wo = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
@ -1179,20 +1164,10 @@ ccl_device int bsdf_microfacet_hair_sample_elliptic(const KernelGlobals kg,
}
/* get local wi (convention is reversed from other hair bcsdfs) */
const float3 X0 = float4_to_float3(bsdf->extra->geom);
const float3 Y = safe_normalize(sd->dPdu);
const float3 Z0 = safe_normalize(cross(X0, Y));
/* const float curve_parameter = bsdf->extra->attr_descr_intercept; */
/* const float curve_length = bsdf->extra->attr_descr_length; */
/* TODO: compute the ellipse orientation based on the curve normal or user-defined normal? */
const float twist_angle = 0.0f;
const float sin_twist_angle = sinf(twist_angle);
const float cos_twist_angle = cosf(twist_angle);
const float3 Z = cos_twist_angle * Z0 + sin_twist_angle * X0;
const float3 X = -sin_twist_angle * Z0 + cos_twist_angle * X0;
const float3 X = float4_to_float3(bsdf->extra->geom);
float3 Y = sd->dPdu;
const float3 Z = safe_normalize(cross(X, Y));
Y = safe_normalize(cross(Z, X));
const float3 wi = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));

View File

@ -884,8 +884,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
uint4 data_node3 = read_node(kg, &offset);
uint4 data_node4 = read_node(kg, &offset);
uint4 data_node5 = read_node(kg, &offset);
uint4 data_node6 = read_node(kg, &offset);
uint4 data_node7 = read_node(kg, &offset);
Spectrum weight = sd->svm_closure_weight * mix_weight;
@ -894,9 +892,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
float alpha = stack_load_float_default(stack, offset_ofs, data_node.z);
float ior = stack_load_float_default(stack, ior_ofs, data_node.w);
uint coat_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs;
uint Blur_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs;
svm_unpack_node_uchar4(data_node2.x,
&coat_ofs,
&Blur_ofs,
&melanin_ofs,
&melanin_redness_ofs,
&absorption_coefficient_ofs);
@ -905,7 +903,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
svm_unpack_node_uchar4(
data_node3.x, &tint_ofs, &random_ofs, &random_color_ofs, &random_roughness_ofs);
const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, data_node4.y);
const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, data_node3.w);
float random = 0.0f;
if (attr_descr_random.offset != ATTR_STD_NOT_FOUND) {
random = primitive_surface_attribute_float(kg, sd, attr_descr_random, NULL, NULL);
@ -914,16 +912,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
random = stack_load_float_default(stack, random_ofs, data_node3.y);
}
uint R_ofs, TT_ofs, TRT_ofs, temp;
uint Blur_ofs, model_type;
uint R_ofs, TT_ofs, TRT_ofs, model_type;
svm_unpack_node_uchar4(data_node5.x, &R_ofs, &TT_ofs, &TRT_ofs, &temp);
float R = stack_load_float_default(stack, R_ofs, data_node5.y);
float TT = stack_load_float_default(stack, TT_ofs, data_node5.z);
float TRT = stack_load_float_default(stack, TRT_ofs, data_node5.w);
svm_unpack_node_uchar4(data_node6.x, &temp, &Blur_ofs, &temp, &model_type);
float blur = stack_load_float_default(stack, Blur_ofs, data_node6.z);
svm_unpack_node_uchar4(data_node4.x, &R_ofs, &TT_ofs, &TRT_ofs, &model_type);
float R = stack_load_float_default(stack, R_ofs, data_node4.y);
float TT = stack_load_float_default(stack, TT_ofs, data_node4.z);
float TRT = stack_load_float_default(stack, TRT_ofs, data_node4.w);
float blur = stack_load_float_default(stack, Blur_ofs, data_node2.y);
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)bsdf_alloc(
sd, sizeof(MicrofacetHairBSDF), weight);
@ -941,8 +936,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
bsdf->blur = clamp(blur, 0.0f, 1.0f);
/* Random factors range: [-randomization/2, +randomization/2]. */
float random_roughness = stack_load_float_default(
stack, random_roughness_ofs, data_node3.w);
float random_roughness = param2;
float factor_random_roughness = 1.0f + 2.0f * (random - 0.5f) * random_roughness;
float roughness = param1 * factor_random_roughness;
@ -1023,21 +1017,18 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
if (model_type == NODE_MICROFACET_HAIR_ELLIPTIC_GGX ||
model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN) {
uint eccentricity_ofs;
svm_unpack_node_uchar4(data_node7.x, &eccentricity_ofs, &temp, &temp, &temp);
uint eccentricity_ofs, temp;
svm_unpack_node_uchar4(data_node5.x, &eccentricity_ofs, &temp, &temp, &temp);
float eccentricity = stack_load_float_default(stack, eccentricity_ofs, data_node7.y);
float eccentricity = stack_load_float_default(stack, eccentricity_ofs, data_node5.y);
/* Eccentricity */
bsdf->extra->eccentricity = (eccentricity > 1.f) ? 1.f / eccentricity : eccentricity;
const AttributeDescriptor attr_descr_intercept = find_attribute(kg, sd, data_node4.z);
bsdf->extra->attr_descr_intercept = curve_attribute_float(
kg, sd, attr_descr_intercept, NULL, NULL);
const AttributeDescriptor attr_descr_length = find_attribute(kg, sd, data_node4.w);
bsdf->extra->attr_descr_length = curve_attribute_float(
kg, sd, attr_descr_length, NULL, NULL);
const AttributeDescriptor attr_descr_normal = find_attribute(kg, sd, data_node5.z);
const float3 normal = curve_attribute_float3(kg, sd, attr_descr_normal, NULL, NULL);
const float3 binormal = safe_normalize(cross(sd->dPdu, normal));
bsdf->extra->geom = make_float4(binormal.x, binormal.y, binormal.z, 0.0f);
}
sd->flag |= bsdf_microfacet_hair_setup(sd, bsdf);

View File

@ -611,6 +611,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
}
else if (geometry->geometry_type == Geometry::HAIR) {
switch (std) {
case ATTR_STD_VERTEX_NORMAL:
attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_CURVE_KEY);
break;
case ATTR_STD_UV:
attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
break;

View File

@ -3697,9 +3697,8 @@ MicrofacetHairBsdfNode::MicrofacetHairBsdfNode() : BsdfBaseNode(get_node_type())
/* Enable retrieving Hair Info -> Random if Random isn't linked. */
void MicrofacetHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
/* Make sure we have these 2 for elliptical cross section tracking */
attributes->add(ATTR_STD_CURVE_INTERCEPT);
attributes->add(ATTR_STD_CURVE_LENGTH);
/* Make sure we have the normal for elliptical cross section tracking */
attributes->add(ATTR_STD_VERTEX_NORMAL);
if (!input("Random")->link) {
attributes->add(ATTR_STD_CURVE_RANDOM);
@ -3753,63 +3752,49 @@ void MicrofacetHairBsdfNode::compile(SVMCompiler &compiler)
compiler.add_node(
NODE_CLOSURE_BSDF,
/* Socket IDs can be packed 4 at a time into a single data packet */
compiler.encode_uchar4(closure, roughness_ofs, 0, compiler.closure_mix_weight_offset()),
compiler.encode_uchar4(
closure, roughness_ofs, random_roughness_ofs, compiler.closure_mix_weight_offset()),
/* The rest are stored as unsigned integers */
__float_as_uint(roughness),
0);
__float_as_uint(random_roughness));
/* data node */
compiler.add_node(normal_ofs,
compiler.encode_uchar4(offset_ofs, ior_ofs, color_ofs, parametrization),
__float_as_uint(offset),
__float_as_uint(ior));
/* data node 2 */
compiler.add_node(
compiler.encode_uchar4(0, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs),
0,
__float_as_uint(melanin),
__float_as_uint(melanin_redness));
compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(Blur_in),
melanin_ofs,
melanin_redness_ofs,
absorption_coefficient_ofs),
__float_as_uint(Blur),
__float_as_uint(melanin),
__float_as_uint(melanin_redness));
/* data node 3 */
compiler.add_node(
compiler.encode_uchar4(tint_ofs, random_in_ofs, random_color_ofs, random_roughness_ofs),
__float_as_uint(random),
__float_as_uint(random_color),
__float_as_uint(random_roughness));
int attr_intercept = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
int attr_length = compiler.attribute(ATTR_STD_CURVE_LENGTH);
compiler.add_node(compiler.encode_uchar4(tint_ofs, random_in_ofs, random_color_ofs, 0),
__float_as_uint(random),
__float_as_uint(random_color),
attr_random);
/* data node 4 */
compiler.add_node(
compiler.encode_uchar4(
SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID),
attr_random,
attr_intercept,
attr_length);
/* data node 5 */
compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(R_in),
compiler.stack_assign_if_linked(TT_in),
compiler.stack_assign_if_linked(TRT_in),
SVM_STACK_INVALID),
model_type),
__float_as_uint(R),
__float_as_uint(TT),
__float_as_uint(TRT));
/* data node 6 */
compiler.add_node(
compiler.encode_uchar4(0, compiler.stack_assign_if_linked(Blur_in), 0, model_type),
0,
__float_as_uint(Blur),
0);
/* data node 7 */
/* data node 5 */
compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(eccentricity_in),
SVM_STACK_INVALID,
SVM_STACK_INVALID,
SVM_STACK_INVALID),
__float_as_uint(eccentricity),
0,
compiler.attribute(ATTR_STD_VERTEX_NORMAL),
0);
}