|
|
|
|
|
|
|
|
|
|
void EvaluateBSDF_Directional(LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, PreLightData preLightData, |
|
|
|
int lightType, DirectionalLightData lightData, BSDFData bsdfData, |
|
|
|
DirectionalLightData lightData, BSDFData bsdfData, |
|
|
|
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane. |
|
|
|
// 'lightData.right' and 'lightData.up' are pre-scaled on CPU. |
|
|
|
float3 lightToSurface = positionWS - lightData.positionWS; |
|
|
|
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward); |
|
|
|
float3 positionLS = mul(lightToSurface, transpose(lightToWorld)); |
|
|
|
float2 positionNDC = positionLS.xy; |
|
|
|
|
|
|
|
// Clip only box projector lights. |
|
|
|
float clipFactor = 1; |
|
|
|
|
|
|
|
// Static branch. |
|
|
|
if (lightType == GPULIGHTTYPE_PROJECTOR_BOX) |
|
|
|
{ |
|
|
|
// bool isInBounds = max(abs(positionNDC.x), abs(positionNDC.y)) <= 1 && positionLS.z >= 0; |
|
|
|
// float clipFactor = isInBounds ? 1 : 0; |
|
|
|
// This version is slightly more efficient: |
|
|
|
float clipFactor = saturate(FLT_MAX - FLT_MAX * Max3(abs(positionNDC.x), abs(positionNDC.y), positionLS.z >= 0 ? 0 : 1)); |
|
|
|
} |
|
|
|
|
|
|
|
float attenuation = clipFactor; |
|
|
|
|
|
|
|
float illuminance = saturate(NdotL * attenuation); |
|
|
|
float illuminance = saturate(NdotL); |
|
|
|
|
|
|
|
diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure |
|
|
|
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure |
|
|
|
|
|
|
|
|
|
|
[branch] if (lightData.cookieIndex >= 0) |
|
|
|
{ |
|
|
|
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane. |
|
|
|
// 'lightData.right' and 'lightData.up' are pre-scaled on CPU. |
|
|
|
float3 lightToSurface = positionWS - lightData.positionWS; |
|
|
|
|
|
|
|
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward); |
|
|
|
float3 positionLS = mul(lightToSurface, transpose(lightToWorld)); |
|
|
|
float2 positionNDC = positionLS.xy; |
|
|
|
|
|
|
|
float clipFactor = 1.0f; |
|
|
|
|
|
|
|
if (lightData.tileCookie) |
|
|
|
{ |
|
|
|
// Tile the texture if the 'repeat' wrap mode is enabled. |
|
|
|
coord = frac(coord); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// bool isInBounds = max(abs(positionNDC.x), abs(positionNDC.y)) <= 1 && positionLS.z >= 0; |
|
|
|
// float clipFactor = isInBounds ? 1 : 0; |
|
|
|
// This version is slightly more efficient: |
|
|
|
clipFactor = saturate(FLT_MAX - FLT_MAX * Max3(abs(positionNDC.x), abs(positionNDC.y), positionLS.z >= 0 ? 0 : 1)); |
|
|
|
} |
|
|
|
|
|
|
|
cookie = c.rgb * c.a; |
|
|
|
cookie = c.rgb * c.a * clipFactor; |
|
|
|
} |
|
|
|
|
|
|
|
[branch] if (illuminance > 0.0) |
|
|
|