vidar.games

Hex-tiling anti-tiling

2026-10-31 · Discuss on X

Same 3 m ground texture on both halves of this field.
Left: plain tiling. Once the camera rises, the grid shows.
Right: hex-tiling. Every hex cell reads the texture with its own offset and rotation.

The problem

Any tiled texture repeats. Up close you don't notice. Raise the camera and a 3 m ground texture becomes a grid of the same moss patch and the same 2 big pebbles. The left half is plain tiling.

How it works

Hex-tiling (Mikkelsen, JCGT 2022) lays a hexagon grid over the UVs.

  1. Each pixel finds the 3 nearest hex centres and barycentric weights for them.
  2. Each hex cell gets its own random offset and rotation, so it reads a different part of the texture at a different angle.
  3. The 3 reads blend together. The weights are raised to the 7th power, so cell interiors show 1 read and only the borders mix.
  4. Weights also lean on luminance (contrast 0.6), so bright features win at borders instead of fading into grey.

Normal maps go through the same 3 reads, but blended as surface gradients and rotated back into place, so the lighting stays correct.

What I hit

The source is HLSL with row-major float2x2 matrices. GLSL mat2 is column-major, so every mul() needed its order checked by hand, one call at a time.

I painted the test texture with large, distinctive features on purpose. A busy noise texture hides the repeat on its own and the comparison would look weaker than it is.

My build

three.js 0.170, ported into MeshStandardMaterial with onBeforeCompile. Own procedural 1024² soil texture with moss, a wet patch and 36 pebbles, plus a normal map from its height. Hex cells come out about 0.87 m wide with the 3 m tile. Same camera on both halves, rendered twice with a scissor.

Trade-offs

When to use it

Large ground, rock and sand surfaces seen from far away. For directional textures, keep the offsets and drop the rotation.

New breakdowns go out on X first: @vidar_0208. If this one helped, you can buy me a coffee.

Source and credits

Technique: Practical Real-Time Hex-Tiling by Morten S. Mikkelsen (JCGT 2022), building on Heitz & Neyret and Deliot & Heitz.
Repo: github.com/mmikk/hextile-demo (MIT license)

Code: I ported TriangleGrid, LoadRot2x2, MakeCenST, hex2colTex, bumphex2derivNMap and ProduceHexWeights from hextile-demo/hextiling.h (HLSL) to GLSL in three.js. The ground texture, rocks and scene are my own; no textures, models or screenshots from the repo.

Topic inspired by @toreler's anti-tiling posts. TileShuffle (paid Fab product) code and assets were not used.