119 lines
3.3 KiB
GLSL
119 lines
3.3 KiB
GLSL
#version 330 core
|
|
|
|
out vec3 fragColor;
|
|
|
|
in vec2 texCoord;
|
|
|
|
uniform sampler2D gbuffer0_tex;
|
|
uniform sampler2D gbuffer1_tex;
|
|
uniform sampler2D gbuffer2_tex;
|
|
uniform sampler2D depth_tex;
|
|
uniform sampler2D ao_tex;
|
|
|
|
uniform bool ambient_occlusion_enabled;
|
|
uniform bool debug_shadow_cascades;
|
|
|
|
uniform mat4 fg_ViewMatrixInverse;
|
|
uniform mat4 fg_ProjectionMatrix;
|
|
uniform vec3 fg_SunDirection;
|
|
|
|
vec3 decodeNormal(vec2 f);
|
|
vec3 positionFromDepth(vec2 pos, float depth);
|
|
float getShadowing(vec3 p, vec3 n, vec3 l, mat4 viewToClip);
|
|
vec3 debugShadowColor(vec3 p, vec3 n, vec3 l);
|
|
vec3 getF0Reflectance(vec3 baseColor, float metallic);
|
|
vec3 evaluateLight(
|
|
vec3 baseColor,
|
|
float metallic,
|
|
float roughness,
|
|
vec3 f0,
|
|
vec3 intensity,
|
|
float visibility,
|
|
vec3 n,
|
|
vec3 l,
|
|
vec3 v,
|
|
float NdotL,
|
|
float NdotV);
|
|
vec3 evaluateIBL(
|
|
vec3 baseColor,
|
|
float metallic,
|
|
float roughness,
|
|
vec3 f0,
|
|
float visibility,
|
|
vec3 nWorldSpace,
|
|
float NdotV,
|
|
vec3 reflected);
|
|
vec3 addAerialPerspective(vec3 color, vec2 coord, float depth);
|
|
vec3 getSunIntensity();
|
|
|
|
float GTAOMultiBounce(float x, vec3 albedo)
|
|
{
|
|
// Use luminance instead of albedo because colored multibounce looks bad
|
|
// Idea borrowed from Blender Eevee
|
|
float lum = dot(albedo, vec3(0.333));
|
|
float a = 2.0404 * lum - 0.3324;
|
|
float b = -4.7951 * lum + 0.6417;
|
|
float c = 2.7552 * lum + 0.6903;
|
|
return max(x, ((x * a + b) * x + c) * x);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec4 gbuffer0 = texture(gbuffer0_tex, texCoord);
|
|
vec4 gbuffer1 = texture(gbuffer1_tex, texCoord);
|
|
vec4 gbuffer2 = texture(gbuffer2_tex, texCoord);
|
|
float depth = texture(depth_tex, texCoord).r;
|
|
|
|
// Unpack G-Buffer
|
|
vec3 n = decodeNormal(gbuffer0.rg);
|
|
float roughness = gbuffer0.b;
|
|
uint matId = uint(gbuffer0.a * 4.0);
|
|
vec3 baseColor = gbuffer1.rgb;
|
|
float metallic = gbuffer1.a;
|
|
float occlusion = gbuffer2.a;
|
|
|
|
vec3 pos = positionFromDepth(texCoord, depth);
|
|
vec3 v = normalize(-pos);
|
|
vec3 l = fg_SunDirection;
|
|
|
|
float NdotL = dot(n, l);
|
|
float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
|
|
|
|
vec3 f0 = getF0Reflectance(baseColor, metallic);
|
|
|
|
vec3 sunIlluminance = getSunIntensity() * clamp(NdotL, 0.0, 1.0);
|
|
float shadowFactor = getShadowing(pos, n, l, fg_ProjectionMatrix);
|
|
|
|
vec3 color = evaluateLight(baseColor,
|
|
metallic,
|
|
roughness,
|
|
f0,
|
|
sunIlluminance,
|
|
shadowFactor,
|
|
n, l, v,
|
|
NdotL, NdotV);
|
|
|
|
float ao = occlusion;
|
|
if (ambient_occlusion_enabled) {
|
|
ao *= GTAOMultiBounce(texture(ao_tex, texCoord).r, baseColor);
|
|
}
|
|
|
|
vec3 worldNormal = (fg_ViewMatrixInverse * vec4(n, 0.0)).xyz;
|
|
vec3 worldReflected = (fg_ViewMatrixInverse * vec4(reflect(-v, n), 0.0)).xyz;
|
|
|
|
color += evaluateIBL(baseColor,
|
|
metallic,
|
|
roughness,
|
|
f0,
|
|
ao,
|
|
worldNormal,
|
|
NdotV,
|
|
worldNormal);
|
|
|
|
color = addAerialPerspective(color, texCoord, length(pos));
|
|
|
|
if (debug_shadow_cascades)
|
|
color *= debugShadowColor(pos, n, l);
|
|
|
|
fragColor = color;
|
|
}
|