What a machine computes

The near plane can be any plane

Rewrite one row of a projection matrix and the near plane stops being perpendicular to the axis and becomes whatever plane is asked for. Every x and every y is untouched — it is the same projection of the same scene from the same eye — and the depth order is wrecked, which is a clean separation of the two things a projection matrix does.

Worth reading first: What happens behind the eye · Four numbers and a window.

What happens behind the eye is about why a renderer clips before it divides: a point behind the camera has a perfectly plausible image, landing through the principal point on the far side of the frame, and a segment crossing the eye plane is drawn straight, inside the frame, and running in exactly the opposite direction.

The clip is done by the third row of the projection matrix, which maps a point’s depth into a code and lets the clipper compare it against a bound. The row is written to make that bound the near plane, perpendicular to the optical axis at a chosen distance.

It does not have to be perpendicular, and it does not have to be the near plane.

Clip space: the box the frustum becomes, and the plane the segment stops atA plan section through the frustum. The segment runs from 6.60 m in front of the eye to 2.99 m behind it, and the clipper stops it on the near plane at 0.40 m. Clipping happens here, before the divide, because both ends are still finite numbers at this stage.near 0.4 mtoward the far planethe eyein front3.0 m behind the eyeclipped hereeverything below the eye's line has a negative w, and dividing by it flips both signsplan section · near 0.4 m, far 26 mthe segment crosses the eye plane at t = 0.647
Fig. 1 Clip space, which is where the row does its work. A point behind the eye is a perfectly good finite point here, and the clip happens before the divide can ruin it.

One row, rewritten

The clip test is that a point survives when its clip-space z is at least −w. So a third row of the form

row=kplanew\text{row} = k\,\mathbf{plane} - \mathbf{w}

clips exactly on the plane, for any positive k: the test becomes k·(plane · P) ≥ 0, which is the plane’s own inequality.

The w row of this collection’s matrix is (0, 0, 1, 0), so the subtraction lands on the third entry. Writing it on the fourth instead gives a matrix that clips on a plane parallel to the one asked for — and passes every check about where marks are, since the first two rows are untouched either way. That is how it was first written.

The scale k is not free. Fixing it by requiring the far plane to stay where it was, read on the optical axis, is one equation with one root.

The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 18° to the axis: 24 points survive the clip and 26 do not, and no ruler laid on the picture can tell which is which.26 kept · 24 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 18°
Fig. 2 A scene with an oblique near plane. Filled marks survive the clip, hollow ones do not, and no mark has moved.
The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 18° to the axis: 34 points survive the clip and 16 do not, and no ruler laid on the picture can tell which is which.34 kept · 16 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 18°
Fig. 3 The plane slid toward the eye. More of the scene survives, and every surviving mark is exactly where it was.

The picture does not move at all

Not by a small amount: by zero. Every point’s pixel is identical, bit for bit, because the first two rows of the matrix were not touched and nothing else in the pipeline reads the third.

Half the scene is being discarded and no ruler laid on the picture can say which half. The marks that survive and the marks that do not are interleaved across the frame, because the plane cuts the scene in depth and the frame is a picture of a three-dimensional arrangement.

That is the separation this essay is for. A projection matrix does two things — it says where a point goes, and it says whether and in what order the point is kept — and the two live in different rows. Everything the foundations field is about is the first. Everything the near and far planes are about is the second. Rewriting the third row exercises the second without touching the first, which is as clean a demonstration of the split as the machinery admits.

The same grid, clipped and not: straight lines running the wrong wayA ground grid extending 2.4 m behind the eye. Clipped, the lines stop at the near plane. Unclipped, the parts behind the eye are divided by a negative w, which flips both signs and lands them through the principal point on the far side — straight, inside the frame, and reversed. The direction cosine of the two drawings of one segment is -1.0000.clipped at the near planedivided without clippingdirection cosine -1.0000 — the far end is drawn 2142 px away20 grid segments, 2.4 m of them behind the eyea reversed line is not a large error, it is a different picture
Fig. 4 What the ordinary near clip is protecting against: dividing by a negative fourth coordinate flips both signs and lands the point through the principal point on the far side of the frame.

