@@ -112,8 +112,8 @@ BSDFData ConvertSurfaceDataToBSDFData(SurfaceData surfaceData)
112112 bsdfData.diffuseColor = surfaceData.baseColor * (1.0 - surfaceData.metallic);
113113 bsdfData.fresnel0 = lerp (float3 (surfaceData.specular, surfaceData.specular, surfaceData.specular), surfaceData.baseColor, surfaceData.metallic);
114114
115- bsdfData.tangentWS = surfaceData.tangentWS;
116- bsdfData.bitangentWS = cross (surfaceData.normalWS, surfaceData.tangentWS);
115+ bsdfData.tangentWS = surfaceData.tangentWS;
116+ bsdfData.bitangentWS = cross (surfaceData.normalWS, surfaceData.tangentWS);
117117 ConvertAnisotropyToRoughness (bsdfData.roughness, surfaceData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
118118 bsdfData.anisotropy = surfaceData.anisotropy;
119119
@@ -284,7 +284,6 @@ void DecodeFromGBuffer(
284284 bsdfData.fresnel0 = lerp (float3 (specular, specular, specular), baseColor, metallic);
285285
286286 bsdfData.tangentWS = UnpackNormalOctEncode (float2 (inGBuffer2.rg * 2.0 - 1.0 ));
287- // TODO: Do we need to orthonormalize here, IIRC Eric say that we should
288287 bsdfData.bitangentWS = cross (bsdfData.normalWS, bsdfData.tangentWS);
289288 ConvertAnisotropyToRoughness (bsdfData.roughness, anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
290289 bsdfData.anisotropy = anisotropy;
@@ -470,8 +469,8 @@ PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfDat
470469{
471470 PreLightData preLightData;
472471
473- // TODO: check Eric idea about doing that when writting into the GBuffer (with our forward decal)
474- preLightData.NdotV = GetShiftedNdotV (bsdfData.normalWS, V, false );
472+ // We do not saturate to correctly handle double-sided lighting.
473+ preLightData.NdotV = dot (bsdfData.normalWS, V);
475474
476475 preLightData.ggxLambdaV = GetSmithJointGGXLambdaV (preLightData.NdotV, bsdfData.roughness);
477476
@@ -490,7 +489,6 @@ PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfDat
490489 // NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NDotV) and use iblNormalWS
491490 // into function like GetSpecularDominantDir(). However modified normal is just a hack. The goal is just to stretch a cubemap, no accuracy here.
492491 // With this in mind and for performance reasons we chose to only use modified normal to calculate R.
493- // iblNdotV = GetShiftedNdotV(iblNormalWS, V), false);
494492 }
495493
496494 GetPreIntegratedFGD (iblNdotV, bsdfData.perceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD);
@@ -501,7 +499,7 @@ PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfDat
501499
502500 // Area light specific
503501 // UVs for sampling the LUTs
504- float theta = FastACos (dot (bsdfData.normalWS, V) );
502+ float theta = FastACos (preLightData.NdotV );
505503 // Scale and bias for the current precomputed table - the constant use here are the one that have been use when the table in LtcData.DisneyDiffuse.cs and LtcData.GGX.cs was use
506504 float2 uv = 0.0078125 + 0.984375 * float2 (bsdfData.perceptualRoughness, theta * INV_HALF_PI);
507505
@@ -589,6 +587,9 @@ void BSDF( float3 V, float3 L, float3 positionWS, PreLightData preLightData, BS
589587 float BdotH = dot (bsdfData.bitangentWS, H);
590588 float BdotL = dot (bsdfData.bitangentWS, L);
591589
590+ bsdfData.roughnessT = ClampRoughnessForAnalyticalLights (bsdfData.roughnessT);
591+ bsdfData.roughnessB = ClampRoughnessForAnalyticalLights (bsdfData.roughnessB);
592+
592593 #ifdef LIT_USE_BSDF_PRE_LAMBDAV
593594 Vis = V_SmithJointGGXAnisoLambdaV ( preLightData.TdotV, preLightData.BdotV, preLightData.NdotV, TdotL, BdotL, NdotL,
594595 bsdfData.roughnessT, bsdfData.roughnessB, preLightData.anisoGGXLambdaV);
@@ -602,6 +603,8 @@ void BSDF( float3 V, float3 L, float3 positionWS, PreLightData preLightData, BS
602603 }
603604 else
604605 {
606+ bsdfData.roughness = ClampRoughnessForAnalyticalLights (bsdfData.roughness);
607+
605608 #ifdef LIT_USE_BSDF_PRE_LAMBDAV
606609 Vis = V_SmithJointGGX (NdotL, preLightData.NdotV, bsdfData.roughness, preLightData.ggxLambdaV);
607610 #else
@@ -863,9 +866,8 @@ void EvaluateBSDF_Line(LightLoopContext lightLoopContext,
863866 P1 -= positionWS;
864867 P2 -= positionWS;
865868
866- // Construct an orthonormal basis (local coordinate system) around N.
867- // TODO: it could be stored in PreLightData. All LTC lights compute it more than once!
868- // Also consider using 'bsdfData.tangentWS', 'bsdfData.bitangentWS', 'bsdfData.normalWS'.
869+ // Construct a view-dependent orthonormal basis around N.
870+ // TODO: it could be stored in PreLightData, since all LTC lights compute it more than once.
869871 float3x3 basis;
870872 basis[0 ] = normalize (V - bsdfData.normalWS * preLightData.NdotV);
871873 basis[1 ] = normalize (cross (bsdfData.normalWS, basis[0 ]));
@@ -1100,17 +1102,15 @@ void EvaluateBSDF_Area(LightLoopContext lightLoopContext,
11001102// ----------------------------------------------------------------------------
11011103
11021104// Ref: Moving Frostbite to PBR (Appendix A)
1103- float3 IntegrateLambertIBLRef ( LightLoopContext lightLoopContext,
1104- EnvLightData lightData, BSDFData bsdfData,
1105- uint sampleCount = 2048 )
1105+ float3 IntegrateLambertIBLRef (LightLoopContext lightLoopContext,
1106+ float3 V, EnvLightData lightData, BSDFData bsdfData,
1107+ uint sampleCount = 4096 )
11061108{
1107- float3 N = bsdfData.normalWS;
1108- float3 tangentX = bsdfData.tangentWS;
1109- float3x3 localToWorld = GetLocalFrame (N, tangentX);
1109+ float3x3 localToWorld = float3x3 (bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
11101110 float3 acc = float3 (0.0 , 0.0 , 0.0 );
11111111
11121112 // Add some jittering on Hammersley2d
1113- float2 randNum = InitRandom (N .xy * 0.5 + 0.5 );
1113+ float2 randNum = InitRandom (V .xy * 0.5 + 0.5 );
11141114
11151115 for (uint i = 0 ; i < sampleCount; ++i)
11161116 {
@@ -1135,17 +1135,14 @@ float3 IntegrateLambertIBLRef( LightLoopContext lightLoopContext,
11351135}
11361136
11371137float3 IntegrateDisneyDiffuseIBLRef (LightLoopContext lightLoopContext,
1138- float3 V, EnvLightData lightData, BSDFData bsdfData,
1139- uint sampleCount = 2048 )
1138+ float3 V, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
1139+ uint sampleCount = 4096 )
11401140{
1141- float3 N = bsdfData.normalWS;
1142- float3 tangentX = bsdfData.tangentWS;
1143- float3x3 localToWorld = GetLocalFrame (N, tangentX);
1144- float NdotV = GetShiftedNdotV (N, V, false );
1141+ float3x3 localToWorld = float3x3 (bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
11451142 float3 acc = float3 (0.0 , 0.0 , 0.0 );
11461143
11471144 // Add some jittering on Hammersley2d
1148- float2 randNum = InitRandom (N .xy * 0.5 + 0.5 );
1145+ float2 randNum = InitRandom (V .xy * 0.5 + 0.5 );
11491146
11501147 for (uint i = 0 ; i < sampleCount; ++i)
11511148 {
@@ -1164,7 +1161,7 @@ float3 IntegrateDisneyDiffuseIBLRef(LightLoopContext lightLoopContext,
11641161 float LdotH = dot (L, H);
11651162 // Note: we call DisneyDiffuse that require to multiply by Albedo / PI. Divide by PI is already taken into account
11661163 // in weightOverPdf of ImportanceSampleLambert call.
1167- float disneyDiffuse = DisneyDiffuse (NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
1164+ float disneyDiffuse = DisneyDiffuse (preLightData. NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
11681165
11691166 // diffuse Albedo is apply here as describe in ImportanceSampleLambert function
11701167 float4 val = SampleEnv (lightLoopContext, lightData.envIndex, L, 0 );
@@ -1176,18 +1173,13 @@ float3 IntegrateDisneyDiffuseIBLRef(LightLoopContext lightLoopContext,
11761173}
11771174
11781175// Ref: Moving Frostbite to PBR (Appendix A)
1179- float3 IntegrateSpecularGGXIBLRef ( LightLoopContext lightLoopContext,
1180- float3 V, EnvLightData lightData, BSDFData bsdfData,
1181- uint sampleCount = 2048 )
1176+ float3 IntegrateSpecularGGXIBLRef (LightLoopContext lightLoopContext,
1177+ float3 V, PreLightData preLightData , EnvLightData lightData, BSDFData bsdfData,
1178+ uint sampleCount = 4096 )
11821179{
1183- float3 N = bsdfData.normalWS;
1184- float3 tangentX = bsdfData.tangentWS;
1185- float3 tangentY = bsdfData.bitangentWS;
1186- float3x3 localToWorld = GetLocalFrame (N, tangentX);
1187- float NdotV = GetShiftedNdotV (N, V, false );
1180+ float3x3 localToWorld = float3x3 (bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
11881181 float3 acc = float3 (0.0 , 0.0 , 0.0 );
11891182
1190-
11911183 // Add some jittering on Hammersley2d
11921184 float2 randNum = InitRandom (V.xy * 0.5 + 0.5 );
11931185
@@ -1204,11 +1196,11 @@ float3 IntegrateSpecularGGXIBLRef( LightLoopContext lightLoopContext,
12041196 // GGX BRDF
12051197 if (bsdfData.materialId == MATERIALID_LIT_ANISO)
12061198 {
1207- ImportanceSampleAnisoGGX (u, V, N, tangentX, tangentY, bsdfData.roughnessT, bsdfData.roughnessB, NdotV, L, VdotH, NdotL, weightOverPdf);
1199+ ImportanceSampleAnisoGGX (u, V, localToWorld, bsdfData.roughnessT, bsdfData.roughnessB, preLightData. NdotV, L, VdotH, NdotL, weightOverPdf);
12081200 }
12091201 else
12101202 {
1211- ImportanceSampleGGX (u, V, localToWorld, bsdfData.roughness, NdotV, L, VdotH, NdotL, weightOverPdf);
1203+ ImportanceSampleGGX (u, V, localToWorld, bsdfData.roughness, preLightData. NdotV, L, VdotH, NdotL, weightOverPdf);
12121204 }
12131205
12141206
@@ -1239,13 +1231,13 @@ void EvaluateBSDF_Env( LightLoopContext lightLoopContext,
12391231
12401232#ifdef LIT_DISPLAY_REFERENCE_IBL
12411233
1242- specularLighting = IntegrateSpecularGGXIBLRef (lightLoopContext, V, lightData, bsdfData);
1234+ specularLighting = IntegrateSpecularGGXIBLRef (lightLoopContext, V, preLightData, lightData, bsdfData);
12431235
12441236/*
12451237 #ifdef LIT_DIFFUSE_LAMBERT_BRDF
1246- diffuseLighting = IntegrateLambertIBLRef(lightData, bsdfData);
1238+ diffuseLighting = IntegrateLambertIBLRef(lightData, V, bsdfData);
12471239 #else
1248- diffuseLighting = IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, lightData, bsdfData);
1240+ diffuseLighting = IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
12491241 #endif
12501242*/
12511243 diffuseLighting = float3 (0.0 , 0.0 , 0.0 );
@@ -1334,9 +1326,7 @@ void EvaluateBSDF_Env( LightLoopContext lightLoopContext,
13341326 specularLighting *= bsdfData.specularOcclusion;
13351327 diffuseLighting = float3 (0.0 , 0.0 , 0.0 );
13361328
1337- #endif
1329+ #endif
13381330}
13391331
13401332#endif // #ifdef HAS_LIGHTLOOP
1341-
1342-
0 commit comments