function noiseTexture(options = {}) {
let {
width = 800,
height = 600,
coarseness = 30,
background = "white",
color = "red",
baseSize = 1,
sizeModulation = 1,
aspectModulation = 1,
angleModulation = 1,
hueModulation = 0.5,
lumModulation = 0.5,
primitive = "line",
sizeNoiseAmplitude = 100,
aspectNoiseAmplitude = 100,
angleNoiseAmplitude = 200,
hueNoiseAmplitude = 100,
lumNoiseAmplitude = 200,
opacity = 0.7,
randomSeed = 1,
blur = 0
} = options;
const baseColor = d3.hsl(d3.color(color));
baseColor.opacity = opacity;
const canvas = DOM.canvas(width, height);
const ctx = canvas.getContext("2d");
const sep = coarseness;
const [deltax, deltay] = [sep * 0.5, sep * 0.5];
const size = sep * 0.5 * baseSize;
const rand = makeRandFunction(randomSeed);
const makeNoise = (amplitude) => {
const scale = -Math.log2(amplitude);
return createSimplexNoise({
xScaleLog: scale,
yScaleLog: scale,
octaves: 1,
random: rand
});
};
const sizeNoise = makeNoise(sizeNoiseAmplitude);
const aspectNoise = makeNoise(aspectNoiseAmplitude);
const angleNoise = makeNoise(angleNoiseAmplitude);
const hueNoise = makeNoise(hueNoiseAmplitude);
const lumNoise = makeNoise(lumNoiseAmplitude);
const draw =
primitive == "circle"
? () => {
ctx.beginPath();
ctx.arc(0, 0, 0.5, 0, Math.PI * 2);
ctx.fill();
}
: primitive == "square"
? () => {
ctx.fillRect(-0.5, -0.5, 1, 1);
}
: primitive == "triangle"
? () => {
ctx.beginPath();
ctx.moveTo(-0.5, -0.5);
ctx.lineTo(0.5, 0.5);
ctx.lineTo(-0.5, 0.5);
ctx.fill();
}
: () => {
ctx.beginPath();
ctx.moveTo(-0.25, -0.75);
ctx.lineTo(-0.75, -0.25);
ctx.lineTo(0.25, 0.75);
ctx.lineTo(0.75, 0.25);
ctx.fill();
};
ctx.fillStyle = background;
ctx.fillRect(0, 0, width, height);
for (let x = -deltax; x - deltax <= width; x += deltax) {
for (let y = -deltay; y - deltay <= height; y += deltay) {
ctx.resetTransform();
ctx.translate(x, y);
const ang = angleModulation * angleNoise(x, y) * Math.PI;
ctx.rotate(ang);
const s = 1 + sizeModulation * sizeNoise(x, y);
const a = aspectModulation * aspectNoise(x, y);
ctx.scale(size * s * (1 + a), size * s * (1 - a));
const hfactor = hueModulation * 180 * hueNoise(x, y);
const lfactor = lumModulation * 0.5 * lumNoise(x, y);
ctx.fillStyle = d3
.hsl(baseColor.h + hfactor, baseColor.s, baseColor.l + lfactor, opacity)
.formatRgb();
draw();
}
}
const canvas2 = DOM.canvas(width, height);
const ctx2 = canvas2.getContext("2d");
ctx2.filter = `blur(${blur}px)`;
ctx2.drawImage(canvas, 0, 0);
return canvas2;
}