Which half survives, and how it is stated

The plane is given as four numbers, (a, b, c, d), in the camera’s own coordinates, with the surviving half-space the one where a·x + b·y + c·z + d is positive. That sign convention is arbitrary and negating all four numbers keeps the same plane and swaps the halves, which is a thing worth checking rather than assuming: a construction that quietly kept the wrong side would look exactly like one that kept the right side of a plane facing the other way.

Two further conditions are needed and both are checkable. The plane has to have a direction — the first three numbers cannot all be zero — and it has to cross the axis in front of the far plane, or the scale that keeps the far clip in place has no positive root. The second is the interesting one: it is the arrangement in which the plane misses the frustum entirely, and the honest answer is that there is no oblique row to write, not that there is one that does nothing.

Where the plane is perpendicular to the axis, the rewritten row reduces to the ordinary one with the near plane moved, which is the sanity check that costs nothing and is worth having. The construction contains the thing it generalises.

The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 30° to the axis: 19 points survive the clip and 31 do not, and no ruler laid on the picture can tell which is which.19 kept · 31 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 30°
Fig. 5 A more steeply tilted plane. The cut through the scene is nearer to a cut by height than by depth, and the reversal rate rises with it.
The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 18° to the axis: 17 points survive the clip and 33 do not, and no ruler laid on the picture can tell which is which.17 kept · 33 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 18°
Fig. 6 And one more position, to make the point that the picture is a bystander to all of this.

What it costs

The third row was doing something before it was rewritten, and it was doing it well. Mapping depth to a code that is monotone in distance is what lets a buffer decide which of two surfaces is in front.

The oblique row is not a function of the distance along the axis. It is a function of the distance from the plane, and two points at the same distance from the eye at different heights are at different distances from a tilted plane. So the stored depth no longer orders the scene by depth.

What the oblique clip costsThe stored depth against the true distance, for the ordinary matrix and for the same matrix with an oblique near plane. The ordinary one is a function of the distance and nothing else, so it orders the scene. The oblique one is not a function of it at all — two points at the same distance store different depths, because the row now measures the distance from the plane — and 10.3% of pairs come out in the wrong order.-3-2-10146810distance along the optical axis (m)the depth the buffer stores9.7% of pairs reverseda function of distanceand one that is not
Fig. 7 The stored depth against the true distance, for the ordinary matrix and for the same matrix with an oblique near plane. One is a function of the distance and one is not.

Measured over a scene of scattered points, about a tenth of all pairs come out in the wrong order. Not a rounding: a tenth of every comparison the depth buffer would make, reversed.

For the ordinary matrix the figure is zero by construction, because the row is an affine function of one over the distance and an affine function of a monotone function is monotone. That control is what makes the tenth a measurement rather than an artefact of the sampling.

The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 18° to the axis: 14 points survive the clip and 36 do not, and no ruler laid on the picture can tell which is which.14 kept · 36 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 18°
Fig. 8 The plane slid away. Fewer marks survive; none of them has moved; nothing about the framing has changed.

The plane a reader can move

Moving the plane along its own normal changes only which points survive, and watching that happen is the clearest statement of the split.

Slide it toward the eye and more of the scene is kept; slide it away and less. The marks that remain are in precisely the positions they were in at every step — there is no shifting, no rescaling, no change of framing — and the count changes. A reader watching the figure move is watching a picture in which nothing moves and the contents change, which is not an experience the rest of this collection offers.

Tilting it does the same thing with a different cut. A steeply tilted plane divides the scene by something close to height; a shallow one by something close to depth. In every case the surviving marks are unmoved and the discarded ones simply are not drawn.

That is worth doing once because the natural expectation is the opposite. A near plane is usually met as the thing that makes objects disappear when a camera gets close to them, and the disappearance feels like an event in the picture. It is not; it is an event in the set of things being drawn, and the picture is a bystander.

