@firecms/neat 0.8.0 → 0.9.1
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 +162 -0
- package/dist/NeatGradient.js +822 -69
- package/dist/NeatGradient.js.map +1 -1
- package/dist/index.es.js +1347 -706
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +391 -403
- package/dist/index.umd.js.map +1 -1
- package/dist/math.d.ts +33 -1
- package/dist/math.js +339 -24
- package/dist/math.js.map +1 -1
- package/dist/shaders.d.ts +2 -2
- package/dist/shaders.js +179 -34
- package/dist/shaders.js.map +1 -1
- package/dist/types.d.ts +26 -0
- package/package.json +4 -1
- package/src/NeatGradient.ts +945 -75
- package/src/math.ts +381 -28
- package/src/shaders.ts +179 -34
- package/src/types.ts +30 -0
package/src/shaders.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const vertexShaderSource = `void main() {
|
|
2
2
|
vUv = uv;
|
|
3
|
+
vPosition = position;
|
|
3
4
|
|
|
4
5
|
// SCROLLING LOGIC
|
|
5
6
|
// Separate multipliers for wave, color, and flow offsets
|
|
@@ -41,11 +42,36 @@ export const vertexShaderSource = `void main() {
|
|
|
41
42
|
// We take the computed flow UVs and apply the color offset
|
|
42
43
|
// Scale by plane height to match wave offset speed (world space vs UV space)
|
|
43
44
|
vec3 color = u_colors[0].color;
|
|
44
|
-
// ...
|
|
45
|
-
vec2 adjustedUv = flowUv;
|
|
46
|
-
adjustedUv.y += colorOffset / u_plane_height; // Scroll the color mixing pattern
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
vec3 distortedPos = position;
|
|
47
|
+
if (u_flat_shading < 0.5) {
|
|
48
|
+
if (u_flow_enabled > 0.5) {
|
|
49
|
+
if (u_flow_ease > 0.0 || u_flow_distortion_a > 0.0) {
|
|
50
|
+
vec3 ppp = position / 25.0;
|
|
51
|
+
ppp.xyz += 0.1 * cos((1.5 * u_flow_scale) * ppp.yxz + 1.1 * u_time + vec3(0.1, 1.1, 2.1));
|
|
52
|
+
ppp.xyz += 0.1 * cos((2.3 * u_flow_scale) * ppp.zxy + 1.3 * u_time + vec3(3.2, 3.4, 1.2));
|
|
53
|
+
ppp.xyz += 0.1 * cos((2.2 * u_flow_scale) * ppp.yxz + 1.7 * u_time + vec3(1.8, 5.2, 3.1));
|
|
54
|
+
ppp.xyz += u_flow_distortion_a * cos((u_flow_distortion_b * u_flow_scale) * ppp.zxy + 1.4 * u_time + vec3(6.3, 3.9, 4.5));
|
|
55
|
+
|
|
56
|
+
float r = length(ppp);
|
|
57
|
+
distortedPos = mix(position, vec3(
|
|
58
|
+
position.x * (1.0 - u_flow_ease) + r * u_flow_ease * 25.0,
|
|
59
|
+
position.y,
|
|
60
|
+
position.z * (1.0 - u_flow_ease) + r * u_flow_ease * 25.0
|
|
61
|
+
), u_flow_ease);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
vec3 noise_cord;
|
|
67
|
+
if (u_flat_shading < 0.5) {
|
|
68
|
+
noise_cord = vec3(distortedPos.x / 50.0, (distortedPos.y + colorOffset) / 50.0, distortedPos.z / 50.0);
|
|
69
|
+
} else {
|
|
70
|
+
vec2 adjustedUv = flowUv;
|
|
71
|
+
adjustedUv.y += colorOffset / u_plane_height;
|
|
72
|
+
noise_cord = vec3(adjustedUv, 0.0);
|
|
73
|
+
}
|
|
74
|
+
|
|
49
75
|
const float minNoise = .0;
|
|
50
76
|
const float maxNoise = .9;
|
|
51
77
|
|
|
@@ -56,11 +82,16 @@ export const vertexShaderSource = `void main() {
|
|
|
56
82
|
float noiseSpeed = (1. + float(i)) * 0.11;
|
|
57
83
|
float noiseSeed = 13. + float(i) * 7.;
|
|
58
84
|
|
|
85
|
+
float noise_z = u_time * noiseSpeed;
|
|
86
|
+
if (u_flat_shading < 0.5) {
|
|
87
|
+
noise_z = noise_cord.z * u_color_pressure.x * u_color_pressure.x + u_time * noiseSpeed;
|
|
88
|
+
}
|
|
89
|
+
|
|
59
90
|
float noise = snoise(
|
|
60
91
|
vec3(
|
|
61
|
-
noise_cord.x * u_color_pressure.x + u_time * noiseFlow * 2.,
|
|
62
|
-
noise_cord.y * u_color_pressure.y,
|
|
63
|
-
|
|
92
|
+
noise_cord.x * u_color_pressure.x * u_color_pressure.x + u_time * noiseFlow * 2.,
|
|
93
|
+
noise_cord.y * u_color_pressure.y * u_color_pressure.y,
|
|
94
|
+
noise_z
|
|
64
95
|
) + noiseSeed
|
|
65
96
|
) - (.1 * float(i)) + (.5 * u_color_blending);
|
|
66
97
|
|
|
@@ -77,7 +108,10 @@ export const vertexShaderSource = `void main() {
|
|
|
77
108
|
|
|
78
109
|
// 5. VERTEX POSITION
|
|
79
110
|
vec3 newPosition = position + normal * v_displacement_amount * u_wave_amplitude;
|
|
80
|
-
|
|
111
|
+
vec4 mvPosition = modelViewMatrix * vec4(newPosition, 1.0);
|
|
112
|
+
vViewPosition = mvPosition.xyz;
|
|
113
|
+
vNormal = normalize((modelViewMatrix * vec4(normal, 0.0)).xyz);
|
|
114
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
81
115
|
v_new_position = gl_Position;
|
|
82
116
|
}
|
|
83
117
|
`;
|
|
@@ -90,7 +124,7 @@ float fbm(vec3 x) {
|
|
|
90
124
|
float value = 0.0;
|
|
91
125
|
float amplitude = 0.5;
|
|
92
126
|
float frequency = 1.0;
|
|
93
|
-
for (int i = 0; i <
|
|
127
|
+
for (int i = 0; i < 2; i++) {
|
|
94
128
|
value += amplitude * snoise(x * frequency);
|
|
95
129
|
frequency *= 2.0;
|
|
96
130
|
amplitude *= 0.5;
|
|
@@ -108,25 +142,55 @@ void main() {
|
|
|
108
142
|
vec2 finalUv = vFlowUv;
|
|
109
143
|
|
|
110
144
|
vec3 baseColor;
|
|
145
|
+
float texAlpha = 1.0;
|
|
111
146
|
|
|
112
147
|
if (u_enable_procedural_texture > 0.5) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
148
|
+
if (u_flat_shading < 0.5) {
|
|
149
|
+
float parallaxFactor = 0.25;
|
|
150
|
+
float scrollOffset = (u_y_offset * u_y_offset_color_multiplier) * parallaxFactor;
|
|
151
|
+
vec3 scrolledPos = vPosition;
|
|
152
|
+
scrolledPos.y -= scrollOffset;
|
|
153
|
+
|
|
154
|
+
vec3 p = (scrolledPos * 1.5) / 50.0;
|
|
155
|
+
vec2 uvX = p.yz + vec2(0.5);
|
|
156
|
+
vec2 uvY = p.zx + vec2(0.5);
|
|
157
|
+
vec2 uvZ = p.xy + vec2(0.5);
|
|
158
|
+
|
|
159
|
+
vec4 colX = texture2D(u_procedural_texture, uvX);
|
|
160
|
+
vec4 colY = texture2D(u_procedural_texture, uvY);
|
|
161
|
+
vec4 colZ = texture2D(u_procedural_texture, uvZ);
|
|
162
|
+
|
|
163
|
+
vec3 n = normalize(vNormal);
|
|
164
|
+
vec3 blendWeights = abs(n);
|
|
165
|
+
blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z + 0.0001);
|
|
166
|
+
|
|
167
|
+
vec4 texSample = colX * blendWeights.x + colY * blendWeights.y + colZ * blendWeights.z;
|
|
168
|
+
baseColor = texSample.rgb;
|
|
169
|
+
if (u_transparent_texture_void > 0.5) {
|
|
170
|
+
texAlpha = texSample.a;
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
vec2 ppp = -1.0 + 2.0 * finalUv;
|
|
174
|
+
ppp += 0.1 * cos((1.5 * u_flow_scale) * ppp.yx + 1.1 * u_time + vec2(0.1, 1.1));
|
|
175
|
+
ppp += 0.1 * cos((2.3 * u_flow_scale) * ppp.yx + 1.3 * u_time + vec2(3.2, 3.4));
|
|
176
|
+
ppp += 0.1 * cos((2.2 * u_flow_scale) * ppp.yx + 1.7 * u_time + vec2(1.8, 5.2));
|
|
177
|
+
ppp += u_flow_distortion_a * cos((u_flow_distortion_b * u_flow_scale) * ppp.yx + 1.4 * u_time + vec2(6.3, 3.9));
|
|
178
|
+
float r = length(ppp);
|
|
179
|
+
|
|
180
|
+
float vx = (finalUv.x * u_texture_ease) + (r * (1.0 - u_texture_ease));
|
|
181
|
+
float vy = (finalUv.y * u_texture_ease) + (0.0 * (1.0 - u_texture_ease));
|
|
182
|
+
vec2 texUv = vec2(vx, vy);
|
|
183
|
+
|
|
184
|
+
float parallaxFactor = 0.25;
|
|
185
|
+
texUv.y -= (u_y_offset * u_y_offset_color_multiplier / u_plane_height) * parallaxFactor;
|
|
186
|
+
texUv *= 1.5;
|
|
187
|
+
|
|
188
|
+
vec4 texSample = texture2D(u_procedural_texture, texUv);
|
|
189
|
+
baseColor = texSample.rgb;
|
|
190
|
+
if (u_transparent_texture_void > 0.5) {
|
|
191
|
+
texAlpha = texSample.a;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
130
194
|
} else {
|
|
131
195
|
baseColor = v_color;
|
|
132
196
|
}
|
|
@@ -135,7 +199,13 @@ void main() {
|
|
|
135
199
|
|
|
136
200
|
// === DOMAIN WARPING (simplified: 3 fbm calls instead of 5) ===
|
|
137
201
|
if (u_domain_warp_enabled > 0.5) {
|
|
138
|
-
vec3 p
|
|
202
|
+
vec3 p;
|
|
203
|
+
if (u_flat_shading < 0.5) {
|
|
204
|
+
p = vec3((vPosition / 50.0 + vec3(0.5)) * u_domain_warp_scale);
|
|
205
|
+
p.z += u_time * 0.15;
|
|
206
|
+
} else {
|
|
207
|
+
p = vec3(finalUv * u_domain_warp_scale, u_time * 0.15);
|
|
208
|
+
}
|
|
139
209
|
vec2 q = vec2(fbm(p), fbm(p + vec3(5.2, 1.3, 0.0)));
|
|
140
210
|
float f = fbm(p + vec3(4.0 * q, 0.0));
|
|
141
211
|
vec3 warpColor = color * (1.0 + f * 0.8 * u_domain_warp_intensity);
|
|
@@ -144,9 +214,42 @@ void main() {
|
|
|
144
214
|
}
|
|
145
215
|
|
|
146
216
|
// Post-processing
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
217
|
+
// Compute dynamic pixel-perfect normal using smooth normal
|
|
218
|
+
vec3 normal = normalize(vNormal);
|
|
219
|
+
vec3 viewDir = vec3(0.0, 0.0, 1.0);
|
|
220
|
+
float ndotv = dot(normal, viewDir);
|
|
221
|
+
|
|
222
|
+
// Cull back-faces for closed 3D shapes (Sphere=1, Torus=2, Cylinder=3)
|
|
223
|
+
if (u_shape_type > 0.5 && u_shape_type < 3.5) {
|
|
224
|
+
if (ndotv < 0.0) {
|
|
225
|
+
discard;
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
// Double-sided shapes (Plane, Ribbon): flip normal if back-facing
|
|
229
|
+
if (ndotv < 0.0) {
|
|
230
|
+
normal = -normal;
|
|
231
|
+
ndotv = -ndotv;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0));
|
|
235
|
+
float diffuse = max(dot(normal, lightDir), 0.0);
|
|
236
|
+
vec3 halfDir = normalize(lightDir + viewDir);
|
|
237
|
+
float specular = pow(max(dot(normal, halfDir), 0.0), 32.0);
|
|
238
|
+
|
|
239
|
+
// Blend smooth 3D shading with smooth height-based wave shading
|
|
240
|
+
if (u_flat_shading > 0.5) {
|
|
241
|
+
// Flat / height-based wave shading (plane style)
|
|
242
|
+
color += v_displacement_amount * u_highlights;
|
|
243
|
+
float heightShadow = 1.0 - v_displacement_amount;
|
|
244
|
+
color -= heightShadow * heightShadow * u_shadows;
|
|
245
|
+
} else {
|
|
246
|
+
// 3D shading
|
|
247
|
+
color += specular * u_highlights;
|
|
248
|
+
color += v_displacement_amount * u_highlights * 0.5;
|
|
249
|
+
float heightShadow = 1.0 - v_displacement_amount;
|
|
250
|
+
color -= heightShadow * heightShadow * u_shadows * 0.5;
|
|
251
|
+
color -= (1.0 - diffuse) * u_shadows * 0.5;
|
|
252
|
+
}
|
|
150
253
|
color = saturation(color, 1.0 + u_saturation);
|
|
151
254
|
color = color * u_brightness;
|
|
152
255
|
|
|
@@ -166,7 +269,11 @@ void main() {
|
|
|
166
269
|
|
|
167
270
|
// === VIGNETTE ===
|
|
168
271
|
if (u_vignette_intensity > 0.0) {
|
|
169
|
-
|
|
272
|
+
vec2 vigUv = vUv;
|
|
273
|
+
if (u_flat_shading < 0.5) {
|
|
274
|
+
vigUv = (v_new_position.xy / v_new_position.w) * 0.5 + vec2(0.5);
|
|
275
|
+
}
|
|
276
|
+
float dist = length(vigUv - vec2(0.5));
|
|
170
277
|
float vig = smoothstep(u_vignette_radius, u_vignette_radius * 0.3, dist);
|
|
171
278
|
color *= mix(1.0, vig, u_vignette_intensity);
|
|
172
279
|
}
|
|
@@ -181,7 +288,11 @@ void main() {
|
|
|
181
288
|
// === CHROMATIC ABERRATION ===
|
|
182
289
|
if (u_chromatic_aberration > 0.0) {
|
|
183
290
|
float caAmount = u_chromatic_aberration * 0.008;
|
|
184
|
-
|
|
291
|
+
vec2 caUv = vUv;
|
|
292
|
+
if (u_flat_shading < 0.5) {
|
|
293
|
+
caUv = (v_new_position.xy / v_new_position.w) * 0.5 + vec2(0.5);
|
|
294
|
+
}
|
|
295
|
+
float dist = length(caUv - vec2(0.5));
|
|
185
296
|
float rShift = v_displacement_amount + caAmount * dist;
|
|
186
297
|
float bShift = v_displacement_amount - caAmount * dist;
|
|
187
298
|
color.r *= 1.0 + rShift * caAmount * 10.0;
|
|
@@ -192,7 +303,7 @@ void main() {
|
|
|
192
303
|
float grain = 0.0;
|
|
193
304
|
if (u_grain_intensity > 0.0) {
|
|
194
305
|
vec2 noiseCoords = gl_FragCoord.xy / u_grain_scale;
|
|
195
|
-
if (u_grain_speed != 0.0) {
|
|
306
|
+
if (u_grain_speed != 0.0 || u_flat_shading > 0.5) {
|
|
196
307
|
grain = fbm(vec3(noiseCoords, u_time * u_grain_speed));
|
|
197
308
|
} else {
|
|
198
309
|
// Static grain: use cheap hash instead of fbm
|
|
@@ -207,7 +318,25 @@ void main() {
|
|
|
207
318
|
|
|
208
319
|
color += vec3(grain);
|
|
209
320
|
|
|
210
|
-
|
|
321
|
+
float edgeAlpha = 1.0;
|
|
322
|
+
|
|
323
|
+
// Silhouette falloff for 3D shapes (skip when flat shading or fade is zero)
|
|
324
|
+
if (u_silhouette_fade > 0.0 && u_flat_shading < 0.5) {
|
|
325
|
+
edgeAlpha = smoothstep(0.0, u_silhouette_fade, ndotv);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// UV boundary falloff for open shapes
|
|
329
|
+
if (u_shape_type == 3.0) { // Cylinder: fade top/bottom ends
|
|
330
|
+
float vFade = smoothstep(0.0, u_cylinder_fade, vUv.y) * smoothstep(1.0, 1.0 - u_cylinder_fade, vUv.y);
|
|
331
|
+
edgeAlpha *= vFade;
|
|
332
|
+
} else if (u_shape_type == 4.0) { // Ribbon: fade all 4 borders
|
|
333
|
+
float uFade = smoothstep(0.0, u_ribbon_fade, vUv.x) * smoothstep(1.0, 1.0 - u_ribbon_fade, vUv.x);
|
|
334
|
+
float vFade = smoothstep(0.0, u_ribbon_fade, vUv.y) * smoothstep(1.0, 1.0 - u_ribbon_fade, vUv.y);
|
|
335
|
+
edgeAlpha *= uFade * vFade;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
edgeAlpha *= texAlpha;
|
|
339
|
+
gl_FragColor = vec4(color, edgeAlpha);
|
|
211
340
|
}
|
|
212
341
|
`;
|
|
213
342
|
|
|
@@ -226,6 +355,9 @@ varying vec2 vFlowUv;
|
|
|
226
355
|
varying vec4 v_new_position;
|
|
227
356
|
varying vec3 v_color;
|
|
228
357
|
varying float v_displacement_amount;
|
|
358
|
+
varying vec3 vViewPosition;
|
|
359
|
+
varying vec3 vNormal;
|
|
360
|
+
varying vec3 vPosition;
|
|
229
361
|
|
|
230
362
|
uniform float u_time;
|
|
231
363
|
uniform vec2 u_resolution;
|
|
@@ -262,6 +394,9 @@ uniform float u_fresnel_enabled;
|
|
|
262
394
|
uniform float u_fresnel_power;
|
|
263
395
|
uniform float u_fresnel_intensity;
|
|
264
396
|
uniform vec3 u_fresnel_color;
|
|
397
|
+
|
|
398
|
+
uniform float u_shape_type;
|
|
399
|
+
uniform float u_flat_shading;
|
|
265
400
|
`;
|
|
266
401
|
}
|
|
267
402
|
|
|
@@ -270,8 +405,12 @@ export function buildFragUniforms(): string {
|
|
|
270
405
|
|
|
271
406
|
varying vec2 vUv;
|
|
272
407
|
varying vec2 vFlowUv;
|
|
408
|
+
varying vec4 v_new_position;
|
|
273
409
|
varying vec3 v_color;
|
|
274
410
|
varying float v_displacement_amount;
|
|
411
|
+
varying vec3 vViewPosition;
|
|
412
|
+
varying vec3 vNormal;
|
|
413
|
+
varying vec3 vPosition;
|
|
275
414
|
|
|
276
415
|
uniform float u_time;
|
|
277
416
|
uniform vec2 u_resolution;
|
|
@@ -327,6 +466,12 @@ uniform float u_bloom_threshold;
|
|
|
327
466
|
|
|
328
467
|
// Chromatic aberration
|
|
329
468
|
uniform float u_chromatic_aberration;
|
|
469
|
+
uniform float u_shape_type;
|
|
470
|
+
uniform float u_transparent_texture_void;
|
|
471
|
+
uniform float u_silhouette_fade;
|
|
472
|
+
uniform float u_cylinder_fade;
|
|
473
|
+
uniform float u_ribbon_fade;
|
|
474
|
+
uniform float u_flat_shading;
|
|
330
475
|
`;
|
|
331
476
|
}
|
|
332
477
|
|
package/src/types.ts
CHANGED
|
@@ -68,6 +68,36 @@ export type NeatConfig = {
|
|
|
68
68
|
|
|
69
69
|
// Chromatic aberration
|
|
70
70
|
chromaticAberration?: number;
|
|
71
|
+
|
|
72
|
+
// 3D Shapes config
|
|
73
|
+
shapeType?: 'plane' | 'sphere' | 'torus' | 'cylinder' | 'ribbon';
|
|
74
|
+
shapeRotationX?: number;
|
|
75
|
+
shapeRotationY?: number;
|
|
76
|
+
shapeRotationZ?: number;
|
|
77
|
+
shapeAutoRotateSpeedX?: number;
|
|
78
|
+
shapeAutoRotateSpeedY?: number;
|
|
79
|
+
sphereRadius?: number;
|
|
80
|
+
torusRadius?: number;
|
|
81
|
+
torusTube?: number;
|
|
82
|
+
cylinderRadius?: number;
|
|
83
|
+
cylinderHeight?: number;
|
|
84
|
+
planeBend?: number;
|
|
85
|
+
planeTwist?: number;
|
|
86
|
+
transparentTextureVoid?: boolean;
|
|
87
|
+
flatShading?: boolean;
|
|
88
|
+
silhouetteFade?: number;
|
|
89
|
+
cylinderFade?: number;
|
|
90
|
+
ribbonFade?: number;
|
|
91
|
+
|
|
92
|
+
// Camera settings
|
|
93
|
+
cameraLock?: boolean;
|
|
94
|
+
cameraX?: number;
|
|
95
|
+
cameraY?: number;
|
|
96
|
+
cameraZ?: number;
|
|
97
|
+
cameraRotationX?: number;
|
|
98
|
+
cameraRotationY?: number;
|
|
99
|
+
cameraRotationZ?: number;
|
|
100
|
+
cameraZoom?: number;
|
|
71
101
|
};
|
|
72
102
|
|
|
73
103
|
export type NeatColor = {
|