#if !defined FRESNEL_LIB
#define FRESNEL_LIB
    vec3 fresnelNonPolarized(in float voh, in complexVec3 n1, in complexVec3 n2) {
        complexVec3 eta = complexDiv(n1, n2);
        vec3 cosThetaI = vec3(voh);
        float sinThetaI = sqrt(saturate(1.0 - voh * voh));
        complexVec3 sinThetaT = complexVec3(eta.r * sinThetaI, eta.i * sinThetaI);
        complexVec3 cosThetaT = complexSqrt(complexSub(vec3(1.0), complexMul(sinThetaT, sinThetaT)));

        vec3 Rs = square(complexAbs(
            complexDiv(complexSub(complexMul(n1, cosThetaI), complexMul(n2, cosThetaT)), complexAdd(complexMul(n1, cosThetaI), complexMul(n2, cosThetaT)))
        ));

        vec3 Rp = square(complexAbs(
            complexDiv(complexSub(complexMul(n1, cosThetaT), complexMul(n2, cosThetaI)), complexAdd(complexMul(n1, cosThetaT), complexMul(n2, cosThetaI)))
        ));

        return saturate((Rs + Rp) * 0.5);
    }

    vec3 fresnelFunction(in float cosTheta, in vec3 n, in vec3 k) {
        if(sd.isAlbedoMetal < 0.9) {
            return fresnelNonPolarized(cosTheta, complexVec3(vec3(1.00029), vec3(0.0)), complexVec3(n, k));
        } else {
            //This is using Schlick fresnel for albedo metals. It looks a bit better than using the exact fresnel, but is definitely less accurate. However albedo metals are not accurate to begin with, so I don't give a damn.
            vec3 f0 = square((n - 1.00029) / (n + 1.00029));
            return saturate(k * (f0 + (1.0 - f0) * pow(1.0 - cosTheta, 5.0)));
        }
    }
#endif