Where a depth buffer's codes actually goThe share of a 24-bit buffer used up within each distance, for a near plane at 0.1 m and a far plane at 1000 m. Ninety per cent of the range is spent inside the first metre; the last nine hundred metres share what is left.near 0.1 m · far 1000 m · 24-bit codeswithin 20 cm50.0%within 50 cm80.0%within 1 m90.0%within 5 m98.0%within 50 m99.8%half the codes are gone by 0.20 m — the harmonic mean of the two planesshare of the depth buffer used up within each distancearithmetic midpoint would be 500 m
Fig. 9 What the row was doing before it was rewritten: mapping depth into a code that is monotone in distance, so that a buffer can decide which of two surfaces is in front.

What it is for

The construction is not a curiosity, and the case it exists for is one this site already has in a different field.

A mirror in a scene is rendered by reflecting the camera through the mirror’s plane and drawing the scene again — which is exactly a mirror is a second camera, where a reflection is computed by reflecting the scene and by reflecting the camera, and the two agree once one image axis is reversed. The reflected camera sees the whole room, including everything behind the mirror, which must not appear in the reflection.

The thing that must not appear is bounded by the mirror’s own plane, which is at an arbitrary angle to the reflected camera’s axis. So the clip needed is exactly an oblique near plane, and the alternative — clipping the geometry against the plane before drawing it — is more work and has to be redone whenever anything moves.

The same shape of problem arrives with a portal, a doorway, a window cut in a wall, or any arrangement in which one part of a scene is visible only through an opening in another. In each case the boundary is a plane in the world and not a plane the camera chose.

A box over a reflecting floor, with the reflection computed twiceReflecting the scene and reflecting the camera disagree by 315 px and agree to 0e+0 px once one image axis is reversed — which is what a mirror reversing handedness looks like in numbers.grey: the reflectiontwo routes, agreeing to 0e+0 px after one flip
Fig. 10 The construction the oblique clip exists to serve. A reflection is the view from a camera on the far side of the mirror, and the two routes to it disagree until one image axis is reversed.

And the reflection has one more twist in it

A mirror rendered this way carries a second consequence the collection has already measured, and it is worth joining up.

The reflected camera is a camera on the far side of the mirror plane, and a reflection reverses handedness — so the reflected camera’s basis is left-handed where the original’s was right-handed. A mirror is a second camera records what happens when that is missed: the two routes to a reflection, reflecting the scene and reflecting the camera, disagree by hundreds of pixels until one image axis is reversed.

That reversal and the oblique clip are independent and both are needed. The reversal is about which way the picture runs; the clip is about what is in it. A renderer that reflects the camera, gets the handedness right and forgets the clip draws the room behind the mirror as though it were in front of it — the mirror shows the wall it is hanging on. A renderer that clips correctly and forgets the handedness draws the right things, mirrored.

The two failures look nothing alike, which is fortunate, and they arise from the same operation, which is why they are usually met together.

The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 6° to the axis: 25 points survive the clip and 25 do not, and no ruler laid on the picture can tell which is which.25 kept · 25 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 6°
Fig. 11 A nearly perpendicular plane, where the construction reduces to the ordinary near clip with the plane moved and the depth order is nearly intact.
A mirror ball 2.00 m across, and the point its lines of sight missThe backward continuations are drawn to the point that fits them best. They miss it by up to 2.46 mm — over 20 cm of mirror, so a photograph of this ball is a projection of nothing from anywhere.eyethe best fit — no ray goes through itno single viewpoint — the rays miss by 2.46 mmover 20 cm of a 2.00 m ball
Fig. 12 The case a flat mirror is not: a curved one, whose reflected rays pass through no common point at all, so there is no second camera to build and no plane to clip against.

And why the cost is acceptable there

A tenth of depth comparisons reversed sounds fatal and is not, in the case the construction is for, and the reason is worth having because it is a good example of a cost that is real and irrelevant.

