@fps-games/vfx 0.3.9 → 0.3.11
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/CHANGELOG.md +16 -0
- package/dist/chunks/smoke22-B_WJKB0y.js +6 -0
- package/dist/chunks/{space-shared-BXV1hc0k.js → space-shared-xh5IOcLH.js} +1 -16
- package/dist/effects/coin-burst/index.js +1 -1
- package/dist/effects/comet-trail-flame/index.js +1 -1
- package/dist/effects/debris-smoke/index.js +2 -3
- package/dist/effects/explosion/index.js +1 -1
- package/dist/effects/laser-beam/index.js +151 -59
- package/dist/effects/magnet-suction/index.js +1 -1
- package/dist/effects/mining-hit/index.d.ts +25 -0
- package/dist/effects/mining-hit/index.js +232 -0
- package/dist/effects/pulse-laser-volley/index.js +1 -20
- package/dist/effects/thruster-flame/index.js +1 -1
- package/dist/effects/ufo-thread-flame/index.js +1 -1
- package/dist/effects/weapon-trail/index.js +1 -1
- package/index.json +11 -1
- package/package.json +1 -1
- package/packages/effects/mining-hit/vfx-params.json +5 -0
|
@@ -1,28 +1,142 @@
|
|
|
1
1
|
import { TransformNode } from "@babylonjs/core/Meshes/transformNode";
|
|
2
2
|
import { Mesh } from "@babylonjs/core/Meshes/mesh";
|
|
3
3
|
import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ShaderMaterial } from "@babylonjs/core/Materials/shaderMaterial";
|
|
5
|
+
import { Effect } from "@babylonjs/core/Materials/effect";
|
|
6
6
|
import { Texture } from "@babylonjs/core/Materials/Textures/texture";
|
|
7
7
|
import { Color3 } from "@babylonjs/core/Maths/math.color";
|
|
8
8
|
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
|
|
9
9
|
import { Space } from "@babylonjs/core/Maths/math.axis";
|
|
10
10
|
import { Constants } from "@babylonjs/core/Engines/constants";
|
|
11
|
-
import { L as LIFETIME_DEBUG_PARAMS, a as LIFETIME_DEFAULTS,
|
|
11
|
+
import { L as LIFETIME_DEBUG_PARAMS, a as LIFETIME_DEFAULTS, s as scheduleLifetime } from "../../chunks/space-shared-xh5IOcLH.js";
|
|
12
12
|
const arcTextureUrl = "data:image/webp;base64,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";
|
|
13
13
|
const noiseTextureUrl = "data:image/webp;base64,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";
|
|
14
|
+
const START_FADE_FRACTION = 0.055;
|
|
15
|
+
const START_ALPHA_FULL_FRACTION = 0.22;
|
|
16
|
+
const LASER_VERTEX = `precision highp float;
|
|
17
|
+
attribute vec3 position;
|
|
18
|
+
attribute vec2 uv;
|
|
19
|
+
uniform mat4 worldViewProjection;
|
|
20
|
+
varying vec2 vUV;
|
|
21
|
+
void main() {
|
|
22
|
+
vUV = uv;
|
|
23
|
+
gl_Position = worldViewProjection * vec4(position, 1.0);
|
|
24
|
+
}`;
|
|
25
|
+
const LASER_FRAGMENT = `precision highp float;
|
|
26
|
+
varying vec2 vUV;
|
|
27
|
+
uniform sampler2D tex;
|
|
28
|
+
uniform vec3 tint;
|
|
29
|
+
uniform float uScale;
|
|
30
|
+
uniform float uOffset;
|
|
31
|
+
uniform float alphaFromRgb;
|
|
32
|
+
uniform float startFade;
|
|
33
|
+
uniform float startFull;
|
|
34
|
+
void main() {
|
|
35
|
+
vec4 sampleColor = texture2D(tex, vec2(vUV.x * uScale + uOffset, vUV.y));
|
|
36
|
+
float textureAlpha = mix(sampleColor.a, max(max(sampleColor.r, sampleColor.g), sampleColor.b), alphaFromRgb);
|
|
37
|
+
float startMask = smoothstep(startFade, startFull, vUV.x);
|
|
38
|
+
gl_FragColor = vec4(sampleColor.rgb * tint, textureAlpha * startMask);
|
|
39
|
+
}`;
|
|
40
|
+
let laserShadersRegistered = false;
|
|
41
|
+
function registerLaserShaders() {
|
|
42
|
+
if (laserShadersRegistered) return;
|
|
43
|
+
Effect.ShadersStore["vfxLaserBeamVertexShader"] = LASER_VERTEX;
|
|
44
|
+
Effect.ShadersStore["vfxLaserBeamFragmentShader"] = LASER_FRAGMENT;
|
|
45
|
+
laserShadersRegistered = true;
|
|
46
|
+
}
|
|
14
47
|
function createBeamPlaneGeo(name, width, axis, scene) {
|
|
15
48
|
const h = width / 2;
|
|
16
|
-
const positions = axis === "x" ? [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
49
|
+
const positions = axis === "x" ? [
|
|
50
|
+
-h,
|
|
51
|
+
0,
|
|
52
|
+
0,
|
|
53
|
+
h,
|
|
54
|
+
0,
|
|
55
|
+
0,
|
|
56
|
+
-h,
|
|
57
|
+
0,
|
|
58
|
+
START_FADE_FRACTION,
|
|
59
|
+
h,
|
|
60
|
+
0,
|
|
61
|
+
START_FADE_FRACTION,
|
|
62
|
+
-h,
|
|
63
|
+
0,
|
|
64
|
+
1,
|
|
65
|
+
h,
|
|
66
|
+
0,
|
|
67
|
+
1
|
|
68
|
+
] : [
|
|
69
|
+
0,
|
|
70
|
+
-h,
|
|
71
|
+
0,
|
|
72
|
+
0,
|
|
73
|
+
h,
|
|
74
|
+
0,
|
|
75
|
+
0,
|
|
76
|
+
-h,
|
|
77
|
+
START_FADE_FRACTION,
|
|
78
|
+
0,
|
|
79
|
+
h,
|
|
80
|
+
START_FADE_FRACTION,
|
|
81
|
+
0,
|
|
82
|
+
-h,
|
|
83
|
+
1,
|
|
84
|
+
0,
|
|
85
|
+
h,
|
|
86
|
+
1
|
|
87
|
+
];
|
|
88
|
+
const normals = axis === "x" ? [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0] : [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0];
|
|
89
|
+
const uvs = [
|
|
90
|
+
0,
|
|
91
|
+
0,
|
|
92
|
+
0,
|
|
93
|
+
1,
|
|
94
|
+
START_FADE_FRACTION,
|
|
95
|
+
0,
|
|
96
|
+
START_FADE_FRACTION,
|
|
97
|
+
1,
|
|
98
|
+
1,
|
|
99
|
+
0,
|
|
100
|
+
1,
|
|
101
|
+
1
|
|
102
|
+
];
|
|
103
|
+
const colors = [
|
|
104
|
+
1,
|
|
105
|
+
1,
|
|
106
|
+
1,
|
|
107
|
+
0,
|
|
108
|
+
1,
|
|
109
|
+
1,
|
|
110
|
+
1,
|
|
111
|
+
0,
|
|
112
|
+
1,
|
|
113
|
+
1,
|
|
114
|
+
1,
|
|
115
|
+
1,
|
|
116
|
+
1,
|
|
117
|
+
1,
|
|
118
|
+
1,
|
|
119
|
+
1,
|
|
120
|
+
1,
|
|
121
|
+
1,
|
|
122
|
+
1,
|
|
123
|
+
1,
|
|
124
|
+
1,
|
|
125
|
+
1,
|
|
126
|
+
1,
|
|
127
|
+
1
|
|
128
|
+
];
|
|
129
|
+
const indices = [0, 1, 3, 0, 3, 2, 2, 3, 5, 2, 5, 4];
|
|
20
130
|
const mesh = new Mesh(name, scene);
|
|
131
|
+
mesh.useVertexColors = true;
|
|
132
|
+
mesh.hasVertexAlpha = true;
|
|
21
133
|
const vd = new VertexData();
|
|
22
134
|
vd.positions = positions;
|
|
23
135
|
vd.normals = normals;
|
|
24
136
|
vd.uvs = uvs;
|
|
137
|
+
vd.colors = colors;
|
|
25
138
|
vd.indices = indices;
|
|
139
|
+
vd.hasVertexAlpha = true;
|
|
26
140
|
vd.applyToMesh(mesh);
|
|
27
141
|
return mesh;
|
|
28
142
|
}
|
|
@@ -48,27 +162,15 @@ function createLaserBeamEffectPackage(id, nameZh, core) {
|
|
|
48
162
|
create({ scene, root, position, rotationY, params, inputs }) {
|
|
49
163
|
root.position.copyFrom(position);
|
|
50
164
|
root.rotation.y = rotationY;
|
|
165
|
+
registerLaserShaders();
|
|
51
166
|
const { width, intensity } = params;
|
|
52
167
|
const segLen = width * 5;
|
|
53
168
|
const arcTex = new Texture(arcTextureUrl, scene);
|
|
54
169
|
arcTex.wrapU = Texture.WRAP_ADDRESSMODE;
|
|
55
|
-
const arcMat =
|
|
56
|
-
arcMat.emissiveTexture = arcTex;
|
|
57
|
-
arcMat.opacityTexture = arcTex;
|
|
58
|
-
arcMat.emissiveColor = new Color3(0.45 * intensity, 0.62 * intensity, 1.35 * intensity);
|
|
59
|
-
arcMat.disableLighting = true;
|
|
60
|
-
arcMat.backFaceCulling = false;
|
|
61
|
-
arcMat.alphaMode = Constants.ALPHA_ADD;
|
|
170
|
+
const arcMat = createLaserMaterial(scene, "vfx_laser_arcMat", arcTex, new Color3(0.45 * intensity, 0.62 * intensity, 1.35 * intensity), 0);
|
|
62
171
|
const noiseTex = new Texture(noiseTextureUrl, scene);
|
|
63
172
|
noiseTex.wrapU = Texture.WRAP_ADDRESSMODE;
|
|
64
|
-
const noiseMat =
|
|
65
|
-
noiseMat.emissiveTexture = noiseTex;
|
|
66
|
-
noiseMat.opacityTexture = noiseTex;
|
|
67
|
-
noiseMat.opacityTexture.getAlphaFromRGB = true;
|
|
68
|
-
noiseMat.emissiveColor = new Color3(0.2 * intensity, 0.35 * intensity, 0.9 * intensity);
|
|
69
|
-
noiseMat.disableLighting = true;
|
|
70
|
-
noiseMat.backFaceCulling = false;
|
|
71
|
-
noiseMat.alphaMode = Constants.ALPHA_ADD;
|
|
173
|
+
const noiseMat = createLaserMaterial(scene, "vfx_laser_noiseMat", noiseTex, new Color3(0.2 * intensity, 0.35 * intensity, 0.9 * intensity), 1);
|
|
72
174
|
const beamRoot = new TransformNode("vfx_laser_beamRoot", scene);
|
|
73
175
|
beamRoot.parent = root;
|
|
74
176
|
const planes = [];
|
|
@@ -85,27 +187,10 @@ function createLaserBeamEffectPackage(id, nameZh, core) {
|
|
|
85
187
|
p.isPickable = false;
|
|
86
188
|
planes.push(p);
|
|
87
189
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const f = CreatePlane(name, { size }, scene);
|
|
91
|
-
f.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
|
92
|
-
const m = new StandardMaterial(name + "Mat", scene);
|
|
93
|
-
m.emissiveTexture = flareTex;
|
|
94
|
-
m.opacityTexture = flareTex;
|
|
95
|
-
m.emissiveColor = new Color3(0.7, 0.85, 1.6);
|
|
96
|
-
m.disableLighting = true;
|
|
97
|
-
m.alphaMode = Constants.ALPHA_ADD;
|
|
98
|
-
f.material = m;
|
|
99
|
-
f.isPickable = false;
|
|
100
|
-
f.parent = root;
|
|
101
|
-
return f;
|
|
102
|
-
}
|
|
103
|
-
const muzzleFlare = makeFlare("vfx_laser_muzzle", width * 3.2);
|
|
104
|
-
const hitFlare = makeFlare("vfx_laser_hit", width * 3.2);
|
|
105
|
-
let time = 0;
|
|
190
|
+
let arcOffset = 0;
|
|
191
|
+
let noiseOffset = 0;
|
|
106
192
|
const observer = scene.onBeforeRenderObservable.add(() => {
|
|
107
193
|
const dt = Math.min(scene.getEngine().getDeltaTime() / 1e3, 0.05);
|
|
108
|
-
time += dt;
|
|
109
194
|
let dist = params.targetDistance;
|
|
110
195
|
if (inputs?.aim) {
|
|
111
196
|
const tgt = inputs.aim();
|
|
@@ -114,19 +199,12 @@ function createLaserBeamEffectPackage(id, nameZh, core) {
|
|
|
114
199
|
}
|
|
115
200
|
beamRoot.scaling.z = dist;
|
|
116
201
|
const tiles = Math.max(1, dist / segLen);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
arcMat.
|
|
120
|
-
arcMat.
|
|
121
|
-
noiseMat.
|
|
122
|
-
noiseMat.
|
|
123
|
-
noiseMat.opacityTexture.uScale = tiles * 0.6;
|
|
124
|
-
noiseMat.opacityTexture.uOffset = noiseMat.emissiveTexture.uOffset;
|
|
125
|
-
const pulse = 1 + Math.sin(time * 24) * 0.18;
|
|
126
|
-
muzzleFlare.position.set(0, 0, 0);
|
|
127
|
-
muzzleFlare.scaling.setAll(pulse);
|
|
128
|
-
hitFlare.position.set(0, 0, dist);
|
|
129
|
-
hitFlare.scaling.setAll(pulse * 1.4);
|
|
202
|
+
arcOffset -= params.laserSpeed * dt;
|
|
203
|
+
noiseOffset -= params.laserSpeed * 0.31 * dt;
|
|
204
|
+
arcMat.setFloat("uScale", tiles);
|
|
205
|
+
arcMat.setFloat("uOffset", arcOffset);
|
|
206
|
+
noiseMat.setFloat("uScale", tiles * 0.6);
|
|
207
|
+
noiseMat.setFloat("uOffset", noiseOffset);
|
|
130
208
|
});
|
|
131
209
|
let disposed = false;
|
|
132
210
|
let ltTimer = 0;
|
|
@@ -136,16 +214,11 @@ function createLaserBeamEffectPackage(id, nameZh, core) {
|
|
|
136
214
|
if (ltTimer) window.clearTimeout(ltTimer);
|
|
137
215
|
scene.onBeforeRenderObservable.remove(observer);
|
|
138
216
|
for (const p of planes) p.dispose();
|
|
139
|
-
muzzleFlare.material?.dispose();
|
|
140
|
-
muzzleFlare.dispose();
|
|
141
|
-
hitFlare.material?.dispose();
|
|
142
|
-
hitFlare.dispose();
|
|
143
217
|
beamRoot.dispose();
|
|
144
218
|
arcMat.dispose();
|
|
145
219
|
arcTex.dispose();
|
|
146
220
|
noiseMat.dispose();
|
|
147
221
|
noiseTex.dispose();
|
|
148
|
-
flareTex.dispose();
|
|
149
222
|
root.dispose();
|
|
150
223
|
};
|
|
151
224
|
ltTimer = scheduleLifetime(params, dispose);
|
|
@@ -153,6 +226,25 @@ function createLaserBeamEffectPackage(id, nameZh, core) {
|
|
|
153
226
|
}
|
|
154
227
|
};
|
|
155
228
|
}
|
|
229
|
+
function createLaserMaterial(scene, name, texture, tint, alphaFromRgb) {
|
|
230
|
+
const material = new ShaderMaterial(name, scene, { vertex: "vfxLaserBeam", fragment: "vfxLaserBeam" }, {
|
|
231
|
+
attributes: ["position", "uv"],
|
|
232
|
+
uniforms: ["worldViewProjection", "tint", "uScale", "uOffset", "alphaFromRgb", "startFade", "startFull"],
|
|
233
|
+
samplers: ["tex"],
|
|
234
|
+
needAlphaBlending: true
|
|
235
|
+
});
|
|
236
|
+
material.setTexture("tex", texture);
|
|
237
|
+
material.setColor3("tint", tint);
|
|
238
|
+
material.setFloat("uScale", 1);
|
|
239
|
+
material.setFloat("uOffset", 0);
|
|
240
|
+
material.setFloat("alphaFromRgb", alphaFromRgb);
|
|
241
|
+
material.setFloat("startFade", START_FADE_FRACTION);
|
|
242
|
+
material.setFloat("startFull", START_ALPHA_FULL_FRACTION);
|
|
243
|
+
material.backFaceCulling = false;
|
|
244
|
+
material.disableDepthWrite = true;
|
|
245
|
+
material.alphaMode = Constants.ALPHA_ADD;
|
|
246
|
+
return material;
|
|
247
|
+
}
|
|
156
248
|
const laserBeamEffectPackage = createLaserBeamEffectPackage("laser-beam", "激光束", {
|
|
157
249
|
width: 0.55,
|
|
158
250
|
intensity: 1,
|
|
@@ -9,7 +9,7 @@ import { Mesh } from "@babylonjs/core/Meshes/mesh";
|
|
|
9
9
|
import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData";
|
|
10
10
|
import { TransformNode } from "@babylonjs/core/Meshes/transformNode";
|
|
11
11
|
import { V as VFX_RENDERING_GROUP_ID } from "../../chunks/rendering-CV3nhygX.js";
|
|
12
|
-
import { s as scheduleLifetime } from "../../chunks/space-shared-
|
|
12
|
+
import { s as scheduleLifetime } from "../../chunks/space-shared-xh5IOcLH.js";
|
|
13
13
|
const id = "magnet-suction";
|
|
14
14
|
const nameZh = "磁铁吸入线";
|
|
15
15
|
const assets = [];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { VfxColorValue, VfxEffectPackage, VfxParamValues } from '../../types';
|
|
2
|
+
interface MiningHitParams extends VfxParamValues {
|
|
3
|
+
flashCount: number;
|
|
4
|
+
flashSize: number;
|
|
5
|
+
flashLength: number;
|
|
6
|
+
flashBright: number;
|
|
7
|
+
flashColor: VfxColorValue;
|
|
8
|
+
height: number;
|
|
9
|
+
debrisCount: number;
|
|
10
|
+
debrisSize: number;
|
|
11
|
+
debrisRadius: number;
|
|
12
|
+
debrisSpeed: number;
|
|
13
|
+
debrisHorizontalSpeed: number;
|
|
14
|
+
debrisUpSpeed: number;
|
|
15
|
+
debrisDirectionX: number;
|
|
16
|
+
debrisDirectionY: number;
|
|
17
|
+
debrisDirectionZ: number;
|
|
18
|
+
debrisGravity: number;
|
|
19
|
+
debrisLifetime: number;
|
|
20
|
+
smokeCount: number;
|
|
21
|
+
smokeSize: number;
|
|
22
|
+
smokeRise: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const miningHitEffectPackage: VfxEffectPackage<MiningHitParams>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { Mesh } from "@babylonjs/core/Meshes/mesh";
|
|
2
|
+
import { ParticleSystem } from "@babylonjs/core/Particles/particleSystem";
|
|
3
|
+
import { DynamicTexture } from "@babylonjs/core/Materials/Textures/dynamicTexture";
|
|
4
|
+
import { Color4 } from "@babylonjs/core/Maths/math.color";
|
|
5
|
+
import { Vector3, Matrix } from "@babylonjs/core/Maths/math.vector";
|
|
6
|
+
import { SceneLoader } from "@babylonjs/core/Loading/sceneLoader";
|
|
7
|
+
import "@babylonjs/loaders/glTF/2.0/glTFLoader";
|
|
8
|
+
import { F as FlyerPool, m as makeBurstPS } from "../../chunks/space-shared-xh5IOcLH.js";
|
|
9
|
+
import { s as smokeUrl, r as rockModelUrl } from "../../chunks/smoke22-B_WJKB0y.js";
|
|
10
|
+
const DEFAULT_PARAMS = {
|
|
11
|
+
flashCount: 14,
|
|
12
|
+
flashSize: 0.9,
|
|
13
|
+
flashLength: 0.9,
|
|
14
|
+
flashBright: 2.1,
|
|
15
|
+
flashColor: { r: 1, g: 0.9, b: 0.46 },
|
|
16
|
+
height: 0,
|
|
17
|
+
debrisCount: 12,
|
|
18
|
+
debrisSize: 0.32,
|
|
19
|
+
debrisRadius: 1.35,
|
|
20
|
+
debrisSpeed: 0.9,
|
|
21
|
+
debrisHorizontalSpeed: 0.95,
|
|
22
|
+
debrisUpSpeed: 0.85,
|
|
23
|
+
debrisDirectionX: 0,
|
|
24
|
+
debrisDirectionY: 0,
|
|
25
|
+
debrisDirectionZ: 0,
|
|
26
|
+
debrisGravity: 8,
|
|
27
|
+
debrisLifetime: 1.15,
|
|
28
|
+
smokeCount: 14,
|
|
29
|
+
smokeSize: 0.95,
|
|
30
|
+
smokeRise: 1.1
|
|
31
|
+
};
|
|
32
|
+
const flashTextureCache = /* @__PURE__ */ new WeakMap();
|
|
33
|
+
function getFlashTexture(scene) {
|
|
34
|
+
const cached = flashTextureCache.get(scene);
|
|
35
|
+
if (cached) return cached;
|
|
36
|
+
const glow = new DynamicTexture("vfx_mining_hit_glow", 128, scene, false);
|
|
37
|
+
glow.hasAlpha = true;
|
|
38
|
+
const ctx = glow.getContext();
|
|
39
|
+
ctx.clearRect(0, 0, 128, 128);
|
|
40
|
+
const gradient = ctx.createRadialGradient(64, 64, 0, 64, 64, 64);
|
|
41
|
+
gradient.addColorStop(0, "rgba(255,255,255,1)");
|
|
42
|
+
gradient.addColorStop(0.85, "rgba(255,255,255,0.9)");
|
|
43
|
+
gradient.addColorStop(1, "rgba(255,255,255,0)");
|
|
44
|
+
ctx.fillStyle = gradient;
|
|
45
|
+
ctx.beginPath();
|
|
46
|
+
ctx.arc(64, 64, 64, 0, Math.PI * 2);
|
|
47
|
+
ctx.fill();
|
|
48
|
+
glow.update();
|
|
49
|
+
flashTextureCache.set(scene, glow);
|
|
50
|
+
return glow;
|
|
51
|
+
}
|
|
52
|
+
const cachedRockTemplates = /* @__PURE__ */ new WeakMap();
|
|
53
|
+
function loadRockTemplates(scene) {
|
|
54
|
+
const existing = cachedRockTemplates.get(scene);
|
|
55
|
+
if (existing) return existing;
|
|
56
|
+
const isDataUri = rockModelUrl.startsWith("data:");
|
|
57
|
+
const lastSlash = isDataUri ? -1 : rockModelUrl.lastIndexOf("/");
|
|
58
|
+
const rootUrl = lastSlash >= 0 ? rockModelUrl.slice(0, lastSlash + 1) : "";
|
|
59
|
+
const fileName = lastSlash >= 0 ? rockModelUrl.slice(lastSlash + 1) : rockModelUrl;
|
|
60
|
+
const promise = SceneLoader.ImportMeshAsync("", rootUrl, fileName, scene, void 0, ".glb").then((res) => {
|
|
61
|
+
const templates = res.meshes.filter((mesh) => mesh instanceof Mesh && mesh.getTotalVertices() > 0);
|
|
62
|
+
for (const template of templates) {
|
|
63
|
+
template.setParent(null);
|
|
64
|
+
const center = template.getBoundingInfo().boundingBox.centerWorld.clone();
|
|
65
|
+
template.bakeTransformIntoVertices(Matrix.Translation(-center.x, -center.y, -center.z));
|
|
66
|
+
template.position.set(0, 0, 0);
|
|
67
|
+
template.setEnabled(false);
|
|
68
|
+
template.isPickable = false;
|
|
69
|
+
}
|
|
70
|
+
return templates;
|
|
71
|
+
}).catch((error) => {
|
|
72
|
+
cachedRockTemplates.delete(scene);
|
|
73
|
+
throw error;
|
|
74
|
+
});
|
|
75
|
+
cachedRockTemplates.set(scene, promise);
|
|
76
|
+
return promise;
|
|
77
|
+
}
|
|
78
|
+
function c4(color, multiplier = 1, alpha = 1) {
|
|
79
|
+
return new Color4(color.r * multiplier, color.g * multiplier, color.b * multiplier, alpha);
|
|
80
|
+
}
|
|
81
|
+
function averageScale(scale) {
|
|
82
|
+
return Math.max(1e-4, (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z)) / 3);
|
|
83
|
+
}
|
|
84
|
+
const miningHitEffectPackage = {
|
|
85
|
+
id: "mining-hit",
|
|
86
|
+
nameZh: "采矿受击",
|
|
87
|
+
placement: "world",
|
|
88
|
+
debugAnchor: "playerRight",
|
|
89
|
+
defaultParams: DEFAULT_PARAMS,
|
|
90
|
+
debugParams: [
|
|
91
|
+
{ key: "flashCount", label: "闪光·数量", kind: "number", min: 0, max: 40, step: 1 },
|
|
92
|
+
{ key: "flashSize", label: "闪光·尺寸", kind: "scale", min: 0.2, max: 3, step: 0.05 },
|
|
93
|
+
{ key: "flashLength", label: "闪光·拉伸", kind: "scale", min: 0.2, max: 3, step: 0.05 },
|
|
94
|
+
{ key: "flashBright", label: "闪光·亮度", kind: "number", min: 0.5, max: 5, step: 0.05 },
|
|
95
|
+
{ key: "flashColor", label: "闪光·颜色", kind: "color" },
|
|
96
|
+
{ key: "height", label: "高度", kind: "number", min: -2, max: 3, step: 0.05 },
|
|
97
|
+
{ key: "debrisCount", label: "碎石·数量", kind: "number", min: 0, max: 30, step: 1 },
|
|
98
|
+
{ key: "debrisSize", label: "碎石·大小", kind: "number", min: 0.1, max: 1, step: 0.01 },
|
|
99
|
+
{ key: "debrisRadius", label: "碎石·范围", kind: "scale", min: 0.5, max: 5, step: 0.1 },
|
|
100
|
+
{ key: "debrisSpeed", label: "碎石·整体速度", kind: "number", min: 0, max: 5, step: 0.05 },
|
|
101
|
+
{ key: "debrisHorizontalSpeed", label: "碎石·横向速度", kind: "number", min: 0, max: 5, step: 0.05 },
|
|
102
|
+
{ key: "debrisUpSpeed", label: "碎石·上抛速度", kind: "number", min: 0, max: 5, step: 0.05 },
|
|
103
|
+
{ key: "debrisDirectionX", label: "碎石·方向 X", kind: "number", min: -1, max: 1, step: 0.01 },
|
|
104
|
+
{ key: "debrisDirectionY", label: "碎石·方向 Y", kind: "number", min: -1, max: 1, step: 0.01 },
|
|
105
|
+
{ key: "debrisDirectionZ", label: "碎石·方向 Z", kind: "number", min: -1, max: 1, step: 0.01 },
|
|
106
|
+
{ key: "debrisGravity", label: "碎石·下落重力", kind: "number", min: 0, max: 20, step: 0.1 },
|
|
107
|
+
{ key: "debrisLifetime", label: "碎石·可见时长", kind: "lifetime", min: 0.2, max: 4, step: 0.05 },
|
|
108
|
+
{ key: "smokeCount", label: "烟雾·数量", kind: "number", min: 0, max: 40, step: 1 },
|
|
109
|
+
{ key: "smokeSize", label: "烟雾·尺寸", kind: "scale", min: 0.2, max: 3, step: 0.05 },
|
|
110
|
+
{ key: "smokeRise", label: "烟雾·上浮", kind: "number", min: 0, max: 4, step: 0.05 }
|
|
111
|
+
],
|
|
112
|
+
create({ scene, root, position, params, scale }) {
|
|
113
|
+
root.position.copyFrom(position);
|
|
114
|
+
const spawnScale = averageScale(scale);
|
|
115
|
+
const origin = position.clone();
|
|
116
|
+
origin.y += params.height * spawnScale;
|
|
117
|
+
const flash = createFlashBurst(scene, origin, params, spawnScale);
|
|
118
|
+
const smoke = createSmokeBurst(scene, origin, params, spawnScale);
|
|
119
|
+
const debrisPool = new FlyerPool(scene);
|
|
120
|
+
let disposed = false;
|
|
121
|
+
const ready = (params.debrisCount > 0 ? loadRockTemplates(scene) : Promise.resolve([])).then((templates) => {
|
|
122
|
+
if (disposed || templates.length === 0) return;
|
|
123
|
+
const count = Math.round(params.debrisCount);
|
|
124
|
+
const radius = params.debrisRadius * spawnScale;
|
|
125
|
+
for (let i = 0; i < count; i += 1) {
|
|
126
|
+
const template = templates[Math.random() * templates.length | 0];
|
|
127
|
+
const debris = template.clone("vfx_mining_hit_debris", null, false);
|
|
128
|
+
if (!debris) continue;
|
|
129
|
+
debris.setEnabled(true);
|
|
130
|
+
debris.isPickable = false;
|
|
131
|
+
debris.normalizeToUnitCube();
|
|
132
|
+
debris.scaling.scaleInPlace(radius * params.debrisSize * (0.5 + Math.random() * 0.8));
|
|
133
|
+
debrisPool.spawn(debris, origin, makeDebrisVelocity(params, spawnScale), params.debrisGravity, params.debrisLifetime);
|
|
134
|
+
}
|
|
135
|
+
}).catch((error) => {
|
|
136
|
+
console.warn("[VFX] mining-hit load failed", error);
|
|
137
|
+
});
|
|
138
|
+
let elapsed = 0;
|
|
139
|
+
let flashStopped = false;
|
|
140
|
+
const observer = scene.onBeforeRenderObservable.add(() => {
|
|
141
|
+
elapsed += scene.getEngine().getDeltaTime();
|
|
142
|
+
if (!flashStopped && elapsed >= 180) {
|
|
143
|
+
flash.stop();
|
|
144
|
+
flashStopped = true;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
const disposeDelay = Math.max(2200, params.debrisLifetime * 1e3 + 1e3);
|
|
148
|
+
const disposeTimer = window.setTimeout(() => disposeAll(), disposeDelay);
|
|
149
|
+
function disposeAll() {
|
|
150
|
+
if (disposed) return;
|
|
151
|
+
disposed = true;
|
|
152
|
+
window.clearTimeout(disposeTimer);
|
|
153
|
+
scene.onBeforeRenderObservable.remove(observer);
|
|
154
|
+
debrisPool.dispose();
|
|
155
|
+
flash.dispose(false);
|
|
156
|
+
smoke.dispose();
|
|
157
|
+
root.dispose();
|
|
158
|
+
}
|
|
159
|
+
return { root, ready, dispose() {
|
|
160
|
+
disposeAll();
|
|
161
|
+
} };
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
function createFlashBurst(scene, origin, params, spawnScale) {
|
|
165
|
+
const flash = new ParticleSystem("vfx_mining_hit_flash", 120, scene);
|
|
166
|
+
flash.emitter = origin.clone();
|
|
167
|
+
flash.minEmitBox = new Vector3(0, 0, 0);
|
|
168
|
+
flash.maxEmitBox = new Vector3(0, 0, 0);
|
|
169
|
+
flash.billboardMode = ParticleSystem.BILLBOARDMODE_STRETCHED;
|
|
170
|
+
flash.minLifeTime = 0.12;
|
|
171
|
+
flash.maxLifeTime = 0.25;
|
|
172
|
+
flash.minEmitPower = 9.1 * spawnScale;
|
|
173
|
+
flash.maxEmitPower = 15.6 * spawnScale;
|
|
174
|
+
flash.direction1 = new Vector3(-1, 0.05, -1);
|
|
175
|
+
flash.direction2 = new Vector3(1, 0.15, 1);
|
|
176
|
+
flash.gravity = new Vector3(0, 0, 0);
|
|
177
|
+
flash.emitRate = 0;
|
|
178
|
+
flash.blendMode = ParticleSystem.BLENDMODE_ADD;
|
|
179
|
+
flash.particleTexture = getFlashTexture(scene);
|
|
180
|
+
flash.minSize = 0.78 * params.flashSize * spawnScale;
|
|
181
|
+
flash.maxSize = 1.3 * params.flashSize * spawnScale;
|
|
182
|
+
flash.minScaleY = 3.38 * params.flashLength;
|
|
183
|
+
flash.maxScaleY = 5.46 * params.flashLength;
|
|
184
|
+
flash.minScaleX = 0.18 * params.flashSize;
|
|
185
|
+
flash.maxScaleX = 0.36 * params.flashSize;
|
|
186
|
+
flash.addColorGradient(0, c4(params.flashColor, params.flashBright, 1));
|
|
187
|
+
flash.addColorGradient(0.5, c4(params.flashColor, params.flashBright * 0.75, 1));
|
|
188
|
+
flash.addColorGradient(1, c4(params.flashColor, params.flashBright * 0.5, 0));
|
|
189
|
+
flash.manualEmitCount = Math.round(params.flashCount);
|
|
190
|
+
flash.start();
|
|
191
|
+
return flash;
|
|
192
|
+
}
|
|
193
|
+
function createSmokeBurst(scene, origin, params, spawnScale) {
|
|
194
|
+
const smoke = makeBurstPS("vfx_mining_hit_smoke", scene, smokeUrl, {
|
|
195
|
+
cap: 120,
|
|
196
|
+
size: [2.2 * spawnScale, 4.5 * spawnScale],
|
|
197
|
+
life: [0.9, 1.6],
|
|
198
|
+
power: [1.5 * spawnScale, 4 * spawnScale],
|
|
199
|
+
gravity: new Vector3(0, params.smokeRise, 0),
|
|
200
|
+
blend: ParticleSystem.BLENDMODE_STANDARD,
|
|
201
|
+
c1: new Color4(0.5, 0.45, 0.42, 0.65),
|
|
202
|
+
c2: new Color4(0.32, 0.3, 0.3, 0.5),
|
|
203
|
+
cd: new Color4(0.2, 0.2, 0.2, 0)
|
|
204
|
+
});
|
|
205
|
+
smoke.minSize *= params.smokeSize;
|
|
206
|
+
smoke.maxSize *= params.smokeSize;
|
|
207
|
+
smoke.emitter.copyFrom(origin);
|
|
208
|
+
smoke.manualEmitCount += Math.round(params.smokeCount);
|
|
209
|
+
return smoke;
|
|
210
|
+
}
|
|
211
|
+
function makeDebrisVelocity(params, spawnScale) {
|
|
212
|
+
const velocity = new Vector3(
|
|
213
|
+
(Math.random() - 0.5) * 13 * params.debrisHorizontalSpeed,
|
|
214
|
+
(Math.random() * 6.75 + 2.25) * params.debrisUpSpeed,
|
|
215
|
+
(Math.random() - 0.5) * 13 * params.debrisHorizontalSpeed
|
|
216
|
+
);
|
|
217
|
+
const direction = new Vector3(params.debrisDirectionX, params.debrisDirectionY, params.debrisDirectionZ);
|
|
218
|
+
const directionLength = direction.length();
|
|
219
|
+
if (directionLength > 1e-4) {
|
|
220
|
+
direction.scaleInPlace(1 / directionLength);
|
|
221
|
+
const directionSpeed = 6.5 * Math.min(directionLength, 1);
|
|
222
|
+
velocity.addInPlace(new Vector3(
|
|
223
|
+
direction.x * directionSpeed * params.debrisHorizontalSpeed,
|
|
224
|
+
direction.y * directionSpeed * params.debrisUpSpeed,
|
|
225
|
+
direction.z * directionSpeed * params.debrisHorizontalSpeed
|
|
226
|
+
));
|
|
227
|
+
}
|
|
228
|
+
return velocity.scaleInPlace(params.debrisSpeed * spawnScale);
|
|
229
|
+
}
|
|
230
|
+
export {
|
|
231
|
+
miningHitEffectPackage
|
|
232
|
+
};
|