#version 330 core layout(location = 0) out vec3 fragColor; in vec2 texcoord; uniform sampler2D gbuffer0_tex; uniform sampler2D gbuffer1_tex; uniform samplerCube prefiltered_envmap_tex; uniform mat4 fg_ViewMatrixInverse; uniform vec3 fg_SunDirection; const float MAX_PREFILTERED_LOD = 4.0; // math.glsl float M_PI(); float M_1_PI(); // normal_encoding.glsl vec3 decode_normal(vec2 f); // pos_from_depth.glsl vec3 get_view_space_from_depth(vec2 uv); // aerial_perspective.glsl vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); vec3 get_sun_radiance_sea_level(); float F_Schlick(float VdotH, float F0) { return F0 + (1.0 - F0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); } float D_GGX(float NdotH, float a2) { float f = (NdotH * a2 - NdotH) * NdotH + 1.0; return a2 / (M_PI() * f * f); } void main() { vec4 gbuffer0 = texture(gbuffer0_tex, texcoord); vec4 gbuffer1 = texture(gbuffer1_tex, texcoord); // Unpack G-Buffer vec3 N = decode_normal(gbuffer0.rg); vec3 sea_color = gbuffer1.rgb; vec3 P = get_view_space_from_depth(texcoord); vec3 V = normalize(-P); vec3 L = fg_SunDirection; vec3 refl = reflect(-V, N); vec3 ws_N = (fg_ViewMatrixInverse * vec4(N, 0.0)).xyz; vec3 ws_refl = (fg_ViewMatrixInverse * vec4(refl, 0.0)).xyz; vec3 H = normalize(L + V); float NdotL = clamp(dot(N, L), 0.0, 1.0); float NdotV = clamp(abs(dot(N, V)), 0.001, 1.0); float NdotH = clamp(dot(N, H), 0.0, 1.0); const float f0 = 0.02; // For IOR=1.33 float fresnel = F_Schlick(NdotV, f0); // Refracted light vec3 Esky = textureLod(prefiltered_envmap_tex, ws_N, MAX_PREFILTERED_LOD).rgb; vec3 refracted = sea_color * Esky * M_1_PI(); // Reflected sky light vec3 reflected = textureLod(prefiltered_envmap_tex, ws_refl, 1.0).rgb; vec3 color = mix(refracted, reflected, fresnel); // Add reflected Sun light vec3 sun_intensity = get_sun_radiance_sea_level(); color += M_1_PI() * fresnel * D_GGX(NdotH, 0.001) * sun_intensity * NdotL; color = add_aerial_perspective(color, texcoord, length(P)); fragColor = color; }