Behind a mirror or through a portal, the visible scene is entirely on one side of the plane, and it is bounded. The depth range that has to be ordered is the range from the plane outward, not from the eye outward — and the reversals counted above are between points on opposite sides of a tilt, most of which are not both in the visible set.

The residual cost is a loss of precision rather than of order: the codes are no longer spread over the range the way the ordinary row spreads them, so nearby surfaces are harder to separate. That is the ordinary depth-buffer complaint, and the precision a depth buffer has left prices it in the ordinary case. Here it is worse by a factor that depends on the tilt, and it is worse in a way that shows up as flickering between two coplanar surfaces rather than as objects appearing through each other.

A frustum is four numbers and a windowThe camera's own section, looking down on it. The two slanted lines are the left and right sides: divide either by the near plane and it is a direction, -0.4663 and 0.4663, which between them carry the focal length 739.9 px and the principal point 345. The two crossbars are the near and far planes, and moving either of them moves no mark in the picture at all.the eyenear 0.90 mfar 4.20 mfocal 740 pxprincipal 345, 210
Fig. 13 The frustum the row belongs to. The two crossbars are what the third row normally encodes; an oblique plane replaces the near one and leaves the four sides alone.

Read as a change of what the picture is a picture of

There is a way of describing the oblique clip that makes both its virtue and its cost obvious at once, and it is the description this collection’s premise suggests.

Every picture on this site states the point it is correct from. The oblique clip does not change that point, does not change the focal length, and does not change the window — so the picture is correct from exactly where it was. What it changes is the scene: the arrangement being projected is now the original with a half-space removed.

So the honest reading is that the matrix is projecting a different scene from the same eye, and the depth row has been spent on saying which scene rather than on ordering it. A projection matrix cannot do both jobs with one row, and the choice of which to do is the whole of the construction.

That framing also says what would happen if the clip were done the other way, by cutting the geometry against the plane before drawing it. The picture would be identical, the depth ordering would be intact, and the cost would be moved from the matrix to the scene — which is exactly the trade, and is why the matrix version is preferred wherever the scene is large and the plane moves.

There is a third reading available too, and it is the one that connects this essay to the field’s own premise. A frustum is a window; an oblique near plane is a second window, at an angle, cut into the same view. The picture is what the eye sees through both, and the second window is the mirror’s frame or the portal’s opening. Nothing about that description needs a matrix, and it is the description a person in the room would give.

The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 18° to the axis: 29 points survive the clip and 21 do not, and no ruler laid on the picture can tell which is which.29 kept · 21 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 18°
Fig. 14 A third position of the plane, for a reader wanting to see the count change while nothing else does.

The check, and the two things it has to say

Three claims, and each one fails differently if the row is wrong.

No point moves. If a mark shifts by even a fraction of a pixel, something has leaked out of the third row into the first two, which in a hand-written matrix is entirely possible.

Points on the wrong side really are dropped, and points on the right side really are kept. Both halves, because a row that clipped everything or nothing would satisfy the first claim perfectly.

And the order is genuinely disturbed. If the reversal rate came out at zero, the row would be a re-parametrisation of the original rather than the oblique clip it claims to be — and there is a version of the construction, the one that subtracts on the fourth entry, that produces exactly that.

The third claim also needed its own convergence check, and it got one in the collection’s convergence gate. A rate computed over a scattering of points is a statistic, and a statistic taken over forty points and over nine hundred has to settle before it can be quoted. It does, within a few tenths of a per cent, which is what says the tenth is a property of the arrangement rather than of the sample.

