Skip to content

Commit aefaa8b

Browse files
committed
docs: update maxime particle example with angular logo
wip feat: Distribute particles based on transformed curve vertices from shapes.json wipwip refactor: Properly create BufferGeometry from shapes data in particle simulation refactor: Optimize particle simulation code and remove debug log refactor: Adjust particle simulation to preserve shape while adding subtle motion refactor: Distribute shapes evenly by applying individual transformations refactor: Rename variables for clarity in particle simulation material refactor: Improve particle distribution and reduce noise in shape simulation refactor: Distribute points randomly within shape boundaries feat: Distribute particles within triangles using geometry indices fix: Correct shape position indexing in particle simulation matrix transformation refactor: Rename `positions` to `positionsArr` for clarity in particle simulation feat: Reposition shapes to form Angular "A" logo pattern refactor: Adjust triangle positions and swap left/right triangles refactor: Adjust shape positions to improve Angular "A" logo geometry refactor: Lower top triangle y-coordinate to 0.3 wip feat: Enhance particle noise animation with more chaotic movement feat: Add pulsing effect to particle simulation for periodic shape return working working
1 parent c6f4fdd commit aefaa8b

File tree

8 files changed

+371
-36
lines changed

8 files changed

+371
-36
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ Thumbs.db
4545
.nx/workspace-data
4646

4747
vite.config.*.timestamp*
48-
vitest.config.*.timestamp*
48+
vitest.config.*.timestamp*
49+
.aider*
Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
1+
varying vec3 vPosition;
2+
3+
const vec3 COLOR_1 = vec3(0.894, 0.0, 0.208); // #E40035
4+
const vec3 COLOR_2 = vec3(0.965, 0.039, 0.282); // #F60A48
5+
const vec3 COLOR_3 = vec3(0.949, 0.027, 0.333); // #F20755
6+
const vec3 COLOR_4 = vec3(0.863, 0.031, 0.490); // #DC087D
7+
const vec3 COLOR_5 = vec3(0.592, 0.090, 0.906); // #9717E7
8+
const vec3 COLOR_6 = vec3(0.424, 0.0, 0.961); // #6C00F5
9+
10+
const float STEP_1 = 0.24;
11+
const float STEP_2 = 0.352;
12+
const float STEP_3 = 0.494;
13+
const float STEP_4 = 0.745;
14+
115
void main() {
2-
vec3 color = vec3(0.34, 0.53, 0.96);
16+
float gradientPos = (vPosition.y + 1.0) * 0.5;
17+
18+
vec3 color = gradientPos < STEP_1 ? mix(COLOR_1, COLOR_2, gradientPos / STEP_1) :
19+
gradientPos < STEP_2 ? mix(COLOR_2, COLOR_3, (gradientPos - STEP_1) / (STEP_2 - STEP_1)) :
20+
gradientPos < STEP_3 ? mix(COLOR_3, COLOR_4, (gradientPos - STEP_2) / (STEP_3 - STEP_2)) :
21+
gradientPos < STEP_4 ? mix(COLOR_4, COLOR_5, (gradientPos - STEP_3) / (STEP_4 - STEP_3)) :
22+
mix(COLOR_5, COLOR_6, (gradientPos - STEP_4) / (1.0 - STEP_4));
23+
324
gl_FragColor = vec4(color, 1.0);
425
}

apps/examples/src/app/misc/particle-maxime/scene.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, viewChild } from '@angular/core';
22
import { extend, injectBeforeRender, NgtArgs, NgtPortal } from 'angular-three';
3+
import { NgtpBloom, NgtpEffectComposer } from 'angular-three-postprocessing';
34
import { NgtsPerspectiveCamera } from 'angular-three-soba/cameras';
45
import { NgtsOrbitControls } from 'angular-three-soba/controls';
56
import { injectFBO } from 'angular-three-soba/misc';
@@ -37,7 +38,7 @@ extend({ SimulationMaterial });
3738
</ng-template>
3839
</ngt-portal>
3940
40-
<ngt-points>
41+
<ngt-points [position]="[-1, -1, 0]" [rotation]="[0.05, -0.1, 0]">
4142
<ngt-buffer-geometry>
4243
<ngt-buffer-attribute
4344
attach="attributes.position"
@@ -119,29 +120,32 @@ export class FBOParticles {
119120
gl.render(this.virtualScene, this.virtualCamera);
120121
gl.setRenderTarget(null);
121122

122-
const simulationMateria = this.simulationMaterialRef()?.nativeElement;
123-
124-
if (!simulationMateria) return;
123+
const simulationMaterial = this.simulationMaterialRef()?.nativeElement;
124+
if (!simulationMaterial) return;
125125

126126
this.uniforms['uPositions'].value = this.renderTarget().texture;
127-
simulationMateria.uniforms['uTime'].value = clock.elapsedTime;
127+
simulationMaterial.uniforms['uTime'].value = clock.elapsedTime;
128128
});
129129
}
130130
}
131131

