@@ -797,9 +797,29 @@ void EvaluateBSDF_Line(LightLoopContext lightLoopContext,
797797 float len = lightData.size.x;
798798 float3 T = lightData.right;
799799
800+ float3 unL = positionWS - lightData.positionWS;
801+
802+ // Pick the axis along which to expand the fade-out sphere into an ellipsoid.
803+ float3 axis = lightData.right;
804+
805+ // We define the ellipsoid s.t. r1 = r, r2 = (r + len / 2).
800806 // TODO: This could be precomputed.
801- float3 P1 = lightData.positionWS - T * (0.5 * len);
802- float3 P2 = lightData.positionWS + T * (0.5 * len);
807+ float radius = rsqrt (lightData.invSqrAttenuationRadius);
808+ float invAspectRatio = radius / (radius + (0.5 * len));
809+
810+ // Compute the light attenuation.
811+ float intensity = GetEllipsoidalDistanceAttenuation (unL, lightData.invSqrAttenuationRadius,
812+ axis, invAspectRatio);
813+
814+ // Terminate if the shaded point is too far away.
815+ if (intensity == 0.0 ) return ;
816+
817+ lightData.diffuseScale *= intensity;
818+ lightData.specularScale *= intensity;
819+
820+ // TODO: This could be precomputed.
821+ float3 P1 = lightData.positionWS - T * (0.5 * len);
822+ float3 P2 = lightData.positionWS + T * (0.5 * len);
803823
804824 // Translate the endpoints s.t. the shaded point is at the origin of the coordinate system.
805825 P1 -= positionWS;
@@ -952,66 +972,47 @@ void EvaluateBSDF_Area(LightLoopContext lightLoopContext,
952972 diffuseLighting = float3 (0.0 , 0.0 , 0.0 );
953973 specularLighting = float3 (0.0 , 0.0 , 0.0 );
954974
955- // TODO: This could be precomputed
975+ // TODO: This could be precomputed.
956976 float halfWidth = lightData.size.x * 0.5 ;
957977 float halfHeight = lightData.size.y * 0.5 ;
958978
959- // TODO: store 4 points and save 12 cycles (24x MADs - 12x MOVs).
960- float3 p0 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
961- float3 p1 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;
962- float3 p2 = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;
963- float3 p3 = lightData.positionWS + lightData.right * halfWidth + lightData.up * halfHeight;
979+ float3 unL = positionWS - lightData.positionWS;
964980
965- float4x3 matL = float4x3 (p0, p1, p2, p3);
966- float4x3 L = matL - float4x3 (positionWS, positionWS, positionWS, positionWS) ;
981+ // Pick the axis along which to expand the fade-out sphere into an ellipsoid.
982+ float3 axis = (halfWidth >= halfHeight) ? lightData.right : lightData.up ;
967983
968- // Pick the correct axis along which to expand the fade-out sphere into an ellipsoid.
969- float3 axisLS;
970- float minDim, maxDim;
971-
972- // The compiler should generate conditional MOVs.
973- if (halfWidth >= halfHeight)
974- {
975- axisLS = lightData.right;
976- minDim = halfHeight;
977- maxDim = halfWidth;
978- }
979- else
980- {
981- axisLS = lightData.up;
982- minDim = halfWidth;
983- maxDim = halfHeight;
984- }
985-
986- float3 dirLS = positionWS - lightData.positionWS;
987- float lightSpaceProj = dot (dirLS, axisLS);
988- float invAspectRatio = minDim / maxDim;
989-
990- // We want 'dirLS' to shrink along 'axisLS' by the aspect ratio. Therefore,
991- // we compute the difference between the original length and the shrunk one.
992- // This is equivalent to the expansion of the fade-out sphere into an ellipsoid.
993- float scaleLS = lightSpaceProj - lightSpaceProj * invAspectRatio;
994- dirLS -= scaleLS * axisLS;
984+ // We define the ellipsoid s.t. r1 = r, r2 = (r + |w - h| / 2).
985+ // TODO: This could be precomputed.
986+ float radius = rsqrt (lightData.invSqrAttenuationRadius);
987+ float invAspectRatio = radius / (radius + abs (halfWidth - halfHeight));
995988
996989 // Compute the light attenuation.
997- float sqDist = dot (dirLS, dirLS);
998- float intensity = SmoothDistanceAttenuation (sqDist, lightData.invSqrAttenuationRadius );
990+ float intensity = GetEllipsoidalDistanceAttenuation (unL, lightData.invSqrAttenuationRadius,
991+ axis, invAspectRatio );
999992
1000- // Return the black color if the shaded point is too far away.
993+ // Terminate if the shaded point is too far away.
1001994 if (intensity == 0.0 ) return ;
1002995
1003996 lightData.diffuseScale *= intensity;
1004997 lightData.specularScale *= intensity;
1005998
999+ // TODO: store 4 points and save 12 cycles (24x MADs - 12x MOVs).
1000+ float3 p0 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
1001+ float3 p1 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;
1002+ float3 p2 = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;
1003+ float3 p3 = lightData.positionWS + lightData.right * halfWidth + lightData.up * halfHeight;
1004+
1005+ float4x3 matL = float4x3 (p0, p1, p2, p3) - float4x3 (positionWS, positionWS, positionWS, positionWS);
1006+
10061007 float ltcValue;
10071008
10081009 // Evaluate the diffuse part.
10091010 {
10101011 #ifdef LIT_DIFFUSE_LAMBERT_BRDF
1011- ltcValue = LTCEvaluate (L , V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
1012+ ltcValue = LTCEvaluate (matL , V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
10121013 _identity3x3);
10131014 #else
1014- ltcValue = LTCEvaluate (L , V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
1015+ ltcValue = LTCEvaluate (matL , V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
10151016 preLightData.ltcXformDisneyDiffuse);
10161017 #endif
10171018
@@ -1036,7 +1037,7 @@ void EvaluateBSDF_Area(LightLoopContext lightLoopContext,
10361037 float3 fresnelTerm = bsdfData.fresnel0 * preLightData.ltcGGXFresnelMagnitudeDiff
10371038 + (float3 )preLightData.ltcGGXFresnelMagnitude;
10381039
1039- ltcValue = LTCEvaluate (L , V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
1040+ ltcValue = LTCEvaluate (matL , V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
10401041 preLightData.ltcXformGGX);
10411042 ltcValue *= lightData.specularScale;
10421043 specularLighting = fresnelTerm * lightData.color * ltcValue;
0 commit comments