Command Palette

Search for a command to run...

Hectal
Course outline
Topic 6.2Intermediate ~19 min · step 2 of 7

UV Wrapping, Repeat and Offset

In one line

UV coordinates say which point of the picture lands on which point of the shape. wrapS, wrapT, repeat, offset, rotation and center decide what happens outside 0 to 1 and how the picture is stretched, tiled and moved.

0/7 · 0%

Think of it like this

Wrapping a present. The paper is a flat sheet with a pattern. How you lay it on the box decides where the pattern lands: shifted, turned, or repeated if you use a small sheet many times. The box does not change; only the laying does.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

UV
Two numbers per vertex: where on the picture this corner of the shape sits. u is across, v is up.
wrap mode
The rule for a UV outside 0 to 1: clamp to the edge, repeat, or repeat mirrored.
repeat
How many times the picture fits across u and v. It scales the UVs.
offset
How far the picture is shifted, in UV units (1 = the whole picture).

Step by step

01Look at the layout

In the UV viewer pick the plane, then the cylinder. The plane's UVs are a flat square; the cylinder's unroll to a long strip, with a seam where the strip's ends meet.

02Set the wrap mode first

Set wrapS and wrapT to THREE.RepeatWrapping before you change repeat. With the default clamp, any repeat above 1 shows a smear.

03Choose repeat from real sizes

Divide the shape's size by the size one picture should cover. For the tyre: 2.07 m ÷ 0.07 m is about 30 round, 0.138 m ÷ 0.07 m about 2 across.

04Move it with offset

Add a number to offset.x each frame, wrapped with % 1. The picture slides along u: round a tyre, that looks like the tread rolling.

05Turn it around the middle

Set center.set(0.5, 0.5) before rotation. Without it the picture swings round its corner and slides away. Read the matrix in the second example to see it.

Try it yourself

  1. 1

    Square tiles

    In the tyre example change both repeat.set(30, 2) lines to repeat.set(30, 8). The chevrons squash into thin zigzag stripes: each tile is still 7 cm long but only 1.7 cm high (0.138 m ÷ 8). Tiles are square only when repeat x ÷ repeat y is about 15 here (2.07 ÷ 0.138).

  2. 2

    Turn without a centre

    Delete tread.center.set(0.5, 0.5); from the third row's change. The matrix ends 0.25 0 1 instead of -0.25 1 1: the picture now turns round its bottom-left corner, so it moves as well as turns.

Code & diagrams

Try it: interactive

UV viewer

Pick each shape and read the UV layout beside it. Try Repeat 3 with each wrap mode, then switch on Nearest and mipmaps.

Three wrap modes, same picture New tab

The "F" shows what happens. Clamp: one small F and a smear of edge pixels. Repeat: four copies. Mirrored: copies flipped like a book.

idle

Console

Run the scene to see its console.

Expected console output

ClampToEdgeWrapping (default)  | wrapS: 1001 | repeat: 2, 2
RepeatWrapping                 | wrapS: 1000 | repeat: 2, 2
MirroredRepeatWrapping         | wrapS: 1002 | repeat: 2, 2
A tread on a tyre: repeat, offset, rotation New tab

A tread tile drawn with a canvas (a canvas is as good a texture source as a file). The tyre is 2.07 m round, so repeat (30, 2) gives about 7 cm tiles. The tread slides round the tyre. The matrix lines show that repeat sits on the diagonal, offset in the last column, and rotation mixes in.

idle

Console

Run the scene to see its console.

Expected console output

repeat (2, 1)                | matrix: 2 0 0 0 1 0 0 0 1
+ offset (0.25, 0)           | matrix: 2 0 0 0 1 0 0.25 0 1
+ rotation 90 deg at centre  | matrix: 0 -1 0 2 0 0 -0.25 1 1

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Repeat with the default wrap

In the first example change the second plane's mode THREE.RepeatWrapping to THREE.ClampToEdgeWrapping.

terminal
$ Run
── what you'll see ──
RepeatWrapping | wrapS: 1001 | repeat: 2, 2
The label is still typed as RepeatWrapping, but wrapS is 1001. The middle plane now looks like the left one: a single small F in the bottom-left corner and a plain blue smear everywhere else.

Myth vs fact

Myth

repeat.set(2, 2) makes the texture twice as big.

Fact

It makes the UVs twice as big, so the picture is half the size on the surface and appears four times.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Wrapping works for any size in WebGL 2. In WebGL 1 a texture with RepeatWrapping and mipmaps had to be a power of two (256, 512, 1024...). three.js r186 is WebGL 2 only, so 300 × 200 repeats and mipmaps fine; old tutorials telling you to resize pictures are out of date.

  • ▸

    A seamless tile still shows a visible pattern when it repeats many times. Mix two scales (one big, one fine) in a shader (Phase 12) or add a noise-based variation. For a tyre 30 tiles round, the repeat is fine because the block pattern is meant to repeat.

Remember this

  1. 1

    The problem this solves: a 1 m floor and a 20 m floor can use the same small picture if you tile it. A tyre needs a tread block repeated 30 times round. Without repeat and wrapping you get one huge blurry picture, or one small picture and a smear of edge pixels.

  2. 2

    UVs recap (Topic 4.5). Every vertex has a uv: two numbers, u across and v up, where (0, 0) is the bottom-left corner of the picture and (1, 1) the top-right. The GPU gives every pixel of a triangle an interpolated UV and reads the texture there. Open the UV viewer below to see the real layout on a plane, box, cylinder and sphere.

  3. 3

    Wrap modes decide what a UV outside 0 to 1 means. ClampToEdgeWrapping (the default) repeats the edge pixel for ever: with repeat at 2 you get one small picture and a smear. RepeatWrapping tiles it. MirroredRepeatWrapping tiles it and flips every other copy, hiding seams. wrapS is for u, wrapT for v; set both. The first example shows all three.

  4. 4

    **repeat is a scale, not a count of copies you chose.** repeat.set(30, 2) multiplies the UVs by 30 and 2, so 30 copies fit across u and 2 across v. To keep tiles square you need the shape's real size: a tyre is 2.07 m round and 0.138 m across, so (30, 2) gives tiles about 7 cm each way.

  5. 5

    **offset, rotation and center move the picture.** offset shifts it (a texture sliding round a tyre fakes rolling). rotation turns it in radians around center, which starts at (0, 0), the corner. Set center to (0.5, 0.5) to turn around the middle. All of it is stored in a 3 × 3 matrix, texture.matrix, which three.js rebuilds for you each time the texture is drawn (matrixAutoUpdate). The example calls updateMatrix() itself only because it reads the matrix before any frame.

  6. 6

    Every map has its own transform. In r186 map, normalMap and roughnessMap each use their own repeat, offset and rotation. If the colour tiles 30 times and the normal map does not, the bumps will not match the picture. Copy the same values to every map that shares a surface.

Explain it without notes

01

A floor texture shows one small picture and then a smear. What two things are missing?

02

Why does the rotation example need center.set(0.5, 0.5)?

Practice

01

A 4 m × 4 m floor uses a tile that should cover 0.5 m. Write the three lines that tile it.

02

How do you make a tyre's tread appear to roll at 1 turn per second, without turning the mesh?

Done when you can

  • Read a UV layout and say where (0, 0) and (1, 1) are

  • Tile a texture with RepeatWrapping and a repeat computed from sizes

  • Slide or turn a texture and read its 3 × 3 matrix

  • Say why every map needs the same repeat