|
|
|
|
|
|
// Box projector lights require no perspective division. |
|
|
|
float perspectiveZ = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? positionLS.z : 1.0; |
|
|
|
float2 positionCS = positionLS.xy / perspectiveZ; |
|
|
|
|
|
|
|
bool isInBounds; |
|
|
|
|
|
|
|
if (lightData.lightType == GPULIGHTTYPE_SPOT) |
|
|
|
{ |
|
|
|
isInBounds = max(abs(positionCS.x), abs(positionCS.y)) <= 1.0; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
isInBounds = Max3(abs(positionCS.x), abs(positionCS.y), 1.0 - positionLS.z) <= 1.0; |
|
|
|
} |
|
|
|
bool isInBounds = Max3(abs(positionCS.x), abs(positionCS.y), 1.0 - positionLS.z) <= 1.0; |
|
|
|
|
|
|
|
// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2. |
|
|
|
float2 positionNDC = positionCS * 0.5 + 0.5; |
|
|
|
|
|
|
|
|
|
|
float GetPunctualShapeAttenuation(LightData lightData, float3 L, float distSq) |
|
|
|
{ |
|
|
|
float attenuation = 1.0; |
|
|
|
|
|
|
|
if (lightData.lightType != GPULIGHTTYPE_PROJECTOR_BOX) |
|
|
|
{ |
|
|
|
// Note: lightData.invSqrAttenuationRadius is 0 when applyRangeAttenuation is false |
|
|
|
attenuation *= GetDistanceAttenuation(distSq, lightData.invSqrAttenuationRadius); |
|
|
|
} |
|
|
|
|
|
|
|
if (lightData.lightType == GPULIGHTTYPE_SPOT) |
|
|
|
{ |
|
|
|
// Reminder: lights are oriented backward (-Z) |
|
|
|
attenuation *= GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset); |
|
|
|
} |
|
|
|
|
|
|
|
return attenuation; |
|
|
|
// Note: lightData.invSqrAttenuationRadius is 0 when applyRangeAttenuation is false |
|
|
|
float attenuation = GetDistanceAttenuation(distSq, lightData.invSqrAttenuationRadius); |
|
|
|
// Reminder: lights are oriented backward (-Z) |
|
|
|
return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset); |
|
|
|
} |
|
|
|
|
|
|
|
// None of the outputs are premultiplied. |
|
|
|
|
|
|
float3 lightToSample = positionWS - lightData.positionWS; |
|
|
|
int lightType = lightData.lightType; |
|
|
|
|
|
|
|
float3 L; float distSq; |
|
|
|
|
|
|
|
if (lightType == GPULIGHTTYPE_PROJECTOR_BOX) |
|
|
|
{ |
|
|
|
distSq = 1.0; |
|
|
|
L = -lightData.forward; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
distSq = dot(lightToSample, lightToSample); |
|
|
|
L = -lightToSample * rsqrt(distSq); |
|
|
|
} |
|
|
|
|
|
|
|
float3 N = bsdfData.normalWS; |
|
|
|
float NdotL = dot(N, L); |
|
|
|
float3 unL = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? -lightToSample : -lightData.forward; |
|
|
|
float distSq = dot(unL, unL); |
|
|
|
float3 N = bsdfData.normalWS; |
|
|
|
float3 L = unL * rsqrt(distSq); |
|
|
|
float NdotL = dot(N, L); |
|
|
|
|
|
|
|
float3 color; float attenuation, shadow; |
|
|
|
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, N, L, distSq, |
|
|
|