Along a line of constant depth the page is affine
Worth reading first: The divide is postponed, not avoided · Dividing depth by eye.
A texture does not interpolate on the page found that stepping a surface’s attributes by a constant amount per pixel is wrong by a closed form, of the span with the depth ratio between its ends, and that the only thing it depends on is that ratio. Its control was a wall square to the camera, where the ratio is one and the error vanishes, and it called that case the reason the bug survives testing.
The control is larger than a wall. A ratio of one needs the two ends of a span at the same depth, not the whole surface. Every plane in front of a camera, however it is turned, is crossed by a family of lines whose points all share a depth, and along any of them a constant step per pixel is exactly right. That changes the question from whether a renderer must divide to which way it walks.
Why one depth means no division
A point at camera depth lands at across the page and down it. Hold fixed and both are affine in the point’s position: walking the world line at a constant rate walks its image at a constant rate. The division by depth is still there, but it is division by one number for the whole line, and a single number can be divided out once before the walk begins.
That is the whole of the exactness. The postponed divide the divide is postponed described exists because a varying depth turns equal steps in the world into unequal steps on the page; where the depth does not vary, there is nothing to postpone.
So the question is where those lines are. A plane meets each plane of constant depth — each plane parallel to the picture — in a straight line, and that line is parallel to the picture too. A line parallel to the picture has no vanishing point; its image is parallel to itself. And every such line on one plane is parallel to every other, so their images are all parallel on the page, in the direction of the plane’s own vanishing line — the image of the plane’s line at infinity, which passes through the vanishing point of every direction the plane contains, where parallel lines meet.
For a floor seen by a level camera that direction is horizontal, and the lines of constant depth are the page’s rows. Every row of a floor is at one depth; the depth changes only from row to row, as the eye’s height times the focal length over the row’s distance below a horizon that sits, for a level camera, at eye level.
How fast a turned span fails
The first figure holds a span’s length at 120 px, centres it on the floor, and turns it. Parallel to the horizon the worst texel is out by nothing at all. Turn it by a quarter of a degree and it is not nothing.
At 80 px below the horizon, 1° of turn puts the worst texel 0.79 px out; 10°, 7.8 px; a span standing straight across the rows, 54.2 px. At 160 px below, each is about half: 0.39, 3.9 and 23.4. On logarithmic axes the small-angle end is a straight line of slope one: the error grows in proportion to the turn.
The proportion has a simple form. A span of length turned by a small angle reaches above and below its centre, and at a distance below the horizon that is a depth ratio of about . Put that into the closed form and the worst texel is close to
For 120 px at 80 px below the horizon and 1° — 0.01745 of a radian — that is 0.785 px, and the figure measures 0.79. The error grows with the square of the span, in proportion to the turn, and in inverse proportion to the distance below the horizon, which is to say in proportion to the depth. A long span near the horizon is the one that cannot afford to be turned.
Every plane has its own direction
Horizontal is the floor’s answer, not a general one.
Bank the floor 20° about the line of sight, as a road’s camber or a tilted deck would be, and its vanishing line tips by the same 20° on the page. The figure turns the same 120 px span through every direction on both surfaces. Each has exactly one direction in which the span is exact, to px, and it is that surface’s own vanishing line: 0.0° for the level floor, 20.0° for the banked one. The page’s rows, exact on the level floor, are 13.26 px out on the banked floor. A span along the banked floor’s direction, exact there, is 12.45 px out on the level floor.
The same statement covers walls. A wall running away from a level camera contains the vertical direction, which is parallel to the picture, so its vanishing line is vertical and its lines of constant depth are the page’s columns. A floor is exact in rows; a wall beside it is exact in columns; a sloping ramp is exact along lines tipped by its own slope. Nothing about the page’s grid is privileged. What is privileged is each surface’s vanishing line, which is a property of the surface and the camera together.
This is not new to rendering. Alberti draws a pavement by dividing a baseline evenly and running orthogonals to the centric point, then placing the transversals — the lines across the pavement, parallel to the picture. Each transversal is a line of constant depth, and the orthogonals cross it at equal intervals, because along it the page is affine. The painter never divides a transversal by eye: equal tiles along it are equal on the page. Every error dividing depth by eye measured lives in the other direction, across the transversals.
A rolled camera has nothing to walk along
A renderer that draws floors row by row has made an assumption about the camera, and the next figure prices it.
Level, every scanline across the floor is a line of constant depth, and the worst texel on the frame is out by nothing. Roll the camera about its axis and the floor’s vanishing line tips while the scanlines stay horizontal, so every scanline now crosses the lines of constant depth. At a hundredth of a degree the worst scanline is out by 0.69 px; at three hundredths, 1.95 px; at a tenth of a degree, 6.49; at one degree, 58; at ten, 261.
The sensitivity is extreme because the worst scanline is the worst case of the formula above at once. It is the whole frame wide — 690 px, not 120 — and it runs into the far limit of the floor, where the distance below the horizon is smallest. The span is squared and the distance is in the denominator, and both have been taken to their limits by the frame itself.
How little roll a floor survives
The tolerance can be written down, and it has no free constants.
A floor drawn to a far limit has its last row below the horizon, with the focal length in pixels and the eye’s height. A roll tips a full-width scanline of length across of page height beside it, and setting to one pixel gives
With a 597.6 px focal length, an eye 1.5 m up and a 690 px frame, a floor drawn to 10 m tolerates 0.043° of roll; to 30 m, 0.014°; to 100 m, 0.0043°; to 300 m, 0.0014°. The figure finds each by bisecting on the roll over every scanline of the frame, and the measured tolerance is the estimate at every depth to the second decimal — even at 300 m, where the far limit is only 3 px below the horizon and the frame’s last floor row is nearly on it.
The formula says what the tolerance is sensitive to. It falls with the square of the frame’s width, so a frame twice as wide tolerates a quarter of the roll. It falls in proportion to how far the floor is drawn. And it rises with the eye’s height, because a higher eye puts the far floor further below the horizon. None of these moves the tolerance out of the hundredths of a degree for any frame a person would look at. A renderer that walks floors in rows does not need its camera nearly level; it needs it level.
The formula also says the tolerance is not really about degrees. Multiply it by the frame’s width and it becomes the rise of one end of the frame over the other that a roll produces: . For a fixed field of view is fixed — 0.866 for a 60° field — so the rise depends only on the eye’s height over the far limit, and not on how many pixels the frame has. A floor drawn to 10 m survives a roll that lifts one side of the frame 0.52 px above the other; to 30 m, 0.17 px; to 300 m, under a fiftieth of a pixel. A frame of four thousand pixels tolerates a smaller angle than one of 690, and exactly the same fraction of a pixel of rise. The condition is not that the camera be nearly level to some precision of angle; it is that the scanlines not be seen to climb, by less than a pixel, from one side of the picture to the other.
Looking up and down without tipping the camera
Roll is not the only way to spoil a line of constant depth. Tipping the camera to look down spoils a different one.
Tip the axis down and the floor’s rows survive. A tilt turns the camera about its own horizontal axis, and a line on the floor parallel to that axis keeps every point at one depth whatever the tilt, so its image is still a line of constant depth, still a row. The figure confirms it: the floor’s rows are exact at every tilt.
A wall’s columns do not survive. A vertical line on the wall has its top and bottom at different depths once the axis is tipped, and its image is no longer a column but a line leaning toward a vertical vanishing point below the frame. Stepping down it linearly puts the worst texel 0.23 px out at 1°, 0.46 at 2°, 1.14 at 5° and 2.27 at 10°.
There is a second way to look down, and it costs nothing. Keep the camera’s axis level and move the principal point up the frame instead, so that the frame shows more of what is below the horizon and less of what is above. Every line of constant depth is exactly where it was, because nothing about the camera’s orientation has changed — the frame is simply a different window onto a level camera’s picture plane. The figure measures every column at 0 px at every angle, and the floor’s rows likewise.
For a drawing, that is the separation the centre of the picture is not the centre of the paper makes between the point where the eye’s axis meets the picture and the middle of the sheet: move the sheet and not the axis, and a tall building drawn from its foot keeps its verticals parallel. For a camera it is a shifted lens, and the principal point is not the centre is the same fact read back from a photograph. It is not the same picture as a tipped camera’s. Straightening does not move the eye found that a tilt is a homography of the level picture; that homography keeps the floor’s rows as rows but carries a wall’s columns into lines that lean. A shifted principal point is a translation of the picture, and a translation carries every row to a row and every column to a column.
What each choice buys
Put the three pieces together and the picture a renderer can draw without dividing per pixel is exactly described.
Floors and ceilings, level, stepped in rows — and a ceiling costs nothing extra, because a plane parallel to the floor has the floor’s line at infinity and so the same vanishing line, the horizon, however high above the eye it is. Its rows run above the horizon rather than below it, at depths set by its own height over the eye instead of the eye’s height over the floor, and they are lines of constant depth for the same reason. Walls, vertical, stepped in columns. A camera that turns about the vertical freely, because that turn keeps floors’ rows at constant depth and walls’ columns vertical; that never rolls, because a hundredth of a degree of roll costs the far floor a pixel; and that looks up and down by moving the principal point rather than by tipping, because a tip spoils the columns and a shift does not. The price of that last choice is visible in the picture: verticals never converge, and a view straight down a tall wall looks like an architect’s elevation rather than a photograph.
Outside that description every surface needs its depth at every pixel. The division a texture does not interpolate on the page derived — interpolate and and divide at the end — is exact for every surface in every direction, and it is what a renderer does once a division per pixel is cheap. The constant-depth walk is exact only on its own lines. But on them it is exact in exactly the same sense, to the rounding of a double, and its cost is one division per line rather than one per pixel — a 690-pixel scanline divided once instead of 690 times.
What the two routes share is the reciprocal of depth. The per-pixel route interpolates it because it is what the page is linear in, the fact depth is a reciprocal stated for a pair of cameras. The constant-depth route holds it fixed along a line so that it does not need interpolating. Both are ways of never stepping the depth itself across the page.
What this does not settle
Planes only. A curved surface has lines of constant depth, but they are curves on the page, and stepping along a curve is not stepping along a scanline or a column. Nothing here measures how a curved surface fares.
Continuous spans. Every span is a line segment with exact endpoints. A renderer draws pixels, and a span along a tilted direction visits them in a staircase; the error of snapping such a span to the pixel grid is a different error from the one measured here, and was not drawn.
Position, not filtering. The texel error is where a texel lands. Which texels are blended to colour a pixel, and how the blend changes along a span as the texture’s footprint shrinks with depth, is a sampling question outside this geometry.
Still open: a banked floor stepped along tilted spans
The banked floor is exact along lines tipped by its bank, so a renderer can walk it without division by stepping along those tilted lines instead of along scanlines. The page, though, is made of rows. A span at 20° crosses a new row every three pixels, and neighbouring spans must tile the surface between them without gaps or double-drawn pixels.
The question that leaves is what that staircase costs: whether snapping tilted constant-depth spans to the pixel grid leaves a texel error smaller than the 13.26 px a row-walk makes on the same banked floor, how that error depends on the bank angle and the depth, and at what bank a per-pixel division is cheaper than the bookkeeping of tilted spans.
Shares its objects with
Essays that name at least two of the same things, and that neither author linked.
- A drawing has three horizons — both name horizon, principal point, vanishing line
- A lamp behind the camera — both name depth division, homogeneous coordinates, horizon
- A lens destroys the invariant — both name horizon, principal point, projective invariant
- An angle is a cross-ratio — both name homogeneous coordinates, horizon, projective invariant
- Four marks before anything is said — both name horizon, projective invariant, transversal
- The diagonals find the middle — both name depth division, projective invariant, transversal
Named objects
A flat tag is an object no other essay names yet.
Depth divisionForeshorteningHomogeneous coordinatesHorizonPrincipal pointProjective invariantShift lensTransversalVanishing line