The Mirror That Lies to Your Face

You walk into a bathroom in a first-person shooter. Two mirrors, face to face. In real life, that corridor of shrinking reflections tunnels back seemingly forever. In the game, it stops. Maybe after two bounces, maybe four. If you look closely, the deepest reflection is just a flat photograph of the room, frozen mid-scene, slightly blurry, not quite tracking your movement.

You probably noticed and moved on. The reason it stops, though, is more interesting than a simple performance shortcut.

Why Infinite Loops Are Actually Infinite

In the physical world, a photon bouncing between two mirrors loses energy with each bounce until it's too dim to see. The recursion ends naturally. In a renderer, nothing runs out of energy. A ray bouncing between two perfect virtual mirrors would keep spawning new reflection calculations forever, or until the engine crashes, whichever comes first.

Real-time rendering has a hard budget: roughly 16 milliseconds per frame at 60fps. Spend even half of that on one pair of mirrors and the rest of your scene collapses. So every engine imposes a recursion depth limit, a hard ceiling on how many times a reflection ray is allowed to spawn a child ray before the engine returns a fallback color.

The question is where to set that ceiling. And what to show when you hit it.

The Recursion Depth Decision

Most real-time engines default to a reflection depth between 1 and 3. Unreal Engine's Screen Space Reflections, the technique used in the majority of current-generation games, defaults to a single bounce. One. The reflection you see in a mirror is a snapshot of the scene rendered from the mirror's perspective, but that snapshot doesn't itself contain live reflections. It's a photograph, not a window.

Raise that to depth 2 and a mirror reflecting another mirror will show one level of recursive reflection before freezing. Depth 3 gets you two visible corridors of shrinking images. Each additional bounce can double or triple the reflection render cost for that pixel, so the math turns punishing fast.

Picture a hotel corridor with mirrors at both ends. At depth 1, each mirror shows the corridor but the far mirror appears as a flat, untextured grey or a static environment capture. At depth 2, the far mirror shows the near mirror, but the near mirror in that reflection is grey. At depth 4, you get three visible recursive images before the fallback kicks in. Four bounces in a scene with complex lighting, running on a mid-range GPU, can consume enough rendering budget that frame rate visibly stutters.

So engines pick a number that looks convincing to a player moving at speed and stick with it.

What Fills the Frozen Frame

When a reflection ray exhausts its bounce budget, the engine needs to return something. The options are roughly three: a solid fallback color (usually a neutral grey or black, which looks terrible), a pre-baked cubemap, or the last available screen-space data.

Cubemaps are the workhorse solution. A cubemap is a six-sided snapshot of the environment captured from a fixed point, essentially a panoramic photograph baked into the level at build time or scene load. When a reflection ray hits its depth limit, the engine samples the nearest cubemap and returns that color. The result looks plausible as long as you're not moving quickly and the cubemap was placed thoughtfully.

The problem with cubemaps in a mirror-facing-mirror scenario is that they're static. Like a security camera still showing yesterday's footage. If a character walks through the reflection zone, the cubemap doesn't update. Bethesda's Starfield uses this approach in many of its interior spaces, and in certain angled views you can catch your own character not appearing in a reflection, or appearing slightly offset, because the cubemap was baked before you arrived.

Ray-traced reflections change the calculus somewhat, but not as much as marketing suggests. Hardware ray tracing still operates with a maximum ray depth, typically 2 to 4 bounces in real-world implementations like those in Control or Cyberpunk 2077's RT Overdrive mode. The reflections are more accurate and do update dynamically, but the recursion ceiling remains. What you gain is precision at the first and second bounce, not an escape from the fundamental limit.

The Two Players Who Noticed Different Things

Consider two people who played the same survival horror game, same level, same room with opposing mirrors. Maya played on a high-end desktop with ray tracing enabled at depth 3. She saw two clear recursive reflections before the image faded into an ambient grey. It felt atmospheric, even intentional. She assumed the third reflection was obscured by the fog the engine had added to the scene.

Dario played on a mid-range console with screen-space reflections at depth 1. His mirror showed a single reflection, and the mirror within that reflection was a flat grey rectangle. It looked broken. He posted about it. The replies informed him that this was normal, which did not fully satisfy him.

Same artistic intent, same scene geometry, two completely different experiences of the same optical lie. The engine isn't hiding incompetence. It's making a triage decision under a time constraint, and whether that decision reads as atmospheric or broken depends entirely on the hardware budget available to you specifically.

That asymmetry is worth sitting with: why does one version feel intentional and the other feel like a bug, when they're the same underlying choice made at different depth limits?

The Part That Takes Real Work to Solve

Screen-space reflections have a structural weakness beyond just depth limits, and it explains a lot of the visual artifacts players notice and can't quite name.

SSR works by taking what's already rendered on screen and warping it to simulate a reflection. Fast, because it reuses existing pixel data. But it can only reflect what's currently visible on screen. Walk to the edge of a mirror's frame, and the reflection of what's behind you simply disappears, replaced by a fallback. The reflection of a doorway behind you doesn't exist because the doorway isn't being rendered from the mirror's perspective, only from yours.

This is why reflections in SSR-heavy games often look like they're sliding or flickering at grazing angles. The engine is desperately trying to extrapolate reflection data from pixels that are barely on screen, or guessing based on the cubemap when the data runs out entirely. It's less a rendering technique and more an ongoing negotiation with missing information.

The alternative, rendering the scene fully from the mirror's point of view, is called a planar reflection or a reflection render target. Accurate. It also roughly doubles the draw calls for everything the mirror can see, which is why it's reserved for hero mirrors in cutscenes, loading screens, or very controlled environments like a racing game's rear-view mirror, where the reflected scene is deliberately simple.

Portal's mirror puzzles used planar reflections precisely because the game was architected around the render cost. The levels were sparse, the geometry was clean, and the reflections were the point. That's a design-first solution to a rendering-first problem. It worked because the whole game was built around making it work, which is honestly the only way that trade-off ever pays off cleanly.

What You're Actually Looking At

Next time you find a pair of facing mirrors in a game, count the visible reflections before the image goes grey or blurry or simply wrong. That number is the engine's recursion depth limit, rendered visible. One reflection means depth 1. Two means depth 2. The grey wall at the end of the corridor is the fallback cubemap, a photograph of a room that may not even exist in the game's geometry anymore.

The fact that it usually looks fine is the impressive part. Engines aren't solving the infinite mirror problem. They're making you comfortable with a ceiling you can't quite see. Human vision in the physical world also stops caring about the seventh reflection in a barbershop mirror. We never needed the full tunnel. We just needed enough of it to believe in the room, and the craft is in knowing exactly how little that turns out to be.