Skip to content
Texture Sampling
step 1/5

Reading — step 1 of 5

Read

~2 min readRasterization

Texture Sampling

A texture is a 2D image addressed by UV coordinates in [0, 1]: (0, 0) is one corner, (1, 1) the diagonally opposite one. To shade a pixel, you read the texel at the vertex-interpolated UV.

Getting from UV to pixel color sounds trivial — multiply by width/height, round, look up. The actual quality details:

Wrap mode: what happens when UV goes outside [0, 1]?

  • REPEAT: u = u mod 1 (tiles).
  • CLAMP: u = clamp(u, 0, 1) (stretches edges).
  • MIRROR: alternates direction each unit.

Filter mode:

  • Nearest: tex[int(u * W)][int(v * H)]. Sharp / pixelated. Right for retro games and pixel art.
  • Bilinear: weight the four nearest texels by distance from the sample point. Smooth, no Moiré on slow camera motion.

Bilinear formula:

fx = u * W - 0.5            # texel center is at +0.5
fy = v * H - 0.5
x0 = floor(fx), x1 = x0 + 1
y0 = floor(fy), y1 = y0 + 1
ax = fx - x0
ay = fy - y0

c00 = tex[y0][x0]
c10 = tex[y0][x1]
c01 = tex[y1][x0]
c11 = tex[y1][x1]

top    = lerp(c00, c10, ax)
bottom = lerp(c01, c11, ax)
sample = lerp(top, bottom, ay)

(Apply wrap mode to x0, x1, y0, y1 before lookup.)

Mipmaps: pre-filtered downsamples of the texture (tex/2, tex/4, tex/8, ...). When a triangle is far away, sampling the full-resolution texture aliases; instead you sample the mip level whose texel size matches the projected pixel size. mip_level = log2(max(d(u)/dx, d(v)/dy)) — derivatives the GPU computes automatically from the 2x2 pixel quad.

Anisotropic filtering: when a triangle is heavily foreshortened (a floor receding to the horizon), a normal mipmap blurs along the axis perpendicular to view. Aniso samples multiple texels along the elongated direction. 16x aniso is the high-end gold standard.

For now: nearest and bilinear with REPEAT wrap — enough to see textures on triangles.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…