@wolffo/three-fire 1.0.4 → 1.0.6

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/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Three fire
2
2
 
3
3
  [![CI](https://github.com/typeWolffo/THREE.Fire/workflows/CI/badge.svg)](https://github.com/typeWolffo/THREE.Fire/actions)
4
+ [![Tests](https://img.shields.io/github/actions/workflow/status/typeWolffo/THREE.Fire/ci.yml?label=tests)](https://github.com/typeWolffo/THREE.Fire/actions)
5
+ [![Coverage](https://img.shields.io/badge/coverage-92%25-brightgreen)](https://github.com/typeWolffo/THREE.Fire)
4
6
  [![npm version](https://img.shields.io/npm/v/@wolffo/three-fire.svg)](https://www.npmjs.com/package/@wolffo/three-fire)
5
7
  [![npm downloads](https://img.shields.io/npm/dm/@wolffo/three-fire.svg)](https://www.npmjs.com/package/@wolffo/three-fire)
6
8
 
@@ -171,8 +173,29 @@ npm run typecheck
171
173
 
172
174
  # Run tests
173
175
  npm test
176
+
177
+ # Test in watch mode
178
+ npm run test:watch
179
+
180
+ # Visual test UI
181
+ npm run test:ui
182
+
183
+ # Coverage report
184
+ npm run test:coverage
174
185
  ```
175
186
 
187
+ ### Testing
188
+
189
+ The project includes comprehensive tests with **92%+ coverage**:
190
+
191
+ - **49 test cases** covering all functionality
192
+ - **Unit tests** for Fire class and FireShader
193
+ - **Integration tests** for React components
194
+ - **Mock environment** for Three.js and React Three Fiber
195
+ - **Coverage reporting** with detailed metrics
196
+
197
+ Test files are located in `test/` and use Vitest with Testing Library.
198
+
176
199
  ## Credits
177
200
 
178
201
  Based on the original THREE.Fire by [mattatz](https://github.com/mattatz/THREE.Fire)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wolffo/three-fire",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "type": "module",
5
5
  "description": "Modern TypeScript volumetric fire effect for Three.js and React Three Fiber",
6
6
  "main": "dist/index.js",
@@ -8,16 +8,19 @@
8
8
  "module": "dist/index.esm.js",
9
9
  "exports": {
10
10
  ".": {
11
+ "types": "./dist/index.d.ts",
11
12
  "import": "./dist/index.esm.js",
12
- "require": "./dist/index.js",
13
- "types": "./dist/index.d.ts"
13
+ "require": "./dist/index.js"
14
14
  }
15
15
  },
16
16
  "scripts": {
17
17
  "build": "rollup -c",
18
18
  "dev": "rollup -c -w",
19
19
  "typecheck": "tsc --noEmit",
20
- "test": "node test/test-vanilla.js",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "test:ui": "vitest --ui",
23
+ "test:coverage": "vitest run --coverage",
21
24
  "prepublishOnly": "npm run build",
22
25
  "release:patch": "npm version patch && git push origin master --tags",
23
26
  "release:minor": "npm version minor && git push origin master --tags",
@@ -38,9 +41,9 @@
38
41
  "author": "wolffo",
39
42
  "license": "MIT",
40
43
  "peerDependencies": {
41
- "three": ">=0.150.0",
44
+ "@react-three/fiber": ">=8.0.0",
42
45
  "react": ">=18.0.0",
43
- "@react-three/fiber": ">=8.0.0"
46
+ "three": ">=0.150.0"
44
47
  },
45
48
  "peerDependenciesMeta": {
46
49
  "react": {
@@ -51,20 +54,26 @@
51
54
  }
52
55
  },
53
56
  "devDependencies": {
57
+ "@react-three/fiber": "^8.15.12",
58
+ "@rollup/plugin-typescript": "^11.1.5",
59
+ "@testing-library/jest-dom": "^6.6.3",
60
+ "@testing-library/react": "^16.3.0",
54
61
  "@types/react": "^18.2.45",
55
62
  "@types/three": "^0.160.0",
56
- "@react-three/fiber": "^8.15.12",
63
+ "@vitest/coverage-v8": "^3.2.4",
64
+ "@vitest/ui": "^3.2.4",
65
+ "happy-dom": "^18.0.1",
57
66
  "react": "^18.2.0",
58
- "three": "^0.160.0",
59
- "typescript": "^5.3.3",
67
+ "react-dom": "^18.3.1",
60
68
  "rollup": "^4.9.2",
61
- "@rollup/plugin-typescript": "^11.1.5",
62
69
  "rollup-plugin-dts": "^6.1.0",
63
- "tslib": "^2.6.2"
70
+ "three": "^0.160.0",
71
+ "tslib": "^2.6.2",
72
+ "typescript": "^5.3.3",
73
+ "vitest": "^3.2.4"
64
74
  },
65
75
  "files": [
66
76
  "dist",
67
- "src",
68
77
  "README.md",
69
78
  "LICENSE"
70
79
  ],
package/src/Fire.png DELETED
Binary file
package/src/Fire.ts DELETED
@@ -1,208 +0,0 @@
1
- import {
2
- Mesh,
3
- BoxGeometry,
4
- ShaderMaterial,
5
- Texture,
6
- Color,
7
- Vector3,
8
- Vector4,
9
- Matrix4,
10
- LinearFilter,
11
- ClampToEdgeWrapping,
12
- } from 'three'
13
- import { FireShader, FireShaderUniforms } from './FireShader'
14
-
15
- /**
16
- * Properties for creating a Fire instance
17
- */
18
- export interface FireProps {
19
- /** Fire texture (grayscale mask defining fire shape) */
20
- fireTex: Texture
21
- /** Fire color tint (default: 0xeeeeee) */
22
- color?: Color | string | number
23
- /** Ray marching iterations - higher = better quality, lower performance (default: 20) */
24
- iterations?: number
25
- /** Noise octaves for turbulence (default: 3) */
26
- octaves?: number
27
- /** Noise scaling parameters [x, y, z, time] (default: [1, 2, 1, 0.3]) */
28
- noiseScale?: [number, number, number, number]
29
- /** Fire shape intensity (default: 1.3) */
30
- magnitude?: number
31
- /** Noise lacunarity - frequency multiplier (default: 2.0) */
32
- lacunarity?: number
33
- /** Noise gain - amplitude multiplier (default: 0.5) */
34
- gain?: number
35
- }
36
-
37
- /**
38
- * Volumetric fire effect using ray marching shaders
39
- *
40
- * Creates a procedural fire effect that renders as a translucent volume.
41
- * The fire shape is defined by a grayscale texture, with white areas being
42
- * the most dense part of the fire.
43
- *
44
- * @example
45
- * ```ts
46
- * const texture = textureLoader.load('fire.png')
47
- * const fire = new Fire({
48
- * fireTex: texture,
49
- * color: 0xff4400,
50
- * magnitude: 1.5
51
- * })
52
- * scene.add(fire)
53
- *
54
- * // In animation loop
55
- * fire.update(time)
56
- * ```
57
- */
58
- export class Fire extends Mesh {
59
- public declare material: ShaderMaterial & { uniforms: FireShaderUniforms }
60
- private _time = 0
61
-
62
- /**
63
- * Creates a new Fire instance
64
- *
65
- * @param props - Configuration options for the fire effect
66
- */
67
- constructor({
68
- fireTex,
69
- color = 0xeeeeee,
70
- iterations = 20,
71
- octaves = 3,
72
- noiseScale = [1, 2, 1, 0.3],
73
- magnitude = 1.3,
74
- lacunarity = 2.0,
75
- gain = 0.5,
76
- }: FireProps) {
77
- const geometry = new BoxGeometry(1, 1, 1)
78
-
79
- const material = new ShaderMaterial({
80
- defines: {
81
- ITERATIONS: iterations.toString(),
82
- OCTAVES: octaves.toString(),
83
- },
84
- uniforms: {
85
- fireTex: { value: fireTex },
86
- color: { value: color instanceof Color ? color : new Color(color) },
87
- time: { value: 0.0 },
88
- seed: { value: Math.random() * 19.19 },
89
- invModelMatrix: { value: new Matrix4() },
90
- scale: { value: new Vector3(1, 1, 1) },
91
- noiseScale: { value: new Vector4(...noiseScale) },
92
- magnitude: { value: magnitude },
93
- lacunarity: { value: lacunarity },
94
- gain: { value: gain },
95
- },
96
- vertexShader: FireShader.vertexShader,
97
- fragmentShader: FireShader.fragmentShader,
98
- transparent: true,
99
- depthWrite: false,
100
- depthTest: false,
101
- }) as ShaderMaterial & { uniforms: FireShaderUniforms }
102
-
103
- super(geometry, material)
104
-
105
- // Configure texture
106
- fireTex.magFilter = fireTex.minFilter = LinearFilter
107
- fireTex.wrapS = fireTex.wrapT = ClampToEdgeWrapping
108
- }
109
-
110
- /**
111
- * Updates the fire animation and matrix uniforms
112
- *
113
- * Call this method in your animation loop to animate the fire effect.
114
- *
115
- * @param time - Current time in seconds (optional)
116
- *
117
- * @example
118
- * ```ts
119
- * function animate() {
120
- * fire.update(performance.now() / 1000)
121
- * renderer.render(scene, camera)
122
- * requestAnimationFrame(animate)
123
- * }
124
- * ```
125
- */
126
- public update(time?: number): void {
127
- if (time !== undefined) {
128
- this._time = time
129
- this.material.uniforms.time.value = time
130
- }
131
-
132
- this.updateMatrixWorld()
133
- this.material.uniforms.invModelMatrix.value.copy(this.matrixWorld).invert()
134
- this.material.uniforms.scale.value.copy(this.scale)
135
- }
136
-
137
- /**
138
- * Current animation time in seconds
139
- */
140
- public get time(): number {
141
- return this._time
142
- }
143
-
144
- public set time(value: number) {
145
- this._time = value
146
- this.material.uniforms.time.value = value
147
- }
148
-
149
- /**
150
- * Fire color tint
151
- *
152
- * @example
153
- * ```ts
154
- * fire.fireColor = 'orange'
155
- * fire.fireColor = 0xff4400
156
- * fire.fireColor = new Color(1, 0.5, 0)
157
- * ```
158
- */
159
- public get fireColor(): Color {
160
- return this.material.uniforms.color.value
161
- }
162
-
163
- public set fireColor(color: Color | string | number) {
164
- this.material.uniforms.color.value = color instanceof Color ? color : new Color(color)
165
- }
166
-
167
- /**
168
- * Fire shape intensity
169
- *
170
- * Higher values create more dramatic fire shapes.
171
- * Range: 0.5 - 3.0, Default: 1.3
172
- */
173
- public get magnitude(): number {
174
- return this.material.uniforms.magnitude.value
175
- }
176
-
177
- public set magnitude(value: number) {
178
- this.material.uniforms.magnitude.value = value
179
- }
180
-
181
- /**
182
- * Noise lacunarity (frequency multiplier)
183
- *
184
- * Controls how much the frequency increases for each noise octave.
185
- * Range: 1.0 - 4.0, Default: 2.0
186
- */
187
- public get lacunarity(): number {
188
- return this.material.uniforms.lacunarity.value
189
- }
190
-
191
- public set lacunarity(value: number) {
192
- this.material.uniforms.lacunarity.value = value
193
- }
194
-
195
- /**
196
- * Noise gain (amplitude multiplier)
197
- *
198
- * Controls how much the amplitude decreases for each noise octave.
199
- * Range: 0.1 - 1.0, Default: 0.5
200
- */
201
- public get gain(): number {
202
- return this.material.uniforms.gain.value
203
- }
204
-
205
- public set gain(value: number) {
206
- this.material.uniforms.gain.value = value
207
- }
208
- }
@@ -1,188 +0,0 @@
1
- import React, { useRef, useMemo, useImperativeHandle, forwardRef } from 'react'
2
- import { extend, useFrame, ReactThreeFiber, useLoader } from '@react-three/fiber'
3
- import { Fire as FireMesh, FireProps as FireMeshProps } from './Fire'
4
- import { Color, TextureLoader, Texture } from 'three'
5
-
6
- /**
7
- * Helper hook for texture loading (alternative to @react-three/drei)
8
- */
9
- const useTexture = (url: string): Texture => useLoader(TextureLoader, url)
10
-
11
- // Extend R3F with our Fire class
12
- extend({ Fire: FireMesh })
13
-
14
- declare module '@react-three/fiber' {
15
- interface ThreeElements {
16
- fire: ReactThreeFiber.Object3DNode<FireMesh, typeof FireMesh>
17
- }
18
- }
19
-
20
- /**
21
- * Props for the Fire React component
22
- */
23
- export interface FireProps extends Omit<FireMeshProps, 'fireTex'> {
24
- /** Fire texture URL or Three.js Texture object */
25
- texture: string | Texture
26
- /** Auto-update time from useFrame (default: true) */
27
- autoUpdate?: boolean
28
- /** Custom update function called each frame */
29
- onUpdate?: (fire: FireMesh, time: number) => void
30
- /** Child components */
31
- children?: React.ReactNode
32
- /** Position in 3D space */
33
- position?: [number, number, number]
34
- /** Rotation in radians */
35
- rotation?: [number, number, number]
36
- /** Scale factor (uniform or per-axis) */
37
- scale?: [number, number, number] | number
38
- }
39
-
40
- /**
41
- * Ref interface for imperative fire control
42
- */
43
- export interface FireRef {
44
- /** Fire mesh instance */
45
- fire: FireMesh | null
46
- /** Update fire animation manually */
47
- update: (time?: number) => void
48
- }
49
-
50
- /**
51
- * React Three Fiber component for volumetric fire effect
52
- *
53
- * Creates a procedural fire effect that can be easily integrated into R3F scenes.
54
- * The component automatically handles texture loading, animation updates, and
55
- * provides props for all fire parameters.
56
- *
57
- * @example
58
- * ```tsx
59
- * <Canvas>
60
- * <Fire
61
- * texture="/fire.png"
62
- * color="orange"
63
- * magnitude={1.5}
64
- * scale={[2, 3, 2]}
65
- * position={[0, 0, 0]}
66
- * />
67
- * </Canvas>
68
- * ```
69
- *
70
- * @example With custom animation
71
- * ```tsx
72
- * <Fire
73
- * texture="/fire.png"
74
- * onUpdate={(fire, time) => {
75
- * fire.fireColor.setHSL((time * 0.1) % 1, 1, 0.5)
76
- * }}
77
- * />
78
- * ```
79
- */
80
- export const FireComponent = forwardRef<FireRef, FireProps>(
81
- (
82
- {
83
- texture,
84
- color = 0xeeeeee,
85
- iterations = 20,
86
- octaves = 3,
87
- noiseScale = [1, 2, 1, 0.3],
88
- magnitude = 1.3,
89
- lacunarity = 2.0,
90
- gain = 0.5,
91
- autoUpdate = true,
92
- onUpdate,
93
- children,
94
- ...props
95
- },
96
- ref
97
- ) => {
98
- const fireRef = useRef<FireMesh>(null)
99
-
100
- // Load texture if string is provided
101
- const loadedTexture = useTexture(typeof texture === 'string' ? texture : '')
102
- const finalTexture = typeof texture === 'string' ? loadedTexture : texture
103
-
104
- // Memoize fire props to prevent unnecessary recreations
105
- const fireProps = useMemo(
106
- () => ({
107
- fireTex: finalTexture,
108
- color: color instanceof Color ? color : new Color(color),
109
- iterations,
110
- octaves,
111
- noiseScale,
112
- magnitude,
113
- lacunarity,
114
- gain,
115
- }),
116
- [finalTexture, color, iterations, octaves, noiseScale, magnitude, lacunarity, gain]
117
- )
118
-
119
- // Auto-update with useFrame
120
- useFrame((state) => {
121
- if (fireRef.current && autoUpdate) {
122
- const time = state.clock.getElapsedTime()
123
- fireRef.current.update(time)
124
- onUpdate?.(fireRef.current, time)
125
- }
126
- })
127
-
128
- // Expose imperative handle
129
- useImperativeHandle(
130
- ref,
131
- () => ({
132
- get fire() {
133
- return fireRef.current
134
- },
135
- update: (time?: number) => {
136
- if (fireRef.current) {
137
- fireRef.current.update(time)
138
- }
139
- },
140
- }),
141
- []
142
- )
143
-
144
- return (
145
- <fire ref={fireRef} args={[fireProps]} {...props}>
146
- {children}
147
- </fire>
148
- )
149
- }
150
- )
151
-
152
- FireComponent.displayName = 'Fire'
153
-
154
- /**
155
- * Hook for easier access to fire instance and controls
156
- *
157
- * Provides a ref and helper methods for controlling fire imperatively.
158
- *
159
- * @returns Object with ref, fire instance, and update method
160
- *
161
- * @example
162
- * ```tsx
163
- * function MyComponent() {
164
- * const fireRef = useFire()
165
- *
166
- * const handleClick = () => {
167
- * if (fireRef.fire) {
168
- * fireRef.fire.magnitude = 2.0
169
- * }
170
- * }
171
- *
172
- * return (
173
- * <Fire ref={fireRef.ref} texture="/fire.png" />
174
- * )
175
- * }
176
- * ```
177
- */
178
- export const useFire = () => {
179
- const ref = useRef<FireRef>(null)
180
- return {
181
- /** Ref to pass to Fire component */
182
- ref,
183
- /** Fire mesh instance (null until mounted) */
184
- fire: ref.current?.fire || null,
185
- /** Update fire animation manually */
186
- update: (time?: number) => ref.current?.update(time),
187
- }
188
- }
package/src/FireShader.ts DELETED
@@ -1,223 +0,0 @@
1
- import { Vector3, Vector4, Color, Matrix4, Texture } from 'three'
2
-
3
- /**
4
- * Uniforms interface for the fire shader
5
- */
6
- export interface FireShaderUniforms {
7
- /** Fire texture (grayscale mask) */
8
- fireTex: { value: Texture | null }
9
- /** Fire color tint */
10
- color: { value: Color }
11
- /** Current time for animation */
12
- time: { value: number }
13
- /** Random seed for fire variation */
14
- seed: { value: number }
15
- /** Inverse model matrix for ray marching */
16
- invModelMatrix: { value: Matrix4 }
17
- /** Scale of the fire object */
18
- scale: { value: Vector3 }
19
- /** Noise scaling parameters [x, y, z, time] */
20
- noiseScale: { value: Vector4 }
21
- /** Fire shape intensity */
22
- magnitude: { value: number }
23
- /** Noise lacunarity (frequency multiplier) */
24
- lacunarity: { value: number }
25
- /** Noise gain (amplitude multiplier) */
26
- gain: { value: number }
27
- }
28
-
29
- /**
30
- * Volumetric fire shader using ray marching and simplex noise
31
- *
32
- * Based on "Real-Time procedural volumetric fire" by Alfred et al.
33
- * Uses simplex noise for turbulence and ray marching for volume rendering.
34
- *
35
- * @example
36
- * ```ts
37
- * const material = new ShaderMaterial({
38
- * defines: FireShader.defines,
39
- * uniforms: FireShader.uniforms,
40
- * vertexShader: FireShader.vertexShader,
41
- * fragmentShader: FireShader.fragmentShader,
42
- * transparent: true
43
- * })
44
- * ```
45
- */
46
- export const FireShader = {
47
- defines: {
48
- ITERATIONS: '20',
49
- OCTAVES: '3',
50
- },
51
-
52
- uniforms: {
53
- fireTex: { value: null },
54
- color: { value: new Color(0xeeeeee) },
55
- time: { value: 0.0 },
56
- seed: { value: 0.0 },
57
- invModelMatrix: { value: new Matrix4() },
58
- scale: { value: new Vector3(1, 1, 1) },
59
- noiseScale: { value: new Vector4(1, 2, 1, 0.3) },
60
- magnitude: { value: 1.3 },
61
- lacunarity: { value: 2.0 },
62
- gain: { value: 0.5 },
63
- } as FireShaderUniforms,
64
-
65
- vertexShader: /* glsl */ `
66
- varying vec3 vWorldPos;
67
-
68
- void main() {
69
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
70
- vWorldPos = (modelMatrix * vec4(position, 1.0)).xyz;
71
- }
72
- `,
73
-
74
- fragmentShader: /* glsl */ `
75
- uniform vec3 color;
76
- uniform float time;
77
- uniform float seed;
78
- uniform mat4 invModelMatrix;
79
- uniform vec3 scale;
80
- uniform vec4 noiseScale;
81
- uniform float magnitude;
82
- uniform float lacunarity;
83
- uniform float gain;
84
- uniform sampler2D fireTex;
85
-
86
- varying vec3 vWorldPos;
87
-
88
- // GLSL simplex noise function by ashima
89
- vec3 mod289(vec3 x) {
90
- return x - floor(x * (1.0 / 289.0)) * 289.0;
91
- }
92
-
93
- vec4 mod289(vec4 x) {
94
- return x - floor(x * (1.0 / 289.0)) * 289.0;
95
- }
96
-
97
- vec4 permute(vec4 x) {
98
- return mod289(((x * 34.0) + 1.0) * x);
99
- }
100
-
101
- vec4 taylorInvSqrt(vec4 r) {
102
- return 1.79284291400159 - 0.85373472095314 * r;
103
- }
104
-
105
- float snoise(vec3 v) {
106
- const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
107
- const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
108
-
109
- vec3 i = floor(v + dot(v, C.yyy));
110
- vec3 x0 = v - i + dot(i, C.xxx);
111
-
112
- vec3 g = step(x0.yzx, x0.xyz);
113
- vec3 l = 1.0 - g;
114
- vec3 i1 = min(g.xyz, l.zxy);
115
- vec3 i2 = max(g.xyz, l.zxy);
116
-
117
- vec3 x1 = x0 - i1 + C.xxx;
118
- vec3 x2 = x0 - i2 + C.yyy;
119
- vec3 x3 = x0 - D.yyy;
120
-
121
- i = mod289(i);
122
- vec4 p = permute(permute(permute(
123
- i.z + vec4(0.0, i1.z, i2.z, 1.0))
124
- + i.y + vec4(0.0, i1.y, i2.y, 1.0))
125
- + i.x + vec4(0.0, i1.x, i2.x, 1.0));
126
-
127
- float n_ = 0.142857142857;
128
- vec3 ns = n_ * D.wyz - D.xzx;
129
-
130
- vec4 j = p - 49.0 * floor(p * ns.z * ns.z);
131
-
132
- vec4 x_ = floor(j * ns.z);
133
- vec4 y_ = floor(j - 7.0 * x_);
134
-
135
- vec4 x = x_ * ns.x + ns.yyyy;
136
- vec4 y = y_ * ns.x + ns.yyyy;
137
- vec4 h = 1.0 - abs(x) - abs(y);
138
-
139
- vec4 b0 = vec4(x.xy, y.xy);
140
- vec4 b1 = vec4(x.zw, y.zw);
141
-
142
- vec4 s0 = floor(b0) * 2.0 + 1.0;
143
- vec4 s1 = floor(b1) * 2.0 + 1.0;
144
- vec4 sh = -step(h, vec4(0.0));
145
-
146
- vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
147
- vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
148
-
149
- vec3 p0 = vec3(a0.xy, h.x);
150
- vec3 p1 = vec3(a0.zw, h.y);
151
- vec3 p2 = vec3(a1.xy, h.z);
152
- vec3 p3 = vec3(a1.zw, h.w);
153
-
154
- vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
155
- p0 *= norm.x;
156
- p1 *= norm.y;
157
- p2 *= norm.z;
158
- p3 *= norm.w;
159
-
160
- vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
161
- m = m * m;
162
- return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
163
- }
164
-
165
- float turbulence(vec3 p) {
166
- float sum = 0.0;
167
- float freq = 1.0;
168
- float amp = 1.0;
169
-
170
- for(int i = 0; i < OCTAVES; i++) {
171
- sum += abs(snoise(p * freq)) * amp;
172
- freq *= lacunarity;
173
- amp *= gain;
174
- }
175
-
176
- return sum;
177
- }
178
-
179
- vec4 samplerFire(vec3 p, vec4 scale) {
180
- vec2 st = vec2(sqrt(dot(p.xz, p.xz)), p.y);
181
-
182
- if(st.x <= 0.0 || st.x >= 1.0 || st.y <= 0.0 || st.y >= 1.0) {
183
- return vec4(0.0);
184
- }
185
-
186
- p.y -= (seed + time) * scale.w;
187
- p *= scale.xyz;
188
-
189
- st.y += sqrt(st.y) * magnitude * turbulence(p);
190
-
191
- if(st.y <= 0.0 || st.y >= 1.0) {
192
- return vec4(0.0);
193
- }
194
-
195
- return texture2D(fireTex, st);
196
- }
197
-
198
- vec3 localize(vec3 p) {
199
- return (invModelMatrix * vec4(p, 1.0)).xyz;
200
- }
201
-
202
- void main() {
203
- vec3 rayPos = vWorldPos;
204
- vec3 rayDir = normalize(rayPos - cameraPosition);
205
- float rayLen = 0.0288 * length(scale.xyz);
206
-
207
- vec4 col = vec4(0.0);
208
-
209
- for(int i = 0; i < ITERATIONS; i++) {
210
- rayPos += rayDir * rayLen;
211
- vec3 lp = localize(rayPos);
212
- lp.y += 0.5;
213
- lp.xz *= 2.0;
214
- col += samplerFire(lp, noiseScale);
215
- }
216
-
217
- // Apply color tint to the fire
218
- col.rgb *= color;
219
- col.a = col.r;
220
- gl_FragColor = col;
221
- }
222
- `,
223
- } as const
package/src/index.ts DELETED
@@ -1,38 +0,0 @@
1
- /**
2
- * @fileoverview Modern TypeScript volumetric fire effect for Three.js and React Three Fiber
3
- *
4
- * This package provides both vanilla Three.js classes and React Three Fiber components
5
- * for creating realistic volumetric fire effects using ray marching shaders.
6
- *
7
- * @example Vanilla Three.js
8
- * ```ts
9
- * import { FireMesh } from '@wolffo/three-fire'
10
- *
11
- * const fire = new FireMesh({ fireTex: texture })
12
- * scene.add(fire)
13
- * fire.update(time)
14
- * ```
15
- *
16
- * @example React Three Fiber
17
- * ```tsx
18
- * import { Fire } from '@wolffo/three-fire'
19
- *
20
- * <Canvas>
21
- * <Fire texture="/fire.png" color="orange" />
22
- * </Canvas>
23
- * ```
24
- */
25
-
26
- // Vanilla Three.js exports
27
- /** Fire mesh class for vanilla Three.js usage */
28
- export { Fire as FireMesh, type FireProps as FireMeshProps } from './Fire'
29
- /** Fire shader definition and uniforms */
30
- export { FireShader, type FireShaderUniforms } from './FireShader'
31
-
32
- // React Three Fiber exports
33
- /** React component for fire effect */
34
- export { FireComponent, useFire, type FireRef, type FireProps } from './FireComponent'
35
-
36
- // Default export (React component)
37
- /** Default Fire component for React Three Fiber */
38
- export { FireComponent as Fire } from './FireComponent'