// area light
float3x3 minV;
float ltcGGXMagnitude;
// Shadow (sampling rotation disc)
float2 unPositionSS;
};
PreLightData GetPreLightData(float3 V, float3 positionWS, Coordinate coord, BSDFData bsdfData)
preLightData.ltcGGXMagnitude = UNITY_SAMPLE_TEX2D_LOD(_LtcGGXMagnitude, uv, 0).w;
// Shadow
preLightData.unPositionSS = coord.unPositionSS;
return preLightData;
}
// GetBakedDiffuseLigthing function compute the bake lighting + emissive color to be store in emissive buffer (Deferred case)
// In forward it must be add to the final contribution.
// This function require the 3 structure surfaceData, builtinData, bsdfData because it may require both the engine side data, and data that will not be store inside the gbuffer.
float3 GetBakedDiffuseLigthing(PreLightData prel ightData, SurfaceData surfaceData, BuiltinData builtinData, BSDFData bsdfData)
float3 GetBakedDiffuseLigthing(PreLightData preL ightData, SurfaceData surfaceData, BuiltinData builtinData, BSDFData bsdfData)
return builtinData.bakeDiffuseLighting * prel ightData.diffuseFGD * surfaceData.ambientOcclusion * bsdfData.diffuseColor + builtinData.emissiveColor * builtinData.emissiveIntensity;
return builtinData.bakeDiffuseLighting * preL ightData.diffuseFGD * surfaceData.ambientOcclusion * bsdfData.diffuseColor + builtinData.emissiveColor * builtinData.emissiveIntensity;
}
//-----------------------------------------------------------------------------
// BSDF share between area light (reference) and punctual light
//-----------------------------------------------------------------------------
void BSDF( float3 V, float3 L, float3 positionWS, PreLightData prel ightData, BSDFData bsdfData,
void BSDF( float3 V, float3 L, float3 positionWS, PreLightData preL ightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
{
float BdotL = saturate(dot(bsdfData.bitangentWS, L));
#ifdef USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGXAnisoLambdaV( prelightData.TdotV, prelightData.BdotV, prel ightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, prel ightData.anisoGGXlambdaV);
Vis = V_SmithJointGGXAnisoLambdaV( preLightData.TdotV, preLightData.BdotV, preL ightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, preL ightData.anisoGGXlambdaV);
Vis = V_SmithJointGGXAniso( prelightData.TdotV, prelightData.BdotV, prel ightData.NdotV, TdotL, BdotL, NdotL,
Vis = V_SmithJointGGXAniso( preLightData.TdotV, preLightData.BdotV, preL ightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB);
#endif
else
{
#ifdef USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGX(NdotL, prelightData.NdotV, bsdfData.roughness, prel ightData.ggxLambdaV);
Vis = V_SmithJointGGX(NdotL, preLightData.NdotV, bsdfData.roughness, preL ightData.ggxLambdaV);
Vis = V_SmithJointGGX(NdotL, prel ightData.NdotV, bsdfData.roughness);
Vis = V_SmithJointGGX(NdotL, preL ightData.NdotV, bsdfData.roughness);
#endif
D = D_GGXDividePI(NdotH, bsdfData.roughness);
}
#else
float diffuseTerm = DisneyDiffuseDividePI(prel ightData.NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
float diffuseTerm = DisneyDiffuseDividePI(preL ightData.NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
#endif
diffuseLighting.rgb = bsdfData.diffuseColor * diffuseTerm;
}
//-----------------------------------------------------------------------------
void EvaluateBSDF_Punctual( LightLoopContext lightLoopContext,
float3 V, float3 positionWS, PreLightData prel ightData, PunctualLightData lightData, BSDFData bsdfData,
float3 V, float3 positionWS, PreLightData preL ightData, PunctualLightData lightData, BSDFData bsdfData,
out float4 diffuseLighting,
out float4 specularLighting)
{
const bool hasShadow = (lightData.flags & LIGHTFLAGS_HAS_SHADOW) != 0;
[branch] if (hasShadow && illuminance > 0.0f)
{
float4x4 shadowTransform = GetShadowTransform(lightLoopContext, lightData.shadowIndex, L);
float4 positionHS = mul(float4(positionWS, 1), shadowTransform);
float shadowAttenuation = 1; // GetShadowAttenuation(shadowTransform, positionHS.xyz / positionHS.w);
// Apply offset
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
float3 shadowCoord = GetShadowTextureCoordinate(lightLoopContext, lightData.shadowIndex, positionWS + offset, L);
// Caution: formula doesn't work as we are texture atlas...
// if (max3(abs(NDC.x), abs(NDC.y), 1.0f - texCoordXYZ.z) <= 1.0f) return 1.0;
float3 shadowPosDX = ddx_fine(shadowCoord);
float3 shadowPosDY = ddy_fine(shadowCoord);
float shadowAttenuation = GetShadowAttenuation(lightLoopContext, lightData.shadowIndex, shadowCoord, shadowPosDX, shadowPosDY, preLightData.unPositionSS);
if (illuminance > 0.0f)
[branch] if (illuminance > 0.0f)
BSDF(V, L, positionWS, prelightData, bsdfData, diffuseLighting.rgb, specularLighting.rgb);
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting.rgb, specularLighting.rgb);
diffuseLighting.rgb *= lightData.color * illuminance * lightData.diffuseScale;
specularLighting.rgb *= lightData.color * illuminance * lightData.specularScale;
}
// EvaluateBSDF_Area - Reference
//-----------------------------------------------------------------------------
void IntegrateGGXAreaRef( float3 V, float3 positionWS, PreLightData prel ightData, AreaLightData lightData, BSDFData bsdfData,
void IntegrateGGXAreaRef( float3 V, float3 positionWS, PreLightData preL ightData, AreaLightData lightData, BSDFData bsdfData,
out float4 diffuseLighting,
out float4 specularLighting,
uint sampleCount = 512)
if (illuminance > 0.0)
{
BSDF(V, L, positionWS, prel ightData, bsdfData, localDiffuseLighting, localSpecularLighting);
BSDF(V, L, positionWS, preL ightData, bsdfData, localDiffuseLighting, localSpecularLighting);
localDiffuseLighting *= lightData.color * illuminance * lightData.diffuseScale;
localSpecularLighting *= lightData.color * illuminance * lightData.specularScale;
}
//-----------------------------------------------------------------------------
void EvaluateBSDF_Area( LightLoopContext lightLoopContext,
float3 V, float3 positionWS, PreLightData prel ightData, AreaLightData lightData, BSDFData bsdfData,
float3 V, float3 positionWS, PreLightData preL ightData, AreaLightData lightData, BSDFData bsdfData,
IntegrateGGXAreaRef(V, positionWS, prel ightData, lightData, bsdfData, diffuseLighting, specularLighting);
IntegrateGGXAreaRef(V, positionWS, preL ightData, lightData, bsdfData, diffuseLighting, specularLighting);
#else
// TODO: This could be precomputed
specularLighting = float4(0.0f, 0.0f, 0.0f, 1.0f);
// TODO: Fresnel is missing here but should be present
specularLighting.rgb = LTCEvaluate(V, bsdfData.normalWS, prelightData.minV, L, lightData.twoSided) * prel ightData.ltcGGXMagnitude;
specularLighting.rgb = LTCEvaluate(V, bsdfData.normalWS, preLightData.minV, L, lightData.twoSided) * preL ightData.ltcGGXMagnitude;
//#ifdef DIFFUSE_LAMBERT_BRDF
// Lambert diffuse term (here it should be Disney)
// _preIntegratedFGD and _CubemapLD are unique for each BRDF
void EvaluateBSDF_Env( LightLoopContext lightLoopContext,
float3 V, float3 positionWS, PreLightData prel ightData, EnvLightData lightData, BSDFData bsdfData,
float3 V, float3 positionWS, PreLightData preL ightData, EnvLightData lightData, BSDFData bsdfData,
out float4 diffuseLighting,
out float4 specularLighting)
{
// float shrinkedRoughness = AnisotropicStrechAtGrazingAngle(bsdfData.roughness, bsdfData.perceptualRoughness, NdotV);
// Note: As explain in GetPreLightData we use normalWS and not iblNormalWS here (in case of anisotropy)
float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, prel ightData.iblR, bsdfData.roughness);
float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, preL ightData.iblR, bsdfData.roughness);
float3 R = rayWS;
float weight = 1.0;
// We let GetSpecularDominantDir currently as it still an improvement but not as good as it could be
float mip = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
float4 preLD = SampleEnv(lightLoopContext, lightData.envIndex, R, mip);
specularLighting.rgb = preLD.rgb * prel ightData.specularFGD;
specularLighting.rgb = preLD.rgb * preL ightData.specularFGD;
// Apply specular occlusion on it
specularLighting.rgb *= bsdfData.specularOcclusion;