|
|
|
|
|
|
L = 2.0 * dot(V, H) * H - V; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Special case of ImportanceSampleGGXDir() where N == V. |
|
|
|
// Approximates GGX with a BRDF which is isotropic for all viewing angles. |
|
|
|
void ImportanceSampleGGXViewIndDir(float2 u, |
|
|
|
float3 N, |
|
|
|
float3 tangentX, |
|
|
|
float3 tangentY, |
|
|
|
float roughness, |
|
|
|
out float3 L, |
|
|
|
out float NdotH) |
|
|
|
// Special case of ImportanceSampleGGXDir() where V == N. |
|
|
|
void ImportanceSampleGGXDirVeqN(float2 u, |
|
|
|
float3 N, |
|
|
|
float3 tangentX, |
|
|
|
float3 tangentY, |
|
|
|
float roughness, |
|
|
|
out float3 L, |
|
|
|
out float NdotH) |
|
|
|
{ |
|
|
|
// GGX NDF sampling |
|
|
|
float cosThetaH = sqrt((1.0 - u.x) / (1.0 + (roughness * roughness - 1.0) * u.x)); |
|
|
|
|
|
|
// Transform from spherical into Cartesian. |
|
|
|
// Transform from spherical to Cartesian |
|
|
|
// localN == localV == float3(0.0, 0.0, 1.0). |
|
|
|
// localN == localV == float3(0.0, 0.0, 1.0) |
|
|
|
// Compute { L = reflect(-localV, localH) }. |
|
|
|
// Compute { L = reflect(-localV, localH) } |
|
|
|
float VdotH = NdotH; |
|
|
|
L = float3(0.0, 0.0, -1.0) + 2.0 * VdotH * localH; |
|
|
|
|
|
|
|
|
|
|
float3 N, |
|
|
|
float roughness, |
|
|
|
float invOmegaP, |
|
|
|
uint sampleCount, // Must be a Fibonacci number |
|
|
|
bool prefilter = true) // static bool |
|
|
|
uint sampleCount, // static int (must be a Fibonacci number) |
|
|
|
bool prefilter) // static bool |
|
|
|
{ |
|
|
|
float3 acc = float3(0.0, 0.0, 0.0); |
|
|
|
float accWeight = 0; |
|
|
|
|
|
|
|
|
|
|
float3 L; |
|
|
|
float NdotH; |
|
|
|
ImportanceSampleGGXViewIndDir(u, N, tangentX, tangentY, roughness, L, NdotH); |
|
|
|
ImportanceSampleGGXDirVeqN(u, N, tangentX, tangentY, roughness, L, NdotH); |
|
|
|
|
|
|
|
float NdotL = saturate(dot(N, L)); |
|
|
|
|
|
|
|