124 lines
3.7 KiB
Plaintext
124 lines
3.7 KiB
Plaintext
|
#version 460 core
|
||
|
|
||
|
// hdr color
|
||
|
layout (location = 0) out vec3 h_color;
|
||
|
|
||
|
struct Light {
|
||
|
// w contains the radius
|
||
|
vec4 pos_radius;
|
||
|
vec4 color;
|
||
|
};
|
||
|
|
||
|
layout(std430, binding = 0) buffer LightBuffer
|
||
|
{
|
||
|
Light lights[];
|
||
|
};
|
||
|
layout (location = 0) uniform uint light_count;
|
||
|
layout (location = 1) uniform vec3 ambient_color;
|
||
|
|
||
|
// GBuffer
|
||
|
layout (location = 2) uniform sampler2D g_position;
|
||
|
layout (location = 3) uniform sampler2D g_albedo;
|
||
|
layout (location = 4) uniform sampler2D g_normal;
|
||
|
layout (location = 5) uniform sampler2D g_orm;
|
||
|
|
||
|
struct Surface {
|
||
|
vec3 position;
|
||
|
vec3 albedo;
|
||
|
vec3 normal;
|
||
|
float occlusion;
|
||
|
float roughness;
|
||
|
float metallic;
|
||
|
};
|
||
|
|
||
|
in VS_OUT {
|
||
|
vec2 texcoord;
|
||
|
} fs_in;
|
||
|
|
||
|
const float PI = 3.1415926;
|
||
|
|
||
|
float GGXDistribution(float alpha, vec3 normal, vec3 H) {
|
||
|
float a2 = alpha * alpha;
|
||
|
float NdotH = dot(normal, H);
|
||
|
float NdotH2 = NdotH * NdotH;
|
||
|
float num = a2 * max(NdotH, 0.0); // both are length = 1, so this is heaviside
|
||
|
float den = (NdotH2 * (a2 - 1.0) + 1);
|
||
|
return num / (PI * den * den);
|
||
|
}
|
||
|
|
||
|
float SmithJoinMaskingShadowing(float alpha, vec3 normal, vec3 light_dir, vec3 view_dir, vec3 H) {
|
||
|
float NdotL = abs(dot(normal, light_dir));
|
||
|
float NdotV = abs(dot(normal, view_dir));
|
||
|
float NdotL2 = NdotL * NdotL;
|
||
|
float NdotV2 = NdotV * NdotV;
|
||
|
float alpha2 = alpha * alpha;
|
||
|
|
||
|
float num1 = 2 * NdotL * max(dot(H, light_dir), 0);
|
||
|
float den1 = NdotL + sqrt(alpha2 + (1-alpha2)*NdotL2);
|
||
|
float num2 = 2 * NdotV * max(dot(H, view_dir), 0);
|
||
|
float den2 = NdotV + sqrt(alpha2 + (1-alpha2)*NdotV2);
|
||
|
|
||
|
return (num1*num2)/(den1*den2);
|
||
|
}
|
||
|
|
||
|
vec3 FresnelSlick(vec3 f0, vec3 view_dir, vec3 H) {
|
||
|
float VdotH = dot(view_dir, H);
|
||
|
return f0 + (1.0 - f0) * pow(1 - abs(VdotH), 5);
|
||
|
}
|
||
|
|
||
|
vec3 Lerp(vec3 a, vec3 b, float t) {
|
||
|
return a + (b - a) * t;
|
||
|
}
|
||
|
|
||
|
Surface ReadSurface() {
|
||
|
Surface surf;
|
||
|
surf.position = texture(g_position, fs_in.texcoord).rgb;
|
||
|
surf.albedo = texture(g_albedo, fs_in.texcoord).rgb;
|
||
|
surf.normal = texture(g_normal, fs_in.texcoord).rgb;
|
||
|
vec3 orm = texture(g_orm, fs_in.texcoord).rgb;
|
||
|
surf.occlusion = orm.r;
|
||
|
surf.roughness = orm.g;
|
||
|
surf.metallic = orm.b;
|
||
|
return surf;
|
||
|
}
|
||
|
|
||
|
void main() {
|
||
|
Surface surf = ReadSurface();
|
||
|
// Eye location is always (0,0,0) because we calculate everything in view-space
|
||
|
vec3 view_dir = normalize(-1 * surf.position);
|
||
|
vec3 black = vec3(0, 0, 0);
|
||
|
|
||
|
vec3 c_diff = Lerp(surf.albedo, black, surf.metallic);
|
||
|
vec3 f0 = Lerp(vec3(0.04), surf.albedo, surf.metallic);
|
||
|
|
||
|
// We probably want a tiling based approach, but this is good enough for now
|
||
|
vec3 Lo = vec3(0.0);
|
||
|
for (uint i = 0; i < light_count; ++i) {
|
||
|
vec3 light_pos = lights[i].pos_radius.xyz;
|
||
|
float light_radius = lights[i].pos_radius.w;
|
||
|
float light_dist = length(light_pos - surf.position);
|
||
|
if (light_dist > light_radius)
|
||
|
continue;
|
||
|
float attenuation = 1.0 / (light_dist * light_dist);
|
||
|
vec3 radiance = lights[i].color.rgb * attenuation;
|
||
|
|
||
|
vec3 light_dir = normalize(-1 * light_pos);
|
||
|
vec3 H = normalize(light_dir + view_dir);
|
||
|
|
||
|
float NdotL = dot(surf.normal, light_dir);
|
||
|
|
||
|
vec3 F = FresnelSlick(f0, view_dir, H);
|
||
|
|
||
|
vec3 f_diffuse = (1 - F) * (1 / PI) * c_diff;
|
||
|
vec3 f_specular = F * GGXDistribution(surf.roughness, surf.normal, H)
|
||
|
* SmithJoinMaskingShadowing(surf.roughness, surf.normal, light_dir, view_dir, H)
|
||
|
/ (4 * abs(dot(view_dir, surf.normal)) * abs(NdotL) + 0.0001);
|
||
|
|
||
|
vec3 material = f_diffuse + f_specular;
|
||
|
Lo += material * radiance * NdotL;
|
||
|
}
|
||
|
|
||
|
vec3 ambient = ambient_color * surf.albedo * surf.occlusion;
|
||
|
h_color = ambient + Lo;
|
||
|
}
|