1
0
Fork 0
fgdata/Shaders/HDR/ibl.glsl

75 lines
2.4 KiB
GLSL

#version 330 core
uniform sampler2D dfg_tex;
uniform samplerCube prefiltered_envmap_tex;
const float MAX_PREFILTERED_LOD = 4.0;
// math.glsl
float pow5(float x);
vec3 get_reflected(vec3 N, vec3 V, mat4 view_matrix_inverse)
{
return (view_matrix_inverse * vec4(reflect(-V, N), 0.0)).xyz;
}
/*
* Fresnel term with included roughness to get a pleasant visual result.
* See https://seblagarde.wordpress.com/2011/08/17/hello-world/
*/
vec3 F_Schlick_roughness(float NdotV, vec3 F0, float r)
{
return F0 + (max(vec3(1.0 - r), F0) - F0) * pow5(max(1.0 - NdotV, 0.0));
}
/*
* Evaluate the indirect diffuse irradiance.
*
* To get better results we should be precomputing the irradiance into a cubemap
* or calculating spherical harmonics coefficients on the CPU.
* Sampling the roughness=1 mipmap level of the prefiltered specular map works
* fine too. :)
*/
vec3 ibl_eval_diffuse(vec3 N)
{
int max_lod = int(MAX_PREFILTERED_LOD);
ivec2 s = textureSize(prefiltered_envmap_tex, max_lod);
float du = 1.0 / float(s.x);
float dv = 1.0 / float(s.y);
vec3 m0 = normalize(cross(N, vec3(0.0, 1.0, 0.0)));
vec3 m1 = cross(m0, N);
vec3 m0du = m0 * du;
vec3 m1dv = m1 * dv;
vec3 c;
c = textureLod(prefiltered_envmap_tex, N - m0du - m1dv, max_lod).rgb;
c += textureLod(prefiltered_envmap_tex, N + m0du - m1dv, max_lod).rgb;
c += textureLod(prefiltered_envmap_tex, N + m0du + m1dv, max_lod).rgb;
c += textureLod(prefiltered_envmap_tex, N - m0du + m1dv, max_lod).rgb;
return 0.25 * c;
}
/*
* Evaluate the indirect specular.
* Sample from the prefiltered environment map.
*/
vec3 ibl_eval_specular(float NdotV, vec3 refl, float roughness, vec3 f)
{
float lod = roughness * float(MAX_PREFILTERED_LOD);
vec3 prefiltered = textureLod(prefiltered_envmap_tex, refl, lod).rgb;
vec2 env_brdf = texture(dfg_tex, vec2(NdotV, roughness)).rg;
return prefiltered * (f * env_brdf.x + env_brdf.y);
}
/*
* Evaluate the contribution of image-based lights, or indirect lighting.
*/
vec3 eval_ibl(vec3 base_color, float metallic, float roughness, vec3 f0,
float occlusion, vec3 ws_N, vec3 ws_refl, float NdotV)
{
roughness = max(roughness, 0.002025);
vec3 F = F_Schlick_roughness(NdotV, f0, roughness);
vec3 specular = ibl_eval_specular(NdotV, ws_refl, roughness, F);
vec3 diffuse = ibl_eval_diffuse(ws_N) * base_color
* (vec3(1.0) - F) * (1.0 - metallic);
return (diffuse + specular) * occlusion;
}