75 lines
2.4 KiB
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;
|
|
}
|