2021-09-09 20:42:29 -04:00

53 lines
2.1 KiB
HLSL

// Area light textures
//#define USE_LOCAL_AXF_TABLE
#ifdef USE_LOCAL_AXF_TABLE
#define LTC_DATA_ARRAY_NAME _AxFLtcData
#else
#define LTC_DATA_ARRAY_NAME _LtcData // still need to bind it in Axf.cs
#endif
TEXTURE2D_ARRAY(LTC_DATA_ARRAY_NAME); // We pack all Ltc data inside one texture array to limit the number of resource used
#define LTC_LUT_SIZE 64
#define LTC_LUT_SCALE ((LTC_LUT_SIZE - 1) * rcp(LTC_LUT_SIZE))
#define LTC_LUT_OFFSET (0.5 * rcp(LTC_LUT_SIZE))
// Tables are stored with new encoding (i.e. U=Perceptual roughness, V=sqrt( 1 - cos(N.V) ))
// TODO: make the code work with other table, currently everyone use GGX
#define LTC_MATRIX_INDEX_GGX 0//0
#define LTC_MATRIX_INDEX_COOK_TORRANCE 0//1
#define LTC_MATRIX_INDEX_WARD 0//2
#define LTC_MATRIX_INDEX_OREN_NAYAR 0//3
// Expects NdotV clamped in [0,1]
float2 LTCGetSamplingUV(float NdotV, float perceptualRoughness)
{
float2 xy;
#ifndef USE_LOCAL_AXF_TABLE
xy.x = perceptualRoughness;
xy.y = FastACosPos(NdotV) * INV_HALF_PI; // Originally, texture was accessed via theta so we had to take the acos(N.V)
#else
xy.x = perceptualRoughness;
xy.y = sqrt( 1 - NdotV ); // Now, we use V = sqrt( 1 - cos(theta) ) which is kind of linear and only requires a single sqrt() instead of an expensive acos()
#endif
// Original code
// return LTC_LUT_OFFSET + LTC_LUT_SCALE * float2( perceptualRoughness, theta * INV_HALF_PI );
xy *= (LTC_LUT_SIZE-1); // 0 is pixel 0, 1 = last pixel in the table
xy += 0.5; // Perfect pixel sampling starts at the center
return xy / LTC_LUT_SIZE; // Finally, return UVs in [0,1]
}
// Fetches the transposed M^-1 matrix need for runtime LTC estimate
float3x3 LTCSampleMatrix(float2 UV, uint BRDFIndex)
{
// Note we load the matrix transpose (to avoid having to transpose it in shader)
float3x3 invM = 0.0;
invM._m22 = 1.0;
invM._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(LTC_DATA_ARRAY_NAME, s_linear_clamp_sampler, UV, BRDFIndex, 0);
return invM;
}