|
|
|
|
|
|
#ifdef HAS_LIGHTLOOP |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
// |
|
|
|
// Lighting structure for light accumulation |
|
|
|
// This structure allow to accumulate lighting accross the Lit material |
|
|
|
// It is init to zero and transfer by the LightLoop, but the LightLoop can't access its content. |
|
|
|
struct Lighting |
|
|
|
// These structure allow to accumulate lighting accross the Lit material |
|
|
|
// AggregateLighting is init to zero and transfer to EvaluateBSDF, but the LightLoop can't access its content. |
|
|
|
struct DirectLighting |
|
|
|
float3 directDiffuse; |
|
|
|
float3 directSpecular; |
|
|
|
float3 refraction; |
|
|
|
float3 envSpecular; |
|
|
|
float3 diffuse; |
|
|
|
float3 specular; |
|
|
|
|
|
|
|
struct IndirectLighting |
|
|
|
{ |
|
|
|
float3 specularReflected; |
|
|
|
float3 specularTransmitted; |
|
|
|
}; |
|
|
|
|
|
|
|
struct AggregateLighting |
|
|
|
{ |
|
|
|
DirectLighting direct; |
|
|
|
IndirectLighting indirect; |
|
|
|
}; |
|
|
|
|
|
|
|
void AccumulateDirectLighting(DirectLighting src, inout AggregateLighting dst) |
|
|
|
{ |
|
|
|
dst.direct.diffuse += src.diffuse; |
|
|
|
dst.direct.specular += src.specular; |
|
|
|
} |
|
|
|
|
|
|
|
void AccumulateIndirectLighting(IndirectLighting src, inout AggregateLighting dst) |
|
|
|
{ |
|
|
|
dst.indirect.specularReflected += src.specularReflected; |
|
|
|
dst.indirect.specularTransmitted += src.specularTransmitted; |
|
|
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
// BSDF share between directional light, punctual light and area light (reference) |
|
|
|
|
|
|
return cookie; |
|
|
|
} |
|
|
|
|
|
|
|
void EvaluateBSDF_Directional(LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, PreLightData preLightData, |
|
|
|
DirectionalLightData lightData, BSDFData bsdfData, |
|
|
|
inout Lighting lighting) |
|
|
|
DirectLighting EvaluateBSDF_Directional( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, PreLightData preLightData, |
|
|
|
DirectionalLightData lightData, BSDFData bsdfData) |
|
|
|
DirectLighting lighting; |
|
|
|
ZERO_INITIALIZE(DirectLighting, lighting); |
|
|
|
|
|
|
|
float3 positionWS = posInput.positionWS; |
|
|
|
|
|
|
|
float3 L = -lightData.forward; // Lights are pointing backward in Unity |
|
|
|
|
|
|
float3 diffuseLighting = float3(0, 0, 0); |
|
|
|
float3 specularLighting = float3(0, 0, 0); |
|
|
|
float shadow = 1; |
|
|
|
float shadow = 1.0; |
|
|
|
|
|
|
|
[branch] if (lightData.shadowIndex >= 0) |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
[branch] if (illuminance > 0.0) |
|
|
|
{ |
|
|
|
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting); |
|
|
|
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular); |
|
|
|
diffuseLighting *= illuminance * lightData.diffuseScale; |
|
|
|
specularLighting *= illuminance * lightData.specularScale; |
|
|
|
lighting.diffuse *= illuminance * lightData.diffuseScale; |
|
|
|
lighting.specular *= illuminance * lightData.specularScale; |
|
|
|
} |
|
|
|
|
|
|
|
[branch] if (bsdfData.enableTransmission) |
|
|
|
|
|
|
float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT); |
|
|
|
|
|
|
|
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|
|
|
diffuseLighting += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow); |
|
|
|
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow); |
|
|
|
diffuseLighting *= lightData.color; |
|
|
|
specularLighting *= lightData.color; |
|
|
|
lighting.diffuse *= lightData.color; |
|
|
|
lighting.specular *= lightData.color; |
|
|
|
lighting.directDiffuse += diffuseLighting; |
|
|
|
lighting.directSpecular += specularLighting; |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
|
return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset); |
|
|
|
} |
|
|
|
|
|
|
|
void EvaluateBSDF_Punctual( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType, |
|
|
|
inout Lighting lighting) |
|
|
|
DirectLighting EvaluateBSDF_Punctual( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType) |
|
|
|
DirectLighting lighting; |
|
|
|
ZERO_INITIALIZE(DirectLighting, lighting); |
|
|
|
|
|
|
|
float3 positionWS = posInput.positionWS; |
|
|
|
int lightType = GPULightType; |
|
|
|
|
|
|
|
|
|
|
lightData.diffuseScale *= attenuation; |
|
|
|
lightData.specularScale *= attenuation; |
|
|
|
|
|
|
|
float3 diffuseLighting = float3(0.0, 0.0, 0.0); |
|
|
|
float3 specularLighting = float3(0.0, 0.0, 0.0); |
|
|
|
float shadow = 1.0; |
|
|
|
|
|
|
|
[branch] if (lightData.shadowIndex >= 0) |
|
|
|
|
|
|
|
|
|
|
[branch] if (illuminance > 0.0) |
|
|
|
{ |
|
|
|
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual ligth have a radius with this hack |
|
|
|
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting); |
|
|
|
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual light have a radius with this hack |
|
|
|
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular); |
|
|
|
diffuseLighting *= illuminance * lightData.diffuseScale; |
|
|
|
specularLighting *= illuminance * lightData.specularScale; |
|
|
|
lighting.diffuse *= illuminance * lightData.diffuseScale; |
|
|
|
lighting.specular *= illuminance * lightData.specularScale; |
|
|
|
} |
|
|
|
|
|
|
|
[branch] if (bsdfData.enableTransmission) |
|
|
|
|
|
|
float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT); |
|
|
|
|
|
|
|
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|
|
|
diffuseLighting += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow); |
|
|
|
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow); |
|
|
|
diffuseLighting *= lightData.color; |
|
|
|
specularLighting *= lightData.color; |
|
|
|
lighting.diffuse *= lightData.color; |
|
|
|
lighting.specular *= lightData.color; |
|
|
|
lighting.directDiffuse += diffuseLighting; |
|
|
|
lighting.directSpecular += specularLighting; |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
|
|
|
|
#include "LitReference.hlsl" |
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
|
|
void EvaluateBSDF_Line(LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData, |
|
|
|
inout Lighting lighting) |
|
|
|
DirectLighting EvaluateBSDF_Line( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData) |
|
|
|
DirectLighting lighting; |
|
|
|
ZERO_INITIALIZE(DirectLighting, lighting); |
|
|
|
|
|
|
|
float3 diffuseLighting = float3(0.0, 0.0, 0.0); |
|
|
|
float3 specularLighting = float3(0.0, 0.0, 0.0); |
|
|
|
diffuseLighting, specularLighting); |
|
|
|
lighting.diffuse, lighting.specular); |
|
|
|
#else |
|
|
|
float len = lightData.size.x; |
|
|
|
float3 T = lightData.right; |
|
|
|
|
|
|
axis, invAspectRatio); |
|
|
|
|
|
|
|
// Terminate if the shaded point is too far away. |
|
|
|
if (intensity == 0.0) return; |
|
|
|
if (intensity == 0.0) |
|
|
|
return lighting; |
|
|
|
|
|
|
|
lightData.diffuseScale *= intensity; |
|
|
|
lightData.specularScale *= intensity; |
|
|
|
|
|
|
{ |
|
|
|
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformDiffuse); |
|
|
|
ltcValue *= lightData.diffuseScale; |
|
|
|
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue); |
|
|
|
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue); |
|
|
|
} |
|
|
|
|
|
|
|
[branch] if (bsdfData.enableTransmission) |
|
|
|
|
|
|
ltcValue *= lightData.diffuseScale; |
|
|
|
|
|
|
|
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|
|
|
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1); |
|
|
|
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1); |
|
|
|
} |
|
|
|
|
|
|
|
// Evaluate the coat part |
|
|
|
|
|
|
{ |
|
|
|
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformSpecular); |
|
|
|
ltcValue *= lightData.specularScale; |
|
|
|
specularLighting += preLightData.ltcMagnitudeFresnel * ltcValue; |
|
|
|
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue; |
|
|
|
diffuseLighting *= lightData.color; |
|
|
|
specularLighting *= lightData.color; |
|
|
|
lighting.diffuse *= lightData.color; |
|
|
|
lighting.specular *= lightData.color; |
|
|
|
lighting.directDiffuse += diffuseLighting; |
|
|
|
lighting.directSpecular += specularLighting; |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
|
// #define ELLIPSOIDAL_ATTENUATION |
|
|
|
|
|
|
|
void EvaluateBSDF_Rect( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData, |
|
|
|
inout Lighting lighting) |
|
|
|
DirectLighting EvaluateBSDF_Rect( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData) |
|
|
|
DirectLighting lighting; |
|
|
|
ZERO_INITIALIZE(DirectLighting, lighting); |
|
|
|
|
|
|
|
float3 diffuseLighting = float3(0.0, 0.0, 0.0); |
|
|
|
float3 specularLighting = float3(0.0, 0.0, 0.0); |
|
|
|
diffuseLighting, specularLighting); |
|
|
|
lighting.diffuse, lighting.specular); |
|
|
|
#else |
|
|
|
float3 unL = lightData.positionWS - positionWS; |
|
|
|
|
|
|
|
|
|
|
// The light is back-facing. |
|
|
|
return; |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
|
|
|
|
// Rotate the light direction into the light space. |
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
// Terminate if the shaded point is too far away. |
|
|
|
if (intensity == 0.0) return; |
|
|
|
if (intensity == 0.0) |
|
|
|
return lighting; |
|
|
|
|
|
|
|
lightData.diffuseScale *= intensity; |
|
|
|
lightData.specularScale *= intensity; |
|
|
|
|
|
|
// Polygon irradiance in the transformed configuration. |
|
|
|
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformDiffuse)); |
|
|
|
ltcValue *= lightData.diffuseScale; |
|
|
|
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue); |
|
|
|
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue); |
|
|
|
} |
|
|
|
|
|
|
|
[branch] if (bsdfData.enableTransmission) |
|
|
|
|
|
|
ltcValue *= lightData.diffuseScale; |
|
|
|
|
|
|
|
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|
|
|
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1); |
|
|
|
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1); |
|
|
|
} |
|
|
|
|
|
|
|
// Evaluate the coat part |
|
|
|
|
|
|
// ltcValue = LTCEvaluate(lightVerts, V, bsdfData.coatNormalWS, preLightData.coatNdotV, preLightData.ltcXformClearCoat); |
|
|
|
// specularLighting = preLightData.ltcClearCoatFresnelTerm * (ltcValue * bsdfData.coatCoverage); |
|
|
|
// lighting.specular = preLightData.ltcClearCoatFresnelTerm * (ltcValue * bsdfData.coatCoverage); |
|
|
|
|
|
|
|
// modify matL value based on Fresnel transmission |
|
|
|
// matL = mul(matL, preLightData.ltcCoatT); |
|
|
|
|
|
|
// Polygon irradiance in the transformed configuration. |
|
|
|
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformSpecular)); |
|
|
|
ltcValue *= lightData.specularScale; |
|
|
|
specularLighting += preLightData.ltcMagnitudeFresnel * ltcValue; |
|
|
|
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue; |
|
|
|
diffuseLighting *= lightData.color; |
|
|
|
specularLighting *= lightData.color; |
|
|
|
lighting.diffuse *= lightData.color; |
|
|
|
lighting.specular *= lightData.color; |
|
|
|
lighting.directDiffuse += diffuseLighting; |
|
|
|
lighting.directSpecular += specularLighting; |
|
|
|
return lighting; |
|
|
|
void EvaluateBSDF_Area( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType, |
|
|
|
inout Lighting lighting) |
|
|
|
DirectLighting EvaluateBSDF_Area( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType) |
|
|
|
EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, lighting); |
|
|
|
return EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData); |
|
|
|
EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, lighting); |
|
|
|
return EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EvaluateBSDF_SSReflection( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, BSDFData bsdfData, |
|
|
|
inout Lighting lighting, inout float hierarchyWeight) |
|
|
|
IndirectLighting EvaluateBSDF_SSReflection(LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, BSDFData bsdfData, |
|
|
|
inout float hierarchyWeight) |
|
|
|
IndirectLighting lighting; |
|
|
|
ZERO_INITIALIZE(IndirectLighting, lighting); |
|
|
|
|
|
|
|
|
|
|
|
return lighting; |
|
|
|
void EvaluateBSDF_SSRefraction( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, BSDFData bsdfData, |
|
|
|
inout Lighting lighting, inout float hierarchyWeight) |
|
|
|
IndirectLighting EvaluateBSDF_SSRefraction(LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, BSDFData bsdfData, |
|
|
|
inout float hierarchyWeight) |
|
|
|
IndirectLighting lighting; |
|
|
|
ZERO_INITIALIZE(IndirectLighting, lighting); |
|
|
|
|
|
|
|
#if HAS_REFRACTION |
|
|
|
// Refraction process: |
|
|
|
// 1. Depending on the shape model, we calculate the refracted point in world space and the optical depth |
|
|
|
|
|
|
// b. Multiply by the transmittance for absorption (depends on the optical depth) |
|
|
|
|
|
|
|
float3 diffuseLighting = float3(0.0, 0.0, 0.0); |
|
|
|
float3 refractedBackPointWS = float3(0.0, 0.0, 0.0); |
|
|
|
float opticalDepth = 0.0; |
|
|
|
|
|
|
|
|
|
|
|| any(refractedBackPointSS > 1.0)) |
|
|
|
{ |
|
|
|
// Do nothing and don't update the hierarchy weight so we can fall back on refraction probe |
|
|
|
return; |
|
|
|
return lighting; |
|
|
|
diffuseLighting = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointSS, mipLevel).rgb; |
|
|
|
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointSS, mipLevel).rgb; |
|
|
|
diffuseLighting *= transmittance; |
|
|
|
lighting.specularTransmitted *= transmittance; |
|
|
|
UpdateLightingHierarchyWeights(hierarchyWeight, weight); |
|
|
|
lighting.refraction += diffuseLighting * weight; |
|
|
|
UpdateLightingHierarchyWeights(hierarchyWeight, weight); // Shouldn't be needed, but safer in case we decide to change hiearchy priority |
|
|
|
lighting.specularTransmitted *= weight; |
|
|
|
|
|
|
|
return lighting; |
|
|
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
|
// _preIntegratedFGD and _CubemapLD are unique for each BRDF |
|
|
|
void EvaluateBSDF_Env( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType, int GPUImageBasedLightingType, |
|
|
|
inout Lighting lighting, inout float hierarchyWeight) |
|
|
|
IndirectLighting EvaluateBSDF_Env( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType, int GPUImageBasedLightingType, |
|
|
|
inout float hierarchyWeight) |
|
|
|
IndirectLighting lighting; |
|
|
|
ZERO_INITIALIZE(IndirectLighting, lighting); |
|
|
|
return ; |
|
|
|
return lighting; |
|
|
|
float3 envLighting = float3(0.0, 0.0, 0.0); |
|
|
|
float3 specularLighting = float3(0.0, 0.0, 0.0); |
|
|
|
specularLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData); |
|
|
|
envLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData); |
|
|
|
/* |
|
|
|
#ifdef LIT_DIFFUSE_LAMBERT_BRDF |
|
|
|
lighting.directDiffuse += IntegrateLambertIBLRef(lightData, V, bsdfData); |
|
|
|
#else |
|
|
|
lighting.directDiffuse += IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData); |
|
|
|
#endif |
|
|
|
*/ |
|
|
|
hierarchyWeight = 0.0; |
|
|
|
// TODO: Do refraction reference (is it even possible ?) |
|
|
|
|
|
|
|
|
|
|
|
// #ifdef LIT_DIFFUSE_LAMBERT_BRDF |
|
|
|
// envLighting += IntegrateLambertIBLRef(lightData, V, bsdfData); |
|
|
|
// #else |
|
|
|
// envLighting += IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData); |
|
|
|
// #endif |
|
|
|
|
|
|
|
weight = 1.0; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Evaluate the Clear Coat color |
|
|
|
float4 preLD = SampleEnv(lightLoopContext, lightData.envIndex, coatR, 0.0); |
|
|
|
specularLighting += F * preLD.rgb * bsdfData.coatCoverage; |
|
|
|
envLighting += F * preLD.rgb * bsdfData.coatCoverage; |
|
|
|
|
|
|
|
// Change the Fresnel term to account for transmission through Clear Coat and reflection on the base layer. |
|
|
|
F = Sqr(-F * bsdfData.coatCoverage + 1.0); |
|
|
|
|
|
|
specularLighting += F * preLD.rgb * preLightData.specularFGD; |
|
|
|
envLighting += F * preLD.rgb * preLightData.specularFGD; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
lighting.envSpecular += specularLighting * weight; |
|
|
|
lighting.specularReflected = envLighting * weight; |
|
|
|
lighting.refraction += specularLighting * weight; |
|
|
|
lighting.specularTransmitted = envLighting * weight; |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
|
void PostEvaluateBSDF( LightLoopContext lightLoopContext, |
|
|
|
float3 V, PositionInputs posInput, |
|
|
|
PreLightData preLightData, BSDFData bsdfData, float3 bakeDiffuseLighting, Lighting lighting, |
|
|
|
PreLightData preLightData, BSDFData bsdfData, float3 bakeDiffuseLighting, AggregateLighting lighting, |
|
|
|
out float3 diffuseLighting, out float3 specularLighting) |
|
|
|
{ |
|
|
|
// Use GTAOMultiBounce approximation for ambient occlusion (allow to get a tint from the baseColor) |
|
|
|
|
|
|
// Try to mimic multibounce with specular color. Not the point of the original formula but ok result. |
|
|
|
// Take the min of screenspace specular occlusion and visibility cone specular occlusion |
|
|
|
#if GTAO_MULTIBOUNCE_APPROX |
|
|
|
lighting.envSpecular *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0); |
|
|
|
lighting.indirect.specularReflected *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0); |
|
|
|
lighting.envSpecular *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), min(bsdfData.specularOcclusion, specularOcclusion)); |
|
|
|
lighting.indirect.specularReflected *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), min(bsdfData.specularOcclusion, specularOcclusion)); |
|
|
|
lighting.directDiffuse *= |
|
|
|
lighting.direct.diffuse *= |
|
|
|
#if GTAO_MULTIBOUNCE_APPROX |
|
|
|
GTAOMultiBounce(directAmbientOcclusion, bsdfData.diffuseColor); |
|
|
|
#else |
|
|
|
|
|
|
diffuseLighting = lighting.directDiffuse + bakeDiffuseLighting; |
|
|
|
diffuseLighting = lighting.direct.diffuse + bakeDiffuseLighting; |
|
|
|
// Physically speaking, it should be transmittanceMask should be 1, but for artistic reasons, we let the value varie |
|
|
|
// Physically speaking, it should be transmittanceMask should be 1, but for artistic reasons, we let the value vary |
|
|
|
diffuseLighting = lerp(diffuseLighting, lighting.refraction, bsdfData.transmittanceMask); |
|
|
|
diffuseLighting = lerp(diffuseLighting, lighting.indirect.specularTransmitted, bsdfData.transmittanceMask); |
|
|
|
specularLighting = lighting.directSpecular + lighting.envSpecular; |
|
|
|
specularLighting = lighting.direct.specular + lighting.indirect.specularReflected; |
|
|
|
// Rescale the GGX to account for the multiple scattering. |
|
|
|
specularLighting *= 1.0 + bsdfData.fresnel0 * preLightData.energyCompensation; |
|
|
|
|
|
|
|