@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/shaders.js 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
- vec2 noise_cord = adjustedUv * u_color_pressure;
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
- u_time * noiseSpeed
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
- gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
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
  `;
@@ -89,7 +123,7 @@ float fbm(vec3 x) {
89
123
  float value = 0.0;
90
124
  float amplitude = 0.5;
91
125
  float frequency = 1.0;
92
- for (int i = 0; i < 4; i++) {
126
+ for (int i = 0; i < 2; i++) {
93
127
  value += amplitude * snoise(x * frequency);
94
128
  frequency *= 2.0;
95
129
  amplitude *= 0.5;
@@ -107,25 +141,55 @@ void main() {
107
141
  vec2 finalUv = vFlowUv;
108
142
 
109
143
  vec3 baseColor;
144
+ float texAlpha = 1.0;
110
145
 
111
146
  if (u_enable_procedural_texture > 0.5) {
112
- vec2 ppp = -1.0 + 2.0 * finalUv;
113
- ppp += 0.1 * cos((1.5 * u_flow_scale) * ppp.yx + 1.1 * u_time + vec2(0.1, 1.1));
114
- ppp += 0.1 * cos((2.3 * u_flow_scale) * ppp.yx + 1.3 * u_time + vec2(3.2, 3.4));
115
- ppp += 0.1 * cos((2.2 * u_flow_scale) * ppp.yx + 1.7 * u_time + vec2(1.8, 5.2));
116
- ppp += u_flow_distortion_a * cos((u_flow_distortion_b * u_flow_scale) * ppp.yx + 1.4 * u_time + vec2(6.3, 3.9));
117
- float r = length(ppp);
118
-
119
- float vx = (finalUv.x * u_texture_ease) + (r * (1.0 - u_texture_ease));
120
- float vy = (finalUv.y * u_texture_ease) + (0.0 * (1.0 - u_texture_ease));
121
- vec2 texUv = vec2(vx, vy);
122
-
123
- float parallaxFactor = 0.25;
124
- texUv.y -= (u_y_offset * u_y_offset_color_multiplier / u_plane_height) * parallaxFactor;
125
- texUv *= 1.5;
126
-
127
- vec4 texSample = texture2D(u_procedural_texture, texUv);
128
- baseColor = texSample.rgb;
147
+ if (u_flat_shading < 0.5) {
148
+ float parallaxFactor = 0.25;
149
+ float scrollOffset = (u_y_offset * u_y_offset_color_multiplier) * parallaxFactor;
150
+ vec3 scrolledPos = vPosition;
151
+ scrolledPos.y -= scrollOffset;
152
+
153
+ vec3 p = (scrolledPos * 1.5) / 50.0;
154
+ vec2 uvX = p.yz + vec2(0.5);
155
+ vec2 uvY = p.zx + vec2(0.5);
156
+ vec2 uvZ = p.xy + vec2(0.5);
157
+
158
+ vec4 colX = texture2D(u_procedural_texture, uvX);
159
+ vec4 colY = texture2D(u_procedural_texture, uvY);
160
+ vec4 colZ = texture2D(u_procedural_texture, uvZ);
161
+
162
+ vec3 n = normalize(vNormal);
163
+ vec3 blendWeights = abs(n);
164
+ blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z + 0.0001);
165
+
166
+ vec4 texSample = colX * blendWeights.x + colY * blendWeights.y + colZ * blendWeights.z;
167
+ baseColor = texSample.rgb;
168
+ if (u_transparent_texture_void > 0.5) {
169
+ texAlpha = texSample.a;
170
+ }
171
+ } else {
172
+ vec2 ppp = -1.0 + 2.0 * finalUv;
173
+ ppp += 0.1 * cos((1.5 * u_flow_scale) * ppp.yx + 1.1 * u_time + vec2(0.1, 1.1));
174
+ ppp += 0.1 * cos((2.3 * u_flow_scale) * ppp.yx + 1.3 * u_time + vec2(3.2, 3.4));
175
+ ppp += 0.1 * cos((2.2 * u_flow_scale) * ppp.yx + 1.7 * u_time + vec2(1.8, 5.2));
176
+ ppp += u_flow_distortion_a * cos((u_flow_distortion_b * u_flow_scale) * ppp.yx + 1.4 * u_time + vec2(6.3, 3.9));
177
+ float r = length(ppp);
178
+
179
+ float vx = (finalUv.x * u_texture_ease) + (r * (1.0 - u_texture_ease));
180
+ float vy = (finalUv.y * u_texture_ease) + (0.0 * (1.0 - u_texture_ease));
181
+ vec2 texUv = vec2(vx, vy);
182
+
183
+ float parallaxFactor = 0.25;
184
+ texUv.y -= (u_y_offset * u_y_offset_color_multiplier / u_plane_height) * parallaxFactor;
185
+ texUv *= 1.5;
186
+
187
+ vec4 texSample = texture2D(u_procedural_texture, texUv);
188
+ baseColor = texSample.rgb;
189
+ if (u_transparent_texture_void > 0.5) {
190
+ texAlpha = texSample.a;
191
+ }
192
+ }
129
193
  } else {
130
194
  baseColor = v_color;
131
195
  }
@@ -134,7 +198,13 @@ void main() {
134
198
 
135
199
  // === DOMAIN WARPING (simplified: 3 fbm calls instead of 5) ===
136
200
  if (u_domain_warp_enabled > 0.5) {
137
- vec3 p = vec3(finalUv * u_domain_warp_scale, u_time * 0.15);
201
+ vec3 p;
202
+ if (u_flat_shading < 0.5) {
203
+ p = vec3((vPosition / 50.0 + vec3(0.5)) * u_domain_warp_scale);
204
+ p.z += u_time * 0.15;
205
+ } else {
206
+ p = vec3(finalUv * u_domain_warp_scale, u_time * 0.15);
207
+ }
138
208
  vec2 q = vec2(fbm(p), fbm(p + vec3(5.2, 1.3, 0.0)));
139
209
  float f = fbm(p + vec3(4.0 * q, 0.0));
140
210
  vec3 warpColor = color * (1.0 + f * 0.8 * u_domain_warp_intensity);
@@ -143,9 +213,42 @@ void main() {
143
213
  }
144
214
 
145
215
  // Post-processing
146
- color += v_displacement_amount * u_highlights;
147
- float shadowFactor = 1.0 - v_displacement_amount;
148
- color -= shadowFactor * shadowFactor * u_shadows;
216
+ // Compute dynamic pixel-perfect normal using smooth normal
217
+ vec3 normal = normalize(vNormal);
218
+ vec3 viewDir = vec3(0.0, 0.0, 1.0);
219
+ float ndotv = dot(normal, viewDir);
220
+
221
+ // Cull back-faces for closed 3D shapes (Sphere=1, Torus=2, Cylinder=3)
222
+ if (u_shape_type > 0.5 && u_shape_type < 3.5) {
223
+ if (ndotv < 0.0) {
224
+ discard;
225
+ }
226
+ } else {
227
+ // Double-sided shapes (Plane, Ribbon): flip normal if back-facing
228
+ if (ndotv < 0.0) {
229
+ normal = -normal;
230
+ ndotv = -ndotv;
231
+ }
232
+ }
233
+ vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0));
234
+ float diffuse = max(dot(normal, lightDir), 0.0);
235
+ vec3 halfDir = normalize(lightDir + viewDir);
236
+ float specular = pow(max(dot(normal, halfDir), 0.0), 32.0);
237
+
238
+ // Blend smooth 3D shading with smooth height-based wave shading
239
+ if (u_flat_shading > 0.5) {
240
+ // Flat / height-based wave shading (plane style)
241
+ color += v_displacement_amount * u_highlights;
242
+ float heightShadow = 1.0 - v_displacement_amount;
243
+ color -= heightShadow * heightShadow * u_shadows;
244
+ } else {
245
+ // 3D shading
246
+ color += specular * u_highlights;
247
+ color += v_displacement_amount * u_highlights * 0.5;
248
+ float heightShadow = 1.0 - v_displacement_amount;
249
+ color -= heightShadow * heightShadow * u_shadows * 0.5;
250
+ color -= (1.0 - diffuse) * u_shadows * 0.5;
251
+ }
149
252
  color = saturation(color, 1.0 + u_saturation);
150
253
  color = color * u_brightness;
151
254
 
@@ -165,7 +268,11 @@ void main() {
165
268
 
166
269
  // === VIGNETTE ===
167
270
  if (u_vignette_intensity > 0.0) {
168
- float dist = length(vUv - vec2(0.5));
271
+ vec2 vigUv = vUv;
272
+ if (u_flat_shading < 0.5) {
273
+ vigUv = (v_new_position.xy / v_new_position.w) * 0.5 + vec2(0.5);
274
+ }
275
+ float dist = length(vigUv - vec2(0.5));
169
276
  float vig = smoothstep(u_vignette_radius, u_vignette_radius * 0.3, dist);
170
277
  color *= mix(1.0, vig, u_vignette_intensity);
171
278
  }
@@ -180,7 +287,11 @@ void main() {
180
287
  // === CHROMATIC ABERRATION ===
181
288
  if (u_chromatic_aberration > 0.0) {
182
289
  float caAmount = u_chromatic_aberration * 0.008;
183
- float dist = length(vUv - vec2(0.5));
290
+ vec2 caUv = vUv;
291
+ if (u_flat_shading < 0.5) {
292
+ caUv = (v_new_position.xy / v_new_position.w) * 0.5 + vec2(0.5);
293
+ }
294
+ float dist = length(caUv - vec2(0.5));
184
295
  float rShift = v_displacement_amount + caAmount * dist;
185
296
  float bShift = v_displacement_amount - caAmount * dist;
186
297
  color.r *= 1.0 + rShift * caAmount * 10.0;
@@ -191,7 +302,7 @@ void main() {
191
302
  float grain = 0.0;
192
303
  if (u_grain_intensity > 0.0) {
193
304
  vec2 noiseCoords = gl_FragCoord.xy / u_grain_scale;
194
- if (u_grain_speed != 0.0) {
305
+ if (u_grain_speed != 0.0 || u_flat_shading > 0.5) {
195
306
  grain = fbm(vec3(noiseCoords, u_time * u_grain_speed));
196
307
  } else {
197
308
  // Static grain: use cheap hash instead of fbm
@@ -206,7 +317,25 @@ void main() {
206
317
 
207
318
  color += vec3(grain);
208
319
 
209
- gl_FragColor = vec4(color, 1.0);
320
+ float edgeAlpha = 1.0;
321
+
322
+ // Silhouette falloff for 3D shapes (skip when flat shading or fade is zero)
323
+ if (u_silhouette_fade > 0.0 && u_flat_shading < 0.5) {
324
+ edgeAlpha = smoothstep(0.0, u_silhouette_fade, ndotv);
325
+ }
326
+
327
+ // UV boundary falloff for open shapes
328
+ if (u_shape_type == 3.0) { // Cylinder: fade top/bottom ends
329
+ float vFade = smoothstep(0.0, u_cylinder_fade, vUv.y) * smoothstep(1.0, 1.0 - u_cylinder_fade, vUv.y);
330
+ edgeAlpha *= vFade;
331
+ } else if (u_shape_type == 4.0) { // Ribbon: fade all 4 borders
332
+ float uFade = smoothstep(0.0, u_ribbon_fade, vUv.x) * smoothstep(1.0, 1.0 - u_ribbon_fade, vUv.x);
333
+ float vFade = smoothstep(0.0, u_ribbon_fade, vUv.y) * smoothstep(1.0, 1.0 - u_ribbon_fade, vUv.y);
334
+ edgeAlpha *= uFade * vFade;
335
+ }
336
+
337
+ edgeAlpha *= texAlpha;
338
+ gl_FragColor = vec4(color, edgeAlpha);
210
339
  }
211
340
  `;
