Part XIV — 3D Vision, Neural Fields & Gaussian Splatting · Chapter 2

Camera projections & ray casting

Hook

A camera sensor is flat. The world isn't. How does a point floating five meters in front of a lens turn into one specific pixel on a flat grid?

Intuition
world: Z = 5.0, Y = 2.0 (X = 0)
image plane: (u, v) = (50, 90)

Drag the world point. Push it further away (larger Z) and its image-plane dot creeps back toward the center — the same real-world displacement covers less of the frame the farther away it happens. That shrinking-with-distance effect is perspective, and it's the whole reason a camera needs more than a ruler to describe.

Formalize

A pinhole camera projects a 3D point onto the 2D image plane in two stages. First, extrinsics move the point from world coordinates into the camera's own frame — for a camera at center CC with no rotation, that's just a subtraction:

Pcam=PworldCP_{\text{cam}} = P_{\text{world}} - C

Then intrinsics turn the camera-space point into a pixel: divide by depth to get the perspective effect, then scale by focal length ff and shift by the principal point (cx,cy)(c_x, c_y):

u=fXZ+cx,v=fYZ+cyu = f\cdot\frac{X}{Z} + c_x, \qquad v = f\cdot\frac{Y}{Z} + c_y
  • PworldP_{\text{world}}, CC — the 3D point and the camera's center, both in world coordinates.
  • Pcam=(X,Y,Z)P_{\text{cam}} = (X, Y, Z) — the same point re-expressed relative to the camera.
  • ZZ — depth: distance in front of the camera along its viewing axis.
  • ff — focal length, in pixels: how strongly the camera magnifies the scene.
  • (cx,cy)(c_x, c_y) — the principal point: the pixel where the camera's forward axis itself lands.
  • (u,v)(u, v) — the resulting pixel coordinates on the image plane.
  1. Extrinsics: world to camera

    With the camera sitting at the world origin, Pcam=PworldP_{\text{cam}} = P_{\text{world}} exactly — the world point (1,1,5)(1, 1, 5) is already in camera coordinates.

  2. Perspective divide

    Divide by depth: X/Z=1/5=0.2X/Z = 1/5 = 0.2 and Y/Z=1/5=0.2Y/Z = 1/5 = 0.2. This is the step that makes farther points shrink toward the center — the same XX produces a smaller ratio at larger ZZ.

  3. Intrinsics: scale and shift

    With f=100f = 100 and (cx,cy)=(50,50)(c_x, c_y) = (50, 50): u=100(0.2)+50=70u = 100(0.2) + 50 = 70 and v=100(0.2)+50=70v = 100(0.2) + 50 = 70. The point lands at pixel (70,70)(70, 70).

Play
Y/Z = -2.0 / 5.0 = -0.40
v = f·(Y/Z) + cy = 100 × -0.40 + 50 = 10.0

Drag the point and watch Y/ZY/Z directly — it's the single number that decides vv once ff and cyc_y are fixed. Push YY far negative or ZZ close to the camera and Y/ZY/Z blows up, sending the point flying off the edge of the frame.

Worked example

Two more points through the same camera (f=100f = 100, cx=cy=50c_x = c_y = 50):

  1. P = (2, -1, 4), camera at the origin
    • Perspective divide: X/Z=2/4=0.5X/Z = 2/4 = 0.5, Y/Z=1/4=0.25Y/Z = -1/4 = -0.25
    • Scale and shift: u=100(0.5)+50=100u = 100(0.5) + 50 = 100, v=100(0.25)+50=25v = 100(-0.25) + 50 = 25

    Pixel (100,25)(100, 25).

  2. P = (3, 1, 5), camera moved to C = (1, 0, 0)
    1. Extrinsics: Pcam=(3,1,5)(1,0,0)=(2,1,5)P_{\text{cam}} = (3, 1, 5) - (1, 0, 0) = (2, 1, 5)
    2. Perspective divide: X/Z=2/5=0.4X/Z = 2/5 = 0.4, Y/Z=1/5=0.2Y/Z = 1/5 = 0.2
    3. Scale and shift: u=100(0.4)+50=90u = 100(0.4) + 50 = 90, v=100(0.2)+50=70v = 100(0.2) + 50 = 70

    Pixel (90,70)(90, 70) — moving the camera changed the pixel even though the world point never moved.

Checkpoint

Drag the world point until its projected image coordinate reads v ≈ 90.

v = -10.0
Drag the world point to try it
Summary
u=fXCxZCz+cx,v=fYCyZCz+cyu = f\cdot\frac{X - C_x}{Z - C_z} + c_x, \qquad v = f\cdot\frac{Y - C_y}{Z - C_z} + c_y

Every pixel a camera reports is the result of two matrices: extrinsics place the world relative to the camera, intrinsics turn that relative position into a pixel via perspective divide. The next chapter looks at what's on the other side of that projection — the raw 3D data a scene gets represented as before any camera ever looks at it.