Fract and Mod

Creating infinite repetition

The Fract Function

Of all the shader functions, fract might be the most magical. It takes any number and returns just the fractional part: the decimal digits after the point.

fract(2.7) returns 0.7. fract(5.123) returns 0.123. fract(10.0) returns 0.0. No matter how large your input grows, fract keeps bringing it back to the range 0 to 1.

Interactive: See how fract wraps values

fract returns only the decimal part, creating a repeating sawtooth

The definition is simple:

fract(x)=xx\text{fract}(x) = x - \lfloor x \rfloor

This creates a sawtooth wave. As x increases from 0 to 1, fract(x) increases with it. The moment x hits 1, fract snaps back to 0 and starts again. This pattern repeats forever, no matter how large x becomes.

Tiling with Fract

Here is where fract transforms your understanding of shader programming. If you multiply your UV coordinates before taking the fractional part, you create repetition.

fract(uv * 4.0) divides your coordinate space into a 4x4 grid. Each cell of that grid gets its own copy of the 0-1 UV range. Whatever you draw in that space now tiles perfectly.

Interactive: Tile a gradient

fract(uv * 3.0)

This is not just useful, it is fundamental. Almost every procedural pattern you have ever seen: brick walls, fabric weaves, noise textures, they all start with fract. One line of code gives you infinite repetition.

vec2 tiledUV = fract(uv * tiles);
glsl

The Mod Function

While fract is specialized for the 0-1 range, mod generalizes repetition to any interval.

mod(x, y) returns the remainder when x is divided by y. It is like fract, but instead of always wrapping at 1, it wraps at whatever value you specify.

Interactive: Modulo with different divisors

mod wraps at 1.0 instead of 1

The formula mirrors fract:

mod(x,y)=xyx/y\text{mod}(x, y) = x - y \cdot \lfloor x / y \rfloor

When y is 1.0, mod behaves exactly like fract. But mod can do more: mod(x, 2.0) creates a sawtooth that spans 0 to 2. mod(x, 0.5) creates faster repetition.

Checkerboard Patterns

Combining floor and mod creates one of the most classic patterns: the checkerboard.

The trick is to use floor to get integer cell coordinates, then mod to determine if the sum is even or odd:

vec2 cell = floor(uv * tiles);
float checker = mod(cell.x + cell.y, 2.0);
glsl

When both coordinates are even, or both are odd, the sum is even and checker equals 0. When one is even and one is odd, the sum is odd and checker equals 1.

Interactive: Build a checkerboard

mod(floor(uv.x * 4) + floor(uv.y * 4), 2.0)

This pattern shows the power of combining simple functions. Floor gives us which cell we are in. Mod gives us alternating values. Together they create structure from coordinates.

Brick Patterns

Bricks take the checkerboard idea further by offsetting alternating rows. This is a beautiful example of how small modifications create dramatically different results.

vec2 coord = uv * vec2(tiles, tiles * 0.5);
float row = floor(coord.y);
coord.x += mod(row, 2.0) * 0.5;
vec2 brick = fract(coord);
glsl

The key insight is coord.x += mod(row, 2.0) * 0.5. On even rows, we add 0. On odd rows, we add 0.5, shifting the bricks by half a unit.

Interactive: Create a brick pattern

This offset-and-tile technique appears everywhere: in fabric patterns, in circuit board layouts, in countless procedural textures. Master this pattern and you have a powerful tool.

Building Your Own Patterns

Once you understand fract and mod, pattern creation becomes a process of experimentation. Start with tiled coordinates, add offsets, mix in some smooth transitions, and see what emerges.

Interactive: Pattern editor

Each pattern uses fract to create 5x5 repeating tiles

Some ideas to explore:

  • Use sin(fract(uv.x * tiles) * 3.14159) for wavy stripes
  • Combine multiple tile frequencies for complex textures
  • Use distance from cell center for circular patterns within tiles
  • Mix fract results with smoothstep for soft-edged repetition

The Art of Repetition

Fract and mod transform the infinite plane of UV coordinates into a manageable, repeating canvas. Instead of thinking about every pixel individually, you design a single tile and let mathematics replicate it endlessly.

This is a profound shift in how you think about graphics. You are not painting pixels. You are defining rules that generate pixels. The same code produces the same pattern whether your canvas is 100 pixels or 10,000 pixels wide.

Key Takeaways

  • fract(x) returns the fractional part, always in the range [0, 1)
  • fract(uv * n) creates n-by-n tiling of any pattern
  • mod(x, y) generalizes fract to wrap at any value
  • floor gives integer cell coordinates; combined with mod, creates checkerboards
  • Offsetting rows with mod(row, 2.0) * 0.5 creates brick-like patterns
  • These simple functions are the foundation of all procedural textures