Skip to content

Commit 77aeec9

Browse files
committed
fix: set origin tied to canvas
1 parent cd07b54 commit 77aeec9

File tree

2 files changed

+32
-32
lines changed

2 files changed

+32
-32
lines changed

lib/src/shaders/update-vert.glsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#version 300 es
22
precision mediump float;
33

4-
uniform float dt; /** time delta */
4+
uniform float dt;/** time delta */
55
uniform sampler2D rg; /** random rg */
66
uniform vec2 g; /** gravity - forceField */
77
uniform vec2 o; /** origin*/
@@ -18,15 +18,15 @@ out float oL;
1818
out vec2 oV;
1919

2020
void main() {
21-
if(l <= 0.0f) {
21+
if(l <= 0.f) {
2222
ivec2 ij = ivec2(gl_VertexID % 512, gl_VertexID / 512);
2323
vec2 rd = texelFetch(rg, ij, 0).rg;
2424
float th = aR.x + rd.r * (aR.y - aR.x);
2525
float x = cos(th);
2626
float y = sin(th);
2727
oP = o;
2828
oL = lR.x + rd.r * (lR.y - lR.x);
29-
oV = vec2(x, y) * (sR.x + (sR.y - sR.x) * rd.g);
29+
oV = vec2(x, y) * (sR.x + rd.g * (sR.y - sR.x));
3030
} else {
3131
oP = p + v * dt;
3232
oL = l - dt;

lib/src/simulator.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ const OUT_POSITION = "oP";
2727
const OUT_LIFE = "oL";
2828
const OUT_VELOCITY = "oV";
2929

30-
/** module scoped global variables/constants */
31-
let mouseX = 0,
32-
mouseY = 0;
33-
3430
type Vector2D = [number, number];
3531

3632
export interface ParticlesOptions {
@@ -50,6 +46,10 @@ export interface ParticlesOptions {
5046
ageRange?: [number, number];
5147
/** [minSpeed, maxSpeed] */
5248
speedRange?: [number, number];
49+
/** Initial origin -> Will update as per mouse position when mouse moved if mouseOff is not set.
50+
* @defaultValue [0, 0]
51+
*/
52+
origin?: [number, number];
5353
/** todo */
5454
/** todo: WIP constant force [fx, fy] or a force field texture */
5555
forceField?: Vector2D; //| Vector[][] | string;
@@ -65,12 +65,14 @@ const defaultOptions: ParticlesOptions = {
6565
ageRange: [2, 10],
6666
};
6767

68+
/** generate initial data for the simulation */
6869
const getInitialData = (maxParticles: number) => {
6970
const data = [];
70-
for (let i = 0; i < maxParticles; i++) data.push(0, 0, 1, 0, 0);
71+
for (let i = 0; i < maxParticles; i++) data.push(0, 0, 0.1, 0, 0);
7172
return data;
7273
};
7374

75+
/** generate random RG data for source of randomness within the simulation */
7476
const randomRGData = (sizeX: number, sizeY: number): Uint8Array => {
7577
const data = [];
7678
for (let i = 0; i < sizeX * sizeY; i++) data.push(random() * 255.0, random() * 255.0);
@@ -79,14 +81,15 @@ const randomRGData = (sizeX: number, sizeY: number): Uint8Array => {
7981

8082
/** Particles simulator */
8183
const simulate = (
82-
canvas: HTMLCanvasElement,
84+
_canvas: HTMLCanvasElement,
8385
gl: WebGL2RenderingContext,
8486
options: ParticlesOptions,
8587
) => {
86-
/** Normalize options */
87-
options.angleRage?.map(a => a % PI).sort();
88-
options.ageRange?.sort();
89-
options.speedRange?.sort();
88+
/** todo Normalize options
89+
* canvas positions are between -1 to 1 on all axes
90+
*/
91+
// skipcq: JS-0339 -- defined in default options
92+
const angleRage = options.angleRage! as [number, number];
9093
/** Create shader */
9194
const createShader = (type: number, source: string): WebGLShader => {
9295
const shader = gl.createShader(type);
@@ -105,6 +108,7 @@ const simulate = (
105108
return shader;
106109
};
107110

111+
/** Create program */
108112
const createProgram = (
109113
vertexShaderSource: string,
110114
fragmentShaderSource: string,
@@ -227,11 +231,17 @@ const simulate = (
227231
const location = gl.getUniformLocation(updateProgram, name);
228232
y ? gl.uniform2f(location, x, y) : gl.uniform1f(location, x);
229233
};
230-
let bornParticles = 0;
231234
let prevT = 0;
235+
let bornParticles = 0;
232236
let readIndex = 0;
233237
let writeIndex = 1;
238+
let mouseX = 0;
239+
let mouseY = 0;
234240

241+
const setOrigin = (x: number, y: number): void => {
242+
mouseX = x;
243+
mouseY = y;
244+
};
235245
/** The render loop */
236246
const render = (timeStamp: number): void => {
237247
let dt = timeStamp - prevT;
@@ -246,13 +256,12 @@ const simulate = (
246256
// skipcq: JS-0339 -- forcefield is always set by the default options
247257
setUpdateUniform(U_FORCE_FIELD, ...options.forceField!);
248258
setUpdateUniform(U_ORIGIN, mouseX, mouseY);
249-
// skipcq: JS-0339 -- set in default options
250-
setUpdateUniform(U_ANGLE_RANGE, ...options.angleRage!);
259+
setUpdateUniform(U_ANGLE_RANGE, ...angleRage);
251260
// skipcq: JS-0339 -- set in default options
252261
setUpdateUniform(U_LIFE_RANGE, ...options.ageRange!);
253262
// skipcq: JS-0339 -- set in default options
254263
const speedRange = options.speedRange!;
255-
setUpdateUniform(U_SPEED_RANGE, speedRange[0] / canvas.width, speedRange[1] / canvas.height);
264+
setUpdateUniform(U_SPEED_RANGE, speedRange[0], speedRange[1]);
256265
gl.activeTexture(gl.TEXTURE0);
257266
gl.bindTexture(gl.TEXTURE_2D, rgNoiseTexture);
258267
setUpdateUniform(U_RANDOM_RG, 0);
@@ -277,7 +286,7 @@ const simulate = (
277286
// skipcq: JS-0339
278287
options.maxParticles!,
279288
// skipcq: JS-0339
280-
Math.floor(bornParticles + options.maxParticles! * options.generationRate!),
289+
Math.floor(bornParticles + dt * options.generationRate!),
281290
);
282291

283292
requestAnimationFrame(ts => {
@@ -288,6 +297,7 @@ const simulate = (
288297
requestAnimationFrame(ts => {
289298
render(ts);
290299
});
300+
return setOrigin;
291301
};
292302

293303
/**
@@ -301,22 +311,22 @@ export const renderParticles = (canvas: HTMLCanvasElement, options?: ParticlesOp
301311
const gl = canvas.getContext("webgl2");
302312
if (!gl) return undefined;
303313

304-
simulate(canvas, gl, { ...defaultOptions, ...options });
314+
const setOrigin = simulate(canvas, gl, { ...defaultOptions, ...options });
315+
options?.origin && setOrigin(...options.origin);
305316

306317
/** Set up observer to observe size changes */
307318
const observer = new ResizeObserver(entries => {
308319
const { width, height } = entries[0].contentRect;
309320
canvas.width = width;
310321
canvas.height = height;
311-
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
322+
gl.viewport(0, 0, canvas.width, canvas.height);
312323
});
313324
observer.observe(canvas);
314325

315326
const target = options?.overlay ? window : canvas;
316327
/** update mouse position */
317328
const onMouseMove = (e: MouseEvent) => {
318-
mouseX = (e.clientX / canvas.width) * 2 - 1;
319-
mouseY = 1 - (e.clientY / canvas.height) * 2;
329+
setOrigin((e.clientX / canvas.width) * 2 - 1, 1 - (e.clientY / canvas.height) * 2);
320330
};
321331

322332
// @ts-expect-error -- strange type-error
@@ -328,13 +338,3 @@ export const renderParticles = (canvas: HTMLCanvasElement, options?: ParticlesOp
328338
!options?.mouseOff && target.removeEventListener("mousemove", onMouseMove);
329339
};
330340
};
331-
332-
/**
333-
* Should allow users to set origin manually?
334-
*/
335-
336-
/** Extra functions */
337-
export const setOrigin = (x: number, y: number) => {
338-
mouseX = x;
339-
mouseY = y;
340-
};

0 commit comments

Comments
 (0)