132132
@Component({
133133
selector: 'app-scene-graph',
134134
template: `
135-
<ngts-perspective-camera [options]="{ makeDefault: true, position: [1.5, 1.5, 2.5], fov: 75 }" />
135+
<ngts-perspective-camera [options]="{ makeDefault: true, position: [0, 0, 3] }" />
136136
137-
<ngt-color *args="['#20222B']" attach="background" />
137+
<ngt-color *args="['black']" attach="background" />
138138
<ngt-ambient-light [intensity]="Math.PI * 0.5" />
139139
140140
<app-fbo-particles />
141141
142-
<ngts-orbit-controls [options]="{ autoRotate: true }" />
142+
<ngtp-effect-composer>
143+
<ngtp-bloom [options]="{ luminanceThreshold: 0, intensity: 4 }" />
144+
</ngtp-effect-composer>
145+
146+
<ngts-orbit-controls [options]="{ enablePan: false }" />
143147
`,
144-
imports: [NgtsPerspectiveCamera, NgtsOrbitControls, NgtArgs, FBOParticles],
148+
imports: [NgtsPerspectiveCamera, NgtsOrbitControls, NgtArgs, FBOParticles, NgtpEffectComposer, NgtpBloom],
145149
changeDetection: ChangeDetectionStrategy.OnPush,
146150
schemas: [CUSTOM_ELEMENTS_SCHEMA],
147151
})
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
{
2+
"curve": {
3+
"metadata": {
4+
"version": 4.6,
5+
"type": "BufferGeometry",
6+
"generator": "BufferGeometry.toJSON"
7+
},
8+
"uuid": "53489895-da59-4d5d-9a40-eee5e2e229c9",
9+
"type": "BufferGeometry",
10+
"data": {
11+
"attributes": {
12+
"position": {
13+
"itemSize": 3,
14+
"type": "Float32Array",
15+
"array": [
16+
0.22693952918052673, 0.029999999329447746, -0.09325665235519409, 0.15878146886825562,
17+
0.029999999329447746, -0.23989956080913544, 0.23402345180511475, 0.029999999329447746,
18+
-0.20510819554328918, 0.22693952918052673, -0.029999999329447746, -0.09325665235519409,
19+
0.15878146886825562, -0.029999999329447746, -0.23989956080913544, 0.23402345180511475,
20+
-0.029999999329447746, -0.20510819554328918, 0.22693952918052673, -0.029999999329447746,
21+
-0.09325665235519409, 0.22693952918052673, -0.029999999329447746, -0.09325665235519409,
22+
0.22693952918052673, 0.029999999329447746, -0.09325665235519409, 0.22693952918052673,
23+
0.029999999329447746, -0.09325665235519409, 0.15878146886825562, -0.029999999329447746,
24+
-0.23989956080913544, 0.15878146886825562, 0.029999999329447746, -0.23989956080913544,
25+
0.23402345180511475, -0.029999999329447746, -0.20510819554328918, 0.23402345180511475,
26+
0.029999999329447746, -0.20510819554328918
27+
],
28+
"normalized": false
29+
},
30+
"normal": {
31+
"itemSize": 3,
32+
"type": "Float32Array",
33+
"array": [
34+
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0.18479567766189575, 0,
35+
0.9827770590782166, 0.18479567766189575, 0, 0.9827770590782166, 0.18479567766189575, 0,
36+
0.9827770590782166, 0.18479567766189575, 0, 0.9827770590782166, -0.707806408405304, 0,
37+
-0.7064064145088196, -0.707806408405304, 0, -0.7064064145088196, 0.8591474294662476, 0,
38+
-0.5117282271385193, 0.8591474294662476, 0, -0.5117282271385193
39+
],
40+
"normalized": false
41+
},
42+
"uv": {
43+
"itemSize": 2,
44+
"type": "Float32Array",
45+
"array": [
46+
0, 1, 0.5, 1, 1, 1, 0, 1, 0.5, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0.3333333432674408, 1,
47+
0.3333333432674408, 0, 0.6666666865348816, 1, 0.6666666865348816, 0
48+
],
49+
"normalized": false
50+
}
51+
},
52+
"index": {
53+
"type": "Uint16Array",
54+
"array": [0, 2, 1, 3, 4, 5, 8, 11, 10, 8, 10, 6, 11, 13, 12, 11, 12, 10, 13, 9, 7, 13, 7, 12]
55+
},
56+
"boundingSphere": {
57+
"center": [0.19640246033668518, 0, -0.16657810658216476],
58+
"radius": 0.08770048237491211
59+
}
60+
}
61+
},
62+
"curveTwo": {
63+
"metadata": {
64+
"version": 4.6,
65+
"type": "BufferGeometry",
66+
"generator": "BufferGeometry.toJSON"
67+
},
68+
"uuid": "2ba02139-accd-4e26-bbd0-b52206ce8207",
69+
"type": "BufferGeometry",
70+
"data": {
71+
"attributes": {
72+
"position": {
73+
"itemSize": 3,
74+
"type": "Float32Array",
75+
"array": [
76+
0.13535654544830322, 0.029999999329447746, -0.031094953417778015, 0.08387815952301025,
77+
0.029999999329447746, -0.060440465807914734, 0.09434881806373596, 0.029999999329447746,
78+
-0.08580739796161652, 0.17636427283287048, 0.029999999329447746, -0.08580739796161652,
79+
0.1868349313735962, 0.029999999329447746, -0.060440465807914734, 0.13535654544830322,
80+
-0.029999999329447746, -0.031094953417778015, 0.08387815952301025, -0.029999999329447746,
81+
-0.060440465807914734, 0.09434881806373596, -0.029999999329447746, -0.08580739796161652,
82+
0.17636427283287048, -0.029999999329447746, -0.08580739796161652, 0.1868349313735962,
83+
-0.029999999329447746, -0.060440465807914734, 0.13535654544830322, -0.029999999329447746,
84+
-0.031094953417778015, 0.13535654544830322, -0.029999999329447746, -0.031094953417778015,
85+
0.13535654544830322, 0.029999999329447746, -0.031094953417778015, 0.13535654544830322,
86+
0.029999999329447746, -0.031094953417778015, 0.08387815952301025, -0.029999999329447746,
87+
-0.060440465807914734, 0.08387815952301025, 0.029999999329447746, -0.060440465807914734,
88+
0.09434881806373596, -0.029999999329447746, -0.08580739796161652, 0.09434881806373596,
89+
0.029999999329447746, -0.08580739796161652, 0.17636427283287048, -0.029999999329447746,
90+
-0.08580739796161652, 0.17636427283287048, 0.029999999329447746, -0.08580739796161652,
91+
0.1868349313735962, -0.029999999329447746, -0.060440465807914734, 0.1868349313735962,
92+
0.029999999329447746, -0.060440465807914734
93+
],
94+
"normalized": false
95+
},
96+
"normal": {
97+
"itemSize": 3,
98+
"type": "Float32Array",
99+
"array": [
100+
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
101+
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, -0.9458460211753845, 0, 0.32461580634117126,
102+
-0.9458460211753845, 0, 0.32461580634117126, -0.5561071634292603, 0, -0.8311106562614441,
103+
-0.5561071634292603, 0, -0.8311106562614441, 0.5561071634292603, 0, -0.8311106562614441,
104+
0.5561071634292603, 0, -0.8311106562614441, 0.9458460211753845, 0, 0.32461580634117126,
105+
0.9458460211753845, 0, 0.32461580634117126
106+
],
107+
"normalized": false
108+
},
109+
"uv": {
110+
"itemSize": 2,
111+
"type": "Float32Array",
112+
"array": [
113+
0, 1, 0.25, 1, 0.5, 1, 0.75, 1, 1, 1, 0, 1, 0.25, 1, 0.5, 1, 0.75, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1,
114+
0, 0.20000000298023224, 1, 0.20000000298023224, 0, 0.4000000059604645, 1, 0.4000000059604645, 0,
115+
0.6000000238418579, 1, 0.6000000238418579, 0, 0.800000011920929, 1, 0.800000011920929, 0
116+
],
117+
"normalized": false
118+
}
119+
},
120+
"index": {
121+
"type": "Uint16Array",
122+
"array": [
123+
1, 3, 2, 1, 4, 3, 0, 4, 1, 6, 7, 8, 6, 8, 9, 5, 6, 9, 12, 15, 14, 12, 14, 10, 15, 17, 16, 15, 16,
124+
14, 17, 19, 18, 17, 18, 16, 19, 21, 20, 19, 20, 18, 21, 13, 11, 21, 11, 20
125+
]
126+
},
127+
"boundingSphere": {
128+
"center": [0.13535654544830322, 0, -0.058451175689697266],
129+
"radius": 0.06556208564582824
130+
}
131+
}
132+
},
133+
"curveThree": {
134+
"metadata": {
135+
"version": 4.6,
136+
"type": "BufferGeometry",
137+
"generator": "BufferGeometry.toJSON"
138+
},
139+
"uuid": "080fe7a1-c564-47c5-ab29-a7b2e43ad705",
140+
"type": "BufferGeometry",
141+
"data": {
142+
"attributes": {
143+
"position": {
144+
"itemSize": 3,
145+
"type": "Float32Array",
146+
"array": [
147+
0.1623375415802002, 0.029999999329447746, -0.11870823800563812, 0.1084037721157074,
148+
0.029999999329447746, -0.11870823800563812, 0.13535654544830322, 0.029999999329447746,
149+
-0.1842559576034546, 0.1623375415802002, -0.029999999329447746, -0.11870823800563812,
150+
0.1084037721157074, -0.029999999329447746, -0.11870823800563812, 0.13535654544830322,
151+
-0.029999999329447746, -0.1842559576034546, 0.1623375415802002, -0.029999999329447746,
152+
-0.11870823800563812, 0.1623375415802002, -0.029999999329447746, -0.11870823800563812,
153+
0.1623375415802002, 0.029999999329447746, -0.11870823800563812, 0.1623375415802002,
154+
0.029999999329447746, -0.11870823800563812, 0.1084037721157074, -0.029999999329447746,
155+
-0.11870823800563812, 0.1084037721157074, 0.029999999329447746, -0.11870823800563812,
156+
0.13535654544830322, -0.029999999329447746, -0.1842559576034546, 0.13535654544830322,
157+
0.029999999329447746, -0.1842559576034546
158+
],
159+
"normalized": false
160+
},
161+
"normal": {
162+
"itemSize": 3,
163+
"type": "Float32Array",
164+
"array": [
165+
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0.8308638334274292, 0,
166+
0.556475818157196, 0.8308638334274292, 0, 0.556475818157196, 0.8308638334274292, 0,
167+
0.556475818157196, 0.8308638334274292, 0, 0.556475818157196, -0.8307866454124451, 0,
168+
0.5565910339355469, -0.8307866454124451, 0, 0.5565910339355469, -0.00019999999494757503, 0, -1,
169+
-0.00019999999494757503, 0, -1
170+
],
171+
"normalized": false
172+
},
173+
"uv": {
174+
"itemSize": 2,
175+
"type": "Float32Array",
176+
"array": [
177+
0, 1, 0.5, 1, 1, 1, 0, 1, 0.5, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0.3333333432674408, 1,
178+
0.3333333432674408, 0, 0.6666666865348816, 1, 0.6666666865348816, 0
179+
],
180+
"normalized": false
181+
}
182+
},
183+
"index": {
184+
"type": "Uint16Array",
185+
"array": [1, 0, 2, 4, 5, 3, 8, 11, 10, 8, 10, 6, 11, 13, 12, 11, 12, 10, 13, 9, 7, 13, 7, 12]
186+
},
187+
"boundingSphere": {
188+
"center": [0.1353706568479538, 0, -0.15148209780454636],
189+
"radius": 0.051974404451110574
190+
}
191+
}
192+
},
193+
"curveFour": {
194+
"metadata": {
195+
"version": 4.6,
196+
"type": "BufferGeometry",
197+
"generator": "BufferGeometry.toJSON"
198+
},
199+
"uuid": "b12f976f-1e75-47e5-bf28-50eab4321455",
200+
"type": "BufferGeometry",
201+
"data": {
202+
"attributes": {
203+
"position": {
204+
"itemSize": 3,
205+
"type": "Float32Array",
206+
"array": [
207+
0.0366896390914917, 0.029999999329447746, -0.20510819554328918, 0.11193162202835083,
208+
0.029999999329447746, -0.23989956080913544, 0.04377356171607971, 0.029999999329447746,
209+
-0.09325665235519409, 0.0366896390914917, -0.029999999329447746, -0.20510819554328918,
210+
0.11193162202835083, -0.029999999329447746, -0.23989956080913544, 0.04377356171607971,
211+
-0.029999999329447746, -0.09325665235519409, 0.0366896390914917, -0.029999999329447746,
212+
-0.20510819554328918, 0.0366896390914917, -0.029999999329447746, -0.20510819554328918,
213+
0.0366896390914917, 0.029999999329447746, -0.20510819554328918, 0.0366896390914917,
214+
0.029999999329447746, -0.20510819554328918, 0.11193162202835083, -0.029999999329447746,
215+
-0.23989956080913544, 0.11193162202835083, 0.029999999329447746, -0.23989956080913544,
216+
0.04377356171607971, -0.029999999329447746, -0.09325665235519409, 0.04377356171607971,
217+
0.029999999329447746, -0.09325665235519409
218+
],
219+
"normalized": false
220+
},
221+
"normal": {
222+
"itemSize": 3,
223+
"type": "Float32Array",
224+
"array": [
225+
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -0.8591474294662476, 0,
226+
-0.5117282271385193, -0.8591474294662476, 0, -0.5117282271385193, -0.8591474294662476, 0,
227+
-0.5117282271385193, -0.8591474294662476, 0, -0.5117282271385193, 0.707806408405304, 0,
228+
-0.7064064145088196, 0.707806408405304, 0, -0.7064064145088196, -0.18479567766189575, 0,
229+
0.9827770590782166, -0.18479567766189575, 0, 0.9827770590782166
230+
],
231+
"normalized": false
232+
},
233+
"uv": {
234+
"itemSize": 2,
235+
"type": "Float32Array",
236+
"array": [
237+
0, 1, 0.5, 1, 1, 1, 0, 1, 0.5, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0.3333333432674408, 1,
238+
0.3333333432674408, 0, 0.6666666865348816, 1, 0.6666666865348816, 0
239+
],
240+
"normalized": false
241+
}
242+
},
243+
"index": {
244+
"type": "Uint16Array",
245+
"array": [0, 2, 1, 3, 4, 5, 8, 11, 10, 8, 10, 6, 11, 13, 12, 11, 12, 10, 13, 9, 7, 13, 7, 12]
246+
},
247+
"boundingSphere": {
248+
"center": [0.07431063055992126, 0, -0.16657810658216476],
249+
"radius": 0.08770048237491211
250+
}
251+
}
252+
}
253+
}

