Skip to content

Commit

Permalink
[Port] [2021.3] Add clamp to HairAngleWorld to prevent nan from FastASin
Browse files Browse the repository at this point in the history
Jira: [UUM-72279](https://jira.unity3d.com/browse/UUM-72279)

As reported in JIRA, the Scene view flickers due to `NaN` output from the hair shader. It is because in `GetHairAngleWorld`, `angles.sinThetaI` can exceed the range [-1, 1] depending on the input hair `normalWS`. (The `L` vector may not be a unit vector in some cases.)
* `half3x3 localToWorld = GetLocalFrame(bsdfData.normalWS, bsdfData.hairStrandDirectionWS);`
* `half3 L = mul(localL, localToWorld);`

I was able to see that this `NaN` problem could happen if both `T` and `L` vectors are a unit vector due to precision. `angles.sinThetaI` can slightly exceed 1.0 so the `FastASin` result will be `NaN` in this case.

![image](https://media.github.cds.internal.unity3d.com/user/3842/files/f49cd338-9620-4d69-84e3-c9248bfb8a87)

By explicitly clamping the angles, we can prevent `NaN` output from `FastASin` calculation.
  • Loading branch information
svc-reach-platform-support authored and Evergreen committed Dec 10, 2024
1 parent 4e6334d commit 4f918c9
Showing 1 changed file with 3 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -601,8 +601,9 @@ void GetHairAngleLocal(float3 wo, float3 wi, inout HairAngle angles)

void GetHairAngleWorld(float3 V, float3 L, float3 T, inout HairAngle angles)
{
angles.sinThetaO = dot(T, V);
angles.sinThetaI = dot(T, L);
// It might exceed the range [-1, 1], so explicitly clamp here to prevent nan output from FastASin.
angles.sinThetaO = clamp(dot(T, V), -1.0, 1.0);
angles.sinThetaI = clamp(dot(T, L), -1.0, 1.0);

float thetaO = FastASin(angles.sinThetaO);
float thetaI = FastASin(angles.sinThetaI);
Expand Down

0 comments on commit 4f918c9

Please sign in to comment.