r3f-vfx 0.0.5 → 0.0.7
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/dist/index.js +151 -1095
- package/package.json +3 -3
- package/dist/index.d.ts +0 -121
package/dist/index.js
CHANGED
|
@@ -1141,7 +1141,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1141
1141
|
}
|
|
1142
1142
|
);
|
|
1143
1143
|
};
|
|
1144
|
-
useScrubber = (value, onChange,
|
|
1144
|
+
useScrubber = (value, onChange, step = 0.01, min, max) => {
|
|
1145
1145
|
const isDraggingRef = useRef(false);
|
|
1146
1146
|
const hasMoved = useRef(false);
|
|
1147
1147
|
const startX = useRef(0);
|
|
@@ -1166,11 +1166,11 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1166
1166
|
setIsDragging(true);
|
|
1167
1167
|
}
|
|
1168
1168
|
const sensitivity = e2.shiftKey ? 0.1 : 0.5;
|
|
1169
|
-
const change = delta *
|
|
1169
|
+
const change = delta * step * sensitivity;
|
|
1170
1170
|
let newValue = startValue.current + change;
|
|
1171
1171
|
if (min !== void 0) newValue = Math.max(min, newValue);
|
|
1172
1172
|
if (max !== void 0) newValue = Math.min(max, newValue);
|
|
1173
|
-
const precision =
|
|
1173
|
+
const precision = step < 1 ? Math.ceil(-Math.log10(step)) : 0;
|
|
1174
1174
|
newValue = parseFloat(newValue.toFixed(precision));
|
|
1175
1175
|
onChange(newValue);
|
|
1176
1176
|
};
|
|
@@ -1190,7 +1190,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1190
1190
|
document.addEventListener("mousemove", handleMouseMove);
|
|
1191
1191
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1192
1192
|
},
|
|
1193
|
-
[value, onChange,
|
|
1193
|
+
[value, onChange, step, min, max]
|
|
1194
1194
|
);
|
|
1195
1195
|
return { handleMouseDown, hasMoved, isDragging };
|
|
1196
1196
|
};
|
|
@@ -1199,7 +1199,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1199
1199
|
onChange,
|
|
1200
1200
|
min,
|
|
1201
1201
|
max,
|
|
1202
|
-
step
|
|
1202
|
+
step = 0.01,
|
|
1203
1203
|
style,
|
|
1204
1204
|
placeholder
|
|
1205
1205
|
}) => {
|
|
@@ -1209,7 +1209,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1209
1209
|
const { handleMouseDown, hasMoved, isDragging } = useScrubber(
|
|
1210
1210
|
value,
|
|
1211
1211
|
onChange,
|
|
1212
|
-
|
|
1212
|
+
step,
|
|
1213
1213
|
min,
|
|
1214
1214
|
max
|
|
1215
1215
|
);
|
|
@@ -1298,8 +1298,8 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1298
1298
|
}
|
|
1299
1299
|
);
|
|
1300
1300
|
};
|
|
1301
|
-
NumberInput = ({ label, value, onChange, min, max, step
|
|
1302
|
-
const { handleMouseDown } = useScrubber(value, onChange,
|
|
1301
|
+
NumberInput = ({ label, value, onChange, min, max, step = 0.01 }) => {
|
|
1302
|
+
const { handleMouseDown } = useScrubber(value, onChange, step, min, max);
|
|
1303
1303
|
return /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
|
|
1304
1304
|
/* @__PURE__ */ jsx(
|
|
1305
1305
|
"label",
|
|
@@ -1317,7 +1317,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1317
1317
|
onChange,
|
|
1318
1318
|
min,
|
|
1319
1319
|
max,
|
|
1320
|
-
step
|
|
1320
|
+
step,
|
|
1321
1321
|
style: styles.input
|
|
1322
1322
|
}
|
|
1323
1323
|
)
|
|
@@ -1329,7 +1329,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1329
1329
|
onChange,
|
|
1330
1330
|
min = -100,
|
|
1331
1331
|
max = 100,
|
|
1332
|
-
step
|
|
1332
|
+
step = 0.01
|
|
1333
1333
|
}) => {
|
|
1334
1334
|
const [minVal, maxVal] = parseRange(value, [0, 0]);
|
|
1335
1335
|
const [linked, setLinked] = useState(false);
|
|
@@ -1356,7 +1356,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1356
1356
|
const { handleMouseDown } = useScrubber(
|
|
1357
1357
|
minVal,
|
|
1358
1358
|
handleMinChange,
|
|
1359
|
-
|
|
1359
|
+
step,
|
|
1360
1360
|
min,
|
|
1361
1361
|
max
|
|
1362
1362
|
);
|
|
@@ -1389,7 +1389,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1389
1389
|
onChange: handleMinChange,
|
|
1390
1390
|
min,
|
|
1391
1391
|
max,
|
|
1392
|
-
step
|
|
1392
|
+
step,
|
|
1393
1393
|
style: styles.rangeInput,
|
|
1394
1394
|
placeholder: "min"
|
|
1395
1395
|
}
|
|
@@ -1427,7 +1427,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
1427
1427
|
onChange: handleMaxChange,
|
|
1428
1428
|
min,
|
|
1429
1429
|
max,
|
|
1430
|
-
step
|
|
1430
|
+
step,
|
|
1431
1431
|
style: styles.rangeInput,
|
|
1432
1432
|
placeholder: "max"
|
|
1433
1433
|
}
|
|
@@ -5117,7 +5117,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
5117
5117
|
}
|
|
5118
5118
|
});
|
|
5119
5119
|
|
|
5120
|
-
// src/VFXParticles.
|
|
5120
|
+
// src/VFXParticles.tsx
|
|
5121
5121
|
import {
|
|
5122
5122
|
forwardRef,
|
|
5123
5123
|
useImperativeHandle,
|
|
@@ -5129,280 +5129,41 @@ import {
|
|
|
5129
5129
|
} from "react";
|
|
5130
5130
|
import { useFrame, useThree } from "@react-three/fiber";
|
|
5131
5131
|
import * as THREE2 from "three/webgpu";
|
|
5132
|
+
import { uniform, instancedArray } from "three/tsl";
|
|
5132
5133
|
import {
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
cameraNear,
|
|
5161
|
-
cameraFar,
|
|
5162
|
-
clamp
|
|
5163
|
-
} from "three/tsl";
|
|
5134
|
+
Appearance as Appearance2,
|
|
5135
|
+
Blending as Blending2,
|
|
5136
|
+
EmitterShape as EmitterShape2,
|
|
5137
|
+
Lighting as Lighting2,
|
|
5138
|
+
MAX_ATTRACTORS,
|
|
5139
|
+
hexToRgb,
|
|
5140
|
+
toRange,
|
|
5141
|
+
easingToType,
|
|
5142
|
+
axisToNumber,
|
|
5143
|
+
toRotation3D,
|
|
5144
|
+
lifetimeToFadeRate,
|
|
5145
|
+
createCombinedCurveTexture,
|
|
5146
|
+
createInitCompute,
|
|
5147
|
+
createSpawnCompute,
|
|
5148
|
+
createUpdateCompute,
|
|
5149
|
+
createParticleMaterial
|
|
5150
|
+
} from "core-vfx";
|
|
5151
|
+
import {
|
|
5152
|
+
Appearance,
|
|
5153
|
+
Blending,
|
|
5154
|
+
EmitterShape,
|
|
5155
|
+
AttractorType as AttractorType2,
|
|
5156
|
+
Easing as Easing2,
|
|
5157
|
+
Lighting,
|
|
5158
|
+
bakeCurveToArray,
|
|
5159
|
+
createCombinedCurveTexture as createCombinedCurveTexture2
|
|
5160
|
+
} from "core-vfx";
|
|
5164
5161
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
5165
|
-
var
|
|
5162
|
+
var VFXParticles;
|
|
5166
5163
|
var init_VFXParticles = __esm({
|
|
5167
|
-
"src/VFXParticles.
|
|
5164
|
+
"src/VFXParticles.tsx"() {
|
|
5168
5165
|
"use strict";
|
|
5169
5166
|
init_react_store();
|
|
5170
|
-
Appearance = Object.freeze({
|
|
5171
|
-
DEFAULT: "default",
|
|
5172
|
-
GRADIENT: "gradient",
|
|
5173
|
-
CIRCULAR: "circular"
|
|
5174
|
-
});
|
|
5175
|
-
Blending = Object.freeze({
|
|
5176
|
-
NORMAL: THREE2.NormalBlending,
|
|
5177
|
-
ADDITIVE: THREE2.AdditiveBlending,
|
|
5178
|
-
MULTIPLY: THREE2.MultiplyBlending,
|
|
5179
|
-
SUBTRACTIVE: THREE2.SubtractiveBlending
|
|
5180
|
-
});
|
|
5181
|
-
EmitterShape = Object.freeze({
|
|
5182
|
-
POINT: 0,
|
|
5183
|
-
// Single point emission
|
|
5184
|
-
BOX: 1,
|
|
5185
|
-
// Box/cube volume (uses startPosition ranges)
|
|
5186
|
-
SPHERE: 2,
|
|
5187
|
-
// Sphere surface or volume
|
|
5188
|
-
CONE: 3,
|
|
5189
|
-
// Cone shape (great for fire, fountains)
|
|
5190
|
-
DISK: 4,
|
|
5191
|
-
// Flat disk/circle
|
|
5192
|
-
EDGE: 5
|
|
5193
|
-
// Line between two points
|
|
5194
|
-
});
|
|
5195
|
-
AttractorType = Object.freeze({
|
|
5196
|
-
POINT: 0,
|
|
5197
|
-
// Pull toward a point (or push if negative strength)
|
|
5198
|
-
VORTEX: 1
|
|
5199
|
-
// Swirl around an axis
|
|
5200
|
-
});
|
|
5201
|
-
Easing = Object.freeze({
|
|
5202
|
-
LINEAR: 0,
|
|
5203
|
-
EASE_IN: 1,
|
|
5204
|
-
EASE_OUT: 2,
|
|
5205
|
-
EASE_IN_OUT: 3
|
|
5206
|
-
});
|
|
5207
|
-
Lighting = Object.freeze({
|
|
5208
|
-
BASIC: "basic",
|
|
5209
|
-
// No lighting, flat colors (MeshBasicNodeMaterial)
|
|
5210
|
-
STANDARD: "standard",
|
|
5211
|
-
// Standard PBR (MeshStandardNodeMaterial)
|
|
5212
|
-
PHYSICAL: "physical"
|
|
5213
|
-
// Advanced PBR with clearcoat, transmission, etc. (MeshPhysicalNodeMaterial)
|
|
5214
|
-
});
|
|
5215
|
-
MAX_ATTRACTORS = 4;
|
|
5216
|
-
hexToRgb = (hex) => {
|
|
5217
|
-
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
5218
|
-
return result ? [
|
|
5219
|
-
parseInt(result[1], 16) / 255,
|
|
5220
|
-
parseInt(result[2], 16) / 255,
|
|
5221
|
-
parseInt(result[3], 16) / 255
|
|
5222
|
-
] : [1, 1, 1];
|
|
5223
|
-
};
|
|
5224
|
-
toRange = (value, defaultVal = [0, 0]) => {
|
|
5225
|
-
if (value === void 0 || value === null) return defaultVal;
|
|
5226
|
-
if (Array.isArray(value))
|
|
5227
|
-
return value.length === 2 ? value : [value[0], value[0]];
|
|
5228
|
-
return [value, value];
|
|
5229
|
-
};
|
|
5230
|
-
easingToType = (easing) => {
|
|
5231
|
-
if (typeof easing === "number") return easing;
|
|
5232
|
-
switch (easing) {
|
|
5233
|
-
case "easeIn":
|
|
5234
|
-
return 1;
|
|
5235
|
-
case "easeOut":
|
|
5236
|
-
return 2;
|
|
5237
|
-
case "easeInOut":
|
|
5238
|
-
return 3;
|
|
5239
|
-
default:
|
|
5240
|
-
return 0;
|
|
5241
|
-
}
|
|
5242
|
-
};
|
|
5243
|
-
axisToNumber = (axis) => {
|
|
5244
|
-
switch (axis) {
|
|
5245
|
-
case "x":
|
|
5246
|
-
case "+x":
|
|
5247
|
-
case "X":
|
|
5248
|
-
case "+X":
|
|
5249
|
-
return 0;
|
|
5250
|
-
case "y":
|
|
5251
|
-
case "+y":
|
|
5252
|
-
case "Y":
|
|
5253
|
-
case "+Y":
|
|
5254
|
-
return 1;
|
|
5255
|
-
case "z":
|
|
5256
|
-
case "+z":
|
|
5257
|
-
case "Z":
|
|
5258
|
-
case "+Z":
|
|
5259
|
-
return 2;
|
|
5260
|
-
case "-x":
|
|
5261
|
-
case "-X":
|
|
5262
|
-
return 3;
|
|
5263
|
-
case "-y":
|
|
5264
|
-
case "-Y":
|
|
5265
|
-
return 4;
|
|
5266
|
-
case "-z":
|
|
5267
|
-
case "-Z":
|
|
5268
|
-
return 5;
|
|
5269
|
-
default:
|
|
5270
|
-
return 2;
|
|
5271
|
-
}
|
|
5272
|
-
};
|
|
5273
|
-
CURVE_RESOLUTION = 256;
|
|
5274
|
-
evaluateBezierSegment = (t, p0, p1, h0Out, h1In) => {
|
|
5275
|
-
const cp0 = p0;
|
|
5276
|
-
const cp1 = [p0[0] + ((h0Out == null ? void 0 : h0Out[0]) || 0), p0[1] + ((h0Out == null ? void 0 : h0Out[1]) || 0)];
|
|
5277
|
-
const cp2 = [p1[0] + ((h1In == null ? void 0 : h1In[0]) || 0), p1[1] + ((h1In == null ? void 0 : h1In[1]) || 0)];
|
|
5278
|
-
const cp3 = p1;
|
|
5279
|
-
const mt = 1 - t;
|
|
5280
|
-
const mt2 = mt * mt;
|
|
5281
|
-
const mt3 = mt2 * mt;
|
|
5282
|
-
const t2 = t * t;
|
|
5283
|
-
const t3 = t2 * t;
|
|
5284
|
-
return [
|
|
5285
|
-
mt3 * cp0[0] + 3 * mt2 * t * cp1[0] + 3 * mt * t2 * cp2[0] + t3 * cp3[0],
|
|
5286
|
-
mt3 * cp0[1] + 3 * mt2 * t * cp1[1] + 3 * mt * t2 * cp2[1] + t3 * cp3[1]
|
|
5287
|
-
];
|
|
5288
|
-
};
|
|
5289
|
-
sampleCurveAtX = (x, points) => {
|
|
5290
|
-
var _a, _b, _c, _d;
|
|
5291
|
-
if (!points || points.length < 2) return x;
|
|
5292
|
-
if (!((_a = points[0]) == null ? void 0 : _a.pos) || !((_b = points[points.length - 1]) == null ? void 0 : _b.pos)) return x;
|
|
5293
|
-
let segmentIdx = 0;
|
|
5294
|
-
for (let i = 0; i < points.length - 1; i++) {
|
|
5295
|
-
if (((_c = points[i]) == null ? void 0 : _c.pos) && ((_d = points[i + 1]) == null ? void 0 : _d.pos) && x >= points[i].pos[0] && x <= points[i + 1].pos[0]) {
|
|
5296
|
-
segmentIdx = i;
|
|
5297
|
-
break;
|
|
5298
|
-
}
|
|
5299
|
-
}
|
|
5300
|
-
const p0 = points[segmentIdx];
|
|
5301
|
-
const p1 = points[segmentIdx + 1];
|
|
5302
|
-
if (!(p0 == null ? void 0 : p0.pos) || !(p1 == null ? void 0 : p1.pos)) return x;
|
|
5303
|
-
let tLow = 0, tHigh = 1, t = 0.5;
|
|
5304
|
-
for (let iter = 0; iter < 20; iter++) {
|
|
5305
|
-
const [px] = evaluateBezierSegment(
|
|
5306
|
-
t,
|
|
5307
|
-
p0.pos,
|
|
5308
|
-
p1.pos,
|
|
5309
|
-
p0.handleOut,
|
|
5310
|
-
p1.handleIn
|
|
5311
|
-
);
|
|
5312
|
-
if (Math.abs(px - x) < 1e-4) break;
|
|
5313
|
-
if (px < x) {
|
|
5314
|
-
tLow = t;
|
|
5315
|
-
} else {
|
|
5316
|
-
tHigh = t;
|
|
5317
|
-
}
|
|
5318
|
-
t = (tLow + tHigh) / 2;
|
|
5319
|
-
}
|
|
5320
|
-
const [, py] = evaluateBezierSegment(
|
|
5321
|
-
t,
|
|
5322
|
-
p0.pos,
|
|
5323
|
-
p1.pos,
|
|
5324
|
-
p0.handleOut,
|
|
5325
|
-
p1.handleIn
|
|
5326
|
-
);
|
|
5327
|
-
return Math.max(-0.5, Math.min(1.5, py));
|
|
5328
|
-
};
|
|
5329
|
-
bakeCurveToArray = (curveData, resolution = CURVE_RESOLUTION) => {
|
|
5330
|
-
const data = new Float32Array(resolution);
|
|
5331
|
-
if (!(curveData == null ? void 0 : curveData.points) || !Array.isArray(curveData.points) || curveData.points.length < 2) {
|
|
5332
|
-
for (let i = 0; i < resolution; i++) {
|
|
5333
|
-
data[i] = 1 - i / (resolution - 1);
|
|
5334
|
-
}
|
|
5335
|
-
return data;
|
|
5336
|
-
}
|
|
5337
|
-
const firstPoint = curveData.points[0];
|
|
5338
|
-
const lastPoint = curveData.points[curveData.points.length - 1];
|
|
5339
|
-
if (!(firstPoint == null ? void 0 : firstPoint.pos) || !(lastPoint == null ? void 0 : lastPoint.pos) || !Array.isArray(firstPoint.pos) || !Array.isArray(lastPoint.pos)) {
|
|
5340
|
-
for (let i = 0; i < resolution; i++) {
|
|
5341
|
-
data[i] = 1 - i / (resolution - 1);
|
|
5342
|
-
}
|
|
5343
|
-
return data;
|
|
5344
|
-
}
|
|
5345
|
-
for (let i = 0; i < resolution; i++) {
|
|
5346
|
-
const x = i / (resolution - 1);
|
|
5347
|
-
data[i] = sampleCurveAtX(x, curveData.points);
|
|
5348
|
-
}
|
|
5349
|
-
return data;
|
|
5350
|
-
};
|
|
5351
|
-
createCombinedCurveTexture = (sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve) => {
|
|
5352
|
-
const sizeData = bakeCurveToArray(sizeCurve);
|
|
5353
|
-
const opacityData = bakeCurveToArray(opacityCurve);
|
|
5354
|
-
const velocityData = bakeCurveToArray(velocityCurve);
|
|
5355
|
-
const rotationSpeedData = bakeCurveToArray(rotationSpeedCurve);
|
|
5356
|
-
const rgba = new Float32Array(CURVE_RESOLUTION * 4);
|
|
5357
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
5358
|
-
rgba[i * 4] = sizeData[i];
|
|
5359
|
-
rgba[i * 4 + 1] = opacityData[i];
|
|
5360
|
-
rgba[i * 4 + 2] = velocityData[i];
|
|
5361
|
-
rgba[i * 4 + 3] = rotationSpeedData[i];
|
|
5362
|
-
}
|
|
5363
|
-
const tex = new THREE2.DataTexture(
|
|
5364
|
-
rgba,
|
|
5365
|
-
CURVE_RESOLUTION,
|
|
5366
|
-
1,
|
|
5367
|
-
THREE2.RGBAFormat,
|
|
5368
|
-
THREE2.FloatType
|
|
5369
|
-
);
|
|
5370
|
-
tex.minFilter = THREE2.LinearFilter;
|
|
5371
|
-
tex.magFilter = THREE2.LinearFilter;
|
|
5372
|
-
tex.wrapS = THREE2.ClampToEdgeWrapping;
|
|
5373
|
-
tex.needsUpdate = true;
|
|
5374
|
-
return tex;
|
|
5375
|
-
};
|
|
5376
|
-
toRotation3D = (value) => {
|
|
5377
|
-
if (value === void 0 || value === null)
|
|
5378
|
-
return [
|
|
5379
|
-
[0, 0],
|
|
5380
|
-
[0, 0],
|
|
5381
|
-
[0, 0]
|
|
5382
|
-
];
|
|
5383
|
-
if (typeof value === "number")
|
|
5384
|
-
return [
|
|
5385
|
-
[value, value],
|
|
5386
|
-
[value, value],
|
|
5387
|
-
[value, value]
|
|
5388
|
-
];
|
|
5389
|
-
if (Array.isArray(value)) {
|
|
5390
|
-
if (Array.isArray(value[0])) {
|
|
5391
|
-
return [
|
|
5392
|
-
toRange(value[0], [0, 0]),
|
|
5393
|
-
toRange(value[1], [0, 0]),
|
|
5394
|
-
toRange(value[2], [0, 0])
|
|
5395
|
-
];
|
|
5396
|
-
}
|
|
5397
|
-
const range = toRange(value, [0, 0]);
|
|
5398
|
-
return [range, range, range];
|
|
5399
|
-
}
|
|
5400
|
-
return [
|
|
5401
|
-
[0, 0],
|
|
5402
|
-
[0, 0],
|
|
5403
|
-
[0, 0]
|
|
5404
|
-
];
|
|
5405
|
-
};
|
|
5406
5167
|
VFXParticles = forwardRef(function VFXParticles2({
|
|
5407
5168
|
name,
|
|
5408
5169
|
// Optional name for registering with useVFXStore (enables VFXEmitter linking)
|
|
@@ -5437,7 +5198,7 @@ var init_VFXParticles = __esm({
|
|
|
5437
5198
|
friction = { intensity: 0, easing: "linear" },
|
|
5438
5199
|
// { intensity: [start, end] or single value, easing: string }
|
|
5439
5200
|
// intensity: 1 = max friction (almost stopped), 0 = no friction (normal), negative = boost/acceleration
|
|
5440
|
-
appearance =
|
|
5201
|
+
appearance = Appearance2.GRADIENT,
|
|
5441
5202
|
alphaMap = null,
|
|
5442
5203
|
flipbook = null,
|
|
5443
5204
|
// { rows: 4, columns: 8 }
|
|
@@ -5455,11 +5216,11 @@ var init_VFXParticles = __esm({
|
|
|
5455
5216
|
// Which local axis aligns with velocity: "x", "y", "z", "-x", "-y", "-z"
|
|
5456
5217
|
stretchBySpeed = null,
|
|
5457
5218
|
// { factor: 2, maxStretch: 5 } - stretch particles in velocity direction based on effective speed
|
|
5458
|
-
lighting =
|
|
5219
|
+
lighting = Lighting2.STANDARD,
|
|
5459
5220
|
// 'basic' | 'standard' | 'physical' - material type for geometry mode
|
|
5460
5221
|
shadow = false,
|
|
5461
5222
|
// Enable both castShadow and receiveShadow on geometry instances
|
|
5462
|
-
blending =
|
|
5223
|
+
blending = Blending2.NORMAL,
|
|
5463
5224
|
intensity = 1,
|
|
5464
5225
|
position = [0, 0, 0],
|
|
5465
5226
|
autoStart = true,
|
|
@@ -5476,7 +5237,7 @@ var init_VFXParticles = __esm({
|
|
|
5476
5237
|
// TSL node or function for shadow map output (what shadow the particle casts)
|
|
5477
5238
|
emitCount = 1,
|
|
5478
5239
|
// Emitter shape props
|
|
5479
|
-
emitterShape =
|
|
5240
|
+
emitterShape = EmitterShape2.BOX,
|
|
5480
5241
|
// Emission shape type
|
|
5481
5242
|
emitterRadius = [0, 1],
|
|
5482
5243
|
// [inner, outer] radius for sphere/cone/disk (inner=0 for solid)
|
|
@@ -5510,7 +5271,7 @@ var init_VFXParticles = __esm({
|
|
|
5510
5271
|
debug = false
|
|
5511
5272
|
}, ref) {
|
|
5512
5273
|
const { gl: renderer } = useThree();
|
|
5513
|
-
const spriteRef = useRef2();
|
|
5274
|
+
const spriteRef = useRef2(null);
|
|
5514
5275
|
const initialized = useRef2(false);
|
|
5515
5276
|
const nextIndex = useRef2(0);
|
|
5516
5277
|
const [emitting, setEmitting] = useState2(autoStart);
|
|
@@ -5559,7 +5320,6 @@ var init_VFXParticles = __esm({
|
|
|
5559
5320
|
velocityCurve,
|
|
5560
5321
|
rotationSpeedCurve
|
|
5561
5322
|
]);
|
|
5562
|
-
const lifetimeToFadeRate = (seconds) => 1 / seconds;
|
|
5563
5323
|
const sizeRange = useMemo(() => toRange(size, [0.1, 0.3]), [size]);
|
|
5564
5324
|
const speedRange = useMemo(() => toRange(speed, [0.1, 0.1]), [speed]);
|
|
5565
5325
|
const fadeSizeRange = useMemo(() => toRange(fadeSize, [1, 0]), [fadeSize]);
|
|
@@ -5618,8 +5378,9 @@ var init_VFXParticles = __esm({
|
|
|
5618
5378
|
return [0, 0];
|
|
5619
5379
|
}, [friction]);
|
|
5620
5380
|
const frictionEasingType = useMemo(() => {
|
|
5381
|
+
var _a;
|
|
5621
5382
|
if (typeof friction === "object" && friction !== null && "easing" in friction) {
|
|
5622
|
-
return easingToType(friction.easing);
|
|
5383
|
+
return easingToType((_a = friction.easing) != null ? _a : "linear");
|
|
5623
5384
|
}
|
|
5624
5385
|
return 0;
|
|
5625
5386
|
}, [friction]);
|
|
@@ -5850,14 +5611,15 @@ var init_VFXParticles = __esm({
|
|
|
5850
5611
|
);
|
|
5851
5612
|
for (let i = 0; i < MAX_ATTRACTORS; i++) {
|
|
5852
5613
|
const a = attractorList[i];
|
|
5614
|
+
const u = uniforms;
|
|
5853
5615
|
if (a) {
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5616
|
+
u[`attractor${i}Pos`].value.set(...(_d = a.position) != null ? _d : [0, 0, 0]);
|
|
5617
|
+
u[`attractor${i}Strength`].value = (_e = a.strength) != null ? _e : 1;
|
|
5618
|
+
u[`attractor${i}Radius`].value = (_f = a.radius) != null ? _f : 0;
|
|
5619
|
+
u[`attractor${i}Type`].value = a.type === "vortex" ? 1 : 0;
|
|
5620
|
+
u[`attractor${i}Axis`].value.set(...(_g = a.axis) != null ? _g : [0, 1, 0]).normalize();
|
|
5859
5621
|
} else {
|
|
5860
|
-
|
|
5622
|
+
u[`attractor${i}Strength`].value = 0;
|
|
5861
5623
|
}
|
|
5862
5624
|
}
|
|
5863
5625
|
uniforms.attractToCenter.value = attractToCenter ? 1 : 0;
|
|
@@ -5919,16 +5681,7 @@ var init_VFXParticles = __esm({
|
|
|
5919
5681
|
orientAxis,
|
|
5920
5682
|
stretchBySpeed
|
|
5921
5683
|
]);
|
|
5922
|
-
const
|
|
5923
|
-
positions,
|
|
5924
|
-
velocities,
|
|
5925
|
-
lifetimes,
|
|
5926
|
-
fadeRates,
|
|
5927
|
-
particleSizes,
|
|
5928
|
-
particleRotations,
|
|
5929
|
-
particleColorStarts,
|
|
5930
|
-
particleColorEnds
|
|
5931
|
-
} = useMemo(
|
|
5684
|
+
const storage = useMemo(
|
|
5932
5685
|
() => ({
|
|
5933
5686
|
positions: instancedArray(activeMaxParticles, "vec3"),
|
|
5934
5687
|
velocities: instancedArray(activeMaxParticles, "vec3"),
|
|
@@ -5936,774 +5689,60 @@ var init_VFXParticles = __esm({
|
|
|
5936
5689
|
fadeRates: instancedArray(activeMaxParticles, "float"),
|
|
5937
5690
|
particleSizes: instancedArray(activeMaxParticles, "float"),
|
|
5938
5691
|
particleRotations: instancedArray(activeMaxParticles, "vec3"),
|
|
5939
|
-
// X, Y, Z rotations
|
|
5940
5692
|
particleColorStarts: instancedArray(activeMaxParticles, "vec3"),
|
|
5941
5693
|
particleColorEnds: instancedArray(activeMaxParticles, "vec3")
|
|
5942
5694
|
}),
|
|
5943
5695
|
[activeMaxParticles]
|
|
5944
5696
|
);
|
|
5945
|
-
const
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
return Fn(() => {
|
|
5995
|
-
const idx = float(instanceIndex);
|
|
5996
|
-
const startIdx = uniforms.spawnIndexStart;
|
|
5997
|
-
const endIdx = uniforms.spawnIndexEnd;
|
|
5998
|
-
const seed = uniforms.spawnSeed;
|
|
5999
|
-
const inRange = startIdx.lessThan(endIdx).select(
|
|
6000
|
-
idx.greaterThanEqual(startIdx).and(idx.lessThan(endIdx)),
|
|
6001
|
-
idx.greaterThanEqual(startIdx).or(idx.lessThan(endIdx))
|
|
6002
|
-
);
|
|
6003
|
-
If(inRange, () => {
|
|
6004
|
-
const position2 = positions.element(instanceIndex);
|
|
6005
|
-
const velocity = velocities.element(instanceIndex);
|
|
6006
|
-
const lifetime2 = lifetimes.element(instanceIndex);
|
|
6007
|
-
const fadeRate = fadeRates.element(instanceIndex);
|
|
6008
|
-
const particleSize = particleSizes.element(instanceIndex);
|
|
6009
|
-
const particleRotation = particleRotations.element(instanceIndex);
|
|
6010
|
-
const pColorStart = particleColorStarts.element(instanceIndex);
|
|
6011
|
-
const pColorEnd = particleColorEnds.element(instanceIndex);
|
|
6012
|
-
const particleSeed = idx.add(seed);
|
|
6013
|
-
const randDirX = hash(particleSeed.add(333));
|
|
6014
|
-
const randDirY = hash(particleSeed.add(444));
|
|
6015
|
-
const randDirZ = hash(particleSeed.add(555));
|
|
6016
|
-
const randFade = hash(particleSeed.add(666));
|
|
6017
|
-
const randColorStart = hash(particleSeed.add(777));
|
|
6018
|
-
const randColorEnd = hash(particleSeed.add(888));
|
|
6019
|
-
const randSize = hash(particleSeed.add(999));
|
|
6020
|
-
const randSpeed = hash(particleSeed.add(1111));
|
|
6021
|
-
const randRotationX = hash(particleSeed.add(2222));
|
|
6022
|
-
const randRotationY = hash(particleSeed.add(3333));
|
|
6023
|
-
const randRotationZ = hash(particleSeed.add(4444));
|
|
6024
|
-
const randPosX = hash(particleSeed.add(5555));
|
|
6025
|
-
const randPosY = hash(particleSeed.add(6666));
|
|
6026
|
-
const randPosZ = hash(particleSeed.add(7777));
|
|
6027
|
-
const randRadius = hash(particleSeed.add(8880));
|
|
6028
|
-
const randTheta = hash(particleSeed.add(9990));
|
|
6029
|
-
const randPhi = hash(particleSeed.add(10100));
|
|
6030
|
-
const randHeight = hash(particleSeed.add(11110));
|
|
6031
|
-
const shapeType = uniforms.emitterShapeType;
|
|
6032
|
-
const radiusInner = uniforms.emitterRadiusInner;
|
|
6033
|
-
const radiusOuter = uniforms.emitterRadiusOuter;
|
|
6034
|
-
const coneAngle = uniforms.emitterAngle;
|
|
6035
|
-
const heightMin = uniforms.emitterHeightMin;
|
|
6036
|
-
const heightMax = uniforms.emitterHeightMax;
|
|
6037
|
-
const surfaceOnly = uniforms.emitterSurfaceOnly;
|
|
6038
|
-
const emitDir = uniforms.emitterDir;
|
|
6039
|
-
const theta = randTheta.mul(PI.mul(2));
|
|
6040
|
-
const phi = acos(float(1).sub(randPhi.mul(2)));
|
|
6041
|
-
const radiusT = surfaceOnly.greaterThan(0.5).select(
|
|
6042
|
-
float(1),
|
|
6043
|
-
randRadius.pow(float(1).div(3))
|
|
6044
|
-
// Cube root for uniform volume
|
|
6045
|
-
);
|
|
6046
|
-
const radius = mix(radiusInner, radiusOuter, radiusT);
|
|
6047
|
-
const cosAngle = emitDir.y;
|
|
6048
|
-
const axisX = emitDir.z.negate();
|
|
6049
|
-
const axisZ = emitDir.x;
|
|
6050
|
-
const axisLenSq = axisX.mul(axisX).add(axisZ.mul(axisZ));
|
|
6051
|
-
const axisLen = sqrt(axisLenSq.max(1e-4));
|
|
6052
|
-
const kx = axisX.div(axisLen);
|
|
6053
|
-
const kz = axisZ.div(axisLen);
|
|
6054
|
-
const sinAngle = axisLen;
|
|
6055
|
-
const oneMinusCos = float(1).sub(cosAngle);
|
|
6056
|
-
const rotateToEmitDir = (localPos) => {
|
|
6057
|
-
const crossX = kz.mul(localPos.y).negate();
|
|
6058
|
-
const crossY = kz.mul(localPos.x).sub(kx.mul(localPos.z));
|
|
6059
|
-
const crossZ = kx.mul(localPos.y);
|
|
6060
|
-
const kDotV = kx.mul(localPos.x).add(kz.mul(localPos.z));
|
|
6061
|
-
const rotatedX = localPos.x.mul(cosAngle).add(crossX.mul(sinAngle)).add(kx.mul(kDotV).mul(oneMinusCos));
|
|
6062
|
-
const rotatedY = localPos.y.mul(cosAngle).add(crossY.mul(sinAngle));
|
|
6063
|
-
const rotatedZ = localPos.z.mul(cosAngle).add(crossZ.mul(sinAngle)).add(kz.mul(kDotV).mul(oneMinusCos));
|
|
6064
|
-
return cosAngle.greaterThan(0.999).select(
|
|
6065
|
-
localPos,
|
|
6066
|
-
cosAngle.lessThan(-0.999).select(
|
|
6067
|
-
vec3(localPos.x, localPos.y.negate(), localPos.z),
|
|
6068
|
-
vec3(rotatedX, rotatedY, rotatedZ)
|
|
6069
|
-
)
|
|
6070
|
-
);
|
|
6071
|
-
};
|
|
6072
|
-
const boxOffsetX = mix(
|
|
6073
|
-
uniforms.startPosMinX,
|
|
6074
|
-
uniforms.startPosMaxX,
|
|
6075
|
-
randPosX
|
|
6076
|
-
);
|
|
6077
|
-
const boxOffsetY = mix(
|
|
6078
|
-
uniforms.startPosMinY,
|
|
6079
|
-
uniforms.startPosMaxY,
|
|
6080
|
-
randPosY
|
|
6081
|
-
);
|
|
6082
|
-
const boxOffsetZ = mix(
|
|
6083
|
-
uniforms.startPosMinZ,
|
|
6084
|
-
uniforms.startPosMaxZ,
|
|
6085
|
-
randPosZ
|
|
6086
|
-
);
|
|
6087
|
-
const boxPos = vec3(boxOffsetX, boxOffsetY, boxOffsetZ);
|
|
6088
|
-
const sphereX = radius.mul(sin(phi)).mul(cos(theta));
|
|
6089
|
-
const sphereY = radius.mul(cos(phi));
|
|
6090
|
-
const sphereZ = radius.mul(sin(phi)).mul(sin(theta));
|
|
6091
|
-
const spherePos = vec3(sphereX, sphereY, sphereZ);
|
|
6092
|
-
const coneH = mix(heightMin, heightMax, randHeight);
|
|
6093
|
-
const coneR = coneH.mul(sin(coneAngle)).mul(radiusT);
|
|
6094
|
-
const coneLocalX = coneR.mul(cos(theta));
|
|
6095
|
-
const coneLocalY = coneH.mul(cos(coneAngle));
|
|
6096
|
-
const coneLocalZ = coneR.mul(sin(theta));
|
|
6097
|
-
const conePos = rotateToEmitDir(
|
|
6098
|
-
vec3(coneLocalX, coneLocalY, coneLocalZ)
|
|
6099
|
-
);
|
|
6100
|
-
const diskR = surfaceOnly.greaterThan(0.5).select(
|
|
6101
|
-
radiusOuter,
|
|
6102
|
-
mix(radiusInner, radiusOuter, sqrt(randRadius))
|
|
6103
|
-
// sqrt for uniform area distribution
|
|
6104
|
-
);
|
|
6105
|
-
const diskLocalX = diskR.mul(cos(theta));
|
|
6106
|
-
const diskLocalZ = diskR.mul(sin(theta));
|
|
6107
|
-
const diskPos = rotateToEmitDir(vec3(diskLocalX, float(0), diskLocalZ));
|
|
6108
|
-
const edgeT = randPosX;
|
|
6109
|
-
const edgePos = vec3(
|
|
6110
|
-
mix(uniforms.startPosMinX, uniforms.startPosMaxX, edgeT),
|
|
6111
|
-
mix(uniforms.startPosMinY, uniforms.startPosMaxY, edgeT),
|
|
6112
|
-
mix(uniforms.startPosMinZ, uniforms.startPosMaxZ, edgeT)
|
|
6113
|
-
);
|
|
6114
|
-
const pointPos = vec3(0, 0, 0);
|
|
6115
|
-
const shapeOffset = shapeType.lessThan(0.5).select(
|
|
6116
|
-
pointPos,
|
|
6117
|
-
// 0: POINT
|
|
6118
|
-
shapeType.lessThan(1.5).select(
|
|
6119
|
-
boxPos,
|
|
6120
|
-
// 1: BOX
|
|
6121
|
-
shapeType.lessThan(2.5).select(
|
|
6122
|
-
spherePos,
|
|
6123
|
-
// 2: SPHERE
|
|
6124
|
-
shapeType.lessThan(3.5).select(
|
|
6125
|
-
conePos,
|
|
6126
|
-
// 3: CONE
|
|
6127
|
-
shapeType.lessThan(4.5).select(
|
|
6128
|
-
diskPos,
|
|
6129
|
-
// 4: DISK
|
|
6130
|
-
edgePos
|
|
6131
|
-
// 5: EDGE
|
|
6132
|
-
)
|
|
6133
|
-
)
|
|
6134
|
-
)
|
|
6135
|
-
)
|
|
6136
|
-
);
|
|
6137
|
-
position2.assign(uniforms.spawnPosition.add(shapeOffset));
|
|
6138
|
-
const randomFade = mix(
|
|
6139
|
-
uniforms.lifetimeMin,
|
|
6140
|
-
uniforms.lifetimeMax,
|
|
6141
|
-
randFade
|
|
6142
|
-
);
|
|
6143
|
-
fadeRate.assign(randomFade);
|
|
6144
|
-
const useAttractToCenter = uniforms.attractToCenter.greaterThan(0.5);
|
|
6145
|
-
const attractVelocity = shapeOffset.negate().mul(randomFade);
|
|
6146
|
-
const useStartPosAsDir = uniforms.startPositionAsDirection.greaterThan(0.5);
|
|
6147
|
-
const dirX = mix(uniforms.dirMinX, uniforms.dirMaxX, randDirX);
|
|
6148
|
-
const dirY = mix(uniforms.dirMinY, uniforms.dirMaxY, randDirY);
|
|
6149
|
-
const dirZ = mix(uniforms.dirMinZ, uniforms.dirMaxZ, randDirZ);
|
|
6150
|
-
const randomDirVec = vec3(dirX, dirY, dirZ);
|
|
6151
|
-
const randomDirLength = randomDirVec.length();
|
|
6152
|
-
const randomDir = randomDirLength.greaterThan(1e-3).select(randomDirVec.div(randomDirLength), vec3(0, 0, 0));
|
|
6153
|
-
const startPosLength = shapeOffset.length();
|
|
6154
|
-
const startPosDir = startPosLength.greaterThan(1e-3).select(shapeOffset.div(startPosLength), vec3(0, 0, 0));
|
|
6155
|
-
const dir = useStartPosAsDir.select(startPosDir, randomDir);
|
|
6156
|
-
const randomSpeed = mix(
|
|
6157
|
-
uniforms.speedMin,
|
|
6158
|
-
uniforms.speedMax,
|
|
6159
|
-
randSpeed
|
|
6160
|
-
);
|
|
6161
|
-
const normalVelocity = dir.mul(randomSpeed);
|
|
6162
|
-
velocity.assign(
|
|
6163
|
-
useAttractToCenter.select(attractVelocity, normalVelocity)
|
|
6164
|
-
);
|
|
6165
|
-
const randomSize = mix(uniforms.sizeMin, uniforms.sizeMax, randSize);
|
|
6166
|
-
particleSize.assign(randomSize);
|
|
6167
|
-
const rotX = mix(
|
|
6168
|
-
uniforms.rotationMinX,
|
|
6169
|
-
uniforms.rotationMaxX,
|
|
6170
|
-
randRotationX
|
|
6171
|
-
);
|
|
6172
|
-
const rotY = mix(
|
|
6173
|
-
uniforms.rotationMinY,
|
|
6174
|
-
uniforms.rotationMaxY,
|
|
6175
|
-
randRotationY
|
|
6176
|
-
);
|
|
6177
|
-
const rotZ = mix(
|
|
6178
|
-
uniforms.rotationMinZ,
|
|
6179
|
-
uniforms.rotationMaxZ,
|
|
6180
|
-
randRotationZ
|
|
6181
|
-
);
|
|
6182
|
-
particleRotation.assign(vec3(rotX, rotY, rotZ));
|
|
6183
|
-
const startColorIdx = floor(
|
|
6184
|
-
randColorStart.mul(uniforms.colorStartCount)
|
|
6185
|
-
);
|
|
6186
|
-
const selectedStartColor = selectColor(
|
|
6187
|
-
startColorIdx,
|
|
6188
|
-
uniforms.colorStart0,
|
|
6189
|
-
uniforms.colorStart1,
|
|
6190
|
-
uniforms.colorStart2,
|
|
6191
|
-
uniforms.colorStart3,
|
|
6192
|
-
uniforms.colorStart4,
|
|
6193
|
-
uniforms.colorStart5,
|
|
6194
|
-
uniforms.colorStart6,
|
|
6195
|
-
uniforms.colorStart7
|
|
6196
|
-
);
|
|
6197
|
-
pColorStart.assign(selectedStartColor);
|
|
6198
|
-
const endColorIdx = floor(randColorEnd.mul(uniforms.colorEndCount));
|
|
6199
|
-
const selectedEndColor = selectColor(
|
|
6200
|
-
endColorIdx,
|
|
6201
|
-
uniforms.colorEnd0,
|
|
6202
|
-
uniforms.colorEnd1,
|
|
6203
|
-
uniforms.colorEnd2,
|
|
6204
|
-
uniforms.colorEnd3,
|
|
6205
|
-
uniforms.colorEnd4,
|
|
6206
|
-
uniforms.colorEnd5,
|
|
6207
|
-
uniforms.colorEnd6,
|
|
6208
|
-
uniforms.colorEnd7
|
|
6209
|
-
);
|
|
6210
|
-
pColorEnd.assign(selectedEndColor);
|
|
6211
|
-
lifetime2.assign(float(1));
|
|
6212
|
-
});
|
|
6213
|
-
})().compute(activeMaxParticles);
|
|
6214
|
-
}, [
|
|
6215
|
-
activeMaxParticles,
|
|
6216
|
-
positions,
|
|
6217
|
-
velocities,
|
|
6218
|
-
lifetimes,
|
|
6219
|
-
fadeRates,
|
|
6220
|
-
particleSizes,
|
|
6221
|
-
particleRotations,
|
|
6222
|
-
particleColorStarts,
|
|
6223
|
-
particleColorEnds,
|
|
6224
|
-
uniforms,
|
|
6225
|
-
selectColor
|
|
6226
|
-
]);
|
|
6227
|
-
const computeUpdate = useMemo(() => {
|
|
6228
|
-
return Fn(() => {
|
|
6229
|
-
const position2 = positions.element(instanceIndex);
|
|
6230
|
-
const velocity = velocities.element(instanceIndex);
|
|
6231
|
-
const lifetime2 = lifetimes.element(instanceIndex);
|
|
6232
|
-
const fadeRate = fadeRates.element(instanceIndex);
|
|
6233
|
-
const particleRotation = particleRotations.element(instanceIndex);
|
|
6234
|
-
const particleSize = particleSizes.element(instanceIndex);
|
|
6235
|
-
const dt = uniforms.deltaTime;
|
|
6236
|
-
If(lifetime2.greaterThan(0), () => {
|
|
6237
|
-
const gravityMultiplier = float(1).add(
|
|
6238
|
-
particleSize.mul(uniforms.sizeBasedGravity)
|
|
6239
|
-
);
|
|
6240
|
-
velocity.addAssign(uniforms.gravity.mul(dt).mul(gravityMultiplier));
|
|
6241
|
-
const progress = float(1).sub(lifetime2);
|
|
6242
|
-
const velocityCurveSample = texture(
|
|
6243
|
-
curveTexture,
|
|
6244
|
-
vec2(progress, float(0.5))
|
|
6245
|
-
).z;
|
|
6246
|
-
const speedScale = uniforms.velocityCurveEnabled.greaterThan(0.5).select(
|
|
6247
|
-
// Use velocity curve directly as speed multiplier
|
|
6248
|
-
velocityCurveSample,
|
|
6249
|
-
// Legacy friction behavior
|
|
6250
|
-
(() => {
|
|
6251
|
-
const easingType = uniforms.frictionEasingType;
|
|
6252
|
-
const easedProgress = easingType.lessThan(0.5).select(
|
|
6253
|
-
progress,
|
|
6254
|
-
easingType.lessThan(1.5).select(
|
|
6255
|
-
progress.mul(progress),
|
|
6256
|
-
easingType.lessThan(2.5).select(
|
|
6257
|
-
float(1).sub(
|
|
6258
|
-
float(1).sub(progress).mul(float(1).sub(progress))
|
|
6259
|
-
),
|
|
6260
|
-
progress.lessThan(0.5).select(
|
|
6261
|
-
float(2).mul(progress).mul(progress),
|
|
6262
|
-
float(1).sub(
|
|
6263
|
-
float(-2).mul(progress).add(2).pow(2).div(2)
|
|
6264
|
-
)
|
|
6265
|
-
)
|
|
6266
|
-
)
|
|
6267
|
-
)
|
|
6268
|
-
);
|
|
6269
|
-
const currentIntensity = mix(
|
|
6270
|
-
uniforms.frictionIntensityStart,
|
|
6271
|
-
uniforms.frictionIntensityEnd,
|
|
6272
|
-
easedProgress
|
|
6273
|
-
);
|
|
6274
|
-
return float(1).sub(currentIntensity.mul(0.9));
|
|
6275
|
-
})()
|
|
6276
|
-
);
|
|
6277
|
-
const turbIntensity = uniforms.turbulenceIntensity;
|
|
6278
|
-
const turbFreq = uniforms.turbulenceFrequency;
|
|
6279
|
-
const turbTime = uniforms.turbulenceTime;
|
|
6280
|
-
If(turbIntensity.greaterThan(1e-3), () => {
|
|
6281
|
-
const noisePos = position2.mul(turbFreq).add(vec3(turbTime, turbTime.mul(0.7), turbTime.mul(1.3)));
|
|
6282
|
-
const eps = float(0.01);
|
|
6283
|
-
const nPosX = mx_noise_vec3(noisePos.add(vec3(eps, 0, 0)));
|
|
6284
|
-
const nNegX = mx_noise_vec3(noisePos.sub(vec3(eps, 0, 0)));
|
|
6285
|
-
const nPosY = mx_noise_vec3(noisePos.add(vec3(0, eps, 0)));
|
|
6286
|
-
const nNegY = mx_noise_vec3(noisePos.sub(vec3(0, eps, 0)));
|
|
6287
|
-
const nPosZ = mx_noise_vec3(noisePos.add(vec3(0, 0, eps)));
|
|
6288
|
-
const nNegZ = mx_noise_vec3(noisePos.sub(vec3(0, 0, eps)));
|
|
6289
|
-
const dFx_dy = nPosY.x.sub(nNegY.x).div(eps.mul(2));
|
|
6290
|
-
const dFx_dz = nPosZ.x.sub(nNegZ.x).div(eps.mul(2));
|
|
6291
|
-
const dFy_dx = nPosX.y.sub(nNegX.y).div(eps.mul(2));
|
|
6292
|
-
const dFy_dz = nPosZ.y.sub(nNegZ.y).div(eps.mul(2));
|
|
6293
|
-
const dFz_dx = nPosX.z.sub(nNegX.z).div(eps.mul(2));
|
|
6294
|
-
const dFz_dy = nPosY.z.sub(nNegY.z).div(eps.mul(2));
|
|
6295
|
-
const curlX = dFz_dy.sub(dFy_dz);
|
|
6296
|
-
const curlY = dFx_dz.sub(dFz_dx);
|
|
6297
|
-
const curlZ = dFy_dx.sub(dFx_dy);
|
|
6298
|
-
const curl = vec3(curlX, curlY, curlZ);
|
|
6299
|
-
velocity.addAssign(curl.mul(turbIntensity).mul(uniforms.deltaTime));
|
|
6300
|
-
});
|
|
6301
|
-
const attractorCount = uniforms.attractorCount;
|
|
6302
|
-
const applyAttractor = (aPos, aStrength, aRadius, aType, aAxis) => {
|
|
6303
|
-
If(aStrength.abs().greaterThan(1e-3), () => {
|
|
6304
|
-
const toAttractor = aPos.sub(position2);
|
|
6305
|
-
const dist = toAttractor.length();
|
|
6306
|
-
const safeDist = dist.max(0.01);
|
|
6307
|
-
const direction2 = toAttractor.div(safeDist);
|
|
6308
|
-
const falloff = aRadius.greaterThan(1e-3).select(
|
|
6309
|
-
float(1).sub(dist.div(aRadius)).max(0),
|
|
6310
|
-
// Linear falloff within radius
|
|
6311
|
-
float(1).div(safeDist.mul(safeDist).add(1))
|
|
6312
|
-
// Inverse square falloff (softened)
|
|
6313
|
-
);
|
|
6314
|
-
const force = aType.lessThan(0.5).select(
|
|
6315
|
-
// Point attractor: force along direction to attractor
|
|
6316
|
-
direction2.mul(aStrength).mul(falloff),
|
|
6317
|
-
// Vortex: force perpendicular to both (toAttractor) and (axis)
|
|
6318
|
-
// cross(axis, toAttractor) gives tangent direction
|
|
6319
|
-
(() => {
|
|
6320
|
-
const tangent = vec3(
|
|
6321
|
-
aAxis.y.mul(toAttractor.z).sub(aAxis.z.mul(toAttractor.y)),
|
|
6322
|
-
aAxis.z.mul(toAttractor.x).sub(aAxis.x.mul(toAttractor.z)),
|
|
6323
|
-
aAxis.x.mul(toAttractor.y).sub(aAxis.y.mul(toAttractor.x))
|
|
6324
|
-
);
|
|
6325
|
-
const tangentLen = tangent.length().max(1e-3);
|
|
6326
|
-
return tangent.div(tangentLen).mul(aStrength).mul(falloff);
|
|
6327
|
-
})()
|
|
6328
|
-
);
|
|
6329
|
-
velocity.addAssign(force.mul(uniforms.deltaTime));
|
|
6330
|
-
});
|
|
6331
|
-
};
|
|
6332
|
-
If(attractorCount.greaterThan(0), () => {
|
|
6333
|
-
applyAttractor(
|
|
6334
|
-
uniforms.attractor0Pos,
|
|
6335
|
-
uniforms.attractor0Strength,
|
|
6336
|
-
uniforms.attractor0Radius,
|
|
6337
|
-
uniforms.attractor0Type,
|
|
6338
|
-
uniforms.attractor0Axis
|
|
6339
|
-
);
|
|
6340
|
-
});
|
|
6341
|
-
If(attractorCount.greaterThan(1), () => {
|
|
6342
|
-
applyAttractor(
|
|
6343
|
-
uniforms.attractor1Pos,
|
|
6344
|
-
uniforms.attractor1Strength,
|
|
6345
|
-
uniforms.attractor1Radius,
|
|
6346
|
-
uniforms.attractor1Type,
|
|
6347
|
-
uniforms.attractor1Axis
|
|
6348
|
-
);
|
|
6349
|
-
});
|
|
6350
|
-
If(attractorCount.greaterThan(2), () => {
|
|
6351
|
-
applyAttractor(
|
|
6352
|
-
uniforms.attractor2Pos,
|
|
6353
|
-
uniforms.attractor2Strength,
|
|
6354
|
-
uniforms.attractor2Radius,
|
|
6355
|
-
uniforms.attractor2Type,
|
|
6356
|
-
uniforms.attractor2Axis
|
|
6357
|
-
);
|
|
6358
|
-
});
|
|
6359
|
-
If(attractorCount.greaterThan(3), () => {
|
|
6360
|
-
applyAttractor(
|
|
6361
|
-
uniforms.attractor3Pos,
|
|
6362
|
-
uniforms.attractor3Strength,
|
|
6363
|
-
uniforms.attractor3Radius,
|
|
6364
|
-
uniforms.attractor3Type,
|
|
6365
|
-
uniforms.attractor3Axis
|
|
6366
|
-
);
|
|
6367
|
-
});
|
|
6368
|
-
position2.addAssign(velocity.mul(dt).mul(speedScale));
|
|
6369
|
-
If(uniforms.collisionEnabled.greaterThan(0.5), () => {
|
|
6370
|
-
const planeY = uniforms.collisionPlaneY;
|
|
6371
|
-
const bounce = uniforms.collisionBounce;
|
|
6372
|
-
const friction2 = uniforms.collisionFriction;
|
|
6373
|
-
const shouldDie = uniforms.collisionDie;
|
|
6374
|
-
If(position2.y.lessThan(planeY), () => {
|
|
6375
|
-
If(shouldDie.greaterThan(0.5), () => {
|
|
6376
|
-
lifetime2.assign(float(0));
|
|
6377
|
-
position2.y.assign(float(-1e3));
|
|
6378
|
-
}).Else(() => {
|
|
6379
|
-
position2.y.assign(planeY);
|
|
6380
|
-
velocity.y.assign(velocity.y.abs().mul(bounce));
|
|
6381
|
-
velocity.x.mulAssign(friction2);
|
|
6382
|
-
velocity.z.mulAssign(friction2);
|
|
6383
|
-
});
|
|
6384
|
-
});
|
|
6385
|
-
});
|
|
6386
|
-
const idx = float(instanceIndex);
|
|
6387
|
-
const rotSpeedX = mix(
|
|
6388
|
-
uniforms.rotationSpeedMinX,
|
|
6389
|
-
uniforms.rotationSpeedMaxX,
|
|
6390
|
-
hash(idx.add(8888))
|
|
6391
|
-
);
|
|
6392
|
-
const rotSpeedY = mix(
|
|
6393
|
-
uniforms.rotationSpeedMinY,
|
|
6394
|
-
uniforms.rotationSpeedMaxY,
|
|
6395
|
-
hash(idx.add(9999))
|
|
6396
|
-
);
|
|
6397
|
-
const rotSpeedZ = mix(
|
|
6398
|
-
uniforms.rotationSpeedMinZ,
|
|
6399
|
-
uniforms.rotationSpeedMaxZ,
|
|
6400
|
-
hash(idx.add(10101))
|
|
6401
|
-
);
|
|
6402
|
-
const rotSpeedCurveSample = texture(
|
|
6403
|
-
curveTexture,
|
|
6404
|
-
vec2(progress, float(0.5))
|
|
6405
|
-
).w;
|
|
6406
|
-
const rotSpeedMultiplier = uniforms.rotationSpeedCurveEnabled.greaterThan(0.5).select(rotSpeedCurveSample, float(1));
|
|
6407
|
-
particleRotation.addAssign(
|
|
6408
|
-
vec3(rotSpeedX, rotSpeedY, rotSpeedZ).mul(uniforms.deltaTime).mul(rotSpeedMultiplier)
|
|
6409
|
-
);
|
|
6410
|
-
lifetime2.subAssign(fadeRate.mul(uniforms.deltaTime));
|
|
6411
|
-
If(lifetime2.lessThanEqual(0), () => {
|
|
6412
|
-
lifetime2.assign(float(0));
|
|
6413
|
-
position2.y.assign(float(-1e3));
|
|
6414
|
-
});
|
|
6415
|
-
});
|
|
6416
|
-
})().compute(activeMaxParticles);
|
|
6417
|
-
}, [
|
|
6418
|
-
activeMaxParticles,
|
|
6419
|
-
positions,
|
|
6420
|
-
velocities,
|
|
6421
|
-
lifetimes,
|
|
6422
|
-
fadeRates,
|
|
6423
|
-
particleSizes,
|
|
6424
|
-
particleRotations,
|
|
6425
|
-
uniforms,
|
|
6426
|
-
curveTexture
|
|
6427
|
-
]);
|
|
6428
|
-
const material = useMemo(() => {
|
|
6429
|
-
const lifetime2 = lifetimes.element(instanceIndex);
|
|
6430
|
-
const particleSize = particleSizes.element(instanceIndex);
|
|
6431
|
-
const particleRotation = particleRotations.element(instanceIndex);
|
|
6432
|
-
const pColorStart = particleColorStarts.element(instanceIndex);
|
|
6433
|
-
const pColorEnd = particleColorEnds.element(instanceIndex);
|
|
6434
|
-
const particlePos = positions.element(instanceIndex);
|
|
6435
|
-
const particleVel = velocities.element(instanceIndex);
|
|
6436
|
-
const progress = float(1).sub(lifetime2);
|
|
6437
|
-
const currentColor = mix(pColorStart, pColorEnd, progress);
|
|
6438
|
-
const intensifiedColor = currentColor.mul(uniforms.intensity);
|
|
6439
|
-
const curveSample = texture(curveTexture, vec2(progress, float(0.5)));
|
|
6440
|
-
const sizeMultiplier = uniforms.fadeSizeCurveEnabled.greaterThan(0.5).select(
|
|
6441
|
-
curveSample.x,
|
|
6442
|
-
// R channel - size curve value
|
|
6443
|
-
mix(uniforms.fadeSizeStart, uniforms.fadeSizeEnd, progress)
|
|
6444
|
-
// Linear interpolation of fadeSize
|
|
6445
|
-
);
|
|
6446
|
-
const opacityMultiplier = uniforms.fadeOpacityCurveEnabled.greaterThan(0.5).select(
|
|
6447
|
-
curveSample.y,
|
|
6448
|
-
// G channel - opacity curve value
|
|
6449
|
-
mix(uniforms.fadeOpacityStart, uniforms.fadeOpacityEnd, progress)
|
|
6450
|
-
// Linear interpolation of fadeOpacity
|
|
6451
|
-
);
|
|
6452
|
-
let sampleUV = uv();
|
|
6453
|
-
if (flipbook && alphaMap) {
|
|
6454
|
-
const rows = float(flipbook.rows || 1);
|
|
6455
|
-
const columns = float(flipbook.columns || 1);
|
|
6456
|
-
const totalFrames = rows.mul(columns);
|
|
6457
|
-
const frameIndex = floor(
|
|
6458
|
-
progress.mul(totalFrames).min(totalFrames.sub(1))
|
|
6459
|
-
);
|
|
6460
|
-
const col = mod(frameIndex, columns);
|
|
6461
|
-
const row = floor(frameIndex.div(columns));
|
|
6462
|
-
const scaledUV = uv().div(vec2(columns, rows));
|
|
6463
|
-
const offsetX = col.div(columns);
|
|
6464
|
-
const offsetY = rows.sub(1).sub(row).div(rows);
|
|
6465
|
-
sampleUV = scaledUV.add(vec2(offsetX, offsetY));
|
|
6466
|
-
}
|
|
6467
|
-
let shapeMask;
|
|
6468
|
-
if (activeGeometry) {
|
|
6469
|
-
shapeMask = float(1);
|
|
6470
|
-
} else if (alphaMap) {
|
|
6471
|
-
const alphaSample = texture(alphaMap, sampleUV);
|
|
6472
|
-
shapeMask = alphaSample.r;
|
|
6473
|
-
} else {
|
|
6474
|
-
const dist = uv().mul(2).sub(1).length();
|
|
6475
|
-
switch (activeAppearance) {
|
|
6476
|
-
case Appearance.DEFAULT:
|
|
6477
|
-
shapeMask = float(1);
|
|
6478
|
-
break;
|
|
6479
|
-
case Appearance.CIRCULAR:
|
|
6480
|
-
shapeMask = step(dist, float(1));
|
|
6481
|
-
break;
|
|
6482
|
-
case Appearance.GRADIENT:
|
|
6483
|
-
default:
|
|
6484
|
-
shapeMask = float(1).sub(dist).max(0);
|
|
6485
|
-
break;
|
|
6486
|
-
}
|
|
6487
|
-
}
|
|
6488
|
-
const baseOpacity = opacityMultiplier.mul(shapeMask).mul(lifetime2.greaterThan(1e-3).select(float(1), float(0)));
|
|
6489
|
-
const particleData = {
|
|
6490
|
-
progress,
|
|
6491
|
-
// 0→1 over lifetime
|
|
6492
|
-
lifetime: lifetime2,
|
|
6493
|
-
// 1→0 over lifetime (inverse of progress)
|
|
6494
|
-
position: particlePos,
|
|
6495
|
-
// vec3 world position
|
|
6496
|
-
velocity: particleVel,
|
|
6497
|
-
// vec3 velocity
|
|
6498
|
-
size: particleSize,
|
|
6499
|
-
// float size
|
|
6500
|
-
rotation: particleRotation,
|
|
6501
|
-
// vec3 rotation (x, y, z)
|
|
6502
|
-
colorStart: pColorStart,
|
|
6503
|
-
// vec3 start color
|
|
6504
|
-
colorEnd: pColorEnd,
|
|
6505
|
-
// vec3 end color
|
|
6506
|
-
color: currentColor,
|
|
6507
|
-
// vec3 interpolated color
|
|
6508
|
-
intensifiedColor,
|
|
6509
|
-
// vec3 color * intensity
|
|
6510
|
-
shapeMask,
|
|
6511
|
-
// float shape/alpha mask
|
|
6512
|
-
index: instanceIndex
|
|
6513
|
-
// particle index (for randomization)
|
|
6514
|
-
};
|
|
6515
|
-
let finalOpacity = opacityNode ? baseOpacity.mul(
|
|
6516
|
-
typeof opacityNode === "function" ? opacityNode(particleData) : opacityNode
|
|
6517
|
-
) : baseOpacity;
|
|
6518
|
-
if (softParticles) {
|
|
6519
|
-
const sceneDepth = viewportDepthTexture(screenUV).x;
|
|
6520
|
-
const particleViewZ = positionView.z.negate();
|
|
6521
|
-
const near = cameraNear;
|
|
6522
|
-
const far = cameraFar;
|
|
6523
|
-
const sceneViewZ = near.mul(far).mul(2).div(far.add(near).sub(sceneDepth.mul(2).sub(1).mul(far.sub(near))));
|
|
6524
|
-
const depthDiff = sceneViewZ.sub(particleViewZ);
|
|
6525
|
-
const softFade = clamp(depthDiff.div(uniforms.softDistance), 0, 1);
|
|
6526
|
-
finalOpacity = finalOpacity.mul(softFade);
|
|
6527
|
-
}
|
|
6528
|
-
if (activeGeometry) {
|
|
6529
|
-
let mat;
|
|
6530
|
-
switch (activeLighting) {
|
|
6531
|
-
case Lighting.BASIC:
|
|
6532
|
-
mat = new THREE2.MeshBasicNodeMaterial();
|
|
6533
|
-
break;
|
|
6534
|
-
case Lighting.PHYSICAL:
|
|
6535
|
-
mat = new THREE2.MeshPhysicalNodeMaterial();
|
|
6536
|
-
break;
|
|
6537
|
-
case Lighting.STANDARD:
|
|
6538
|
-
default:
|
|
6539
|
-
mat = new THREE2.MeshStandardNodeMaterial();
|
|
6540
|
-
break;
|
|
6541
|
-
}
|
|
6542
|
-
const velocityCurveValue = curveSample.z;
|
|
6543
|
-
const effectiveVelocityMultiplier = uniforms.velocityCurveEnabled.greaterThan(0.5).select(velocityCurveValue, float(1));
|
|
6544
|
-
const effectiveSpeed = particleVel.length().mul(effectiveVelocityMultiplier);
|
|
6545
|
-
const stretchAmount = uniforms.stretchEnabled.greaterThan(0.5).select(
|
|
6546
|
-
float(1).add(effectiveSpeed.mul(uniforms.stretchFactor)).min(uniforms.stretchMax),
|
|
6547
|
-
float(1)
|
|
6548
|
-
);
|
|
6549
|
-
const baseScale = particleSize.mul(sizeMultiplier);
|
|
6550
|
-
const axisType = uniforms.orientAxisType;
|
|
6551
|
-
const axisSign = axisType.lessThan(3).select(float(1), float(-1));
|
|
6552
|
-
const axisIndex = axisType.mod(3);
|
|
6553
|
-
const stretchedLocal = uniforms.stretchEnabled.greaterThan(0.5).select(
|
|
6554
|
-
axisIndex.lessThan(0.5).select(
|
|
6555
|
-
// X axis stretch
|
|
6556
|
-
vec3(
|
|
6557
|
-
positionLocal.x.mul(stretchAmount),
|
|
6558
|
-
positionLocal.y,
|
|
6559
|
-
positionLocal.z
|
|
6560
|
-
),
|
|
6561
|
-
axisIndex.lessThan(1.5).select(
|
|
6562
|
-
// Y axis stretch
|
|
6563
|
-
vec3(
|
|
6564
|
-
positionLocal.x,
|
|
6565
|
-
positionLocal.y.mul(stretchAmount),
|
|
6566
|
-
positionLocal.z
|
|
6567
|
-
),
|
|
6568
|
-
// Z axis stretch
|
|
6569
|
-
vec3(
|
|
6570
|
-
positionLocal.x,
|
|
6571
|
-
positionLocal.y,
|
|
6572
|
-
positionLocal.z.mul(stretchAmount)
|
|
6573
|
-
)
|
|
6574
|
-
)
|
|
6575
|
-
),
|
|
6576
|
-
positionLocal
|
|
6577
|
-
);
|
|
6578
|
-
let rotatedPos;
|
|
6579
|
-
if (activeOrientToDirection) {
|
|
6580
|
-
const velLen = particleVel.length().max(1e-4);
|
|
6581
|
-
const velDir = particleVel.div(velLen).mul(axisSign);
|
|
6582
|
-
const localAxis = axisIndex.lessThan(0.5).select(
|
|
6583
|
-
vec3(1, 0, 0),
|
|
6584
|
-
// X axis
|
|
6585
|
-
axisIndex.lessThan(1.5).select(
|
|
6586
|
-
vec3(0, 1, 0),
|
|
6587
|
-
// Y axis
|
|
6588
|
-
vec3(0, 0, 1)
|
|
6589
|
-
// Z axis
|
|
6590
|
-
)
|
|
6591
|
-
);
|
|
6592
|
-
const dotProduct = localAxis.dot(velDir).clamp(-1, 1);
|
|
6593
|
-
const crossProduct = localAxis.cross(velDir);
|
|
6594
|
-
const crossLen = crossProduct.length();
|
|
6595
|
-
const needsRotation = crossLen.greaterThan(1e-4);
|
|
6596
|
-
const rotAxis = needsRotation.select(
|
|
6597
|
-
crossProduct.div(crossLen),
|
|
6598
|
-
vec3(0, 1, 0)
|
|
6599
|
-
// Fallback axis (won't be used if no rotation needed)
|
|
6600
|
-
);
|
|
6601
|
-
const cosAngle = dotProduct;
|
|
6602
|
-
const sinAngle = crossLen;
|
|
6603
|
-
const oneMinusCos = float(1).sub(cosAngle);
|
|
6604
|
-
const v = stretchedLocal;
|
|
6605
|
-
const kDotV = rotAxis.dot(v);
|
|
6606
|
-
const kCrossV = rotAxis.cross(v);
|
|
6607
|
-
const rotatedByAxis = needsRotation.select(
|
|
6608
|
-
v.mul(cosAngle).add(kCrossV.mul(sinAngle)).add(rotAxis.mul(kDotV.mul(oneMinusCos))),
|
|
6609
|
-
// If vectors are nearly aligned, check if they're opposite (dot ≈ -1)
|
|
6610
|
-
dotProduct.lessThan(-0.99).select(
|
|
6611
|
-
v.negate(),
|
|
6612
|
-
// Flip 180° - just negate
|
|
6613
|
-
v
|
|
6614
|
-
// Already aligned, no rotation
|
|
6615
|
-
)
|
|
6616
|
-
);
|
|
6617
|
-
rotatedPos = rotatedByAxis;
|
|
6618
|
-
} else {
|
|
6619
|
-
const rotX = particleRotation.x;
|
|
6620
|
-
const rotY = particleRotation.y;
|
|
6621
|
-
const rotZ = particleRotation.z;
|
|
6622
|
-
const cX = cos(rotX);
|
|
6623
|
-
const sX = sin(rotX);
|
|
6624
|
-
const afterX = vec3(
|
|
6625
|
-
stretchedLocal.x,
|
|
6626
|
-
stretchedLocal.y.mul(cX).sub(stretchedLocal.z.mul(sX)),
|
|
6627
|
-
stretchedLocal.y.mul(sX).add(stretchedLocal.z.mul(cX))
|
|
6628
|
-
);
|
|
6629
|
-
const cY = cos(rotY);
|
|
6630
|
-
const sY = sin(rotY);
|
|
6631
|
-
const afterY = vec3(
|
|
6632
|
-
afterX.x.mul(cY).add(afterX.z.mul(sY)),
|
|
6633
|
-
afterX.y,
|
|
6634
|
-
afterX.z.mul(cY).sub(afterX.x.mul(sY))
|
|
6635
|
-
);
|
|
6636
|
-
const cZ = cos(rotZ);
|
|
6637
|
-
const sZ = sin(rotZ);
|
|
6638
|
-
rotatedPos = vec3(
|
|
6639
|
-
afterY.x.mul(cZ).sub(afterY.y.mul(sZ)),
|
|
6640
|
-
afterY.x.mul(sZ).add(afterY.y.mul(cZ)),
|
|
6641
|
-
afterY.z
|
|
6642
|
-
);
|
|
6643
|
-
}
|
|
6644
|
-
const scaledPos = rotatedPos.mul(baseScale);
|
|
6645
|
-
mat.positionNode = scaledPos.add(particlePos);
|
|
6646
|
-
const defaultColor = vec4(intensifiedColor, finalOpacity);
|
|
6647
|
-
mat.colorNode = colorNode ? typeof colorNode === "function" ? colorNode(particleData, defaultColor) : colorNode : defaultColor;
|
|
6648
|
-
mat.transparent = true;
|
|
6649
|
-
mat.depthWrite = false;
|
|
6650
|
-
mat.blending = blending;
|
|
6651
|
-
mat.side = THREE2.DoubleSide;
|
|
6652
|
-
if (backdropNode) {
|
|
6653
|
-
mat.backdropNode = typeof backdropNode === "function" ? backdropNode(particleData) : backdropNode;
|
|
6654
|
-
}
|
|
6655
|
-
if (castShadowNode) {
|
|
6656
|
-
mat.castShadowNode = typeof castShadowNode === "function" ? castShadowNode(particleData) : castShadowNode;
|
|
6657
|
-
}
|
|
6658
|
-
if (alphaTestNode) {
|
|
6659
|
-
mat.alphaTestNode = typeof alphaTestNode === "function" ? alphaTestNode(particleData) : alphaTestNode;
|
|
6660
|
-
}
|
|
6661
|
-
return mat;
|
|
6662
|
-
} else {
|
|
6663
|
-
const mat = new THREE2.SpriteNodeMaterial();
|
|
6664
|
-
const defaultColor = vec4(intensifiedColor, finalOpacity);
|
|
6665
|
-
mat.colorNode = colorNode ? typeof colorNode === "function" ? colorNode(particleData, defaultColor) : colorNode : defaultColor;
|
|
6666
|
-
mat.positionNode = positions.toAttribute();
|
|
6667
|
-
mat.scaleNode = particleSize.mul(sizeMultiplier);
|
|
6668
|
-
mat.rotationNode = particleRotation.y;
|
|
6669
|
-
mat.transparent = true;
|
|
6670
|
-
mat.depthWrite = false;
|
|
6671
|
-
mat.blending = blending;
|
|
6672
|
-
if (backdropNode) {
|
|
6673
|
-
mat.backdropNode = typeof backdropNode === "function" ? backdropNode(particleData) : backdropNode;
|
|
6674
|
-
}
|
|
6675
|
-
if (castShadowNode) {
|
|
6676
|
-
mat.castShadowNode = typeof castShadowNode === "function" ? castShadowNode(particleData) : castShadowNode;
|
|
6677
|
-
}
|
|
6678
|
-
if (alphaTestNode) {
|
|
6679
|
-
mat.alphaTestNode = typeof alphaTestNode === "function" ? alphaTestNode(particleData) : alphaTestNode;
|
|
6680
|
-
}
|
|
6681
|
-
return mat;
|
|
6682
|
-
}
|
|
6683
|
-
}, [
|
|
6684
|
-
positions,
|
|
6685
|
-
velocities,
|
|
6686
|
-
lifetimes,
|
|
6687
|
-
particleSizes,
|
|
6688
|
-
particleRotations,
|
|
6689
|
-
particleColorStarts,
|
|
6690
|
-
particleColorEnds,
|
|
6691
|
-
uniforms,
|
|
6692
|
-
activeAppearance,
|
|
6693
|
-
alphaMap,
|
|
6694
|
-
flipbook,
|
|
6695
|
-
blending,
|
|
6696
|
-
activeGeometry,
|
|
6697
|
-
activeOrientToDirection,
|
|
6698
|
-
activeLighting,
|
|
6699
|
-
backdropNode,
|
|
6700
|
-
opacityNode,
|
|
6701
|
-
colorNode,
|
|
6702
|
-
alphaTestNode,
|
|
6703
|
-
castShadowNode,
|
|
6704
|
-
softParticles,
|
|
6705
|
-
curveTexture
|
|
6706
|
-
]);
|
|
5697
|
+
const computeInit = useMemo(
|
|
5698
|
+
() => createInitCompute(storage, activeMaxParticles),
|
|
5699
|
+
[storage, activeMaxParticles]
|
|
5700
|
+
);
|
|
5701
|
+
const computeSpawn = useMemo(
|
|
5702
|
+
() => createSpawnCompute(storage, uniforms, activeMaxParticles),
|
|
5703
|
+
[storage, uniforms, activeMaxParticles]
|
|
5704
|
+
);
|
|
5705
|
+
const computeUpdate = useMemo(
|
|
5706
|
+
() => createUpdateCompute(storage, uniforms, curveTexture, activeMaxParticles),
|
|
5707
|
+
[storage, uniforms, curveTexture, activeMaxParticles]
|
|
5708
|
+
);
|
|
5709
|
+
const material = useMemo(
|
|
5710
|
+
() => createParticleMaterial(storage, uniforms, curveTexture, {
|
|
5711
|
+
alphaMap,
|
|
5712
|
+
flipbook,
|
|
5713
|
+
appearance: activeAppearance,
|
|
5714
|
+
lighting: activeLighting,
|
|
5715
|
+
softParticles,
|
|
5716
|
+
geometry: activeGeometry,
|
|
5717
|
+
orientToDirection: activeOrientToDirection,
|
|
5718
|
+
shadow: activeShadow,
|
|
5719
|
+
blending,
|
|
5720
|
+
opacityNode,
|
|
5721
|
+
colorNode,
|
|
5722
|
+
backdropNode,
|
|
5723
|
+
alphaTestNode,
|
|
5724
|
+
castShadowNode
|
|
5725
|
+
}),
|
|
5726
|
+
[
|
|
5727
|
+
storage,
|
|
5728
|
+
uniforms,
|
|
5729
|
+
curveTexture,
|
|
5730
|
+
activeAppearance,
|
|
5731
|
+
alphaMap,
|
|
5732
|
+
flipbook,
|
|
5733
|
+
blending,
|
|
5734
|
+
activeGeometry,
|
|
5735
|
+
activeOrientToDirection,
|
|
5736
|
+
activeLighting,
|
|
5737
|
+
backdropNode,
|
|
5738
|
+
opacityNode,
|
|
5739
|
+
colorNode,
|
|
5740
|
+
alphaTestNode,
|
|
5741
|
+
castShadowNode,
|
|
5742
|
+
softParticles,
|
|
5743
|
+
activeShadow
|
|
5744
|
+
]
|
|
5745
|
+
);
|
|
6707
5746
|
const renderObject = useMemo(() => {
|
|
6708
5747
|
if (activeGeometry) {
|
|
6709
5748
|
const mesh = new THREE2.InstancedMesh(
|
|
@@ -6729,6 +5768,7 @@ var init_VFXParticles = __esm({
|
|
|
6729
5768
|
});
|
|
6730
5769
|
}, [renderer, computeInit]);
|
|
6731
5770
|
const applySpawnOverrides = useCallback2(
|
|
5771
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6732
5772
|
(overrides) => {
|
|
6733
5773
|
if (!overrides) return null;
|
|
6734
5774
|
const saved = {};
|
|
@@ -6775,15 +5815,16 @@ var init_VFXParticles = __esm({
|
|
|
6775
5815
|
saved.gravity = uniforms.gravity.value.clone();
|
|
6776
5816
|
uniforms.gravity.value.set(...overrides.gravity);
|
|
6777
5817
|
}
|
|
5818
|
+
const u = uniforms;
|
|
6778
5819
|
if (overrides.colorStart !== void 0) {
|
|
6779
5820
|
const colors = overrides.colorStart.slice(0, 8).map(hexToRgb);
|
|
6780
5821
|
while (colors.length < 8)
|
|
6781
5822
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
6782
5823
|
setUniform("colorStartCount", overrides.colorStart.length);
|
|
6783
5824
|
colors.forEach((c, i) => {
|
|
6784
|
-
if (
|
|
6785
|
-
saved[`colorStart${i}`] =
|
|
6786
|
-
|
|
5825
|
+
if (u[`colorStart${i}`]) {
|
|
5826
|
+
saved[`colorStart${i}`] = u[`colorStart${i}`].value.clone();
|
|
5827
|
+
u[`colorStart${i}`].value.setRGB(...c);
|
|
6787
5828
|
}
|
|
6788
5829
|
});
|
|
6789
5830
|
}
|
|
@@ -6793,9 +5834,9 @@ var init_VFXParticles = __esm({
|
|
|
6793
5834
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
6794
5835
|
setUniform("colorEndCount", overrides.colorEnd.length);
|
|
6795
5836
|
colors.forEach((c, i) => {
|
|
6796
|
-
if (
|
|
6797
|
-
saved[`colorEnd${i}`] =
|
|
6798
|
-
|
|
5837
|
+
if (u[`colorEnd${i}`]) {
|
|
5838
|
+
saved[`colorEnd${i}`] = u[`colorEnd${i}`].value.clone();
|
|
5839
|
+
u[`colorEnd${i}`].value.setRGB(...c);
|
|
6799
5840
|
}
|
|
6800
5841
|
});
|
|
6801
5842
|
}
|
|
@@ -6836,7 +5877,8 @@ var init_VFXParticles = __esm({
|
|
|
6836
5877
|
);
|
|
6837
5878
|
const spawn = useCallback2(
|
|
6838
5879
|
(x = 0, y = 0, z = 0, count = 20, overrides = null) => {
|
|
6839
|
-
|
|
5880
|
+
var _a;
|
|
5881
|
+
const [px, py, pz] = (_a = positionRef.current) != null ? _a : [0, 0, 0];
|
|
6840
5882
|
spawnInternal(px + x, py + y, pz + z, count, overrides);
|
|
6841
5883
|
},
|
|
6842
5884
|
[spawnInternal]
|
|
@@ -6935,6 +5977,7 @@ var init_VFXParticles = __esm({
|
|
|
6935
5977
|
const prevGeometryTypeRef = useRef2(null);
|
|
6936
5978
|
const prevGeometryArgsRef = useRef2(null);
|
|
6937
5979
|
const handleDebugUpdate = useCallback2(
|
|
5980
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6938
5981
|
(newValues) => {
|
|
6939
5982
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C;
|
|
6940
5983
|
debugValuesRef.current = __spreadValues(__spreadValues({}, debugValuesRef.current), newValues);
|
|
@@ -7074,7 +6117,7 @@ var init_VFXParticles = __esm({
|
|
|
7074
6117
|
}
|
|
7075
6118
|
}
|
|
7076
6119
|
if ("emitterShape" in newValues) {
|
|
7077
|
-
uniforms.emitterShapeType.value = (_g = newValues.emitterShape) != null ? _g :
|
|
6120
|
+
uniforms.emitterShapeType.value = (_g = newValues.emitterShape) != null ? _g : EmitterShape2.BOX;
|
|
7078
6121
|
}
|
|
7079
6122
|
if ("emitterRadius" in newValues) {
|
|
7080
6123
|
const emitterRadiusR = toRange(newValues.emitterRadius, [0, 1]);
|
|
@@ -7407,7 +6450,7 @@ var init_VFXParticles = __esm({
|
|
|
7407
6450
|
// src/index.ts
|
|
7408
6451
|
init_VFXParticles();
|
|
7409
6452
|
|
|
7410
|
-
// src/VFXEmitter.
|
|
6453
|
+
// src/VFXEmitter.tsx
|
|
7411
6454
|
init_react_store();
|
|
7412
6455
|
import {
|
|
7413
6456
|
useRef as useRef3,
|
|
@@ -7436,7 +6479,7 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7436
6479
|
onEmit,
|
|
7437
6480
|
children
|
|
7438
6481
|
}, ref) {
|
|
7439
|
-
const groupRef = useRef3();
|
|
6482
|
+
const groupRef = useRef3(null);
|
|
7440
6483
|
const emitAccumulator = useRef3(0);
|
|
7441
6484
|
const emitting = useRef3(autoStart);
|
|
7442
6485
|
const hasEmittedOnce = useRef3(false);
|
|
@@ -7446,18 +6489,28 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7446
6489
|
}
|
|
7447
6490
|
return useVFXStore.getState().getParticles(name);
|
|
7448
6491
|
}, [name, particlesRef]);
|
|
7449
|
-
const transformDirectionByQuat = useCallback3(
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
6492
|
+
const transformDirectionByQuat = useCallback3(
|
|
6493
|
+
(dirRange, quat) => {
|
|
6494
|
+
const minDir = _tempVec.set(
|
|
6495
|
+
dirRange[0][0],
|
|
6496
|
+
dirRange[1][0],
|
|
6497
|
+
dirRange[2][0]
|
|
6498
|
+
);
|
|
6499
|
+
minDir.applyQuaternion(quat);
|
|
6500
|
+
const maxDir = new Vector32(
|
|
6501
|
+
dirRange[0][1],
|
|
6502
|
+
dirRange[1][1],
|
|
6503
|
+
dirRange[2][1]
|
|
6504
|
+
);
|
|
6505
|
+
maxDir.applyQuaternion(quat);
|
|
6506
|
+
return [
|
|
6507
|
+
[Math.min(minDir.x, maxDir.x), Math.max(minDir.x, maxDir.x)],
|
|
6508
|
+
[Math.min(minDir.y, maxDir.y), Math.max(minDir.y, maxDir.y)],
|
|
6509
|
+
[Math.min(minDir.z, maxDir.z), Math.max(minDir.z, maxDir.z)]
|
|
6510
|
+
];
|
|
6511
|
+
},
|
|
6512
|
+
[]
|
|
6513
|
+
);
|
|
7461
6514
|
const getEmitParams = useCallback3(() => {
|
|
7462
6515
|
if (!groupRef.current) {
|
|
7463
6516
|
return { position, direction };
|
|
@@ -7563,7 +6616,10 @@ var VFXEmitter = forwardRef2(function VFXEmitter2({
|
|
|
7563
6616
|
}),
|
|
7564
6617
|
[emit, burst, start, stop, getParticleSystem]
|
|
7565
6618
|
);
|
|
7566
|
-
return
|
|
6619
|
+
return (
|
|
6620
|
+
// @ts-expect-error
|
|
6621
|
+
/* @__PURE__ */ jsx3("group", { ref: groupRef, position, children })
|
|
6622
|
+
);
|
|
7567
6623
|
});
|
|
7568
6624
|
function useVFXEmitter(name) {
|
|
7569
6625
|
const getParticles = useVFXStore((s) => s.getParticles);
|
|
@@ -7614,15 +6670,15 @@ function useVFXEmitter(name) {
|
|
|
7614
6670
|
init_react_store();
|
|
7615
6671
|
export {
|
|
7616
6672
|
Appearance,
|
|
7617
|
-
AttractorType,
|
|
6673
|
+
AttractorType2 as AttractorType,
|
|
7618
6674
|
Blending,
|
|
7619
|
-
Easing,
|
|
6675
|
+
Easing2 as Easing,
|
|
7620
6676
|
EmitterShape,
|
|
7621
6677
|
Lighting,
|
|
7622
6678
|
VFXEmitter,
|
|
7623
6679
|
VFXParticles,
|
|
7624
6680
|
bakeCurveToArray,
|
|
7625
|
-
createCombinedCurveTexture,
|
|
6681
|
+
createCombinedCurveTexture2 as createCombinedCurveTexture,
|
|
7626
6682
|
useVFXEmitter,
|
|
7627
6683
|
useVFXStore
|
|
7628
6684
|
};
|