212
341
  export function buildVertUniforms() {
@@ -224,6 +353,9 @@ varying vec2 vFlowUv;
224
353
  varying vec4 v_new_position;
225
354
  varying vec3 v_color;
226
355
  varying float v_displacement_amount;
356
+ varying vec3 vViewPosition;
357
+ varying vec3 vNormal;
358
+ varying vec3 vPosition;
227
359
 
228
360
  uniform float u_time;
229
361
  uniform vec2 u_resolution;
@@ -260,6 +392,9 @@ uniform float u_fresnel_enabled;
260
392
  uniform float u_fresnel_power;
261
393
  uniform float u_fresnel_intensity;
262
394
  uniform vec3 u_fresnel_color;
395
+
396
+ uniform float u_shape_type;
397
+ uniform float u_flat_shading;
263
398
  `;
264
399
  }
265
400
  export function buildFragUniforms() {
@@ -267,8 +402,12 @@ export function buildFragUniforms() {
267
402
 
268
403
  varying vec2 vUv;
269
404
  varying vec2 vFlowUv;
405
+ varying vec4 v_new_position;
270
406
  varying vec3 v_color;
271
407
  varying float v_displacement_amount;
408
+ varying vec3 vViewPosition;
409
+ varying vec3 vNormal;
410
+ varying vec3 vPosition;
272
411
 
273
412
  uniform float u_time;
274
413
  uniform vec2 u_resolution;
@@ -324,6 +463,12 @@ uniform float u_bloom_threshold;
324
463
 
325
464
  // Chromatic aberration
326
465
  uniform float u_chromatic_aberration;
466
+ uniform float u_shape_type;
467
+ uniform float u_transparent_texture_void;
468
+ uniform float u_silhouette_fade;
469
+ uniform float u_cylinder_fade;
470
+ uniform float u_ribbon_fade;
471
+ uniform float u_flat_shading;
327
472
  `;
328
473
  }
