A large bare room with a suspended woven chair, a window at right casting its shadow on the wall.

Case study

Reading the Light

How to tell whether a generated interior is physically lit, and what to do when it isn’t.

← Back to the work
Role
Imaging lead
Built with
Nano Banana, Photoshop
Method
Depth sampling, cast and contact checks
Measured
5 samples, 3 objects

Generated images don’t trace light

A model predicts pixels from local patterns. It paints a shadow that looks right next to the object casting it, with no reference to any single source. So a frame can be lit from the right on the wall and from the left on the floor and still look convincing.

The eye usually accepts it. That’s the problem. The failure stays invisible until someone measures, and by then it’s on a product page.

The room above was built to isolate that one thing. It’s deliberately under-styled, a test rig rather than a room to live in. Foreground furniture came out because it covered the floor where shadows fall, and the corner framing opened up because it flattened the depth cues you need to judge shadow length.

The procedure

Five checks, in order. Each one runs with an eyedropper in under a minute.

  1. 01

    Establish the key from objects, not the window

    Sample both faces of three rounded objects at different depths. The brighter face points at the light. A window can be out of frame, curtained, or a reflection. The objects can't lie about which way they're lit.

  2. 02

    Require agreement

    All three have to indicate the same side. Where one disagrees, work out whether something else is shading it before you throw the reading away.

  3. 03

    Check every shadow falls away from that side

    A room usually has a key light plus fill, so two shadow directions can both be right. What's never right is a shadow matching neither.

  4. 04

    Separate cast shadow from contact shading

    A missing cast shadow can be legitimate. With the key behind the camera it hides behind its own object. Missing contact shading never is. It happens under any lighting.

  5. 05

    Match softness to source scale

    Hard object shadows under soft floor light don't happen. Neither does a crisp window pattern on the floor beneath soft-edged objects.

The readings

← left face brighterright face brighter →
Chair shell rim
+32.4
Plant pot
+16.2
Floor, across frame
+49.7
Seat cushion
+3.4
Floor beside pot
−10.0
Brightness sampled on each object’s left and right faces, 0 to 255. The window is at camera right, so a bar to the right means the object is brighter on the side facing the light. Three agree. Two do not.

Two disagreed. Both are explainable.

The seat cushion sits recessed inside the shell, so the shell’s own right wall shades it. It’s reporting the chair, not the room. The floor beside the pot is a strip against the wall base, so it’s reporting the wall’s shading, not the pot’s shadow.

Neither is a lighting fault. But both would have produced a confident, wrong verdict if I hadn’t checked what was actually inside each sample before trusting the number. That matters more than any of the five checks.

The correction

Iterative generation left two shadows on the floor at once, a directional smear from an earlier pass plus a later pooled shadow. The two implied different light positions, which is a physical contradiction rather than a styling choice.

I stopped generating at the point texture started degrading and resolved the two down to a single occlusion shadow by hand. Regenerating would have re-rendered the whole scene to fix one element.

Floor with two overlapping shadows pointing different ways.
Before. Two shadows, two implied sources.
Floor with a single soft shadow beneath the chair.
After. One shadow, consistent with the measured key.

What this establishes, and what it cannot

A single flat image cannot prove absolute physical correctness. Without depth you can’t recover the true light vector, and perspective changes the angle between an object and its shadow depending on where it sits in frame.

What it can establish is internal consistency, whether every shadow implies the same light. That’s the useful test, because generative failure is almost always inconsistency rather than implausibility.

One more rule, learned the expensive way. Corrections below the threshold of immediate perception get skipped. They protect nothing and they cost native grain.

Pushing the model toward one light

Prevention beats correction. These terms pull a model toward computing a lighting environment rather than painting one locally, and they cut down orphaned shadows. Appended to the render block:

...rendered with a single unified key light, consistent shadow vectors, explicit ambient occlusion at all surface contact points, physically accurate cast shadows, cohesive global illumination.

Unified key light suppresses conflicting sources across the room. Explicit ambient occlusion forces the contact shading that grounds an object. Consistent shadow vectors align cast shadows to one direction. Global illumination pulls on training data from 3D renderers, which compute light bounce rather than inventing it.