paperlab 0.7.1 → 0.8.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.
- package/README.md +7 -5
- package/dist/{FxPostPass-M66QMVVC.js → FxPostPass-V6YDK4H2.js} +23 -5
- package/dist/FxPostPass-V6YDK4H2.js.map +1 -0
- package/dist/chunk-232SU3AQ.js +34 -0
- package/dist/chunk-232SU3AQ.js.map +1 -0
- package/dist/{chunk-GB6BMHC3.js → chunk-7WOGU2D4.js} +7 -19
- package/dist/{chunk-GB6BMHC3.js.map → chunk-7WOGU2D4.js.map} +1 -1
- package/dist/{chunk-NTDVOOBA.js → chunk-SVWWC5UL.js} +372 -151
- package/dist/chunk-SVWWC5UL.js.map +1 -0
- package/dist/{damageContract-DPF1YFLZ.d.cts → damageContract-nF1fgK7P.d.cts} +31 -3
- package/dist/{damageContract-DPF1YFLZ.d.ts → damageContract-nF1fgK7P.d.ts} +31 -3
- package/dist/fx.cjs +320 -91
- package/dist/fx.cjs.map +1 -1
- package/dist/fx.d.cts +81 -55
- package/dist/fx.d.ts +81 -55
- package/dist/fx.js +278 -48
- package/dist/fx.js.map +1 -1
- package/dist/index.cjs +402 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -5
- package/dist/index.d.ts +13 -5
- package/dist/index.js +17 -4
- package/dist/index.js.map +1 -1
- package/dist/{slots-C5PqY0Q5.d.cts → slots-D_EE8GXn.d.cts} +12 -0
- package/dist/{slots-C5PqY0Q5.d.ts → slots-D_EE8GXn.d.ts} +12 -0
- package/dist/stage.cjs +396 -179
- package/dist/stage.cjs.map +1 -1
- package/dist/stage.d.cts +1 -1
- package/dist/stage.d.ts +1 -1
- package/dist/stage.js +2 -2
- package/package.json +1 -1
- package/dist/FxPostPass-M66QMVVC.js.map +0 -1
- package/dist/chunk-7TLIWPGM.js +0 -36
- package/dist/chunk-7TLIWPGM.js.map +0 -1
- package/dist/chunk-NTDVOOBA.js.map +0 -1
package/dist/fx.js
CHANGED
|
@@ -31,11 +31,11 @@ import {
|
|
|
31
31
|
luminance,
|
|
32
32
|
srgbToLinear,
|
|
33
33
|
timesPaperWhite
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-7WOGU2D4.js";
|
|
35
35
|
import {
|
|
36
36
|
DAMAGE_CHANNELS,
|
|
37
37
|
DAMAGE_LOOK_DEFAULTS
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-232SU3AQ.js";
|
|
39
39
|
|
|
40
40
|
// src/fx/particles.ts
|
|
41
41
|
var particlePresets = {
|
|
@@ -90,7 +90,13 @@ var particlePresets = {
|
|
|
90
90
|
* simulation, on purpose; see the fx plan.
|
|
91
91
|
*/
|
|
92
92
|
smoke: {
|
|
93
|
-
|
|
93
|
+
// Shorter, and smaller below: these are the thread beside the
|
|
94
|
+
// simulator's smoke, and the simulator's is gone within a second or two
|
|
95
|
+
// of the last flame. Left to live three and a half seconds and grow to
|
|
96
|
+
// seven centimetres, the last few of them overlapped into a flat wash
|
|
97
|
+
// over the hole with nothing left to move them — the one moment of a
|
|
98
|
+
// burn Noor found the smoke wrong (2026-09-13).
|
|
99
|
+
life: [1.4, 2.6],
|
|
94
100
|
speed: [0.05, 0.15],
|
|
95
101
|
direction: [0, 1, 0],
|
|
96
102
|
spread: 0.3,
|
|
@@ -98,13 +104,13 @@ var particlePresets = {
|
|
|
98
104
|
drag: 0.9,
|
|
99
105
|
jitter: 0.3,
|
|
100
106
|
windCatch: 1,
|
|
101
|
-
size: [0.05, 0.
|
|
107
|
+
size: [0.05, 0.18],
|
|
102
108
|
// #6B6560 grey-brown, linear, and thin — the background stays clear.
|
|
103
109
|
color: [
|
|
104
110
|
[0.147, 0.13, 0.117],
|
|
105
111
|
[0.2, 0.19, 0.18]
|
|
106
112
|
],
|
|
107
|
-
alpha: [0.
|
|
113
|
+
alpha: [0.07, 0],
|
|
108
114
|
spin: 0.4,
|
|
109
115
|
blend: "normal",
|
|
110
116
|
shape: "soft",
|
|
@@ -116,7 +122,9 @@ var particlePresets = {
|
|
|
116
122
|
* burn that proves paper was there.
|
|
117
123
|
*/
|
|
118
124
|
ash: {
|
|
119
|
-
|
|
125
|
+
// A second or two: ash that hung in the air for five read as grey
|
|
126
|
+
// confetti over the hole, dust or stars rather than something falling.
|
|
127
|
+
life: [1.2, 2.6],
|
|
120
128
|
// Thrown UP by the heat it came off, before it is heavier than the air.
|
|
121
129
|
// It used to leave at almost nothing (0.02–0.1) with a lift of −0.35, so
|
|
122
130
|
// every flake began falling the moment it was born — straight through the
|
|
@@ -124,7 +132,9 @@ var particlePresets = {
|
|
|
124
132
|
speed: [0.14, 0.3],
|
|
125
133
|
direction: [0, 1, 0],
|
|
126
134
|
spread: 0.55,
|
|
127
|
-
|
|
135
|
+
// Heavier than the air once the throw is spent: most flakes tumble down,
|
|
136
|
+
// only the lightest ride the heat up a little first.
|
|
137
|
+
lift: -0.42,
|
|
128
138
|
drag: 1.6,
|
|
129
139
|
jitter: 1.2,
|
|
130
140
|
windCatch: 1,
|
|
@@ -132,9 +142,11 @@ var particlePresets = {
|
|
|
132
142
|
// 3.8 mm and there were far too many of them: a shower of specks rather
|
|
133
143
|
// than a few flakes you would notice.
|
|
134
144
|
size: [0.03, 0.026],
|
|
145
|
+
// Charred paper, near black: under a bright key the old value read as
|
|
146
|
+
// pale grey against the black stage, which is the confetti.
|
|
135
147
|
color: [
|
|
136
|
-
[0.
|
|
137
|
-
[0.
|
|
148
|
+
[0.04, 0.037, 0.034],
|
|
149
|
+
[0.07, 0.066, 0.062]
|
|
138
150
|
],
|
|
139
151
|
alpha: [0.95, 0],
|
|
140
152
|
spin: 4,
|
|
@@ -358,13 +370,14 @@ var ParticlePool = class {
|
|
|
358
370
|
|
|
359
371
|
// src/fx/fire.ts
|
|
360
372
|
var fireEmitterDefaults = {
|
|
361
|
-
embers: 0.
|
|
362
|
-
smoke: 0,
|
|
363
|
-
ash: 0.
|
|
373
|
+
embers: 0.39,
|
|
374
|
+
smoke: 0.135,
|
|
375
|
+
ash: 0.36,
|
|
364
376
|
seed: 7,
|
|
365
377
|
caps: {}
|
|
366
378
|
};
|
|
367
379
|
var PER_UPDATE = 24;
|
|
380
|
+
var CRACKLE_SPARKS = 0.06;
|
|
368
381
|
var FireEmitter = class {
|
|
369
382
|
field;
|
|
370
383
|
pool;
|
|
@@ -401,7 +414,10 @@ var FireEmitter = class {
|
|
|
401
414
|
heat /= front;
|
|
402
415
|
const struggle = 0.35 + 1.6 * Math.max(0, 0.7 - heat) + air * 0.8;
|
|
403
416
|
const oxygen = 1 + air * 1.5;
|
|
404
|
-
this.emberDebt = Math.min(
|
|
417
|
+
this.emberDebt = Math.min(
|
|
418
|
+
this.emberDebt + front * o.embers * oxygen * dt + field.lastStats.charred * o.embers * CRACKLE_SPARKS,
|
|
419
|
+
PER_UPDATE
|
|
420
|
+
);
|
|
405
421
|
this.smokeDebt = Math.min(this.smokeDebt + front * o.smoke * struggle * dt, PER_UPDATE);
|
|
406
422
|
while (this.emberDebt >= 1) {
|
|
407
423
|
this.emberDebt -= 1;
|
|
@@ -757,7 +773,7 @@ function FxParticles({ pool }) {
|
|
|
757
773
|
import { Suspense, lazy } from "react";
|
|
758
774
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
759
775
|
var Pass = lazy(
|
|
760
|
-
() => import("./FxPostPass-
|
|
776
|
+
() => import("./FxPostPass-V6YDK4H2.js").then((m) => ({ default: m.FxPostPass })).catch((error) => {
|
|
761
777
|
warnOnce(error);
|
|
762
778
|
return { default: (() => null) };
|
|
763
779
|
})
|
|
@@ -1742,10 +1758,17 @@ void main() {
|
|
|
1742
1758
|
float rootMask = smoothstep(mix(0.4, 0.02, uRootReach), mix(0.6, 0.12, uRootReach), fuel) * (1.0 - smoothstep(0.25, 0.6, t));
|
|
1743
1759
|
fire += uRootColor * rootMask * uRootAmount * uPaperWhite * uGlow * 0.6;
|
|
1744
1760
|
|
|
1745
|
-
// Smoke:
|
|
1746
|
-
//
|
|
1761
|
+
// Smoke: grey-brown, warm (a cool grey over cream reads lavender), and LIT
|
|
1762
|
+
// BY THE FIRE UNDER IT rather than by nothing.
|
|
1763
|
+
//
|
|
1764
|
+
// The base used to be bright enough to read on its own \u2014 beige \u2014 which is
|
|
1765
|
+
// right while flames are lighting it and wrong the moment they stop: the
|
|
1766
|
+
// last of the smoke hung over a black stage as flat beige slabs, the same
|
|
1767
|
+
// colour everywhere, which reads as a filled shape rather than as smoke
|
|
1768
|
+
// (Noor, 2026-09-13). Dim at the base and warm where the fire is: smoke by
|
|
1769
|
+
// the flames looks as it did, smoke after them goes to a dim grey.
|
|
1747
1770
|
float smokeAlpha = 1.0 - exp(-smoke * uSmokeDensity);
|
|
1748
|
-
vec3 smokeColor = vec3(0.
|
|
1771
|
+
vec3 smokeColor = vec3(0.075, 0.068, 0.062) + vec3(0.3, 0.14, 0.045) * smoothstep(0.12, 0.9, t);
|
|
1749
1772
|
float alpha = smokeAlpha + fireAlpha - smokeAlpha * fireAlpha;
|
|
1750
1773
|
// No square edge: the domain fades out before its borders.
|
|
1751
1774
|
float edge = smoothstep(0.0, 0.06, vUv.x) * smoothstep(1.0, 0.94, vUv.x) * smoothstep(0.0, 0.03, vUv.y) * smoothstep(1.0, 0.9, vUv.y);
|
|
@@ -2544,55 +2567,261 @@ function FxFireFluid({
|
|
|
2544
2567
|
import * as THREE6 from "three";
|
|
2545
2568
|
import { useFrame as useFrame5 } from "@react-three/fiber";
|
|
2546
2569
|
import { useRef as useRef4 } from "react";
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2570
|
+
|
|
2571
|
+
// src/fx/fireState.ts
|
|
2572
|
+
var FLAMES = 32;
|
|
2573
|
+
var FIRE_CLUSTERS = 4;
|
|
2574
|
+
var CLUSTER_REACH = 25 / 210;
|
|
2575
|
+
var FireState = class {
|
|
2576
|
+
constructor(field, locate) {
|
|
2577
|
+
this.field = field;
|
|
2578
|
+
this.locate = locate;
|
|
2579
|
+
}
|
|
2580
|
+
field;
|
|
2581
|
+
locate;
|
|
2582
|
+
/** The flames it was taken over. Only the first {@link count} are current. */
|
|
2583
|
+
anchors = [];
|
|
2584
|
+
count = 0;
|
|
2585
|
+
/** Where the fire is, as a whole: its flames' mean. Zero with none. */
|
|
2586
|
+
x = 0;
|
|
2587
|
+
y = 0;
|
|
2588
|
+
z = 0;
|
|
2589
|
+
/** Its flames' mean height. */
|
|
2590
|
+
height = 0;
|
|
2591
|
+
/** Its flames' mean puff. */
|
|
2592
|
+
flicker = 0;
|
|
2593
|
+
/** Where it is gathered. Only the first {@link clusterCount} are current. */
|
|
2594
|
+
clusters = [];
|
|
2595
|
+
clusterCount = 0;
|
|
2596
|
+
frame = Number.NaN;
|
|
2597
|
+
order = [];
|
|
2598
|
+
root = new Float64Array(FIRE_CLUSTERS * 3);
|
|
2599
|
+
weight = new Float64Array(FIRE_CLUSTERS);
|
|
2600
|
+
/**
|
|
2601
|
+
* Bring it up to date for `frame` — any number that is the same for every
|
|
2602
|
+
* reader in one frame and different in the next; R3F's `clock.elapsedTime`
|
|
2603
|
+
* is the one in hand. Free the second time it is asked in a frame.
|
|
2604
|
+
*/
|
|
2605
|
+
update(frame) {
|
|
2606
|
+
if (frame === this.frame) return this;
|
|
2607
|
+
this.frame = frame;
|
|
2608
|
+
const { field, anchors } = this;
|
|
2609
|
+
const n = flameAnchors(field, this.locate, FLAMES, anchors);
|
|
2610
|
+
this.count = n;
|
|
2562
2611
|
let x = 0;
|
|
2563
2612
|
let y = 0;
|
|
2564
2613
|
let z = 0;
|
|
2565
2614
|
let h = 0;
|
|
2566
2615
|
let flicker = 0;
|
|
2567
2616
|
for (let i = 0; i < n; i++) {
|
|
2568
|
-
const f = anchors
|
|
2617
|
+
const f = anchors[i];
|
|
2569
2618
|
x += f.x;
|
|
2570
2619
|
y += f.y;
|
|
2571
2620
|
z += f.z;
|
|
2572
2621
|
h += f.height;
|
|
2573
2622
|
flicker += flamePuff(f.seed, field.time);
|
|
2574
2623
|
}
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2624
|
+
if (n > 0) {
|
|
2625
|
+
x /= n;
|
|
2626
|
+
y /= n;
|
|
2627
|
+
z /= n;
|
|
2628
|
+
h /= n;
|
|
2629
|
+
flicker /= n;
|
|
2630
|
+
}
|
|
2631
|
+
this.x = x;
|
|
2632
|
+
this.y = y;
|
|
2633
|
+
this.z = z;
|
|
2634
|
+
this.height = h;
|
|
2635
|
+
this.flicker = flicker;
|
|
2636
|
+
this.gather();
|
|
2637
|
+
return this;
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Group the flames into at most {@link FIRE_CLUSTERS} clusters.
|
|
2641
|
+
*
|
|
2642
|
+
* Tallest first, so each cluster is named by its tallest tongue and stands
|
|
2643
|
+
* where that one stands: a flame joins the nearest cluster within
|
|
2644
|
+
* {@link CLUSTER_REACH} of it, or starts one while there is room, or joins
|
|
2645
|
+
* the nearest once there is not. Pure arithmetic over the flames, so the
|
|
2646
|
+
* same burn gathers the same way every time.
|
|
2647
|
+
*/
|
|
2648
|
+
gather() {
|
|
2649
|
+
const anchors = this.anchors;
|
|
2650
|
+
const clusters = this.clusters;
|
|
2651
|
+
const order = this.order;
|
|
2652
|
+
const root = this.root;
|
|
2653
|
+
const weight = this.weight;
|
|
2654
|
+
const n = this.count;
|
|
2655
|
+
order.length = 0;
|
|
2656
|
+
for (let i = 0; i < n; i++) order.push(i);
|
|
2657
|
+
order.sort((i, j) => anchors[j].height - anchors[i].height || i - j);
|
|
2658
|
+
let k = 0;
|
|
2659
|
+
for (const i of order) {
|
|
2660
|
+
const f = anchors[i];
|
|
2661
|
+
let best = -1;
|
|
2662
|
+
let near = Number.POSITIVE_INFINITY;
|
|
2663
|
+
for (let c = 0; c < k; c++) {
|
|
2664
|
+
const d = Math.hypot(f.x - root[c * 3], f.y - root[c * 3 + 1], f.z - root[c * 3 + 2]);
|
|
2665
|
+
if (d < near) {
|
|
2666
|
+
near = d;
|
|
2667
|
+
best = c;
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
if (best < 0 || near > CLUSTER_REACH && k < FIRE_CLUSTERS) {
|
|
2671
|
+
best = k++;
|
|
2672
|
+
root[best * 3] = f.x;
|
|
2673
|
+
root[best * 3 + 1] = f.y;
|
|
2674
|
+
root[best * 3 + 2] = f.z;
|
|
2675
|
+
weight[best] = 0;
|
|
2676
|
+
let cluster2 = clusters[best];
|
|
2677
|
+
if (!cluster2) {
|
|
2678
|
+
cluster2 = { x: 0, y: 0, z: 0, height: 0, tallest: 0, flicker: 0, heat: 0, count: 0 };
|
|
2679
|
+
clusters[best] = cluster2;
|
|
2680
|
+
}
|
|
2681
|
+
cluster2.x = 0;
|
|
2682
|
+
cluster2.y = 0;
|
|
2683
|
+
cluster2.z = 0;
|
|
2684
|
+
cluster2.height = 0;
|
|
2685
|
+
cluster2.tallest = f.height;
|
|
2686
|
+
cluster2.flicker = 0;
|
|
2687
|
+
cluster2.heat = 0;
|
|
2688
|
+
cluster2.count = 0;
|
|
2689
|
+
}
|
|
2690
|
+
const cluster = clusters[best];
|
|
2691
|
+
const w = f.height;
|
|
2692
|
+
cluster.x += f.x * w;
|
|
2693
|
+
cluster.y += f.y * w;
|
|
2694
|
+
cluster.z += f.z * w;
|
|
2695
|
+
weight[best] = weight[best] + w;
|
|
2696
|
+
cluster.height += f.height;
|
|
2697
|
+
cluster.flicker += flamePuff(f.seed, this.field.time);
|
|
2698
|
+
cluster.heat += f.heat;
|
|
2699
|
+
cluster.count++;
|
|
2700
|
+
}
|
|
2701
|
+
for (let c = 0; c < k; c++) {
|
|
2702
|
+
const cluster = clusters[c];
|
|
2703
|
+
const w = weight[c];
|
|
2704
|
+
if (w > 0) {
|
|
2705
|
+
cluster.x /= w;
|
|
2706
|
+
cluster.y /= w;
|
|
2707
|
+
cluster.z /= w;
|
|
2708
|
+
} else {
|
|
2709
|
+
cluster.x = root[c * 3];
|
|
2710
|
+
cluster.y = root[c * 3 + 1];
|
|
2711
|
+
cluster.z = root[c * 3 + 2];
|
|
2712
|
+
}
|
|
2713
|
+
cluster.height /= cluster.count;
|
|
2714
|
+
cluster.flicker /= cluster.count;
|
|
2715
|
+
cluster.heat /= cluster.count;
|
|
2716
|
+
}
|
|
2717
|
+
this.clusterCount = k;
|
|
2718
|
+
}
|
|
2719
|
+
};
|
|
2720
|
+
var shared = /* @__PURE__ */ new WeakMap();
|
|
2721
|
+
function fireStateOf(field, locate) {
|
|
2722
|
+
let byLocator = shared.get(field);
|
|
2723
|
+
if (!byLocator) {
|
|
2724
|
+
byLocator = /* @__PURE__ */ new WeakMap();
|
|
2725
|
+
shared.set(field, byLocator);
|
|
2726
|
+
}
|
|
2727
|
+
let state = byLocator.get(locate);
|
|
2728
|
+
if (!state) {
|
|
2729
|
+
state = new FireState(field, locate);
|
|
2730
|
+
byLocator.set(locate, state);
|
|
2731
|
+
}
|
|
2732
|
+
return state;
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
// src/fx/FxFireLight.tsx
|
|
2736
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2737
|
+
function FxFireLight({ field, locate, gain = FIRE_LIGHT_GAIN, shadows = false }) {
|
|
2738
|
+
const front = useRef4([]);
|
|
2739
|
+
const through = useRef4(null);
|
|
2740
|
+
const spot = useRef4(null);
|
|
2741
|
+
useFrame5(({ camera, clock }) => {
|
|
2742
|
+
const b = through.current;
|
|
2743
|
+
if (!b) return;
|
|
2744
|
+
const fire = fireStateOf(field, locate).update(clock.elapsedTime);
|
|
2745
|
+
const level = field.lastStats.front * gain;
|
|
2746
|
+
let total = 0;
|
|
2747
|
+
let brightest = -1;
|
|
2748
|
+
let most = 0;
|
|
2749
|
+
for (let c = 0; c < fire.clusterCount; c++) {
|
|
2750
|
+
const cluster = fire.clusters[c];
|
|
2751
|
+
const share = cluster.count * cluster.height;
|
|
2752
|
+
total += share;
|
|
2753
|
+
if (share > most) {
|
|
2754
|
+
most = share;
|
|
2755
|
+
brightest = c;
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
const s = shadows ? spot.current : null;
|
|
2759
|
+
if (s) s.intensity = 0;
|
|
2760
|
+
for (let i = 0; i < FIRE_CLUSTERS; i++) {
|
|
2761
|
+
const light = front.current[i];
|
|
2762
|
+
if (!light) continue;
|
|
2763
|
+
const cluster = i < fire.clusterCount ? fire.clusters[i] : null;
|
|
2764
|
+
if (!cluster || !(total > 0)) {
|
|
2765
|
+
light.intensity = 0;
|
|
2766
|
+
continue;
|
|
2767
|
+
}
|
|
2768
|
+
toward.set(camera.position.x - cluster.x, 0, camera.position.z - cluster.z).normalize().multiplyScalar(0.035);
|
|
2769
|
+
light.position.set(cluster.x + toward.x, cluster.y + cluster.height * 0.5, cluster.z + toward.z);
|
|
2770
|
+
light.intensity = level * cluster.flicker * (cluster.count * cluster.height / total);
|
|
2771
|
+
light.color.copy(COOLING).lerp(FIRE_COLOR, Math.min(1, Math.max(0, cluster.heat)));
|
|
2772
|
+
if (s && i === brightest) {
|
|
2773
|
+
s.position.copy(light.position);
|
|
2774
|
+
s.target.position.set(cluster.x, cluster.y, cluster.z);
|
|
2775
|
+
s.target.updateMatrixWorld();
|
|
2776
|
+
s.intensity = light.intensity;
|
|
2777
|
+
s.color.copy(light.color);
|
|
2778
|
+
light.intensity = 0;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
if (fire.count === 0) {
|
|
2782
|
+
b.intensity = 0;
|
|
2783
|
+
return;
|
|
2784
|
+
}
|
|
2785
|
+
toward.set(camera.position.x - fire.x, 0, camera.position.z - fire.z).normalize().multiplyScalar(0.035);
|
|
2786
|
+
b.position.set(fire.x - toward.x, fire.y + fire.height * 0.5, fire.z - toward.z);
|
|
2787
|
+
b.intensity = level * fire.flicker * 0.35;
|
|
2588
2788
|
});
|
|
2589
2789
|
return /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
2590
|
-
|
|
2790
|
+
Array.from({ length: FIRE_CLUSTERS }, (_, i) => /* @__PURE__ */ jsx6(
|
|
2791
|
+
"pointLight",
|
|
2792
|
+
{
|
|
2793
|
+
ref: (light) => {
|
|
2794
|
+
front.current[i] = light;
|
|
2795
|
+
},
|
|
2796
|
+
color: FIRE_COLOR,
|
|
2797
|
+
intensity: 0,
|
|
2798
|
+
decay: 0.9,
|
|
2799
|
+
distance: 0
|
|
2800
|
+
},
|
|
2801
|
+
i
|
|
2802
|
+
)),
|
|
2803
|
+
shadows && /* @__PURE__ */ jsx6(
|
|
2804
|
+
"spotLight",
|
|
2805
|
+
{
|
|
2806
|
+
ref: spot,
|
|
2807
|
+
color: FIRE_COLOR,
|
|
2808
|
+
intensity: 0,
|
|
2809
|
+
decay: 0.9,
|
|
2810
|
+
distance: 0,
|
|
2811
|
+
angle: 1.3,
|
|
2812
|
+
penumbra: 0.8,
|
|
2813
|
+
castShadow: true,
|
|
2814
|
+
"shadow-mapSize": [512, 512],
|
|
2815
|
+
"shadow-bias": -4e-4
|
|
2816
|
+
}
|
|
2817
|
+
),
|
|
2591
2818
|
/* @__PURE__ */ jsx6("pointLight", { ref: through, color: FIRE_COLOR, intensity: 0, decay: 0.9, distance: 0 })
|
|
2592
2819
|
] });
|
|
2593
2820
|
}
|
|
2821
|
+
var toward = new THREE6.Vector3();
|
|
2594
2822
|
var FIRE_COLOR = new THREE6.Color("#ffa24c");
|
|
2595
|
-
var
|
|
2823
|
+
var COOLING = new THREE6.Color("#ff8a33");
|
|
2824
|
+
var FIRE_LIGHT_GAIN = 26;
|
|
2596
2825
|
|
|
2597
2826
|
// src/fx/FxMatchFlame.tsx
|
|
2598
2827
|
import * as THREE7 from "three";
|
|
@@ -3148,6 +3377,7 @@ export {
|
|
|
3148
3377
|
FIELD_SIZE,
|
|
3149
3378
|
FIRE_GLOW,
|
|
3150
3379
|
FIRE_HEAT_SCALE,
|
|
3380
|
+
FIRE_LIGHT_GAIN,
|
|
3151
3381
|
FIRE_SOOT_SCALE,
|
|
3152
3382
|
FIRE_ZONES,
|
|
3153
3383
|
FIXED_DT,
|