Cycles: adjust normal in Principled Hair Huang to be orthogonal to the tangent
The geometry normal of the curve might not be precisely orthogonal to the tangent due to interpolation. Previously, the tangent was adjusted to be orthogonal to the normal. However, the normal is linearly interpolated, which is less accurate than the tangent computed using Catmull-Rom. This commit keeps the tangent and adjust the normal instead, besides better accuracy, it ensures a smooth transition when the cross-section shifts between circular and elliptical.
This commit is contained in:
parent
17842d4d40
commit
c592fa14f1
|
@ -188,8 +188,8 @@ ccl_device int bsdf_hair_huang_setup(ccl_private ShaderData *sd,
|
||||||
/* Compute local frame. The Y axis is aligned with the curve tangent; the X axis is perpendicular
|
/* Compute local frame. The Y axis is aligned with the curve tangent; the X axis is perpendicular
|
||||||
to the ray direction for circular cross-sections, or aligned with the major axis for elliptical
|
to the ray direction for circular cross-sections, or aligned with the major axis for elliptical
|
||||||
cross-sections. */
|
cross-sections. */
|
||||||
const float3 Y = safe_normalize(sd->dPdu);
|
bsdf->extra->Y = safe_normalize(sd->dPdu);
|
||||||
const float3 X = safe_normalize(cross(Y, sd->wi));
|
const float3 X = safe_normalize(cross(sd->dPdu, sd->wi));
|
||||||
|
|
||||||
/* h from -1..0..1 means the rays goes from grazing the hair, to hitting it at the center, to
|
/* h from -1..0..1 means the rays goes from grazing the hair, to hitting it at the center, to
|
||||||
* grazing the other edge. This is the cosine of the angle between `sd->N` and `X`. */
|
* grazing the other edge. This is the cosine of the angle between `sd->N` and `X`. */
|
||||||
|
@ -199,6 +199,8 @@ ccl_device int bsdf_hair_huang_setup(ccl_private ShaderData *sd,
|
||||||
kernel_assert(isfinite_safe(bsdf->h));
|
kernel_assert(isfinite_safe(bsdf->h));
|
||||||
|
|
||||||
if (bsdf->aspect_ratio != 1.0f && (sd->type & PRIMITIVE_CURVE)) {
|
if (bsdf->aspect_ratio != 1.0f && (sd->type & PRIMITIVE_CURVE)) {
|
||||||
|
/* Adjust `bsdf->N` to be orthogonal to `sd->dPdu`. */
|
||||||
|
bsdf->N = safe_normalize(cross(sd->dPdu, safe_normalize(cross(bsdf->N, sd->dPdu))));
|
||||||
/* Align local frame with the curve normal. */
|
/* Align local frame with the curve normal. */
|
||||||
if (bsdf->aspect_ratio > 1.0f) {
|
if (bsdf->aspect_ratio > 1.0f) {
|
||||||
/* Switch major and minor axis. */
|
/* Switch major and minor axis. */
|
||||||
|
@ -214,14 +216,12 @@ ccl_device int bsdf_hair_huang_setup(ccl_private ShaderData *sd,
|
||||||
|
|
||||||
/* Fill extra closure. */
|
/* Fill extra closure. */
|
||||||
if (is_zero(bsdf->N) || !isfinite_safe(bsdf->N)) {
|
if (is_zero(bsdf->N) || !isfinite_safe(bsdf->N)) {
|
||||||
bsdf->extra->Y = Y;
|
|
||||||
/* Construct arbitrary local coordinate system. The implementation should ensure smooth
|
/* Construct arbitrary local coordinate system. The implementation should ensure smooth
|
||||||
* transition along the hair shaft. */
|
* transition along the hair shaft. */
|
||||||
make_orthonormals(Y, &bsdf->extra->Z, &bsdf->N);
|
make_orthonormals(bsdf->extra->Y, &bsdf->extra->Z, &bsdf->N);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bsdf->extra->Z = safe_normalize(cross(bsdf->N, sd->dPdu));
|
bsdf->extra->Z = safe_normalize(cross(bsdf->N, sd->dPdu));
|
||||||
bsdf->extra->Y = safe_normalize(cross(bsdf->extra->Z, bsdf->N));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const float3 I = make_float3(
|
const float3 I = make_float3(
|
||||||
|
|
Loading…
Reference in New Issue