I tried the first two methods linked to above. Performance on an AMD 280 (released in 2014) at 1920x1080 was indistinguishable from the texture-based approach. So I think I probably should not worry about it.
Are you the Warren who used to hang out in the Blitz3D forums?
//---------------------------------------------------------------
// Specular Image-based Lighting
//---------------------------------------------------------------
#define ALGOBRDF
#ifdef ALGOBRDF
// https://knarkowicz.wordpress.com/2014/12/27/analytical-dfg-term-for-ibl/
vec3 EnvDFGPolynomial(in vec3 specularColor, float roughness, float ndotv)
{
float x = 1.0 - roughness;
float y = ndotv;
float b1 = -0.1688;
float b2 = 1.895;
float b3 = 0.9903;
float b4 = -4.853;
float b5 = 8.404;
float b6 = -5.069;
float bias = clamp( min( b1 * x + b2 * x * x, b3 + b4 * y + b5 * y * y + b6 * y * y * y ), 0.0, 1.0);
float d0 = 0.6045;
float d1 = 1.699;
float d2 = -0.5228;
float d3 = -3.603;
float d4 = 1.404;
float d5 = 0.1939;
float d6 = 2.661;
float delta = clamp( d0 + d1 * x + d2 * y + d3 * x * x + d4 * x * y + d5 * y * y + d6 * x * x * x, 0.0, 1.0);
float scale = delta - bias;
bias *= clamp( 50.0 * specularColor.y, 0.0, 1.0);
return specularColor * scale + bias;
}
//https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
vec3 EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV )
{
const vec4 c0 = { -1, -0.0275, -0.572, 0.022 };
const vec4 c1 = { 1, 0.0425, 1.04, -0.04 };
vec4 r = Roughness * c0 + c1;
float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
return SpecularColor * AB.x + AB.y;
}
#endif
vec3 getIBLRadianceGGX(in sampler2D u_GGXLUT, in vec3 specularSample, vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight)
{
float NdotV = clampedDot(n, v);
#ifdef ALGOBRDF
return EnvBRDFApprox(specularSample, roughness, NdotV) * specularWeight;
//return EnvDFGPolynomial(specularSample, roughness, NdotV) * specularWeight;
#else
vec3 reflection = normalize(reflect(-v, n));
vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0));
vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg;
//vec4 specularSample = getSpecularSample(u_GGXEnvSampler, reflection, lod);
vec3 specularLight = specularSample.rgb;
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
// Roughness dependent fresnel, from Fdez-Aguera
vec3 Fr = max(vec3(1.0 - roughness), F0) - F0;
vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0);
vec3 FssEss = k_S * f_ab.x + f_ab.y;
return specularWeight * specularLight * FssEss;
#endif
}