|
|
|
|
|
|
float tLDDL2 = l2rcpD / (d * d + l2 * l2); |
|
|
|
float intWt = LineFwt(tLDDL2, l2) - LineFwt(tLDDL1, l1); |
|
|
|
float intP0 = LineFpo(tLDDL2, l2rcpD, rcp(d)) - LineFpo(tLDDL1, l1rcpD, rcp(d)); |
|
|
|
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. |
|
|
|
// TODO: consider using an inverse-transpose of 'invM' - potentially faster. |
|
|
|
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 |