Skip to content

Commit 857d2b4

Browse files
committed
feat: Add speed rannge and age range
1 parent 675de43 commit 857d2b4

File tree

8 files changed

+52
-33
lines changed

8 files changed

+52
-33
lines changed

.tkb

+2-14
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
"description": "Add `NPM_AUTH_TOKEN` to repository secrets to automate package publishing\n - Log in to your [`npm` account](https://www.npmjs.com/login) and create an automation token\n - Create a new repository secret `NPM_AUTH_TOKEN`",
1717
"columnId": "column-todo"
1818
},
19-
"_BfuX7quWBANpDK1bI7YM": {
20-
"id": "_BfuX7quWBANpDK1bI7YM",
21-
"description": "Update description in `lib/package.json`",
22-
"columnId": "column-todo"
23-
},
2419
"dC7QDBLH8BmHUfaYmIt81": {
2520
"id": "dC7QDBLH8BmHUfaYmIt81",
2621
"description": "(Optional) Add Repo Stats by visiting and setting up [repobeats](https://repobeats.axiom.co/)",
@@ -68,12 +63,7 @@
6863
},
6964
"9-0sxOV9Cw-jVjngwbWKm": {
7065
"id": "9-0sxOV9Cw-jVjngwbWKm",
71-
"description": "Add colors",
72-
"columnId": "column-KpcfQ3OwiDZ1c11EOpcsT"
73-
},
74-
"GJ4z5bji9Cpt9LjmhSwkW": {
75-
"id": "GJ4z5bji9Cpt9LjmhSwkW",
76-
"description": "fix angles",
66+
"description": "Add multiple colors",
7767
"columnId": "column-KpcfQ3OwiDZ1c11EOpcsT"
7868
}
7969
},
@@ -85,7 +75,6 @@
8575
"RX4J5v4y5IOe_ucf8pMRT",
8676
"MLLUsAhCKaKxvEXFY0HSq",
8777
"gMYfaAh2RABMP8uZRQgNx",
88-
"_BfuX7quWBANpDK1bI7YM",
8978
"dC7QDBLH8BmHUfaYmIt81",
9079
"P_NrSJQ8m91Odgz8E1fS6",
9180
"1dRWJhy45E1Rq5wZAmPHt",
@@ -101,8 +90,7 @@
10190
"id": "column-KpcfQ3OwiDZ1c11EOpcsT",
10291
"title": "Backlog",
10392
"tasksIds": [
104-
"9-0sxOV9Cw-jVjngwbWKm",
105-
"GJ4z5bji9Cpt9LjmhSwkW"
93+
"9-0sxOV9Cw-jVjngwbWKm"
10694
]
10795
},
10896
{

.vscode/settings.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@
1313
"editor.formatOnSave": true,
1414
"editor.formatOnPaste": true,
1515
"editor.formatOnSaveMode": "file",
16-
"mayank1513.trello-kanban.Workspace.filePath": ".tkb"
16+
"mayank1513.trello-kanban.Workspace.filePath": ".tkb",
17+
"[glsl]": {
18+
"editor.defaultFormatter": "circledev.glsl-canvas"
19+
}
1720
}

examples/nextjs/src/app/layout.tsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,18 @@ export default function RootLayout({ children }: { children: React.ReactNode }):
2020
{children}
2121
</Layout>
2222
<GlobalLoader />
23-
<Particles fullScreenOverlay />
23+
<Particles
24+
fullScreenOverlay
25+
options={{
26+
speedRange: [200, 250],
27+
maxParticles: 10000,
28+
generationRate: 0.2,
29+
angleRage: [Math.PI / 4, (3 * Math.PI) / 4],
30+
forceField: [0, -0.02],
31+
ageRange: [0.2, 0.5],
32+
}}
33+
/>
34+
<Particles style={{ height: "500px", width: "600px" }} />
2435
</body>
2536
</html>
2637
);

lib/src/shaders/render-frag.glsl

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#version 300 es
22
precision mediump float;
33

4-
uniform vec4 c; /** Particle Color */
4+
uniform vec4 c;/** Particle Color */
55

66
out vec4 oC;
77