329
474
  export function buildNoise() {
@@ -1 +1 @@
1
- {"version":3,"file":"shaders.js","sourceRoot":"","sources":["../src/shaders.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkFjC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+HnC,CAAC;AAEF,MAAM,UAAU,iBAAiB;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkDV,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6DV,CAAC;AACF,CAAC;AAED,MAAM,UAAU,UAAU;IACtB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwJV,CAAC;AACF,CAAC;AAED,MAAM,UAAU,mBAAmB;IAC/B,OAAO;;;;;;CAMV,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"shaders.js","sourceRoot":"","sources":["../src/shaders.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoHjC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8NnC,CAAC;AAEF,MAAM,UAAU,iBAAiB;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDV,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuEV,CAAC;AACF,CAAC;AAED,MAAM,UAAU,UAAU;IACtB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwJV,CAAC;AACF,CAAC;AAED,MAAM,UAAU,mBAAmB;IAC/B,OAAO;;;;;;CAMV,CAAC;AACF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -56,6 +56,32 @@ export type NeatConfig = {
56
56
  bloomIntensity?: number;
57
57
  bloomThreshold?: number;
58
58
  chromaticAberration?: number;
59
+ shapeType?: 'plane' | 'sphere' | 'torus' | 'cylinder' | 'ribbon';
60
+ shapeRotationX?: number;
61
+ shapeRotationY?: number;
62
+ shapeRotationZ?: number;
63
+ shapeAutoRotateSpeedX?: number;
64
+ shapeAutoRotateSpeedY?: number;
65
+ sphereRadius?: number;
66
+ torusRadius?: number;
67
+ torusTube?: number;
68
+ cylinderRadius?: number;
69
+ cylinderHeight?: number;
70
+ planeBend?: number;
71
+ planeTwist?: number;
72
+ transparentTextureVoid?: boolean;
73
+ flatShading?: boolean;
74
+ silhouetteFade?: number;
75
+ cylinderFade?: number;
76
+ ribbonFade?: number;
77
+ cameraLock?: boolean;
78
+ cameraX?: number;
79
+ cameraY?: number;
80
+ cameraZ?: number;
81
+ cameraRotationX?: number;
82
+ cameraRotationY?: number;
83
+ cameraRotationZ?: number;
84
+ cameraZoom?: number;
59
85
  };
60
86
  export type NeatColor = {
61
87
  color: string;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@firecms/neat",
3
3
  "description": "Beautiful 3D gradients for your website",
4
4
  "access": "public",
5
- "version": "0.8.0",
5
+ "version": "0.9.1",
6
6
  "main": "./dist/index.umd.js",
7
7
  "module": "./dist/index.es.js",
8
8
  "types": "dist/index.d.ts",
@@ -47,6 +47,9 @@
47
47
  "url": "https://github.com/FireCMSco/neat/issues"
48
48
  },
49
49
  "homepage": "https://github.com/FireCMSco/neat#readme",
50
+ "pnpm": {
51
+ "onlyBuiltDependencies": ["esbuild"]
52
+ },
50
53
  "publishConfig": {
51
54
  "access": "public"
52
55
  }