API

Texture Repetition

The Problem

When the same texture is tiled many times across a large surface, the human eye picks up the repetition very quickly — what should look like a continuous patch of grass, sand, or rock turns into an obvious grid pattern. The screenshot below shows this: a 5×5 tiling of the same grass.png texture, with the grid clearly visible.

Default tiling — repetition is visible

Starting with Babylon.js v9.7.0, every material exposes a textureRepetitionMode property that can apply one of four repetition-breaking techniques to all the surface textures (albedo / diffuse, bump, ambient, specular, emissive, etc.) sampled by the material.

Quick Start

import { Constants } from "@babylonjs/core/Engines/constants";
import { PBRMaterial } from "@babylonjs/core/Materials/PBR/pbrMaterial";
import { Texture } from "@babylonjs/core/Materials/Textures/texture";
const mat = new PBRMaterial("mat", scene);
mat.albedoTexture = new Texture("textures/grass.png", scene);
mat.albedoTexture.uScale = 5;
mat.albedoTexture.vScale = 5;
// Enable hex tiling — a good default that works on most textures
mat.textureRepetitionMode = Constants.TEXTURE_REPETITION_HEX_TILING;

That single property change is enough to break the visible repetition.

Available Modes

The property is a numeric enum on the Constants class. Modes are ordered by GPU cost (number of texture fetches per pixel):

ConstantFetchesVisual character
TEXTURE_REPETITION_NONE
1
Default tiling, no breaking.
TEXTURE_REPETITION_NOISE_BLEND
3
Two virtual offset patterns selected by a low-frequency noise lookup. Cheapest breaking mode.
TEXTURE_REPETITION_HEX_TILING
3
Hex-tile grid with per-tile rotation and luminance-weighted blending. Best visual quality for the cost.
TEXTURE_REPETITION_TILE_RANDOMIZATION
4
Per-tile random offset and mirror, blended at borders.
TEXTURE_REPETITION_VORONOI_BOMBING
9
Smooth Voronoi pattern with Gaussian-weighted blending. Highest quality.

Visual comparison

All shots below use the same UV scale, same camera, and same lighting.

ModeGrassRock
None
Noise blend
Hex tiling
Tile randomization
Voronoi bombing

Hex Tiling Parameters

The hex tiling mode (TEXTURE_REPETITION_HEX_TILING) is the only mode with user-configurable parameters. They are exposed as a single 4-component array, material.textureRepetitionHexTilingParams:

IndexParameterRangeDefaultDescription
[0]
Rotation strength
0..1
1.0
How much each hex tile is rotated. 0 disables per-tile rotation.
[1]
Fall-off contrast
0..1
0.6
How much the local luminance affects the blending weight at tile borders. Higher values produce sharper transitions.
[2]
Exponent
1..20
7.0
Sharpness of the weight falloff between adjacent tiles. Higher values make tile boundaries more distinct.
[3]
Contrast
0..1
0.5
Boosts the blending contrast (0.5 = neutral, >0.5 = higher contrast).
import { Constants } from "@babylonjs/core/Engines/constants";
mat.textureRepetitionMode = Constants.TEXTURE_REPETITION_HEX_TILING;
mat.textureRepetitionHexTilingParams = [1.0, 0.6, 7.0, 0.5];

The other three modes have no user-configurable parameters.

Materials Supported

The feature is implemented on the base Material class, but the actual shader work is done in:

  • StandardMaterial — affects diffuseTexture, bumpTexture, ambientTexture, specularTexture, emissiveTexture, opacityTexture, lightmapTexture.
  • PBRMaterial and PBRBaseMaterial subclasses — affects all surface textures including albedoTexture, bumpTexture, metallicTexture, reflectivityTexture, sheen, clear coat, anisotropy, iridescence, sub-surface, etc.
  • OpenPBRMaterial — same coverage as PBR plus OpenPBR-specific layers (coat, fuzz, thin film, transmission, sub-surface).

The following textures are intentionally not affected, even when a non-default mode is active:

  • decalTexture — decals are placed at specific positions, blending them across tiles would break that.
  • detailMap (the detail texture plugin) — it is itself a tiling-breaking helper; running it through another tiling-breaking pass is counter-productive.
  • The bump/parallax sampling for height (the .w channel of the bump texture used by parallax occlusion) — this read is structural, not surface color.
  • Reflection / refraction / environment cube samplers.

Live Demo

Texture Repetition Breaking — Interactive Demo

The demo lets you switch:

  • Material Type — Standard, PBR, OpenPBR.
  • Texture Set — grass, rock, or rocky ground (the rocky ground set's metalness/roughness map is only used by PBR / OpenPBR; Standard ignores it).
  • Repetition Mode — applied only to the right side of the split.
  • UV Scale — to see how the breaking holds up at different repetition densities.
  • Hex tiling parameters — when hex tiling is selected.

Drag the yellow vertical line with the mouse to slide the comparison.

Limitations

  • Normal maps with hex tiling: per-tile UV rotation is applied to the lookup, but the sampled normal vectors are not rotated to match. This can cause subtle directional artifacts on normal-mapped surfaces under strong directional lighting. The other modes (which don't rotate UVs) are unaffected.
  • WebGL 1: this feature is not supported on WebGL 1. The mode is silently forced to TEXTURE_REPETITION_NONE when the engine is WebGL 1.
  • Cost is per-pixel and per-texture: every active surface sampler in the material is replaced. A PBR material with albedo + bump + metallic + AO running in hex tiling mode performs 3× sampling work for each of those four maps. Use the cheaper modes (Noise Blend) for distant surfaces or large screens.
  • Texture must be tileable: the techniques break visible repetition, but they assume the source texture itself can be sampled outside the [0..1] UV range without seams. Use textures with wrapU / wrapV set to WRAP_ADDRESSMODE (the default).

Inspector

The Inspector v2 exposes the property under a "Texture Repetition" section in the material properties pane, including the four hex tiling parameter sliders that appear when the hex tiling mode is selected.

Further reading