95 lines
No EOL
2.5 KiB
Text
95 lines
No EOL
2.5 KiB
Text
include "pipelines/common.glsl"
|
|
|
|
vertex_shader [[
|
|
|
|
layout (location = 0) out vec2 v_uv;
|
|
|
|
void main()
|
|
{
|
|
gl_Position = fullscreenQuad(gl_VertexID, v_uv);
|
|
}
|
|
]]
|
|
|
|
|
|
|
|
fragment_shader [[
|
|
// inspired by https://github.com/tobspr/RenderPipeline/blob/master/rpplugins/ao/shader/ue4ao.kernel.glsl
|
|
layout (location = 0) in vec2 v_uv;
|
|
layout (location = 0) out vec4 o_color;
|
|
layout (binding=0) uniform sampler2D u_depth_buffer;
|
|
layout (binding=1) uniform sampler2D u_normal_buffer;
|
|
layout(std140, binding = 4) uniform Drawcall {
|
|
uniform vec4 u_params;
|
|
};
|
|
|
|
#define RADIUS u_params.x
|
|
#define INTENSITY u_params.y
|
|
|
|
vec3 getViewNormal(vec2 tex_coord)
|
|
{
|
|
vec3 wnormal = texture(u_normal_buffer, tex_coord).xyz * 2 - 1;
|
|
vec4 vnormal = u_camera_view * vec4(wnormal, 0);
|
|
return vnormal.xyz;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec3 view_pos = getViewPosition(u_depth_buffer, u_camera_inv_projection, v_uv);
|
|
vec3 view_normal = getViewNormal(v_uv);
|
|
|
|
float occlusion = 0;
|
|
float occlusion_count = 0;
|
|
|
|
const int SAMPLE_COUNT = 4;
|
|
|
|
float random_angle = rand(view_pos.xyz) * 6.283285;
|
|
float s = sin(random_angle);
|
|
float c = cos(random_angle);
|
|
float depth_scale = RADIUS / view_pos.z;
|
|
for (int i = 0; i < SAMPLE_COUNT; ++i)
|
|
{
|
|
vec2 poisson = POISSON_DISK_16[i];
|
|
vec2 s = vec2(poisson.x * c + poisson.y * s, poisson.x * -s + poisson.y * c);
|
|
s = s * depth_scale;
|
|
|
|
vec3 vpos_a = getViewPosition(u_depth_buffer, u_camera_inv_projection, v_uv + s);
|
|
vec3 vpos_b = getViewPosition(u_depth_buffer, u_camera_inv_projection, v_uv - s);
|
|
|
|
vec3 sample_vec_a = normalize(vpos_a - view_pos);
|
|
vec3 sample_vec_b = normalize(vpos_b - view_pos);
|
|
|
|
float dist_a = distance(vpos_a, view_pos);
|
|
float dist_b = distance(vpos_b, view_pos);
|
|
|
|
float valid_a = step(dist_a - 1.0, 0.0);
|
|
float valid_b = step(dist_b - 1.0, 0.0);
|
|
|
|
float angle_a = max(0, dot(sample_vec_a, view_normal));
|
|
float angle_b = max(0, dot(sample_vec_b, view_normal));
|
|
|
|
if (valid_a != valid_b)
|
|
{
|
|
angle_a = mix(-angle_b, angle_a, valid_a);
|
|
angle_b = mix(angle_a, -angle_b, valid_b);
|
|
dist_a = mix(dist_b, dist_a, valid_a);
|
|
dist_b = mix(dist_a, dist_b, valid_b);
|
|
}
|
|
|
|
if (valid_a > 0.5 || valid_b > 0.5)
|
|
{
|
|
occlusion += (angle_a + angle_b) * 0.25 * (2 - (dist_a + dist_b));
|
|
occlusion_count += 1.0;
|
|
}
|
|
else
|
|
{
|
|
occlusion_count += 0.5;
|
|
}
|
|
}
|
|
|
|
occlusion /= max(1.0, occlusion_count);
|
|
float value = 1 - occlusion * INTENSITY;
|
|
|
|
o_color.rgb = vec3(mix(value, 1, saturate(-view_pos.z * 0.02)));
|
|
o_color.w = 1;
|
|
}
|
|
]] |