chroma-noise 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/dist/Gradient.svelte +177 -221
- package/dist/Gradient.svelte.d.ts +2 -19
- package/dist/gradient.frag.glsl +83 -82
- package/dist/index.d.ts +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.js +1 -0
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Gradient noise for Svelte 5.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### New in 0.0.2
|
|
6
|
+
- types
|
|
7
|
+
- new modes: swirl and radial waves
|
|
8
|
+
- removed unused dependencies
|
|
6
9
|
|
|
7
|
-
### Roadmap
|
|
8
|
-
- [] docs
|
|
9
|
-
- [] optimization
|
|
10
10
|
|
|
11
11
|
### Site & playground
|
|
12
|
-
https://chromanoise.netlify.app
|
|
12
|
+
https://chromanoise.netlify.app
|
|
13
|
+
|
|
14
|
+
### Roadmap
|
|
15
|
+
- [] docs
|
|
16
|
+
- [] fix grain size option
|
package/dist/Gradient.svelte
CHANGED
|
@@ -1,221 +1,177 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import vert from './gradient.vert.glsl?raw';
|
|
3
|
-
import frag from './gradient.frag.glsl?raw';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
points
|
|
10
|
-
radius
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
gl.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
gl.
|
|
103
|
-
gl.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
gl.
|
|
120
|
-
gl.
|
|
121
|
-
gl.
|
|
122
|
-
|
|
123
|
-
gl.
|
|
124
|
-
gl.uniform1f(
|
|
125
|
-
|
|
126
|
-
gl.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
gl.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
u_positions = gl.getUniformLocation(program, 'u_positions');
|
|
179
|
-
// @ts-ignore
|
|
180
|
-
u_radius = gl.getUniformLocation(program, 'u_radius');
|
|
181
|
-
// @ts-ignore
|
|
182
|
-
u_intensity = gl.getUniformLocation(program, 'u_intensity');
|
|
183
|
-
// @ts-ignore
|
|
184
|
-
u_warpMode = gl.getUniformLocation(program, 'u_warpMode');
|
|
185
|
-
// @ts-ignore
|
|
186
|
-
u_warpSize = gl.getUniformLocation(program, 'u_warpSize');
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
u_warpAmount = gl.getUniformLocation(program, 'u_warpAmount');
|
|
189
|
-
// @ts-ignore
|
|
190
|
-
u_grainAmount = gl.getUniformLocation(program, 'u_grainAmount');
|
|
191
|
-
// @ts-ignore
|
|
192
|
-
u_grainSize = gl.getUniformLocation(program, 'u_grainSize');
|
|
193
|
-
// @ts-ignore
|
|
194
|
-
u_grainAnimate = gl.getUniformLocation(program, 'u_grainAnimate');
|
|
195
|
-
// @ts-ignore
|
|
196
|
-
u_seed = gl.getUniformLocation(program, 'u_seed');
|
|
197
|
-
|
|
198
|
-
frameId = requestAnimationFrame(render);
|
|
199
|
-
window.addEventListener('resize', updateUniforms);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
onDestroy(() => {
|
|
203
|
-
if (!browser) return;
|
|
204
|
-
|
|
205
|
-
running = false;
|
|
206
|
-
if (frameId) cancelAnimationFrame(frameId);
|
|
207
|
-
window.removeEventListener('resize', updateUniforms);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
$effect(() => {
|
|
211
|
-
if (gl && program) {
|
|
212
|
-
updateUniforms();
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
</script>
|
|
216
|
-
|
|
217
|
-
<canvas bind:this={canvas}></canvas>
|
|
218
|
-
|
|
219
|
-
<style>
|
|
220
|
-
canvas { width: 100%; height: 100%; display: block; }
|
|
221
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import vert from './gradient.vert.glsl?raw';
|
|
3
|
+
import frag from './gradient.frag.glsl?raw';
|
|
4
|
+
import { hexToRgb } from 'ventoui-utils';
|
|
5
|
+
import { onMount, onDestroy } from 'svelte';
|
|
6
|
+
import type { Warp, Grain, GradientOptions } from './index.js';
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
points = [],
|
|
10
|
+
radius = 0.6,
|
|
11
|
+
intensity = 1.0,
|
|
12
|
+
warp: initialWarp = {},
|
|
13
|
+
speed = 1.0,
|
|
14
|
+
grain: initialGrain = {},
|
|
15
|
+
maxPoints = 12,
|
|
16
|
+
seed = Math.random(),
|
|
17
|
+
...rest
|
|
18
|
+
}: GradientOptions = $props();
|
|
19
|
+
|
|
20
|
+
const defaultWarp: Required<Warp> = { mode: 0, amount: 0, size: 1 };
|
|
21
|
+
const defaultGrain: Required<Grain> = { amount: 0, size: 1 };
|
|
22
|
+
|
|
23
|
+
const warp: Required<Warp> = $derived({ ...defaultWarp, ...initialWarp });
|
|
24
|
+
const grain: Required<Grain> = $derived({ ...defaultGrain, ...initialGrain });
|
|
25
|
+
const browser = () => typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
26
|
+
|
|
27
|
+
let canvas: HTMLCanvasElement | undefined = $state();
|
|
28
|
+
let gl: WebGLRenderingContext | undefined = $state();
|
|
29
|
+
let program: WebGLProgram | undefined = $state();
|
|
30
|
+
|
|
31
|
+
let uniforms: Record<string, WebGLUniformLocation> = {} as Record<string, WebGLUniformLocation>;
|
|
32
|
+
let frameId: number;
|
|
33
|
+
let running = true;
|
|
34
|
+
let lastTime = 0;
|
|
35
|
+
let animTime = 0;
|
|
36
|
+
|
|
37
|
+
const shaderUniforms = ['u_resolution',
|
|
38
|
+
'u_time', 'u_count', 'u_colors',
|
|
39
|
+
'u_positions', 'u_radius', 'u_intensity',
|
|
40
|
+
'u_warpMode', 'u_warpSize', 'u_warpAmount',
|
|
41
|
+
'u_grainAmount', 'u_grainSize', 'u_seed'
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
function createShader(gl: WebGLRenderingContext, type: number, src: string) {
|
|
45
|
+
const s = gl.createShader(type)!;
|
|
46
|
+
gl.shaderSource(s, src);
|
|
47
|
+
gl.compileShader(s);
|
|
48
|
+
if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
|
|
49
|
+
console.error(gl.getShaderInfoLog(s));
|
|
50
|
+
gl.deleteShader(s);
|
|
51
|
+
throw new Error('Shader compile error');
|
|
52
|
+
}
|
|
53
|
+
return s;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function createProgram(gl: WebGLRenderingContext, vsSrc: string, fsSrc: string) {
|
|
57
|
+
const vs = createShader(gl, gl.VERTEX_SHADER, vsSrc);
|
|
58
|
+
const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSrc);
|
|
59
|
+
const p = gl.createProgram()!;
|
|
60
|
+
gl.attachShader(p, vs);
|
|
61
|
+
gl.attachShader(p, fs);
|
|
62
|
+
gl.linkProgram(p);
|
|
63
|
+
if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
|
|
64
|
+
console.error(gl.getProgramInfoLog(p));
|
|
65
|
+
gl.deleteProgram(p);
|
|
66
|
+
throw new Error('Program link error');
|
|
67
|
+
}
|
|
68
|
+
return p;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function resizeCanvasToDisplaySize() {
|
|
72
|
+
if (!canvas) return false;
|
|
73
|
+
const dpr = Math.max(1, window.devicePixelRatio || 1);
|
|
74
|
+
const width = Math.floor(canvas.clientWidth * dpr);
|
|
75
|
+
const height = Math.floor(canvas.clientHeight * dpr);
|
|
76
|
+
if (canvas.width !== width || canvas.height !== height) {
|
|
77
|
+
canvas.width = width;
|
|
78
|
+
canvas.height = height;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function updateUniforms() {
|
|
85
|
+
if (!gl || !program || !canvas) return;
|
|
86
|
+
gl.useProgram(program);
|
|
87
|
+
gl.uniform2f(uniforms.u_resolution, canvas.width, canvas.height);
|
|
88
|
+
|
|
89
|
+
const colorsArr = new Float32Array(maxPoints * 3);
|
|
90
|
+
const posArr = new Float32Array(maxPoints * 2);
|
|
91
|
+
|
|
92
|
+
for (let i = 0; i < points.length && i < maxPoints; i++) {
|
|
93
|
+
const [r, g, b] = hexToRgb(points[i].color);
|
|
94
|
+
colorsArr.set([r, g, b], i * 3);
|
|
95
|
+
posArr.set([points[i].x, points[i].y], i * 2);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
gl.uniform3fv(uniforms.u_colors, colorsArr);
|
|
99
|
+
gl.uniform2fv(uniforms.u_positions, posArr);
|
|
100
|
+
gl.uniform1i(uniforms.u_count, Math.min(points.length, maxPoints));
|
|
101
|
+
gl.uniform1f(uniforms.u_radius, radius);
|
|
102
|
+
gl.uniform1f(uniforms.u_intensity, intensity);
|
|
103
|
+
gl.uniform1i(uniforms.u_warpMode, warp.mode);
|
|
104
|
+
gl.uniform1f(uniforms.u_warpSize, warp.size);
|
|
105
|
+
gl.uniform1f(uniforms.u_warpAmount, warp.amount);
|
|
106
|
+
gl.uniform1f(uniforms.u_grainAmount, grain.amount);
|
|
107
|
+
gl.uniform1f(uniforms.u_grainSize, grain.size);
|
|
108
|
+
gl.uniform1f(uniforms.u_seed, seed);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function render(time: number) {
|
|
112
|
+
if (!gl || !program || !canvas) return;
|
|
113
|
+
if (lastTime === 0) lastTime = time;
|
|
114
|
+
const dt = (time - lastTime) * 0.001;
|
|
115
|
+
lastTime = time;
|
|
116
|
+
animTime += dt * speed;
|
|
117
|
+
|
|
118
|
+
resizeCanvasToDisplaySize();
|
|
119
|
+
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
120
|
+
gl.clearColor(0, 0, 0, 0);
|
|
121
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
122
|
+
|
|
123
|
+
gl.useProgram(program);
|
|
124
|
+
gl.uniform1f(uniforms.u_time, animTime);
|
|
125
|
+
updateUniforms();
|
|
126
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
127
|
+
|
|
128
|
+
if (running) frameId = requestAnimationFrame(render);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function getUniform(gl: WebGLRenderingContext, program: WebGLProgram, name: string): WebGLUniformLocation {
|
|
132
|
+
const loc = gl.getUniformLocation(program, name);
|
|
133
|
+
if (!loc) throw new Error(`Uniform ${name} not found`);
|
|
134
|
+
return loc;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
onMount(() => {
|
|
138
|
+
if (!canvas || !browser) return;
|
|
139
|
+
gl = canvas.getContext('webgl', { antialias: true })!;
|
|
140
|
+
if (!gl) return console.warn('WebGL not supported');
|
|
141
|
+
|
|
142
|
+
program = createProgram(gl, vert, frag);
|
|
143
|
+
gl.useProgram(program);
|
|
144
|
+
|
|
145
|
+
const verts = new Float32Array([-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);
|
|
146
|
+
const vbo = gl.createBuffer();
|
|
147
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
148
|
+
gl.bufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW);
|
|
149
|
+
const a_pos = gl.getAttribLocation(program, 'a_pos');
|
|
150
|
+
gl.enableVertexAttribArray(a_pos);
|
|
151
|
+
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);
|
|
152
|
+
|
|
153
|
+
for (const name of shaderUniforms) {
|
|
154
|
+
uniforms[name] = getUniform(gl, program, name);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
frameId = requestAnimationFrame(render);
|
|
158
|
+
window.addEventListener('resize', updateUniforms);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
onDestroy(() => {
|
|
162
|
+
running = false;
|
|
163
|
+
if (!canvas || !browser) return;
|
|
164
|
+
if (frameId) cancelAnimationFrame(frameId);
|
|
165
|
+
window.removeEventListener('resize', updateUniforms);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
$effect(() => {
|
|
169
|
+
if (gl && program) updateUniforms();
|
|
170
|
+
});
|
|
171
|
+
</script>
|
|
172
|
+
|
|
173
|
+
<canvas bind:this={canvas} {...rest}></canvas>
|
|
174
|
+
|
|
175
|
+
<style>
|
|
176
|
+
canvas { width: 100%; height: 100%; display: block; }
|
|
177
|
+
</style>
|
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
color: string;
|
|
4
|
-
x: number;
|
|
5
|
-
y: number;
|
|
6
|
-
}[];
|
|
7
|
-
radius?: number;
|
|
8
|
-
timeAmount?: number;
|
|
9
|
-
intensity?: number;
|
|
10
|
-
warpMode?: number;
|
|
11
|
-
warpSize?: number;
|
|
12
|
-
warpAmount?: number;
|
|
13
|
-
grainAmount?: number;
|
|
14
|
-
grainSize?: number;
|
|
15
|
-
seed?: number;
|
|
16
|
-
}
|
|
17
|
-
declare const Gradient: import("svelte").Component<Props, {
|
|
18
|
-
MAX_POINTS: 12;
|
|
19
|
-
}, "">;
|
|
1
|
+
import type { GradientOptions } from './index.js';
|
|
2
|
+
declare const Gradient: import("svelte").Component<GradientOptions, {}, "">;
|
|
20
3
|
type Gradient = ReturnType<typeof Gradient>;
|
|
21
4
|
export default Gradient;
|
package/dist/gradient.frag.glsl
CHANGED
|
@@ -5,7 +5,7 @@ precision mediump float;
|
|
|
5
5
|
#define MAX_POINTS 12
|
|
6
6
|
|
|
7
7
|
uniform vec2 u_resolution;
|
|
8
|
-
uniform float u_time;
|
|
8
|
+
uniform float u_time;
|
|
9
9
|
uniform int u_count;
|
|
10
10
|
uniform vec3 u_colors[MAX_POINTS];
|
|
11
11
|
uniform vec2 u_positions[MAX_POINTS];
|
|
@@ -13,53 +13,37 @@ uniform float u_radius;
|
|
|
13
13
|
uniform float u_intensity;
|
|
14
14
|
uniform float u_grainAmount;
|
|
15
15
|
uniform float u_grainSize;
|
|
16
|
-
|
|
17
|
-
// warp uniforms
|
|
18
|
-
uniform int u_warpMode; // 0 = none, 1 = waves, 2 = simplex, 3 = fbm, 4 = ridged
|
|
16
|
+
uniform int u_warpMode;
|
|
19
17
|
uniform float u_warpSize;
|
|
20
18
|
uniform float u_warpAmount;
|
|
21
|
-
uniform float u_seed;
|
|
19
|
+
uniform float u_seed;
|
|
22
20
|
|
|
23
|
-
// --- Simplex (from Ashima / webgl-noise) ---
|
|
24
21
|
vec3 permute(vec3 x) {
|
|
25
22
|
return mod(((x * 34.0) + 1.0) * x, 289.0);
|
|
26
23
|
}
|
|
24
|
+
|
|
27
25
|
float snoise(vec2 v) {
|
|
28
|
-
const vec4 C = vec4(0.211324865405187,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
vec2 i = floor(v + dot(v, C.yy) );
|
|
33
|
-
vec2 x0 = v - i + dot(i, C.xx);
|
|
34
|
-
|
|
35
|
-
vec2 i1;
|
|
36
|
-
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
|
26
|
+
const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
|
|
27
|
+
vec2 i = floor(v + dot(v, C.yy));
|
|
28
|
+
vec2 x0 = v - i + dot(i, C.xx);
|
|
29
|
+
vec2 i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
|
37
30
|
vec4 x12 = x0.xyxy + C.xxzz;
|
|
38
31
|
x12.xy -= i1;
|
|
39
|
-
|
|
40
32
|
i = mod(i, 289.0);
|
|
41
|
-
vec3 p = permute(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
|
|
45
|
-
m = m * m;
|
|
46
|
-
m = m * m;
|
|
47
|
-
|
|
33
|
+
vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));
|
|
34
|
+
vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);
|
|
35
|
+
m = m * m * m * m;
|
|
48
36
|
vec3 x = 2.0 * fract(p * C.www) - 1.0;
|
|
49
37
|
vec3 h = abs(x) - 0.5;
|
|
50
38
|
vec3 ox = floor(x + 0.5);
|
|
51
39
|
vec3 a0 = x - ox;
|
|
52
|
-
|
|
53
40
|
m *= 1.79284291400159 - 0.85373472095314 * (a0*a0 + h*h);
|
|
54
|
-
|
|
55
41
|
vec3 g;
|
|
56
|
-
g.x
|
|
42
|
+
g.x = a0.x * x0.x + h.x * x0.y;
|
|
57
43
|
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
|
58
|
-
|
|
59
44
|
return 130.0 * dot(m, g);
|
|
60
45
|
}
|
|
61
46
|
|
|
62
|
-
// fbm helper
|
|
63
47
|
float fbm(vec2 p) {
|
|
64
48
|
float f = 0.0;
|
|
65
49
|
float amp = 0.5;
|
|
@@ -71,84 +55,101 @@ float fbm(vec2 p) {
|
|
|
71
55
|
return f;
|
|
72
56
|
}
|
|
73
57
|
|
|
74
|
-
|
|
75
|
-
vec2 waveWarp(vec2 uv, float t, float seed) {
|
|
76
|
-
// phase field from noise so waves are not uniform / repeatless across seed
|
|
58
|
+
vec2 warpWave(vec2 uv, float t, float seed) {
|
|
77
59
|
float phase = snoise(uv * (u_warpSize * 1.5 + 0.1) + vec2(seed * 5.0));
|
|
78
60
|
float w1 = sin((uv.y * u_warpSize * 10.0) + t * 0.6 + phase * 6.28318);
|
|
79
61
|
float w2 = cos((uv.x * u_warpSize * 8.0) + t * 0.4 - phase * 6.28318 * 0.5);
|
|
80
62
|
vec2 disp = vec2(w1, w2) * (u_warpAmount * 0.5);
|
|
81
|
-
// adjust for aspect
|
|
82
63
|
disp.x *= u_resolution.x / u_resolution.y;
|
|
83
64
|
return uv + disp;
|
|
84
65
|
}
|
|
85
66
|
|
|
67
|
+
vec2 warpSimplex(vec2 uv, float t, float seed) {
|
|
68
|
+
vec2 noiseUv = uv * (u_warpSize * 4.0 + 0.001) + vec2(seed * 10.0, seed * 20.0);
|
|
69
|
+
float n = snoise(noiseUv + vec2(t * 0.05));
|
|
70
|
+
vec2 disp = vec2(n, snoise(noiseUv + vec2(12.34))) * u_warpAmount * 0.8;
|
|
71
|
+
disp.x *= u_resolution.x / u_resolution.y;
|
|
72
|
+
return uv + disp;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
vec2 warpFBM(vec2 uv, float t, float seed) {
|
|
76
|
+
vec2 noiseUv = uv * (u_warpSize * 3.0) + vec2(seed * 7.0);
|
|
77
|
+
float f = fbm(noiseUv + vec2(t * 0.02));
|
|
78
|
+
vec2 disp = vec2(f, fbm(noiseUv + vec2(31.4))) * u_warpAmount;
|
|
79
|
+
disp.x *= u_resolution.x / u_resolution.y;
|
|
80
|
+
return uv + disp;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
vec2 warpRidged(vec2 uv, float t, float seed) {
|
|
84
|
+
vec2 nUv = uv * (u_warpSize * 2.5) + vec2(seed * 9.0);
|
|
85
|
+
float r = 1.0 - abs(fbm(nUv));
|
|
86
|
+
vec2 disp = vec2(r, r * 0.5) * (u_warpAmount * 1.2);
|
|
87
|
+
disp.x *= u_resolution.x / u_resolution.y;
|
|
88
|
+
return uv + disp;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
vec2 warpSwirl(vec2 uv, float t) {
|
|
92
|
+
vec2 centered = uv - 0.5;
|
|
93
|
+
float radius = length(centered);
|
|
94
|
+
float angle = radius * u_warpSize * 5.0 - t * 0.5;
|
|
95
|
+
float s = sin(angle) * u_warpAmount;
|
|
96
|
+
float c = cos(angle) * u_warpAmount;
|
|
97
|
+
centered = vec2(c * centered.x - s * centered.y, s * centered.x + c * centered.y);
|
|
98
|
+
centered.x *= u_resolution.x / u_resolution.y;
|
|
99
|
+
return centered + 0.5;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
vec2 warpRadial(vec2 uv, float t) {
|
|
103
|
+
vec2 centered = uv - 0.5;
|
|
104
|
+
float r = length(centered);
|
|
105
|
+
float theta = atan(centered.y, centered.x);
|
|
106
|
+
float wave = sin(r * u_warpSize * 20.0 - t * 2.0) * u_warpAmount;
|
|
107
|
+
r += wave;
|
|
108
|
+
vec2 p;
|
|
109
|
+
p.x = r * cos(theta);
|
|
110
|
+
p.y = r * sin(theta);
|
|
111
|
+
p.x *= u_resolution.x / u_resolution.y;
|
|
112
|
+
return p + 0.5;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
vec2 applyWarp(vec2 uv) {
|
|
116
|
+
if (u_warpMode == 1) return warpWave(uv, u_time, u_seed);
|
|
117
|
+
else if (u_warpMode == 2) return warpSimplex(uv, u_time, u_seed);
|
|
118
|
+
else if (u_warpMode == 3) return warpFBM(uv, u_time, u_seed);
|
|
119
|
+
else if (u_warpMode == 4) return warpRidged(uv, u_time, u_seed);
|
|
120
|
+
else if (u_warpMode == 5) return warpSwirl(uv, u_time);
|
|
121
|
+
else if (u_warpMode == 6) return warpRadial(uv, u_time);
|
|
122
|
+
return uv;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
float grain(vec2 uv) {
|
|
126
|
+
float n = fract(sin(dot(uv * u_grainSize, vec2(12.9898, 78.233))) * 43758.5453);
|
|
127
|
+
return n - 0.5;
|
|
128
|
+
}
|
|
129
|
+
|
|
86
130
|
void main() {
|
|
87
131
|
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
|
|
88
132
|
vec2 centered = uv - 0.5;
|
|
89
|
-
|
|
90
|
-
vec2 aspectUV = uv;
|
|
91
|
-
aspectUV.x *= u_resolution.x / u_resolution.y;
|
|
92
|
-
|
|
93
|
-
// --- Handle warp modes (use u_time as smooth animTime, and u_seed to randomize field) ---
|
|
94
|
-
if (u_warpMode == 1) {
|
|
95
|
-
uv = waveWarp(uv, u_time, u_seed);
|
|
96
|
-
} else if (u_warpMode == 2) {
|
|
97
|
-
// Simplex single-octave with seed; animated slowly (u_time influences motion but smoothly)
|
|
98
|
-
vec2 noiseUv = uv * (u_warpSize * 4.0 + 0.001) + vec2(u_seed * 10.0, u_seed * 20.0);
|
|
99
|
-
float n = snoise(noiseUv + vec2(u_time * 0.05)); // slow drift
|
|
100
|
-
vec2 disp = vec2(n, snoise(noiseUv + vec2(12.34))) * u_warpAmount * 0.8;
|
|
101
|
-
disp.x *= u_resolution.x / u_resolution.y;
|
|
102
|
-
uv += disp;
|
|
103
|
-
} else if (u_warpMode == 3) {
|
|
104
|
-
// fbm turbulence
|
|
105
|
-
vec2 noiseUv = uv * (u_warpSize * 3.0) + vec2(u_seed * 7.0);
|
|
106
|
-
float f = fbm(noiseUv + vec2(u_time * 0.02));
|
|
107
|
-
vec2 disp = vec2(f, fbm(noiseUv + vec2(31.4))) * u_warpAmount;
|
|
108
|
-
disp.x *= u_resolution.x / u_resolution.y;
|
|
109
|
-
uv += disp;
|
|
110
|
-
} else if (u_warpMode == 4) {
|
|
111
|
-
// ridged noise variation
|
|
112
|
-
vec2 nUv = uv * (u_warpSize * 2.5) + vec2(u_seed * 9.0);
|
|
113
|
-
float r = 1.0 - abs(fbm(nUv));
|
|
114
|
-
vec2 disp = vec2(r, r * 0.5) * (u_warpAmount * 1.2);
|
|
115
|
-
disp.x *= u_resolution.x / u_resolution.y;
|
|
116
|
-
uv += disp;
|
|
117
|
-
}
|
|
133
|
+
uv = applyWarp(uv);
|
|
118
134
|
|
|
119
|
-
|
|
120
|
-
vec2 grainUv = gl_FragCoord.xy / u_resolution.xy;
|
|
121
|
-
// grainSize: bigger -> larger grains. so invert (1/size)
|
|
122
|
-
float grainScale = max(u_grainSize, 0.0001);
|
|
123
|
-
grainUv *= 1.0 / grainScale;
|
|
124
|
-
// classic hash -> value in [0,1)
|
|
125
|
-
float grain = fract(sin(dot(grainUv, vec2(12.9898, 78.233))) * 43758.5453);
|
|
126
|
-
grain = grain - 0.5; // center at 0
|
|
135
|
+
float g = grain(gl_FragCoord.xy / u_resolution.xy);
|
|
127
136
|
|
|
128
|
-
// --- Accumulate colors from points ---
|
|
129
137
|
vec3 accum = vec3(0.0);
|
|
130
138
|
float totalWeight = 0.0;
|
|
131
139
|
for (int i = 0; i < MAX_POINTS; ++i) {
|
|
132
140
|
if (i >= u_count) break;
|
|
133
|
-
vec2
|
|
134
|
-
vec2 diff = (uv - p);
|
|
141
|
+
vec2 diff = uv - u_positions[i];
|
|
135
142
|
diff.x *= u_resolution.x / u_resolution.y;
|
|
136
143
|
float d = length(diff);
|
|
137
|
-
float w = exp(- (d * d) / (u_radius * u_radius));
|
|
138
|
-
|
|
139
|
-
float intensity = max(0.001, u_intensity);
|
|
140
|
-
w = pow(w, intensity); // intensity >1 -> sharper peaks; <1 -> broader
|
|
144
|
+
float w = exp(- (d * d) / (u_radius * u_radius));
|
|
145
|
+
w = pow(w, max(0.001, u_intensity));
|
|
141
146
|
accum += u_colors[i] * w;
|
|
142
147
|
totalWeight += w;
|
|
143
148
|
}
|
|
144
|
-
vec3 color = totalWeight > 0.0 ? accum / totalWeight : vec3(0.95);
|
|
145
149
|
|
|
146
|
-
|
|
150
|
+
vec3 color = totalWeight > 0.0 ? accum / totalWeight : vec3(0.95);
|
|
147
151
|
float vign = 1.0 - smoothstep(0.6, 0.9, length(centered));
|
|
148
152
|
color *= mix(0.98, 1.02, vign);
|
|
149
|
-
|
|
150
|
-
// add grain
|
|
151
|
-
color += grain * u_grainAmount;
|
|
152
|
-
|
|
153
|
+
color += g * u_grainAmount;
|
|
153
154
|
gl_FragColor = vec4(color, 1.0);
|
|
154
155
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a color position in 2D space.
|
|
3
|
+
*/
|
|
4
|
+
export interface Point {
|
|
5
|
+
/** Color of the point in hex format, e.g. "#FF0000" */
|
|
6
|
+
color: string;
|
|
7
|
+
/** X coordinate of the point (0 to 1) */
|
|
8
|
+
x: number;
|
|
9
|
+
/** Y coordinate of the point (0 to 1) */
|
|
10
|
+
y: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for warp effect.
|
|
14
|
+
*/
|
|
15
|
+
export interface Warp {
|
|
16
|
+
/** Warp mode, default: 0 */
|
|
17
|
+
mode?: number;
|
|
18
|
+
/** Warp amount, default: 0 (if 0, warp is not applied) */
|
|
19
|
+
amount?: number;
|
|
20
|
+
/** Warp size, default: 1 */
|
|
21
|
+
size?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for grain effect.
|
|
25
|
+
*/
|
|
26
|
+
export interface Grain {
|
|
27
|
+
/** Grain intensity, default: 0 */
|
|
28
|
+
amount?: number;
|
|
29
|
+
/** Grain size, default: 1 */
|
|
30
|
+
size?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Configuration for the gradient.
|
|
34
|
+
*/
|
|
35
|
+
export interface GradientOptions {
|
|
36
|
+
/** Array of color positions */
|
|
37
|
+
points?: Point[];
|
|
38
|
+
/** Maximum number of points */
|
|
39
|
+
maxPoints?: number;
|
|
40
|
+
/** Blend radius, default: 0.6 */
|
|
41
|
+
radius?: number;
|
|
42
|
+
/** Blend intensity, default: 1 */
|
|
43
|
+
intensity?: number;
|
|
44
|
+
/** Warp effect configuration */
|
|
45
|
+
warp?: Warp;
|
|
46
|
+
/** Warp animation speed, default: 1 */
|
|
47
|
+
speed?: number;
|
|
48
|
+
/** Seed for warp effect, default: random */
|
|
49
|
+
seed?: number;
|
|
50
|
+
/** Grain effect configuration */
|
|
51
|
+
grain?: Grain;
|
|
52
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chroma-noise",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite dev",
|
|
6
6
|
"build": "vite build && npm run prepack",
|
|
@@ -31,8 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"svelte": "^5.0.0",
|
|
34
|
-
"ventoui-utils": "^0.0.2"
|
|
35
|
-
"@sveltejs/kit": "^2.0.0"
|
|
34
|
+
"ventoui-utils": "^0.0.2"
|
|
36
35
|
},
|
|
37
36
|
"devDependencies": {
|
|
38
37
|
"@sveltejs/adapter-auto": "^6.1.0",
|
|
@@ -45,22 +44,25 @@
|
|
|
45
44
|
"publint": "^0.3.13",
|
|
46
45
|
"svelte": "^5.39.5",
|
|
47
46
|
"svelte-check": "^4.3.2",
|
|
47
|
+
"svelte-fancy-transitions": "^0.0.7",
|
|
48
48
|
"typescript": "^5.9.2",
|
|
49
|
+
"ventoui-button": "^0.0.2",
|
|
50
|
+
"ventoui-slider": "^0.0.1",
|
|
51
|
+
"ventoui-styles": "^0.0.2",
|
|
49
52
|
"vite": "^7.1.7"
|
|
50
53
|
},
|
|
51
54
|
"keywords": [
|
|
52
|
-
"svelte",
|
|
55
|
+
"svelte",
|
|
56
|
+
"simplex",
|
|
57
|
+
"noise",
|
|
58
|
+
"gradient",
|
|
59
|
+
"chroma",
|
|
60
|
+
"chroma-noise"
|
|
53
61
|
],
|
|
54
62
|
"pnpm": {
|
|
55
63
|
"onlyBuiltDependencies": [
|
|
56
64
|
"esbuild"
|
|
57
65
|
]
|
|
58
66
|
},
|
|
59
|
-
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac"
|
|
60
|
-
"dependencies": {
|
|
61
|
-
"ventoui-button": "^0.0.2",
|
|
62
|
-
"ventoui-slider": "^0.0.1",
|
|
63
|
-
"ventoui-styles": "^0.0.2",
|
|
64
|
-
"ventoui-utils": "^0.0.2"
|
|
65
|
-
}
|
|
67
|
+
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac"
|
|
66
68
|
}
|