8-
void main() {
9-
oC = c;
8+
void main(){
9+
oC=c;
1010
}

lib/src/shaders/render-vert.glsl

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ precision mediump float;
44
in vec2 p;
55

66
void main() {
7-
gl_PointSize = 1.0;
8-
gl_Position = vec4(p, 0.0, 1.0);
7+
gl_PointSize = 1.f;
8+
gl_Position = vec4(p, 0.f, 1.f);
99
}

lib/src/shaders/update-vert.glsl

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ uniform sampler2D rg; /** random rg */
66
uniform vec2 g; /** gravity - forceField */
77
uniform vec2 o; /** origin*/
88
uniform vec2 aR; /** Angle Range */
9+
uniform vec2 sR; /** scalar Speed Range pixels/sec */
10+
uniform vec2 lR; /** life range */
911

1012
in vec2 p; /** position */
1113
in float l; /** Life */
@@ -16,15 +18,15 @@ out float oL;
1618
out vec2 oV;
1719

1820
void main() {
19-
if(l <= 0.0) {
21+
if(l <= 0.0f) {
2022
ivec2 ij = ivec2(gl_VertexID % 512, gl_VertexID / 512);
2123
vec2 rd = texelFetch(rg, ij, 0).rg;
2224
float th = aR.x + rd.r * (aR.y - aR.x);
2325
float x = cos(th);
2426
float y = sin(th);
2527
oP = o;
26-
oL = rd.r + rd.g;
27-
oV = vec2(x, y) * rd.g;
28+
oL = lR.x + rd.r * (lR.y - lR.x);
29+
oV = vec2(x, y) * (sR.x + (sR.y - sR.x) * rd.g);
2830
} else {
2931
oP = p + v * dt;
3032
oL = l - dt;

lib/src/simulator.ts

+24-8
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ import renderFragmentShaderSource from "./shaders/render-frag.glsl?raw";
55

66
// constnats
77
const PI = Math.PI;
8+
const random = Math.random;
89
/** shader names */
910
// Uniforms
1011
const U_DT = "dt";
1112
const U_RANDOM_RG = "rg";
1213
const U_FORCE_FIELD = "g"; /** gravity */
1314
const U_ORIGIN = "o";
1415
const U_ANGLE_RANGE = "aR";
16+
const U_SPEED_RANGE = "sR";
17+
const U_LIFE_RANGE = "lR";
1518
const U_PARTICLE_COLOR = "c";
1619

1720
// inputs
@@ -43,21 +46,23 @@ export interface ParticlesOptions {
4346
mouseOff?: boolean;
4447
/** min and max Angles in radians: @defaultValue [-Math.PI, Math.PI] */
4548
angleRage?: [number, number];
46-
/** todo */
47-
/** min and max age of particles */
49+
/** min and max age of particles in seconds */
4850
ageRange?: [number, number];
4951
/** [minSpeed, maxSpeed] */
5052
speedRange?: [number, number];
53+
/** todo */
5154
/** todo: WIP constant force [fx, fy] or a force field texture */
5255
forceField?: Vector2D; //| Vector[][] | string;
5356
}
5457

5558
const defaultOptions: ParticlesOptions = {
5659
rgba: [1, 0, 0, 1],
57-
maxParticles: 100_000,
58-
generationRate: 0.5,
59-
forceField: [0, -0.1],
60+
maxParticles: 1000_000,
61+
generationRate: 1,
62+
forceField: [0, -0.25],
6063
angleRage: [-PI, PI],
64+
speedRange: [0.5, 1],
65+
ageRange: [2, 10],
6166
};
6267

6368
const getInitialData = (maxParticles: number) => {
@@ -68,14 +73,20 @@ const getInitialData = (maxParticles: number) => {
6873

6974
const randomRGData = (sizeX: number, sizeY: number): Uint8Array => {
7075
const data = [];
71-
for (let i = 0; i < sizeX * sizeY; ++i) data.push(Math.random() * sizeX, Math.random() * sizeX);
76+
for (let i = 0; i < sizeX * sizeY; i++) data.push(random() * 255.0, random() * 255.0);
7277
return new Uint8Array(data);
7378
};
7479

7580
/** Particles simulator */
76-
const simulate = (gl: WebGL2RenderingContext, options: ParticlesOptions) => {
81+
const simulate = (
82+
canvas: HTMLCanvasElement,
83+
gl: WebGL2RenderingContext,
84+
options: ParticlesOptions,
85+
) => {
7786
/** Normalize options */
7887
options.angleRage?.map(a => a % PI).sort();
88+
options.ageRange?.sort();
89+
options.speedRange?.sort();
7990
/** Create shader */
8091
const createShader = (type: number, source: string): WebGLShader => {
8192
const shader = gl.createShader(type);
@@ -237,6 +248,11 @@ const simulate = (gl: WebGL2RenderingContext, options: ParticlesOptions) => {
237248
setUpdateUniform(U_ORIGIN, mouseX, mouseY);
238249
// skipcq: JS-0339 -- set in default options
239250
setUpdateUniform(U_ANGLE_RANGE, ...options.angleRage!);
251+
// skipcq: JS-0339 -- set in default options
252+
setUpdateUniform(U_LIFE_RANGE, ...options.ageRange!);
253+
// skipcq: JS-0339 -- set in default options
254+
const speedRange = options.speedRange!;
255+
setUpdateUniform(U_SPEED_RANGE, speedRange[0] / canvas.width, speedRange[1] / canvas.height);
240256
gl.activeTexture(gl.TEXTURE0);
241257
gl.bindTexture(gl.TEXTURE_2D, rgNoiseTexture);
242258
setUpdateUniform(U_RANDOM_RG, 0);
@@ -285,7 +301,7 @@ export const renderParticles = (canvas: HTMLCanvasElement, options?: ParticlesOp
285301
const gl = canvas.getContext("webgl2");
286302
if (!gl) return undefined;
287303

288-
simulate(gl, { ...defaultOptions, ...options });
304+
simulate(canvas, gl, { ...defaultOptions, ...options });
289305

290306
/** Set up observer to observe size changes */
291307
const observer = new ResizeObserver(entries => {

lib/tsup.config.ts

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export default defineConfig(
2121
setup(build) {
2222
if (!options.watch)
2323
build.onLoad({ filter: /simulator\.ts$/, namespace: "file" }, args => {
24-
console.log("utils ----- >", args.path);
2524
const text = fs.readFileSync(args.path, "utf8");
2625
const contents = text
2726
.replace(/if \(!gl\.[^}]*}/gm, "")

0 commit comments

Comments
 (0)