LumixEngine/data/pipelines/ssao.shd
Mikulas Florek 64adfa50cc DX fixes
2019-11-06 21:56:02 +01:00

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;
}
]]