What the oblique clip costsThe stored depth against the true distance, for the ordinary matrix and for the same matrix with an oblique near plane. The ordinary one is a function of the distance and nothing else, so it orders the scene. The oblique one is not a function of it at all — two points at the same distance store different depths, because the row now measures the distance from the plane — and 14.6% of pairs come out in the wrong order.-3-2-10146810distance along the optical axis (m)the depth the buffer stores14.6% of pairs reverseda function of distanceand one that is not
Fig. 15 The stored depth at a steeper tilt. The scatter is wider and the share of reversed pairs is higher, which is the cost stated in the only currency the row has.
What a depth buffer can still resolve, against distanceΔz = 2z²/(N|B|) — quadratic in distance, so the resolution at 100 m is ten thousand times coarser than at 1 m. At the near plane it is 0.0 µm and at 100 m it is 6.0 mm.-8-6-4-20-10123distance from the eye — log₁₀ metresdepth separation the buffer can still resolve, log₁₀ metres (24-bit)1 m → 0.6 µm100 m → 6.0 mmnear 0.1 m, far 1000 m, 24-bit codesquadratic in distance
Fig. 16 Where the codes are spent, which is what an oblique row redistributes. The near end is where the precision is, so a row rewritten for a near boundary disturbs the region that mattered.

The far plane could have been the oblique one instead

Symmetry is worth checking, and here it half holds.

The same rewriting could be aimed at the far clip rather than the near one — a plane beyond which nothing is drawn, at an arbitrary angle. The arithmetic is the mirror image and the scale would be fixed by holding the near plane instead.

What is not symmetric is the cost. The near plane is where a depth buffer spends most of its codes, so a row rewritten to serve the near clip disturbs the region the precision was concentrated in. A row rewritten for the far clip would disturb the far region, where the codes are already spread thin and the ordering already coarse — so the same trick costs much less there.

It is also wanted much less. The cases the construction exists for are all near boundaries: a mirror’s surface, a portal’s opening, a wall the camera is looking through. Nothing common is bounded by an arbitrary plane at the far end. So the asymmetry in the cost and the asymmetry in the demand point opposite ways, which is a mildly unfortunate arrangement and is the situation.

One projection, two routes: divide by depth, or multiply and divide laterThe same box through the site's pinhole and through a 4×4 projection matrix with the divide postponed until after clip space. The worst disagreement over all twelve edges is 4.0e-14 px, which is the noise floor of double precision rather than an approximation.x/z, y/z — the pinholeM·p, then divide by wworst disagreement 4.0e-14 px over 8 verticescorrect from 21 cm, at 160 mm wide42° across · near 0.1 m, far 1000 m
Fig. 17 The agreement the whole construction is measured against: the matrix and the pinhole put every point on the same pixel, so a claim that no point moved is a claim about the matrix rather than about the drawing.
The same picture, a different set of pointsEvery mark is where the ordinary matrix put it, to 0e+0 px — the first two rows of the matrix were not touched. What changed is the third row, which now reads a plane tilted 12° to the axis: 25 points survive the clip and 25 do not, and no ruler laid on the picture can tell which is which.25 kept · 25 clipped · every mark unmovedcorrect from 17 cm, at 160 mm wideclip plane tilted 12°
Fig. 18 A gentle tilt, where the row is close to the ordinary one and the reversal rate is correspondingly low.

What the row can and cannot be made to do

One limit is worth naming, because the construction looks more general than it is.

The row clips on a plane and only on a plane. It cannot clip on a sphere, a cylinder, a box or any other surface, because a row of a matrix applied to a homogeneous point is a linear form and a linear form’s zero set is a plane. Everything else has to be done by cutting the geometry or by discarding points later.

And there is exactly one such row. A matrix has one third row, so one oblique plane is available, and a scene needing two — a portal seen through a mirror — needs the second one handled another way. That is a hard limit rather than an implementation detail: the projection matrix has four rows and three of them are spoken for.

Which is a small illustration of the accounting four numbers and a window sets out. The matrix is a fixed budget of numbers, each with a job; taking one over for something else means the original job is not being done. Here the original job was ordering the scene, and about a tenth of it is gone.

Shares its objects with

Essays that name at least two of the same things, and that neither author linked.

Named objects

A flat tag is an object no other essay names yet.

Camera matrixClip spacedegrees of freedomDepth divisionHomogeneous coordinatesMirror planeOcclusionQuantisationReflectionView frustum