@firecms/neat 0.2.2 → 0.4.0
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/dist/NeatGradient.d.ts +16 -0
- package/dist/NeatGradient.js +128 -34
- package/dist/NeatGradient.js.map +1 -1
- package/dist/index.es.js +185 -107
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +68 -32
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
- package/src/NeatGradient.ts +147 -34
package/src/NeatGradient.ts
CHANGED
|
@@ -32,9 +32,14 @@ export type NeatConfig = {
|
|
|
32
32
|
colorBrightness?: number;
|
|
33
33
|
colors: NeatColor[];
|
|
34
34
|
colorBlending?: number;
|
|
35
|
+
grainScale?: number;
|
|
36
|
+
grainIntensity?: number;
|
|
37
|
+
grainSparsity?: number;
|
|
38
|
+
grainSpeed?: number;
|
|
35
39
|
wireframe?: boolean;
|
|
36
40
|
backgroundColor?: string;
|
|
37
41
|
backgroundAlpha?: number;
|
|
42
|
+
yOffset?: number;
|
|
38
43
|
};
|
|
39
44
|
|
|
40
45
|
export type NeatColor = {
|
|
@@ -68,6 +73,11 @@ export class NeatGradient implements NeatController {
|
|
|
68
73
|
private _saturation: number = -1;
|
|
69
74
|
private _brightness: number = -1;
|
|
70
75
|
|
|
76
|
+
private _grainScale: number = -1;
|
|
77
|
+
private _grainIntensity: number = -1;
|
|
78
|
+
private _grainSparsity: number = -1;
|
|
79
|
+
private _grainSpeed: number = -1;
|
|
80
|
+
|
|
71
81
|
private _colorBlending: number = -1;
|
|
72
82
|
|
|
73
83
|
private _colors: NeatColor[] = [];
|
|
@@ -80,6 +90,8 @@ export class NeatGradient implements NeatController {
|
|
|
80
90
|
private sizeObserver: ResizeObserver;
|
|
81
91
|
private sceneState: SceneState;
|
|
82
92
|
|
|
93
|
+
private _yOffset: number = 0;
|
|
94
|
+
|
|
83
95
|
constructor(config: NeatConfig & { ref: HTMLCanvasElement, resolution?: number, seed?: number }) {
|
|
84
96
|
|
|
85
97
|
const {
|
|
@@ -96,11 +108,16 @@ export class NeatGradient implements NeatController {
|
|
|
96
108
|
colorSaturation = 0,
|
|
97
109
|
colorBrightness = 1,
|
|
98
110
|
colorBlending = 5,
|
|
111
|
+
grainScale = 2,
|
|
112
|
+
grainIntensity = 0.55,
|
|
113
|
+
grainSparsity = 0.0,
|
|
114
|
+
grainSpeed = 0.1,
|
|
99
115
|
wireframe = false,
|
|
100
116
|
backgroundColor = "#FFFFFF",
|
|
101
117
|
backgroundAlpha = 1.0,
|
|
102
118
|
resolution = 1,
|
|
103
|
-
seed
|
|
119
|
+
seed,
|
|
120
|
+
yOffset = 0
|
|
104
121
|
} = config;
|
|
105
122
|
|
|
106
123
|
|
|
@@ -117,6 +134,10 @@ export class NeatGradient implements NeatController {
|
|
|
117
134
|
this.waveFrequencyY = waveFrequencyY;
|
|
118
135
|
this.waveAmplitude = waveAmplitude;
|
|
119
136
|
this.colorBlending = colorBlending;
|
|
137
|
+
this.grainScale = grainScale;
|
|
138
|
+
this.grainIntensity = grainIntensity;
|
|
139
|
+
this.grainSparsity = grainSparsity;
|
|
140
|
+
this.grainSpeed = grainSpeed;
|
|
120
141
|
this.colors = colors;
|
|
121
142
|
this.shadows = shadows;
|
|
122
143
|
this.highlights = highlights;
|
|
@@ -125,6 +146,7 @@ export class NeatGradient implements NeatController {
|
|
|
125
146
|
this.wireframe = wireframe;
|
|
126
147
|
this.backgroundColor = backgroundColor;
|
|
127
148
|
this.backgroundAlpha = backgroundAlpha;
|
|
149
|
+
this.yOffset = yOffset;
|
|
128
150
|
|
|
129
151
|
this.sceneState = this._initScene(resolution);
|
|
130
152
|
|
|
@@ -143,11 +165,15 @@ export class NeatGradient implements NeatController {
|
|
|
143
165
|
height = this._ref.height;
|
|
144
166
|
|
|
145
167
|
const colors = [
|
|
146
|
-
...this._colors.map(color =>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
...this._colors.map(color => {
|
|
169
|
+
let threeColor = new THREE.Color();
|
|
170
|
+
threeColor.setStyle(color.color, "");
|
|
171
|
+
return ({
|
|
172
|
+
is_active: color.enabled,
|
|
173
|
+
color: threeColor,
|
|
174
|
+
influence: color.influence
|
|
175
|
+
});
|
|
176
|
+
}),
|
|
151
177
|
...Array.from({ length: COLORS_COUNT - this._colors.length }).map(() => ({
|
|
152
178
|
is_active: false,
|
|
153
179
|
color: new THREE.Color(0x000000)
|
|
@@ -186,6 +212,16 @@ export class NeatGradient implements NeatController {
|
|
|
186
212
|
// @ts-ignore
|
|
187
213
|
mesh.material.uniforms.u_brightness = { value: this._brightness };
|
|
188
214
|
// @ts-ignore
|
|
215
|
+
mesh.material.uniforms.u_grain_intensity = { value: this._grainIntensity };
|
|
216
|
+
// @ts-ignore
|
|
217
|
+
mesh.material.uniforms.u_grain_sparsity = { value: this._grainSparsity };
|
|
218
|
+
// @ts-ignore
|
|
219
|
+
mesh.material.uniforms.u_grain_speed = { value: this._grainSpeed };
|
|
220
|
+
// @ts-ignore
|
|
221
|
+
mesh.material.uniforms.u_grain_scale = { value: this._grainScale };
|
|
222
|
+
// @ts-ignore
|
|
223
|
+
mesh.material.uniforms.u_y_offset = { value: this._yOffset };
|
|
224
|
+
// @ts-ignore
|
|
189
225
|
mesh.material.wireframe = this._wireframe;
|
|
190
226
|
});
|
|
191
227
|
|
|
@@ -221,6 +257,13 @@ export class NeatGradient implements NeatController {
|
|
|
221
257
|
}
|
|
222
258
|
}
|
|
223
259
|
|
|
260
|
+
downloadAsPNG(filename = "neat.png") {
|
|
261
|
+
console.log("Downloading as PNG", this._ref);
|
|
262
|
+
const dataURL = this._ref.toDataURL("image/png");
|
|
263
|
+
console.log("data", dataURL);
|
|
264
|
+
downloadURI(dataURL, filename);
|
|
265
|
+
}
|
|
266
|
+
|
|
224
267
|
set speed(speed: number) {
|
|
225
268
|
this._speed = speed / 20;
|
|
226
269
|
}
|
|
@@ -269,6 +312,22 @@ export class NeatGradient implements NeatController {
|
|
|
269
312
|
this._colorBlending = colorBlending / 10;
|
|
270
313
|
}
|
|
271
314
|
|
|
315
|
+
set grainScale(grainScale: number) {
|
|
316
|
+
this._grainScale = grainScale == 0 ? 1 : grainScale;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
set grainIntensity(grainIntensity: number) {
|
|
320
|
+
this._grainIntensity = grainIntensity;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
set grainSparsity(grainSparsity: number) {
|
|
324
|
+
this._grainSparsity = grainSparsity;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
set grainSpeed(grainSpeed: number) {
|
|
328
|
+
this._grainSpeed = grainSpeed;
|
|
329
|
+
}
|
|
330
|
+
|
|
272
331
|
set wireframe(wireframe: boolean) {
|
|
273
332
|
this._wireframe = wireframe;
|
|
274
333
|
}
|
|
@@ -285,6 +344,10 @@ export class NeatGradient implements NeatController {
|
|
|
285
344
|
this._backgroundAlpha = backgroundAlpha;
|
|
286
345
|
}
|
|
287
346
|
|
|
347
|
+
set yOffset(yOffset: number) {
|
|
348
|
+
this._yOffset = yOffset;
|
|
349
|
+
}
|
|
350
|
+
|
|
288
351
|
_initScene(resolution: number): SceneState {
|
|
289
352
|
|
|
290
353
|
const width = this._ref.width,
|
|
@@ -293,6 +356,7 @@ export class NeatGradient implements NeatController {
|
|
|
293
356
|
const renderer = new THREE.WebGLRenderer({
|
|
294
357
|
// antialias: true,
|
|
295
358
|
alpha: true,
|
|
359
|
+
preserveDrawingBuffer: true,
|
|
296
360
|
canvas: this._ref
|
|
297
361
|
});
|
|
298
362
|
|
|
@@ -353,12 +417,16 @@ export class NeatGradient implements NeatController {
|
|
|
353
417
|
u_plane_height: { value: PLANE_HEIGHT },
|
|
354
418
|
u_shadows: { value: this._shadows },
|
|
355
419
|
u_highlights: { value: this._highlights },
|
|
420
|
+
u_grain_intensity: { value: this._grainIntensity },
|
|
421
|
+
u_grain_sparsity: { value: this._grainSparsity },
|
|
422
|
+
u_grain_scale: { value: this._grainScale },
|
|
423
|
+
u_grain_speed: { value: this._grainSpeed },
|
|
356
424
|
};
|
|
357
425
|
|
|
358
426
|
const material = new THREE.ShaderMaterial({
|
|
359
427
|
uniforms: uniforms,
|
|
360
428
|
vertexShader: buildUniforms() + buildNoise() + buildColorFunctions() + buildVertexShader(),
|
|
361
|
-
fragmentShader: buildUniforms() + buildColorFunctions() + buildFragmentShader()
|
|
429
|
+
fragmentShader: buildUniforms() + buildColorFunctions() + buildNoise() + buildFragmentShader()
|
|
362
430
|
});
|
|
363
431
|
|
|
364
432
|
material.wireframe = WIREFRAME;
|
|
@@ -417,51 +485,50 @@ void main() {
|
|
|
417
485
|
u_wave_frequency_y * position.y + u_time,
|
|
418
486
|
u_time
|
|
419
487
|
));
|
|
420
|
-
|
|
488
|
+
|
|
421
489
|
vec3 color;
|
|
422
490
|
|
|
423
491
|
// float t = mod(u_base_color, 100.0);
|
|
424
492
|
color = u_colors[0].color;
|
|
425
|
-
|
|
493
|
+
|
|
494
|
+
// Apply y_offset to the noise coordinates
|
|
426
495
|
vec2 noise_cord = vUv * u_color_pressure;
|
|
427
|
-
|
|
496
|
+
// Apply the y-offset to shift the pattern vertically (1:1 pixel ratio)
|
|
497
|
+
// Scale the offset to match the UV coordinate space
|
|
498
|
+
float scaledOffset = u_y_offset / u_resolution.y;
|
|
499
|
+
noise_cord.y -= scaledOffset;
|
|
500
|
+
|
|
428
501
|
const float minNoise = .0;
|
|
429
502
|
const float maxNoise = .9;
|
|
430
|
-
|
|
503
|
+
|
|
431
504
|
for (int i = 1; i < u_colors_count; i++) {
|
|
432
|
-
|
|
505
|
+
|
|
433
506
|
if(u_colors[i].is_active == 1.0){
|
|
434
507
|
float noiseFlow = (1. + float(i)) / 30.;
|
|
435
508
|
float noiseSpeed = (1. + float(i)) * 0.11;
|
|
436
509
|
float noiseSeed = 13. + float(i) * 7.;
|
|
437
|
-
|
|
510
|
+
|
|
511
|
+
int reverseIndex = u_colors_count - i;
|
|
512
|
+
|
|
438
513
|
float noise = snoise(
|
|
439
514
|
vec3(
|
|
440
515
|
noise_cord.x * u_color_pressure.x + u_time * noiseFlow * 2.,
|
|
441
516
|
noise_cord.y * u_color_pressure.y,
|
|
442
517
|
u_time * noiseSpeed
|
|
443
518
|
) + noiseSeed
|
|
444
|
-
);
|
|
445
|
-
|
|
519
|
+
) - (.1 * float(i)) + (.5 * u_color_blending);
|
|
520
|
+
|
|
446
521
|
noise = clamp(minNoise, maxNoise + float(i) * 0.02, noise);
|
|
447
522
|
vec3 nextColor = u_colors[i].color;
|
|
448
|
-
|
|
449
|
-
// vec3 colorOklab = oklab2rgb(color);
|
|
450
|
-
// vec3 nextColorOklab = oklab2rgb(nextColor);
|
|
451
|
-
// vec3 mixColor = mix(colorOklab, nextColorOklab, smoothstep(0.0, u_color_blending, noise));
|
|
452
|
-
//
|
|
453
|
-
// color = rgb2oklab(mixColor);
|
|
454
|
-
|
|
455
523
|
color = mix(color, nextColor, smoothstep(0.0, u_color_blending, noise));
|
|
456
524
|
}
|
|
457
|
-
|
|
458
525
|
}
|
|
459
|
-
|
|
526
|
+
|
|
460
527
|
v_color = color;
|
|
461
|
-
|
|
528
|
+
|
|
462
529
|
vec3 newPosition = position + normal * v_displacement_amount * u_wave_amplitude;
|
|
463
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(
|
|
464
|
-
|
|
530
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
|
|
531
|
+
|
|
465
532
|
v_new_position = gl_Position;
|
|
466
533
|
}
|
|
467
534
|
`;
|
|
@@ -469,18 +536,49 @@ void main() {
|
|
|
469
536
|
|
|
470
537
|
function buildFragmentShader() {
|
|
471
538
|
return `
|
|
539
|
+
float random(vec2 p) {
|
|
540
|
+
return fract(sin(dot(p, vec2(12.9898,78.233))) * 43758.5453);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
float fbm(vec3 x) {
|
|
544
|
+
float value = 0.0;
|
|
545
|
+
float amplitude = 0.5;
|
|
546
|
+
float frequency = 1.0;
|
|
547
|
+
for (int i = 0; i < 4; i++) {
|
|
548
|
+
value += amplitude * snoise(x * frequency);
|
|
549
|
+
frequency *= 2.0;
|
|
550
|
+
amplitude *= 0.5;
|
|
551
|
+
}
|
|
552
|
+
return value;
|
|
553
|
+
}
|
|
472
554
|
|
|
473
|
-
void main(){
|
|
555
|
+
void main() {
|
|
474
556
|
vec3 color = v_color;
|
|
475
|
-
|
|
476
|
-
color
|
|
477
|
-
color.rgb -= pow(1.0 - v_displacement_amount, 2.0) * u_shadows;
|
|
557
|
+
color += pow(v_displacement_amount, 1.0) * u_highlights;
|
|
558
|
+
color -= pow(1.0 - v_displacement_amount, 2.0) * u_shadows;
|
|
478
559
|
color = saturation(color, 1.0 + u_saturation);
|
|
479
560
|
color = color * u_brightness;
|
|
480
|
-
|
|
481
|
-
|
|
561
|
+
|
|
562
|
+
// Generate grain using fbm
|
|
563
|
+
vec2 noiseCoords = gl_FragCoord.xy / u_grain_scale;
|
|
564
|
+
float grain = (u_grain_speed != 0.0) ? fbm(vec3(noiseCoords, u_time * u_grain_speed)) : fbm(vec3(noiseCoords, 0.0));
|
|
565
|
+
|
|
566
|
+
// Center the grain around zero
|
|
567
|
+
grain = grain * 0.5 + 0.5;
|
|
568
|
+
grain -= 0.5;
|
|
569
|
+
|
|
570
|
+
// Add sparsity control
|
|
571
|
+
grain = (grain > u_grain_sparsity) ? grain : 0.0;
|
|
572
|
+
|
|
573
|
+
// Apply grain intensity
|
|
574
|
+
grain *= u_grain_intensity;
|
|
575
|
+
|
|
576
|
+
// Add grain to color
|
|
577
|
+
color += vec3(grain);
|
|
578
|
+
|
|
579
|
+
gl_FragColor = vec4(color, 1.0);
|
|
482
580
|
}
|
|
483
|
-
`;
|
|
581
|
+
`;
|
|
484
582
|
}
|
|
485
583
|
|
|
486
584
|
const buildUniforms = () => `
|
|
@@ -492,6 +590,10 @@ struct Color {
|
|
|
492
590
|
float value;
|
|
493
591
|
};
|
|
494
592
|
|
|
593
|
+
uniform float u_grain_intensity;
|
|
594
|
+
uniform float u_grain_sparsity;
|
|
595
|
+
uniform float u_grain_scale;
|
|
596
|
+
uniform float u_grain_speed;
|
|
495
597
|
uniform float u_time;
|
|
496
598
|
|
|
497
599
|
uniform float u_wave_amplitude;
|
|
@@ -514,6 +616,8 @@ uniform int u_colors_count;
|
|
|
514
616
|
uniform Color u_colors[5];
|
|
515
617
|
uniform vec2 u_resolution;
|
|
516
618
|
|
|
619
|
+
uniform float u_y_offset;
|
|
620
|
+
|
|
517
621
|
varying vec2 vUv;
|
|
518
622
|
varying vec4 v_new_position;
|
|
519
623
|
varying vec3 v_color;
|
|
@@ -829,3 +933,12 @@ function generateRandomString(length: number = 6): string {
|
|
|
829
933
|
}
|
|
830
934
|
return result;
|
|
831
935
|
}
|
|
936
|
+
|
|
937
|
+
function downloadURI(uri: string, name: string) {
|
|
938
|
+
const link = document.createElement("a");
|
|
939
|
+
link.download = name;
|
|
940
|
+
link.href = uri;
|
|
941
|
+
document.body.appendChild(link);
|
|
942
|
+
link.click();
|
|
943
|
+
document.body.removeChild(link);
|
|
944
|
+
}
|