apps/examples/src/app/misc/particle-maxime/simulation-fragment.glsl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,18 @@ void main() {
143143
vec3 pos = texture2D(positions, vUv).rgb;
144144
vec3 curlPos = texture2D(positions, vUv).rgb;
145145

146-
pos = curlNoise(pos * uFrequency + uTime * 0.1);
147-
curlPos = curlNoise(curlPos * uFrequency + uTime * 0.1);
148-
curlPos += curlNoise(curlPos * uFrequency * 2.0) * 0.5;
149-
150-
gl_FragColor = vec4(mix(pos, curlPos, sin(uTime)), 1.0);
146+
vec3 originalPos = pos;
147+
vec3 noise = curlNoise(pos * uFrequency + uTime * 0.1);
148+
149+
// Calculate pulsing mix factor (0 to 1)
150+
float pulseSpeed = 0.5;
151+
float mixFactor = (sin(uTime * pulseSpeed) + 1.0) * 0.5;
152+
153+
// Mix between original position and noise with pulsing effect
154+
pos = mix(originalPos, originalPos + noise * 0.8, mixFactor);
155+
156+
// Add secondary motion that also pulses
157+
pos += curlNoise(pos * uFrequency * 3.0) * 0.2 * mixFactor;
158+
159+
gl_FragColor = vec4(pos, 1.0);
151160
}

0 commit comments

Comments
 (0)