float3 vLayerEnergyCoeff[NB_VLAYERS];
// TODOENERGY
// For now since FGD fetches aren't used in compute adding (instead we do non integrated
// Fresnel( ) evaluations and 1 - Fresnel( ) which is wrong, the former only ok for analytical
// lights for the top interface for R12), we will use these for FGD fetches but keep them
// For now since FGD fetches aren't used in compute adding (instead we do non integrated
// Fresnel( ) evaluations and 1 - Fresnel( ) which is wrong, the former only ok for analytical
// lights for the top interface for R12), we will use these for FGD fetches but keep them
// for BSDF( ) eval for analytical lights since the later don't use FGD terms.
//float topIor = bsdfData.coatIor;
// TODO:
// We will avoid using coatIor directly as with the fake refraction, it can cause TIR
// which even when handled in EvalIridescence (tested), doesn't look pleasing and
// which even when handled in EvalIridescence (tested), doesn't look pleasing and
// creates a discontinuity.
float scale = clamp((1.0-bsdfData.coatPerceptualRoughness), 0.0, 1.0);
float topIor = lerp(1.0001, bsdfData.coatIor, scale);
float theta[NB_NORMALS];
float2 uv[TOTAL_NB_LOBES];
// These 2 cases will generate the same code when no dual normal maps since COAT_NORMAL_IDX == BASE_NORMAL_IDX == 0,
// These 2 cases will generate the same code when no dual normal maps since COAT_NORMAL_IDX == BASE_NORMAL_IDX == 0,
// and one will be pruned out:
theta[COAT_NORMAL_IDX] = FastACosPos(NdotV[COAT_NORMAL_IDX]);
theta[BASE_NORMAL_IDX] = FastACosPos(NdotV[BASE_NORMAL_IDX]);
preLightData.TdotV = TdotV;
preLightData.BdotV = BdotV;
#endif
// perceptualRoughness is use as input and output here
float3 outNormal;
float outPerceptualRoughness;
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_IRIDESCENCE))
{
float3 fresnelIridescent = preLightData.fresnelIridforCalculatingFGD;
#ifdef IRIDESCENCE_RECOMPUTE_PERLIGHT
float topIor = 1.0; // default air on top.
fresnelIridescent = EvalIridescence(topIor, savedLdotH, bsdfData.iridescenceThickness, bsdfData.fresnel0);
float NdotV = ClampNdotV(unclampedNdotV);
float LdotV = dot(L, V);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
// TODOENERGYDIFFUSE:
// TODOENERGYDIFFUSE:
// but we would need to balance it with the term used from e_Ti0 == preLightData.diffuseEnergy, as
// but we would need to balance it with the term used from e_Ti0 == preLightData.diffuseEnergy, as
// If we use the same term, we could just apply it in the end to diffuse light since coat can't produce diffuse lighting,
// so diffuse lighting from the base interface should all have the term applied. (Then, we would need to make sure the
// If we use the same term, we could just apply it in the end to diffuse light since coat can't produce diffuse lighting,
// so diffuse lighting from the base interface should all have the term applied. (Then, we would need to make sure the
// energy term is separate from diffuseFGD.) But the terms are not the same:
//
// Even without energy conservation, preLightData.diffuseEnergyTransmitted should still != preLightData.diffuseEnergy
float len = lightData.size.x;
float3 T = lightData.right;
float3 unL = lightData.positionWS - positionWS;
float3 unL = lightData.positionR WS - positionWS;
// Pick the major axis of the ellipsoid.
float3 axis = lightData.right;
lightData.specularScale *= intensity;
// Translate the light s.t. the shaded point is at the origin of the coordinate system.
lightData.positionWS -= positionWS;
lightData.positionR WS -= positionWS;
float3 P1 = lightData.positionWS - T * (0.5 * len);
float3 P2 = lightData.positionWS + T * (0.5 * len);
float3 P1 = lightData.positionR WS - T * (0.5 * len);
float3 P2 = lightData.positionR WS + T * (0.5 * len);
// Rotate the endpoints into the local coordinate system.
float3 localP1 = mul(P1, transpose(preLightData.orthoBasisViewNormal[BASE_NORMAL_IDX]));
ltcValue *= lightData.diffuseScale;
// TODOENERGYDIFFUSE: In Lit with Lambert, there's no diffuseFGD, it is one. In our case, we also
// need a diffuse energy term when vlayered. See preLightData.diffuseEnergyTransmitted
// 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 += bsdfData.transmittance * ltcValue;
IntegrateBSDF_AreaRef(V, positionWS, preLightData, lightData, bsdfData,
lighting.diffuse, lighting.specular);
#else
float3 unL = lightData.positionWS - positionWS;
float3 unL = lightData.positionR WS - positionWS;
if (dot(lightData.forward, unL) >= 0.0001)
{
lightData.specularScale *= intensity;
// Translate the light s.t. the shaded point is at the origin of the coordinate system.
lightData.positionWS -= positionWS;
lightData.positionR WS -= positionWS;
lightVerts[0] = lightData.positionWS + lightData.right * halfWidth + lightData.up * halfHeight;
lightVerts[1] = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;
lightVerts[2] = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;
lightVerts[3] = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
lightVerts[0] = lightData.positionR WS + lightData.right * halfWidth + lightData.up * halfHeight;
lightVerts[1] = lightData.positionR WS + lightData.right * halfWidth + lightData.up * -halfHeight;
lightVerts[2] = lightData.positionR WS + lightData.right * -halfWidth + lightData.up * -halfHeight;
lightVerts[3] = lightData.positionR WS + lightData.right * -halfWidth + lightData.up * halfHeight;
// Rotate the endpoints into the local coordinate system.
float4x3 localLightVerts = mul(lightVerts, transpose(preLightData.orthoBasisViewNormal[BASE_NORMAL_IDX]));