react-particle-physics 1.0.0

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.
@@ -0,0 +1,2 @@
1
+ export declare const lineVertexShader = "\nprecision highp float;\n\nuniform float uTime;\nuniform float uAmplitude;\nuniform float uLineWidth;\nuniform float uPixelRatio;\nuniform float uInteractionRadius;\nuniform float uDisplacementStrength;\nuniform float uDestructTime;\nuniform vec2 uPointer;\n\nattribute float aBrightness;\nattribute vec2 aUv;\nattribute float aSeed;\nattribute vec3 aOriginalColor;\n\nvarying float vBrightness;\nvarying float vSeed;\nvarying vec3 vOriginalColor;\nvarying vec2 vUv;\n\nfloat hash11(float p) {\n p = fract(p * 0.1031);\n p *= p + 33.33;\n p *= p + p;\n return fract(p);\n}\n\nvoid main() {\n vec3 transformed = position;\n\n // Pointer repulsion (same as particle system)\n vec2 delta = aUv - uPointer;\n float distanceToPointer = length(delta);\n float influence = 1.0 - smoothstep(0.0, uInteractionRadius, distanceToPointer);\n influence = pow(influence, 1.75);\n vec2 safeDelta = delta / max(distanceToPointer, 0.0001);\n vec2 repel = safeDelta * influence * uDisplacementStrength;\n transformed.xy += repel;\n\n // Subtle ambient motion\n float noise = hash11(aSeed + uTime * 0.15);\n vec2 ambient = vec2(\n sin(uTime * 0.3 + aSeed * 8.0),\n cos(uTime * 0.25 + aSeed * 5.0)\n ) * 0.001;\n transformed.xy += ambient * (0.5 + noise);\n\n // Self-destruct\n if (uDestructTime > 0.0) {\n vec3 outward = normalize(transformed + vec3(\n hash11(aSeed) - 0.5,\n hash11(aSeed * 2.0) - 0.5,\n hash11(aSeed * 3.0) - 0.5\n ) * 0.5);\n float speed = (2.0 + hash11(aSeed * 5.0) * 8.0) * uDestructTime + uDestructTime * uDestructTime * 15.0;\n transformed += outward * speed;\n }\n\n vec4 mvPosition = modelViewMatrix * vec4(transformed, 1.0);\n float perspectiveScale = 1.0 / max(0.6, -mvPosition.z);\n gl_PointSize = uLineWidth * uPixelRatio * perspectiveScale;\n gl_Position = projectionMatrix * mvPosition;\n\n vBrightness = aBrightness;\n vSeed = aSeed;\n vOriginalColor = aOriginalColor;\n vUv = aUv;\n}\n";
2
+ export declare const lineFragmentShader = "\nprecision highp float;\n\nuniform float uTime;\nuniform vec3 uColor;\nuniform float uGlowIntensity;\nuniform int uColorMode;\nuniform float uOpacityVariation;\nuniform float uDestructTime;\n\nvarying float vBrightness;\nvarying float vSeed;\nvarying vec3 vOriginalColor;\nvarying vec2 vUv;\n\nfloat hash11(float p) {\n p = fract(p * 0.1031);\n p *= p + 33.33;\n p *= p + p;\n return fract(p);\n}\n\nvec3 seedToColor(float s) {\n return vec3(\n 0.5 + 0.5 * sin(s * 6.2831 * 1.0 + 0.0),\n 0.5 + 0.5 * sin(s * 6.2831 * 1.5 + 2.094),\n 0.5 + 0.5 * sin(s * 6.2831 * 2.0 + 4.188)\n );\n}\n\nvoid main() {\n // Soft circular point for smooth line appearance\n vec2 centered = gl_PointCoord - 0.5;\n float dist = length(centered);\n float soft = 1.0 - smoothstep(0.3, 0.5, dist);\n\n float alpha = vBrightness * mix(1.0, 0.55 + vBrightness * 0.45, uOpacityVariation);\n alpha *= soft;\n float sparkle = mix(0.88, 1.08, hash11(vSeed * 37.0 + floor(uTime * 4.0)));\n\n vec3 baseColor = uColor;\n if (uColorMode == 1) {\n baseColor = seedToColor(vSeed);\n } else if (uColorMode == 2) {\n baseColor = vOriginalColor;\n }\n\n float glow = uGlowIntensity * 0.4;\n vec3 color = baseColor * (0.72 + vBrightness * 0.32 + glow) * sparkle;\n\n if (uDestructTime > 0.0) {\n alpha *= max(0.0, 1.0 - uDestructTime * 0.4);\n }\n\n gl_FragColor = vec4(color, alpha);\n}\n";
@@ -0,0 +1,4 @@
1
+ export declare const particleVertexShader = "\nprecision highp float;\n\nuniform float uTime;\nuniform float uPixelRatio;\nuniform float uParticleSize;\nuniform float uInteractionRadius;\nuniform float uDisplacementStrength;\nuniform float uTrailStrength;\nuniform float uDestructTime;\nuniform vec2 uPointer;\nuniform sampler2D uTrailTexture;\n\nattribute vec2 aUv;\nattribute float aSeed;\nattribute float aOpacity;\nattribute vec3 aOriginalColor;\n\nvarying float vOpacity;\nvarying float vSeed;\nvarying float vTrail;\nvarying vec3 vOriginalColor;\n\nfloat hash11(float p) {\n p = fract(p * 0.1031);\n p *= p + 33.33;\n p *= p + p;\n return fract(p);\n}\n\nvoid main() {\n vec3 transformed = position;\n vec2 delta = aUv - uPointer;\n float distanceToPointer = length(delta);\n float influence = 1.0 - smoothstep(0.0, uInteractionRadius, distanceToPointer);\n influence = pow(influence, 1.75);\n\n vec2 safeDelta = delta / max(distanceToPointer, 0.0001);\n vec2 repel = safeDelta * influence * uDisplacementStrength;\n\n vec4 trailSample = texture2D(uTrailTexture, aUv);\n vec2 trail = trailSample.rg * 2.0 - 1.0;\n float trailEnergy = trailSample.a;\n\n float noise = hash11(aSeed + uTime * 0.2);\n vec2 ambient = vec2(sin(uTime * 0.5 + aSeed * 12.1), cos(uTime * 0.37 + aSeed * 4.9)) * 0.0015;\n\n transformed.xy += repel;\n transformed.xy += trail * (uTrailStrength * (0.2 + trailEnergy));\n transformed.xy += ambient * (0.5 + noise);\n transformed.z += trailEnergy * 0.04;\n\n if (uDestructTime > 0.0) {\n vec3 outward = normalize(transformed + vec3(hash11(aSeed) - 0.5, hash11(aSeed * 2.0) - 0.5, hash11(aSeed * 3.0) - 0.5) * 0.5);\n float speed = (2.0 + hash11(aSeed * 5.0) * 8.0) * uDestructTime + uDestructTime * uDestructTime * 15.0;\n transformed += outward * speed;\n transformed.x += sin(uDestructTime * 10.0 + aSeed * 20.0) * uDestructTime * 0.5;\n transformed.y += cos(uDestructTime * 12.0 + aSeed * 25.0) * uDestructTime * 0.5;\n }\n\n vec4 mvPosition = modelViewMatrix * vec4(transformed, 1.0);\n float perspectiveScale = 1.0 / max(0.6, -mvPosition.z);\n gl_PointSize = uParticleSize * uPixelRatio * perspectiveScale * (0.72 + aOpacity * 0.55);\n gl_Position = projectionMatrix * mvPosition;\n\n vOpacity = aOpacity;\n vSeed = aSeed;\n vTrail = trailEnergy;\n vOriginalColor = aOriginalColor;\n}\n";
2
+ export declare const particleFragmentShader = "\nprecision highp float;\n\nuniform float uTime;\nuniform vec3 uColor;\nuniform float uGlowIntensity;\nuniform int uColorMode;\nuniform float uOpacityVariation;\nuniform float uDestructTime;\n\nvarying float vOpacity;\nvarying float vSeed;\nvarying float vTrail;\nvarying vec3 vOriginalColor;\n\nfloat hash11(float p) {\n p = fract(p * 0.1031);\n p *= p + 33.33;\n p *= p + p;\n return fract(p);\n}\n\nvec3 seedToColor(float s) {\n return vec3(\n 0.5 + 0.5 * sin(s * 6.2831 * 1.0 + 0.0),\n 0.5 + 0.5 * sin(s * 6.2831 * 1.5 + 2.094),\n 0.5 + 0.5 * sin(s * 6.2831 * 2.0 + 4.188)\n );\n}\n\nvoid main() {\n vec2 centered = gl_PointCoord - 0.5;\n float dist = length(centered);\n float soft = 1.0 - smoothstep(0.22, 0.5, dist);\n float halo = 1.0 - smoothstep(0.0, 0.5, dist);\n float sparkle = mix(0.88, 1.08, hash11(vSeed * 37.0 + floor(uTime * 4.0)));\n\n float alpha = soft * soft * mix(1.0, 0.55 + vOpacity * 0.45, uOpacityVariation);\n alpha *= mix(0.9, 1.12, vTrail);\n\n vec3 baseColor = uColor;\n if (uColorMode == 1) {\n baseColor = seedToColor(vSeed);\n } else if (uColorMode == 2) {\n baseColor = vOriginalColor;\n }\n\n float glow = pow(halo, max(0.1, 2.0 - uGlowIntensity)) * uGlowIntensity * 0.6;\n vec3 color = baseColor * (0.72 + halo * 0.32 + glow) * sparkle;\n\n if (uDestructTime > 0.0) {\n alpha *= max(0.0, 1.0 - uDestructTime * 0.4);\n }\n\n gl_FragColor = vec4(color, alpha);\n}\n";
3
+ export declare const trailVertexShader = "\nprecision highp float;\n\nvarying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n";
4
+ export declare const trailFragmentShader = "\nprecision highp float;\n\nuniform sampler2D uPreviousTrail;\nuniform vec2 uPointer;\nuniform vec2 uPreviousPointer;\nuniform float uDecay;\nuniform float uBrushSize;\nuniform float uBrushStrength;\nuniform float uTime;\n\nvarying vec2 vUv;\n\nfloat lineMask(vec2 p, vec2 a, vec2 b, float radius) {\n vec2 pa = p - a;\n vec2 ba = b - a;\n float h = clamp(dot(pa, ba) / max(dot(ba, ba), 0.0001), 0.0, 1.0);\n return 1.0 - smoothstep(radius * 0.72, radius, length(pa - ba * h));\n}\n\nvoid main() {\n vec4 texColor = texture2D(uPreviousTrail, vUv);\n \n // Decode flow from 0..1 to -1..1\n vec2 prevFlow = texColor.rg * 2.0 - 1.0;\n \n // Apply decay\n prevFlow *= uDecay;\n float prevEnergy = texColor.a * uDecay;\n\n float pointerGlow = 1.0 - smoothstep(uBrushSize, uBrushSize * 1.7, length(vUv - uPointer));\n float trailGlow = lineMask(vUv, uPreviousPointer, uPointer, uBrushSize * 0.75);\n float pulse = 0.9 + 0.1 * sin(uTime * 2.0);\n\n vec2 motion = uPointer - uPreviousPointer;\n // Scale motion by a constant so faster movements create larger flow, \n // without jumping to 100% force on tiny directional changes.\n vec2 flow = motion * 50.0 * (pointerGlow + trailGlow);\n \n vec2 newFlow = clamp(prevFlow + flow * uBrushStrength, -1.0, 1.0);\n float newEnergy = max(prevEnergy, max(pointerGlow, trailGlow) * pulse * uBrushStrength);\n\n // Encode flow back to 0..1\n gl_FragColor = vec4(newFlow * 0.5 + 0.5, newEnergy, newEnergy);\n}\n";
@@ -0,0 +1,14 @@
1
+ export type PerformanceTier = 'low' | 'medium' | 'high' | 'ultra';
2
+ /**
3
+ * Safely sniffs hardware concurrency and device memory.
4
+ * Falls back to conservative defaults if the browser restricts access.
5
+ */
6
+ export declare function detectPerformanceTier(): PerformanceTier;
7
+ /**
8
+ * Returns preset config for a given tier.
9
+ */
10
+ export declare function getPresetSettings(tier: PerformanceTier): {
11
+ particleCount: number;
12
+ particleSize: number;
13
+ lineCount: number;
14
+ };
@@ -0,0 +1,19 @@
1
+ export type ParticleSample = {
2
+ position: Float32Array;
3
+ uv: Float32Array;
4
+ color: Float32Array;
5
+ seed: Float32Array;
6
+ opacity: Float32Array;
7
+ count: number;
8
+ width: number;
9
+ height: number;
10
+ };
11
+ export type ParticleSampleMode = 'alpha' | 'luma' | 'edge' | 'hybrid';
12
+ export type ParticleSamplingOptions = {
13
+ maxTextureSize?: number;
14
+ mode?: ParticleSampleMode;
15
+ alphaThreshold?: number;
16
+ lumaThreshold?: number;
17
+ edgeThreshold?: number;
18
+ };
19
+ export declare function sampleLogoToParticles(imageUrl: string, targetCount: number, options?: ParticleSamplingOptions): Promise<ParticleSample>;
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "react-particle-physics",
3
+ "version": "1.0.0",
4
+ "description": "A high-performance particle and topographic line simulation library for React Three Fiber (R3F), powered by Ping-Pong GPU Frame Buffer Objects (FBOs).",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "BEST_PRACTICES.md"
19
+ ],
20
+ "scripts": {
21
+ "test": "echo \"Error: no test specified\" && exit 1",
22
+ "build": "tsup src/index.ts --format cjs,esm --clean && tsc --emitDeclarationOnly --outDir dist"
23
+ },
24
+ "keywords": [
25
+ "react",
26
+ "three-fiber",
27
+ "r3f",
28
+ "particles",
29
+ "fbo",
30
+ "gpu-physics",
31
+ "shaders",
32
+ "webgl",
33
+ "topography"
34
+ ],
35
+ "author": "",
36
+ "license": "MIT",
37
+ "devDependencies": {
38
+ "@react-three/fiber": "^9.6.1",
39
+ "@types/react": "^19.2.17",
40
+ "@types/three": "^0.184.1",
41
+ "react": "^19.2.7",
42
+ "three": "^0.184.0",
43
+ "tsup": "^8.5.1",
44
+ "typescript": "^6.0.3"
45
+ },
46
+ "peerDependencies": {
47
+ "@react-three/fiber": "^8.0.0 || ^9.0.0",
48
+ "react": "^18.0.0 || ^19.0.0",
49
+ "three": "^0.160.0 || ^0.184.0"
50
+ }
51
+ }