|
|
|
|
|
|
// Clamp to avoid artifacts. This particular constant gives the best results. |
|
|
|
cosTheta = Clamp(cosTheta, -0.9999, 0.9999); |
|
|
|
float theta = FastACos(cosTheta); |
|
|
|
float res = cross(v1, v2).z * theta / sin(theta); |
|
|
|
float res = cross(v1, v2).z * theta * rsqrt(1.0f - cosTheta * cosTheta); // optimization from * 1 / sin(theta) |
|
|
|
|
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
float LineFpo(float tLDDL, float lrcpD, float rcpD) |
|
|
|
{ |
|
|
|
// Compute: ((l / d) / (d * d + l * l)) + (1.0 / (d * d)) * atan(l / d). |
|
|
|
return tLDDL + Square(rcpD) * atan(lrcpD); |
|
|
|
return tLDDL + (rcpD * rcpD) * FastATan(lrcpD); |
|
|
|
} |
|
|
|
|
|
|
|
float LineFwt(float tLDDL, float l) |
|
|
|
|
|
|
float d = length(normal); |
|
|
|
float l1rcpD = l1 * rcp(d); |
|
|
|
float l2rcpD = l2 * rcp(d); |
|
|
|
float tLDDL1 = l1rcpD * rcp(Square(d) + Square(l1)); |
|
|
|
float tLDDL2 = l2rcpD * rcp(Square(d) + Square(l2)); |
|
|
|
float tLDDL1 = l1rcpD / (d * d + l1 * l1); |
|
|
|
float tLDDL2 = l2rcpD / (d * d + l2 * l2); |
|
|
|
return intP0 * normal.z + intWt * tangent.z; |
|
|
|
// Guard against numerical precision issues. |
|
|
|
return max(intP0 * normal.z + intWt * tangent.z, 0.0); |
|
|
|
} |
|
|
|
|
|
|
|
// Computes 1.0 / length(mul(ortho, transpose(inverse(invM)))). |
|
|
|
float ComputeLineWidthFactor(float3x3 invM, float3 ortho) |
|
|
|
{ |
|
|
|
// transpose(inverse(M)) = (1.0 / determinant(M)) * cofactor(M). |
|
|
|
// Take into account that m12 = m21 = m23 = m32 = 0 and m33 = 1. |
|
|
|
float det = invM._11 * invM._22 - invM._22 * invM._31 * invM._13; |
|
|
|
float3x3 cof = {invM._22, 0.0, -invM._22 * invM._31, |
|
|
|
0.0, invM._11 - invM._13 * invM._31, 0.0, |
|
|
|
-invM._13 * invM._22, 0.0, invM._11 * invM._22}; |
|
|
|
|
|
|
|
// 1.0 / length(mul(V, (1.0 / s * M))) = abs(s) / length(mul(V, M)). |
|
|
|
return abs(det) / length(mul(ortho, cof)); |
|
|
|
// Inverse-transform the endpoints and the binormal. |
|
|
|
// Inverse-transform the endpoints. |
|
|
|
B = mul(B, invM); |
|
|
|
|
|
|
|
float width = ComputeLineWidthFactor(invM, B); |
|
|
|
|
|
|
|
if (P2.z <= 0.0) |
|
|
|
{ |
|
|
|
|
|
|
// Integrate the clamped cosine over the line segment. |
|
|
|
float irradiance = LineIrradiance(l1, l2, P0, T); |
|
|
|
|
|
|
|
// Compute the width factor. We take the absolute value because the points may be swapped. |
|
|
|
float width = abs(dot(B, normalize(cross(T, P1)))); |
|
|
|
|
|
|
|
// Guard against numerical precision issues. |
|
|
|
return max(INV_PI * width * irradiance, 0.0); |
|
|
|
return INV_PI * width * irradiance; |
|
|
|
} |
|
|
|
|
|
|
|
#endif // UNITY_AREA_LIGHTING_INCLUDED |