@@ -185,7 +185,7 @@ float LTCEvaluate(float4x3 L, float3 V, float3 N, float NdotV, bool twoSided, fl
185
185
float LineFpo (float tLDDL, float lrcpD, float rcpD)
186
186
{
187
187
// Compute: ((l / d) / (d * d + l * l)) + (1.0 / (d * d)) * atan(l / d).
188
- return tLDDL + Square (rcpD) * atan (lrcpD);
188
+ return tLDDL + (rcpD * rcpD ) * FastATan (lrcpD);
189
189
}
190
190
191
191
float LineFwt (float tLDDL, float l)
@@ -204,24 +204,40 @@ float LineIrradiance(float l1, float l2, float3 normal, float3 tangent)
204
204
float d = length (normal);
205
205
float l1rcpD = l1 * rcp (d);
206
206
float l2rcpD = l2 * rcp (d);
207
- float tLDDL1 = l1rcpD * rcp ( Square (d) + Square (l1) );
208
- float tLDDL2 = l2rcpD * rcp ( Square (d) + Square (l2) );
207
+ float tLDDL1 = l1rcpD / (d * d + l1 * l1 );
208
+ float tLDDL2 = l2rcpD / (d * d + l2 * l2 );
209
209
float intWt = LineFwt (tLDDL2, l2) - LineFwt (tLDDL1, l1);
210
210
float intP0 = LineFpo (tLDDL2, l2rcpD, rcp (d)) - LineFpo (tLDDL1, l1rcpD, rcp (d));
211
- return intP0 * normal.z + intWt * tangent.z;
211
+ // Guard against numerical precision issues.
212
+ return max (intP0 * normal.z + intWt * tangent.z, 0.0 );
213
+ }
214
+
215
+ // Computes 1.0 / length(mul(ortho, transpose(inverse(invM)))).
216
+ float ComputeLineWidthFactor (float3x3 invM, float3 ortho)
217
+ {
218
+ // transpose(inverse(M)) = (1.0 / determinant(M)) * cofactor(M).
219
+ // Take into account that m12 = m21 = m23 = m32 = 0 and m33 = 1.
220
+ float det = invM._11 * invM._22 - invM._22 * invM._31 * invM._13;
221
+ float3x3 cof = {invM._22, 0.0 , -invM._22 * invM._31,
222
+ 0.0 , invM._11 - invM._13 * invM._31, 0.0 ,
223
+ -invM._13 * invM._22, 0.0 , invM._11 * invM._22};
224
+
225
+ // 1.0 / length(mul(V, (1.0 / s * M))) = abs(s) / length(mul(V, M)).
226
+ return abs (det) / length (mul (ortho, cof));
212
227
}
213
228
214
229
// For line lights.
215
230
float LTCEvaluate (float3 P1, float3 P2, float3 B, float3x3 invM)
216
231
{
217
- // Inverse-transform the endpoints and the binormal .
232
+ // Inverse-transform the endpoints.
218
233
P1 = mul (P1, invM);
219
234
P2 = mul (P2, invM);
220
- B = mul (B, invM);
221
235
222
236
// Terminate the algorithm if both points are below the horizon.
223
237
if (P1.z <= 0.0 && P2.z <= 0.0 ) return 0.0 ;
224
238
239
+ float width = ComputeLineWidthFactor (invM, B);
240
+
225
241
if (P2.z <= 0.0 )
226
242
{
227
243
// Convention: 'P2' is above the horizon.
@@ -256,11 +272,7 @@ float LTCEvaluate(float3 P1, float3 P2, float3 B, float3x3 invM)
256
272
// Integrate the clamped cosine over the line segment.
257
273
float irradiance = LineIrradiance (l1, l2, P0, T);
258
274
259
- // Compute the width factor. We take the absolute value because the points may be swapped.
260
- float width = abs (dot (B, normalize (cross (T, P1))));
261
-
262
- // Guard against numerical precision issues.
263
- return max (INV_PI * width * irradiance, 0.0 );
275
+ return INV_PI * width * irradiance;
264
276
}
265
277
266
278
#endif // UNITY_AREA_LIGHTING_INCLUDED
0 commit comments