浏览代码

Implement GetEllipsoidalDistanceAttenuation() for line and area lights

/main
Evgenii Golubev 8 年前
当前提交
bfabcc16
共有 2 个文件被更改,包括 61 次插入43 次删除
  1. 87
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  2. 17
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl

87
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl


float len = lightData.size.x;
float3 T = lightData.right;
float3 unL = positionWS - lightData.positionWS;
// Pick the axis along which to expand the fade-out sphere into an ellipsoid.
float3 axis = lightData.right;
// We define the ellipsoid s.t. r1 = r, r2 = (r + len / 2).
float3 P1 = lightData.positionWS - T * (0.5 * len);
float3 P2 = lightData.positionWS + T * (0.5 * len);
float radius = rsqrt(lightData.invSqrAttenuationRadius);
float invAspectRatio = radius / (radius + (0.5 * len));
// Compute the light attenuation.
float intensity = GetEllipsoidalDistanceAttenuation(unL, lightData.invSqrAttenuationRadius,
axis, invAspectRatio);
// Terminate if the shaded point is too far away.
if (intensity == 0.0) return;
lightData.diffuseScale *= intensity;
lightData.specularScale *= intensity;
// TODO: This could be precomputed.
float3 P1 = lightData.positionWS - T * (0.5 * len);
float3 P2 = lightData.positionWS + T * (0.5 * len);
// Translate the endpoints s.t. the shaded point is at the origin of the coordinate system.
P1 -= positionWS;

diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
// TODO: This could be precomputed
// TODO: This could be precomputed.
// TODO: store 4 points and save 12 cycles (24x MADs - 12x MOVs).
float3 p0 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
float3 p1 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;
float3 p2 = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;
float3 p3 = lightData.positionWS + lightData.right * halfWidth + lightData.up * halfHeight;
float3 unL = positionWS - lightData.positionWS;
float4x3 matL = float4x3(p0, p1, p2, p3);
float4x3 L = matL - float4x3(positionWS, positionWS, positionWS, positionWS);
// Pick the axis along which to expand the fade-out sphere into an ellipsoid.
float3 axis = (halfWidth >= halfHeight) ? lightData.right : lightData.up;
// Pick the correct axis along which to expand the fade-out sphere into an ellipsoid.
float3 axisLS;
float minDim, maxDim;
// The compiler should generate conditional MOVs.
if (halfWidth >= halfHeight)
{
axisLS = lightData.right;
minDim = halfHeight;
maxDim = halfWidth;
}
else
{
axisLS = lightData.up;
minDim = halfWidth;
maxDim = halfHeight;
}
float3 dirLS = positionWS - lightData.positionWS;
float lightSpaceProj = dot(dirLS, axisLS);
float invAspectRatio = minDim / maxDim;
// We want 'dirLS' to shrink along 'axisLS' by the aspect ratio. Therefore,
// we compute the difference between the original length and the shrunk one.
// This is equivalent to the expansion of the fade-out sphere into an ellipsoid.
float scaleLS = lightSpaceProj - lightSpaceProj * invAspectRatio;
dirLS -= scaleLS * axisLS;
// We define the ellipsoid s.t. r1 = r, r2 = (r + |w - h| / 2).
// TODO: This could be precomputed.
float radius = rsqrt(lightData.invSqrAttenuationRadius);
float invAspectRatio = radius / (radius + abs(halfWidth - halfHeight));
float sqDist = dot(dirLS, dirLS);
float intensity = SmoothDistanceAttenuation(sqDist, lightData.invSqrAttenuationRadius);
float intensity = GetEllipsoidalDistanceAttenuation(unL, lightData.invSqrAttenuationRadius,
axis, invAspectRatio);
// Return the black color if the shaded point is too far away.
// Terminate if the shaded point is too far away.
// TODO: store 4 points and save 12 cycles (24x MADs - 12x MOVs).
float3 p0 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
float3 p1 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;
float3 p2 = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;
float3 p3 = lightData.positionWS + lightData.right * halfWidth + lightData.up * halfHeight;
float4x3 matL = float4x3(p0, p1, p2, p3) - float4x3(positionWS, positionWS, positionWS, positionWS);
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
ltcValue = LTCEvaluate(matL, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
ltcValue = LTCEvaluate(matL, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
preLightData.ltcXformDisneyDiffuse);
#endif

float3 fresnelTerm = bsdfData.fresnel0 * preLightData.ltcGGXFresnelMagnitudeDiff
+ (float3)preLightData.ltcGGXFresnelMagnitude;
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
ltcValue = LTCEvaluate(matL, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
preLightData.ltcXformGGX);
ltcValue *= lightData.specularScale;
specularLighting = fresnelTerm * lightData.color * ltcValue;

17
Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl


return attenuation;
}
// Applies SmoothDistanceAttenuation() after stretching the fade-out sphere of the given radius
// into an ellipsoid with the specified aspect ratio and the longest axis.
float GetEllipsoidalDistanceAttenuation(float3 unL, float invSqrAttenuationRadius,
float3 axis, float invAspectRatio)
{
// Project the unnormalized light vector onto the expansion axis.
float projL = dot(unL, axis);
// We want 'unL' to shrink along 'axis' by the aspect ratio. Therefore, we compute
// the difference between the length of the original projection and the shrunk one.
// It is equivalent to the expansion of the fade-out sphere into an ellipsoid.
float scale = projL - projL * invAspectRatio;
unL -= scale * axis;
return SmoothDistanceAttenuation(dot(unL, unL), invSqrAttenuationRadius);
}
//-----------------------------------------------------------------------------
// IES Helper
//-----------------------------------------------------------------------------

正在加载...
取消
保存