|
|
|
|
|
|
PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfData) |
|
|
|
{ |
|
|
|
PreLightData preLightData; |
|
|
|
ZERO_INITIALIZE(PreLightData, preLightData); |
|
|
|
|
|
|
|
float3 N; |
|
|
|
float NdotV; |
|
|
|
|
|
|
#elif LIT_DIFFUSE_GGX_BRDF |
|
|
|
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness); |
|
|
|
#else |
|
|
|
// A note on subsurface scattering. |
|
|
|
// A note on subsurface scattering: [SSS-NOTE-TRSM] |
|
|
|
// The correct way to handle SSS is to transmit light inside the surface, perform SSS, |
|
|
|
// and then transmit it outside towards the viewer. |
|
|
|
// Transmit(X) = F_Transm_Schlick(F0, F90, NdotX), where F0 = 0, F90 = 1. |
|
|
|
|
|
|
return cookie; |
|
|
|
} |
|
|
|
|
|
|
|
// 'intensity' is already premultiplied with 'shadow', 'color' is NOT premultiplied with anything. |
|
|
|
void EvaluateLight_Directional(LightLoopContext lightLoopContext, |
|
|
|
float3 N, float3 L, float NdotL, PositionInputs posInput, |
|
|
|
// None of the outputs are premultiplied. |
|
|
|
void EvaluateLight_Directional(LightLoopContext lightLoopContext, PositionInputs posInput, |
|
|
|
out float3 color, out float intensity, out float shadow) |
|
|
|
float3 N, float3 L, |
|
|
|
out float3 color, out float attenuation, out float shadow) |
|
|
|
color = lightData.color; |
|
|
|
intensity = saturate(NdotL); |
|
|
|
shadow = 1.0; |
|
|
|
color = lightData.color; |
|
|
|
attenuation = 1.0; |
|
|
|
shadow = 1.0; |
|
|
|
|
|
|
|
#ifdef SHADOWS_SHADOWMASK |
|
|
|
// shadowMaskSelector.x is -1 if there is no shadow mask |
|
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
intensity *= shadow; |
|
|
|
|
|
|
|
color *= cookie.rgb; |
|
|
|
intensity *= cookie.a; |
|
|
|
color *= cookie.rgb; |
|
|
|
attenuation *= cookie.a; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float3 N = bsdfData.normalWS; |
|
|
|
float3 L = -lightData.forward; // Lights point backward in Unity |
|
|
|
float NdotL = dot(bsdfData.normalWS, L); |
|
|
|
float NdotL = dot(N, L); |
|
|
|
float3 color; float intensity, shadow; |
|
|
|
EvaluateLight_Directional(lightLoopContext, N, L, NdotL, posInput, lightData, bakeLightingData, |
|
|
|
color, intensity, shadow); |
|
|
|
float3 color; float attenuation, shadow; |
|
|
|
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, N, L, |
|
|
|
color, attenuation, shadow); |
|
|
|
|
|
|
|
float intensity = shadow * attenuation * saturate(NdotL); |
|
|
|
|
|
|
|
[branch] if (intensity > 0.0) |
|
|
|
{ |
|
|
|
|
|
|
// Apply wrapped lighting to better handle thin objects (cards) at grazing angles. |
|
|
|
float wrappedNdotL = ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT); |
|
|
|
|
|
|
|
// Apply the BSDF to attenuation. See also: [SSS-NOTE-TRSM] |
|
|
|
intensity = Lambert() * wrappedNdotL; |
|
|
|
attenuation *= Lambert(); |
|
|
|
intensity = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL; |
|
|
|
attenuation *= INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL); |
|
|
|
// Shadowing is applied inside EvaluateTransmission(). |
|
|
|
intensity = attenuation * wrappedNdotL; |
|
|
|
|
|
|
|
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|
|
|
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF(). |
|
|
|
lighting.diffuse += EvaluateTransmission(bsdfData, intensity * lightData.diffuseScale, shadow); |
|
|
|
|
|
|
return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset); |
|
|
|
} |
|
|
|
|
|
|
|
// 'intensity' is already premultiplied with 'shadow', 'color' is NOT premultiplied with anything. |
|
|
|
void EvaluateLight_Punctual(LightLoopContext lightLoopContext, |
|
|
|
float3 N, float3 L, float NdotL, float distSq, PositionInputs posInput, |
|
|
|
// None of the outputs are premultiplied. |
|
|
|
void EvaluateLight_Punctual(LightLoopContext lightLoopContext, PositionInputs posInput, |
|
|
|
out float3 color, out float intensity, out float shadow) |
|
|
|
float3 N, float3 L, float distSq, |
|
|
|
out float3 color, out float attenuation, out float shadow) |
|
|
|
color = lightData.color; |
|
|
|
intensity = GetPunctualShapeAttenuation(lightData, L, distSq) * saturate(NdotL); |
|
|
|
shadow = 1.0; |
|
|
|
color = lightData.color; |
|
|
|
attenuation = GetPunctualShapeAttenuation(lightData, L, distSq); |
|
|
|
shadow = 1.0; |
|
|
|
|
|
|
|
#ifdef SHADOWS_SHADOWMASK |
|
|
|
// shadowMaskSelector.x is -1 if there is no shadow mask |
|
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
intensity *= shadow; |
|
|
|
|
|
|
|
// Projector lights always have a cookies, so we can perform clipping inside the if(). |
|
|
|
[branch] if (lightData.cookieIndex >= 0) |
|
|
|
{ |
|
|
|
|
|
|
color *= cookie.rgb; |
|
|
|
intensity *= cookie.a; |
|
|
|
color *= cookie.rgb; |
|
|
|
attenuation *= cookie.a; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
float distSq = dot(unL, unL); |
|
|
|
float3 N = bsdfData.normalWS; |
|
|
|
float3 L = unL * rsqrt(distSq); |
|
|
|
float NdotL = dot(bsdfData.normalWS, L); |
|
|
|
float NdotL = dot(N, L); |
|
|
|
|
|
|
|
float3 color; float attenuation, shadow; |
|
|
|
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, N, L, distSq, |
|
|
|
color, attenuation, shadow); |
|
|
|
float3 color; float intensity, shadow; |
|
|
|
EvaluateLight_Punctual(lightLoopContext, N, L, NdotL, distSq, posInput, lightData, bakeLightingData, |
|
|
|
color, intensity, shadow); |
|
|
|
float intensity = shadow * attenuation * saturate(NdotL); |
|
|
|
|
|
|
|
[branch] if (intensity > 0.0) |
|
|
|
{ |
|
|
|
|
|
|
// Apply wrapped lighting to better handle thin objects (cards) at grazing angles. |
|
|
|
float wrappedNdotL = ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT); |
|
|
|
|
|
|
|
// Apply the BSDF to attenuation. See also: [SSS-NOTE-TRSM] |
|
|
|
intensity = Lambert() * wrappedNdotL; |
|
|
|
attenuation *= Lambert(); |
|
|
|
intensity = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL; |
|
|
|
attenuation *= INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL); |
|
|
|
|
|
|
|
// Shadowing is applied inside EvaluateTransmission(). |
|
|
|
intensity = attenuation * wrappedNdotL; |
|
|
|
|
|
|
|
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|
|
|
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF(). |
|
|
|