Screen Space Ambient Occlusion
Introduced by (Shanmugam and Arikan 2007)
Idea #
Generate 3d sample points inside some radius around rendered fragments and check how many of them lie infront or behing the depth image, by projecting them to the image plane. The percentage of samples behind the depth image is the ambient occlusion.
The hemisphere radius is constant in world space, so projected size is depth dependent.
Each sample is treated equally, Lambert’s cosine law
is not repsected
(surfaces at a high angle from the normal should not occlude the point
the same as surfaces at 0 degrees). This changes the normalization factor
to
for one hemisphere (half of the surface area of a
sphere), rather than
if Lambert’s cosine law
was respected,
see Ambient Occlusion
.
History #
Developed at Crytec in 2007, appeard first in Crysis (Mittring 2007)
Normal-Free SSAO #
f32 calc_ao (u32 x, u32 y, f32* depth_image, u32 num_samples) {
f32 ka = 1;
vec3 p_v = reconstruct_coords(x, y, depth_image[x, y]);
f32 r = get_sapling_radius_for_depth(depth_image[x, y]);
Array_List<vec3> samples = generate_samples(num_samples, p_v, r);
for (auto sample : samples) {
vec2 p_s = project_to_image_plane(sample);
if (depth_image[p_s] < vec3_len(sample)) {
ka -= 1.0 / num_samples;
}
}
return ka;
}
Possible improvements #
- Distance based weighting
- sample points closer to the original point are weighted more
SSAO with normals #
Only consider samples infront of the tangent plane of the to-be-shaded fragment.
f32 calc_ao (u32 x, u32 y, f32* depth_image, vec3* normal_image, u32 num_samples) {
f32 ka = 0;
u32 counter = 0;
vec3 p_v = reconstruct_coords(x, y, depth_image[x, y]);
f32 r = get_sapling_radius_for_depth(depth_image[x, y]);
Array_List<vec3> samples = generate_samples(num_samples, p_v, r);
for (auto sample : samples) {
vec2 p_s = project_to_image_plane(sample);
if (!is_over_tangent_plane(normal_image[ps], p_c)) {
continue;
}
counter++;
if (depth_image[p_s] < vec3_len(sample)) {
ka += 1;
}
}
return ka / counter;
}
Checking if a point is over a plane
: