// S4AO (Stupid Simple Screen Space Ambient Occlusion) - Jonathan Dummer (O1S) // This micro version uses only 3 depth samples, the midpoint and a randomly-rotated, balanced pair. const mediump float ssao_falloff_frac = 0.25; // Perform the SSAO. float s4ao(vec2 UV) { #ifdef USE_MULTIVIEW mediump float depth = texture(depth_buffer_array, vec3(UV, view)).r; #else mediump float depth = texture(depth_buffer, UV).r; #endif mediump float inv_falloff = 1.0f / max(1e-4f, depth * ssao_falloff_frac); // Random 2D rotation per pixel (0..1 -> parabola approximating a 180 deg arc) mediump float r01 = fract(dot(UV, ssao_prn_UV)); mediump vec2 duv = vec2(r01 - 0.5f, 2.0f * (r01 - r01 * r01)) * (2.0f * depth * ssao_radius_frac); // 180 degrees. // Grab the samples and determine the occlusion. mediump float occlusion = 0.0f; for (int s = 0; s < 2; ++s) { #ifdef USE_MULTIVIEW mediump float dz = texture(depth_buffer_array, vec3(UV + duv, view)).r - depth; #else mediump float dz = texture(depth_buffer, UV + duv).r - depth; #endif // How 'directly overhead' is it? Factor in the falloff depth. occlusion += normalize(vec3(duv, dz)).z * mix(1.0f, 0.0f, dz * inv_falloff); // Mirror the next sample. duv = -duv; } // Adjust the occlusion for intensity, and # samples. occlusion = 1.0f - clamp(occlusion * 0.5f * ssao_intensity, 0.0f, 1.0f); return occlusion * occlusion; }