Corners Don't Look Like That: Regarding Screenspace Ambient Occlusion (2012)
Corners Don't Look Like That: A Critique of Screenspace Ambient Occlusion (2012)
By Sean Barrett Originally published December 13, 2012
The physical Cornell box, as seen in Goral et al. (1984), "Modeling the Interaction of Light Between Diffuse Surfaces."
Challenge: If you believe I'm wrong, I encourage you to gather your own empirical data to prove it.
The SSAO Obsession
There is a pervasive infatuation among game developers regarding Screenspace Ambient Occlusion (SSAO). This obsession has led to some truly bizarre implementation choices:
- Amateur Mistakes: We see screenshots where convex corners—which should be bright—actually become darker or exhibit strange brightening.
- Professional Blunders: High-budget titles often ship with unsightly halos and jarring artifacts (for instance, check the floor area behind a railing).
- The "Uncanny" Feel: Even when the technical glitches are gone, SSAO often feels "off." A prime example is the tendency for room corners to look unnaturally dark.
I suspect this happens because developers believe corners are naturally dark, and they write their shaders to reinforce this misconception rather than reflecting reality.
The Four Pillars of Failure
I attribute the unrealistic look of SSAO to a combination of these four specific issues:
- Approximation Gap A: Using
SSAOas a proxy forAO. - Approximation Gap B: Using
AOas a proxy forRadiosity. - Application Error: Applying the darkening effect to all light sources instead of strictly the ambient light.
- Tuning Error: Setting the heuristic weight of the effect far too high.
I am a professional graphics researcher. Correction: I am not an active researcher. Therefore, I won't be providing a formal academic framework or a peer-reviewed paper. That responsibility lies with those publishing the SSAO algorithms and shipping them in AAA games. My goal here is simply to share my visual experience and the data I collected to support it.
Evidence: Corners Don't Look Like That
To investigate, I took a series of photographs. These are real photos, not renders.
Technical Specifications
| Parameter | Detail |
|---|---|
| Camera | Canon 5D Mk II |
| Format | JPEG |
| Exposure | to |
| Processing | Downsampled via Photoshop |
| Noise Reduction | 16-wide Gaussian blur on chroma channels |
Note: The ceiling is naturally whiter than the walls; do not mistake this for a lighting effect.
Analyzing a "Dark" Corner
I spent considerable time searching my home for a corner that resembled a typical SSAO render. I eventually found one.
(Image digitally brightened for visibility; gamma preservation attempted.)
Observations:
- Wall (c) is shielded from the light, while Wall (d) is heavily exposed.
- The darkening on the left edge of Wall (d) isn't actually AO (radiosity); it's a soft shadow created by a light source located just off-screen to the top-left.
- The corner between Wall (b) and Wall (c) also casts a shadow, but because it's near the light, it manifests as a broad, soft gradient.
- The top edge of Wall (d) is dark because the light is recessed; the "lip" of the recession blocks light from hitting the uppermost part of the wall.
The Lambertian Effect
What about the darkening on Wall (c) as it hits the right edge, or the Ceiling (a) as it meets Wall (d)? This is primarily an indirect lighting effect governed by the Lambertian dot product:
As a point on Wall (c) approaches the edge, the bright surfaces of Wall (d) become more edge-on relative to that point, reducing the received light. While AO tries to capture this, SSAO often exaggerates it. In this specific photo, the effect is only prominent because the soft shadow on Wall (d) happens to align perfectly to create that contrast.
Data vs. Perception
Can we trust a camera? A camera isn't a human eye, but we can analyze the raw numbers.
The images are labeled as sRGB, but I suspect the camera used complex tone mapping. This means the numbers might not be perfectly linear. However, we can still analyze how we perceive the images on an sRGB display.
By sampling pixels across an edge (e.g., between wall c and d), we can graph the actual numerical darkening.
The Analysis Process
- Capture high-exposure images.
- Downsample and blur chroma.
- Sample pixel lines across corners.
- Plot values to determine the slope of darkening.
The logic for generating these graphs is handled by a script similar to this:
# Conceptual snippet for sampling pixel intensity
def get_edge_profile(image, start_coord, end_coord):
profile = []
for point in interpolate(start_coord, end_coord):
pixel = image.get_pixel(point)
# Convert to perceived luminance
luminance = 0.2126*pixel.r + 0.7152*pixel.g + 0.0722*pixel.b
profile.append(luminance)
return profile
By looking at the resulting graph, we can see exactly how the surfaces darken as they approach the intersection, allowing us to separate psychological contrast from actual light attenuation.