tiling-noise
v1.0.1
Published
Make seamless tileable noise
Downloads
7
Maintainers
Readme
Tiling Noise
A tiny library to make seamless tileable noise from any 4D noise function.
Works by mapping coordinates to a Clifford torus, using the method described by JTippetts.
Installation
Use with your favorite 4D noise library
npm i tiling-noise
Or use with one of these
npm i tiling-noise open-simplex-noise
npm i tiling-noise simplex-noise
npm i tiling-noise asm-noise
Usage
Requires a 4d noise function noise4D(x, y, z, w)
from a library such as those above
import makeTilingNoise from 'tiling-noise';
// Using open-simplex-noise:
import { makeNoise4D } from 'open-simplex-noise';
const noise4D = makeNoise4D(Date.now());
// Using simplex-noise:
import SimplexNoise from 'simplex-noise';
const simplex = new SimplexNoise();
const noise4D = (x, y, z, w) => simplex.noise4D(x, y, z, w);
// Using asm-noise:
const noise4D = require('asm-noise');
const tilingNoise = makeTilingNoise({
width: tileWidth, // required
height: tileHeight, // required
noise4D: noise4D, // required
// Constant used to stretch circle in torus mapping, uniform or per axis
stretch: 1, // or [xStrech, yStretch, zStretch, wStretch]
// Offset constant in 4D space, uniform or per axis
offset: 0, // or [xOffset, yOffset, zOffset, wOffset]
});
const noise = tilingNoise(x, y);
Full example (with open-simplex-noise):
import makeTiling from 'tiling-noise';
import { makeNoise4D } from 'open-simplex-noise';
const [width, height] = [400, 200];
const [tileWidth, tileHeight] = [64, 64];
const noise4D = makeNoise4D(Date.now());
const tilingNoise = makeTiling({
width: tileWidth,
height: tileHeight,
noise4D: noise4D,
stretch: 10,
});
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
const img = ctx.createImageData(width, height);
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const i = 4 * (y * width + x);
const value = (tilingNoise(x, y) + 1) * 128;
img.data[i] = value;
img.data[i + 1] = value;
img.data[i + 2] = value;
img.data[i + 3] = 255;
}
}
ctx.putImageData(img, 0, 0);
Offset (& Animation)
Offset animated:
let time = 0;
setInterval(() => {
const tilingNoise = makeTiling({
width: tileWidth,
height: tileHeight,
noise4D: noise4D,
stretch: 10,
offset: 0.1 * time,
});
const img = ctx.createImageData(width, height);
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const i = 4 * (y * width + x);
const value = (tilingNoise(x, y) + 1) * 128;
img.data[i] = value;
img.data[i + 1] = value;
img.data[i + 2] = value;
img.data[i + 3] = 255;
}
}
ctx.putImageData(img, 0, 0);
time++;
}, 100);
Effect of switching between incrementing each component of offset in equal time intervals:
Stretch
stretch: 1
stretch: 10
stretch: 100
stretch: [10, 1]
or stretch: [10, 1, 10, 1]
stretch: [10, 1, 1, 10]
Setting stretch: [time, 1, 1, time]