@galacean/engine 0.0.0-experimental-2.0-game.10 → 0.0.0-experimental-2.0-game.12

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/browser.js CHANGED
@@ -10787,8 +10787,13 @@
10787
10787
  rotation._onValueChanged = target._onRotationChanged;
10788
10788
  // @ts-ignore
10789
10789
  scale._onValueChanged = target._onScaleChanged;
10790
- // When cloning, other components may obtain properties such as `rotationQuaternion` in the constructor, local related dirty flags need to be corrected
10790
+ // When cloning, other components may obtain properties such as `rotationQuaternion` in the constructor, local related dirty flags need to be corrected.
10791
+ // Earlier in this Entity's construction other components (e.g. DynamicCollider) may have queried
10792
+ // `worldPosition`, which clears the WorldPosition / WorldMatrix dirty flags as a side effect of caching
10793
+ // the computed value. After this _cloneTo writes new local values, those world-derived caches are stale,
10794
+ // so re-dirty them and notify listeners (Collider._updateFlag etc.) so subsequent reads recompute correctly.
10791
10795
  target._setDirtyFlagTrue(2 | 64);
10796
+ target._worldAssociatedChange(444);
10792
10797
  };
10793
10798
  _proto._onLocalMatrixChanging = function _onLocalMatrixChanging() {
10794
10799
  this._setDirtyFlagFalse(64);
@@ -16462,7 +16467,6 @@
16462
16467
  if (charLength > 0) {
16463
16468
  this._buildChunk(curTextChunk, charLength);
16464
16469
  }
16465
- this._setDirtyFlagTrue(4);
16466
16470
  charRenderInfos.length = 0;
16467
16471
  };
16468
16472
  _proto._onTransformChanged = function _onTransformChanged(bit) {
@@ -25434,17 +25438,23 @@
25434
25438
  /**
25435
25439
  * @internal
25436
25440
  */ _proto._onUpdate = function _onUpdate() {
25441
+ var shapes = this._shapes;
25437
25442
  if (this._updateFlag.flag) {
25438
25443
  var transform = this.entity.transform;
25439
- this._nativeCollider.setWorldTransform(transform.worldPosition, transform.worldRotationQuaternion);
25444
+ this._syncEntityTransformToNative(transform.worldPosition, transform.worldRotationQuaternion);
25440
25445
  var worldScale = transform.lossyWorldScale;
25441
- var shapes = this._shapes;
25442
25446
  for(var i = 0, n = shapes.length; i < n; i++){
25443
25447
  var _shapes_i__nativeShape;
25444
25448
  (_shapes_i__nativeShape = shapes[i]._nativeShape) == null ? void 0 : _shapes_i__nativeShape.setWorldScale(worldScale);
25445
25449
  }
25446
25450
  this._updateFlag.flag = false;
25447
25451
  }
25452
+ // Drive per-shape physics update (e.g. MeshColliderShape retries pending
25453
+ // native shape creation when mesh data becomes accessible asynchronously).
25454
+ // No-op for shape types that don't override `_onPhysicsUpdate`.
25455
+ for(var i1 = 0, n1 = shapes.length; i1 < n1; i1++){
25456
+ shapes[i1]._onPhysicsUpdate();
25457
+ }
25448
25458
  };
25449
25459
  /**
25450
25460
  * @internal
@@ -25476,6 +25486,28 @@
25476
25486
  this._addNativeShape(this.shapes[i]);
25477
25487
  }
25478
25488
  this._setCollisionLayer();
25489
+ // Teleport native actor to entity's current world pose.
25490
+ // The native actor was created in constructor() with the entity's then-current
25491
+ // worldPosition/Rotation. On clone, the entity's transform fields are deep-cloned
25492
+ // AFTER the Component (and its native actor) are constructed, so the native actor's
25493
+ // pose lags behind the cloned entity transform until this sync.
25494
+ var transform = this.entity.transform;
25495
+ this._teleportToEntityTransform(transform.worldPosition, transform.worldRotationQuaternion);
25496
+ };
25497
+ /**
25498
+ * Teleport native actor to a world pose (instant, no implied velocity).
25499
+ * Used during initialization paths (clone) where the native actor must be re-aligned
25500
+ * with the entity transform after construction-time pose was based on stale defaults.
25501
+ */ _proto._teleportToEntityTransform = function _teleportToEntityTransform(worldPosition, worldRotation) {
25502
+ this._nativeCollider.setWorldTransform(worldPosition, worldRotation);
25503
+ };
25504
+ /**
25505
+ * Sync entity world transform to native actor for per-frame updates.
25506
+ * Default semantics: teleport (setGlobalPose). Subclasses override to express
25507
+ * physics-aware movement (e.g. DynamicCollider routes kinematic actors through
25508
+ * setKinematicTarget to generate contact events on swept motion).
25509
+ */ _proto._syncEntityTransformToNative = function _syncEntityTransformToNative(worldPosition, worldRotation) {
25510
+ this._nativeCollider.setWorldTransform(worldPosition, worldRotation);
25479
25511
  };
25480
25512
  /**
25481
25513
  * @internal
@@ -25633,6 +25665,9 @@
25633
25665
  this._nativeCollider.setUpDirection(this._upDirection);
25634
25666
  this._nativeCollider.setSlopeLimit(this._slopeLimit);
25635
25667
  };
25668
+ _proto._teleportToEntityTransform = function _teleportToEntityTransform(worldPosition, _worldRotation) {
25669
+ this._nativeCollider.setWorldPosition(worldPosition);
25670
+ };
25636
25671
  _proto._syncWorldPositionFromPhysicalSpace = function _syncWorldPositionFromPhysicalSpace() {
25637
25672
  this._nativeCollider.getWorldPosition(this.entity.transform.worldPosition);
25638
25673
  };
@@ -25732,7 +25767,7 @@
25732
25767
  this._staticFriction = 0.6;
25733
25768
  this._bounceCombine = PhysicsMaterialCombineMode.Average;
25734
25769
  this._frictionCombine = PhysicsMaterialCombineMode.Average;
25735
- this._nativeMaterial = Engine._nativePhysics.createPhysicsMaterial(this._staticFriction, this._dynamicFriction, this._bounciness, this._bounceCombine, this._frictionCombine);
25770
+ this._nativeMaterial = Engine._nativePhysics.createPhysicsMaterial(this._staticFriction, this._dynamicFriction, this._bounciness, this._frictionCombine, this._bounceCombine);
25736
25771
  }
25737
25772
  var _proto = PhysicsMaterial.prototype;
25738
25773
  /**
@@ -25741,6 +25776,21 @@
25741
25776
  !this._destroyed && this._nativeMaterial.destroy();
25742
25777
  this._destroyed = true;
25743
25778
  };
25779
+ /**
25780
+ * @internal
25781
+ */ _proto._cloneTo = function _cloneTo(target) {
25782
+ target._syncNative();
25783
+ };
25784
+ /**
25785
+ * @internal
25786
+ */ _proto._syncNative = function _syncNative() {
25787
+ var nativeMaterial = this._nativeMaterial;
25788
+ nativeMaterial.setStaticFriction(this._staticFriction);
25789
+ nativeMaterial.setDynamicFriction(this._dynamicFriction);
25790
+ nativeMaterial.setBounciness(this._bounciness);
25791
+ nativeMaterial.setFrictionCombine(this._frictionCombine);
25792
+ nativeMaterial.setBounceCombine(this._bounceCombine);
25793
+ };
25744
25794
  _create_class$2(PhysicsMaterial, [
25745
25795
  {
25746
25796
  key: "bounciness",
@@ -25815,6 +25865,9 @@
25815
25865
  ]);
25816
25866
  return PhysicsMaterial;
25817
25867
  }();
25868
+ __decorate$1([
25869
+ ignoreClone
25870
+ ], PhysicsMaterial.prototype, "_nativeMaterial", void 0);
25818
25871
  /**
25819
25872
  * Abstract class for collider shapes.
25820
25873
  */ var ColliderShape = /*#__PURE__*/ function() {
@@ -25866,6 +25919,16 @@
25866
25919
  };
25867
25920
  /**
25868
25921
  * @internal
25922
+ *
25923
+ * Called once per physics update tick by `Collider._onUpdate`. Base no-op.
25924
+ *
25925
+ * Subclasses can override for frame-driven maintenance. Currently used by
25926
+ * `MeshColliderShape` to retry native shape creation when mesh data becomes
25927
+ * accessible later or PhysX cooking previously failed due to transient state
25928
+ * (async resource loading, cook pipeline warmup, etc.).
25929
+ */ _proto._onPhysicsUpdate = function _onPhysicsUpdate() {};
25930
+ /**
25931
+ * @internal
25869
25932
  */ _proto._destroy = function _destroy() {
25870
25933
  if (this._nativeShape) {
25871
25934
  this._nativeShape.destroy();
@@ -26014,7 +26077,11 @@
26014
26077
  _inherits$2(MeshColliderShape, ColliderShape);
26015
26078
  function MeshColliderShape() {
26016
26079
  var _this;
26017
- _this = ColliderShape.apply(this, arguments) || this, _this._mesh = null, _this._isConvex = false, _this._positions = null, _this._indices = null, _this._cookingFlags = MeshColliderShapeCookingFlag.Cleaning | MeshColliderShapeCookingFlag.VertexWelding, _this._isShapeAttached = false;
26080
+ _this = ColliderShape.apply(this, arguments) || this, _this._mesh = null, _this._isConvex = false, _this._positions = null, _this._indices = null, _this._cookingFlags = MeshColliderShapeCookingFlag.Cleaning | MeshColliderShapeCookingFlag.VertexWelding, _this._isShapeAttached = false, /**
26081
+ * `true` if a native shape creation was attempted but failed (mesh data not yet
26082
+ * accessible, PhysX cooking transient failure, etc.). The `_onPhysicsUpdate` hook
26083
+ * will keep retrying every frame until creation succeeds.
26084
+ */ _this._pendingNativeShapeCreation = false;
26018
26085
  return _this;
26019
26086
  }
26020
26087
  var _proto = MeshColliderShape.prototype;
@@ -26098,9 +26165,12 @@
26098
26165
  }
26099
26166
  var nativeShape = Engine._nativePhysics.createMeshColliderShape(this._id, this._positions, this._indices, this._isConvex, this._material._nativeMaterial, this._cookingFlags);
26100
26167
  if (!nativeShape) {
26168
+ // Cook failed — `_onPhysicsUpdate` will retry next frame
26169
+ this._pendingNativeShapeCreation = true;
26101
26170
  return;
26102
26171
  }
26103
26172
  this._nativeShape = nativeShape;
26173
+ this._pendingNativeShapeCreation = false;
26104
26174
  // Sync base class properties (position, rotation, contactOffset, isTrigger, material)
26105
26175
  ColliderShape.prototype._syncNative.call(this);
26106
26176
  // If already attached to a collider, add the newly created native shape to it
@@ -26109,6 +26179,36 @@
26109
26179
  this._attachToCollider();
26110
26180
  }
26111
26181
  };
26182
+ /**
26183
+ * @internal
26184
+ * Retry hook: keep attempting `_createNativeShape` until it succeeds.
26185
+ *
26186
+ * Triggered every physics update tick by `Collider._onUpdate`. Handles the case
26187
+ * where `_cookMesh` fails on first attempt due to PhysX cooking pipeline timing
26188
+ * (the mesh data was extracted successfully at `set mesh` time, but the native
26189
+ * cook call returned null). No-op once a valid native shape exists.
26190
+ *
26191
+ * We DO NOT re-call `_extractMeshData` here — once `set mesh` finished, either:
26192
+ * - extraction succeeded → `_positions` is populated and we reuse it
26193
+ * - extraction failed → `_clearMeshData` cleared `_positions`, and `mesh.accessible`
26194
+ * won't recover (GPU upload is one-way), so re-extracting would fail again
26195
+ */ _proto._onPhysicsUpdate = function _onPhysicsUpdate() {
26196
+ if (!this._pendingNativeShapeCreation || !this._mesh || !this._positions) return;
26197
+ this._createNativeShape();
26198
+ };
26199
+ /**
26200
+ * @internal
26201
+ * After CloneManager deep-copies `_positions` / `_indices` / `_mesh` and remaps `_collider`,
26202
+ * the cloned shape still has no native PhysX shape because `_nativeShape` is `@ignoreClone`.
26203
+ * Cook a fresh native shape now using the already-cloned vertex/index buffers; on transient
26204
+ * cook failure `_createNativeShape` sets `_pendingNativeShapeCreation = true` and
26205
+ * `_onPhysicsUpdate` will retry next tick.
26206
+ */ _proto._cloneTo = function _cloneTo(target) {
26207
+ ColliderShape.prototype._cloneTo.call(this, target);
26208
+ if (target._positions) {
26209
+ target._createNativeShape();
26210
+ }
26211
+ };
26112
26212
  _create_class$2(MeshColliderShape, [
26113
26213
  {
26114
26214
  key: "cookingFlags",
@@ -26168,15 +26268,25 @@
26168
26268
  (_this__mesh = this._mesh) == null ? void 0 : _this__mesh._addReferCount(-1);
26169
26269
  value == null ? void 0 : value._addReferCount(1);
26170
26270
  this._mesh = value;
26171
- if (value && this._extractMeshData(value)) {
26172
- if (this._nativeShape) {
26173
- this._updateNativeShapeData();
26271
+ if (value) {
26272
+ if (this._extractMeshData(value)) {
26273
+ if (this._nativeShape) {
26274
+ this._updateNativeShapeData();
26275
+ } else {
26276
+ this._createNativeShape();
26277
+ }
26278
+ // _createNativeShape can fail silently (cookMesh transient failure); mark pending if so
26279
+ this._pendingNativeShapeCreation = !this._nativeShape;
26174
26280
  } else {
26175
- this._createNativeShape();
26281
+ // Mesh not yet accessible — keep pending so `_onPhysicsUpdate` retries later
26282
+ this._destroyNativeShape();
26283
+ this._clearMeshData();
26284
+ this._pendingNativeShapeCreation = true;
26176
26285
  }
26177
26286
  } else {
26178
26287
  this._destroyNativeShape();
26179
26288
  this._clearMeshData();
26289
+ this._pendingNativeShapeCreation = false;
26180
26290
  }
26181
26291
  }
26182
26292
  }
@@ -26220,6 +26330,27 @@
26220
26330
  */ _proto.applyTorque = function applyTorque(torque) {
26221
26331
  this._phasedActiveInScene && this._nativeCollider.addTorque(torque);
26222
26332
  };
26333
+ /**
26334
+ * Apply a force to the DynamicCollider at a given position in world space.
26335
+ * The force generates both linear acceleration through the center of mass and angular
26336
+ * acceleration about it (torque = (position - centerOfMass) × force).
26337
+ * @param force - The force to apply, in world space
26338
+ * @param position - The position where the force is applied, in world space
26339
+ */ _proto.applyForceAtPosition = function applyForceAtPosition(force, position) {
26340
+ if (!this._phasedActiveInScene) return;
26341
+ var nativeCollider = this._nativeCollider;
26342
+ var localCoM = DynamicCollider._tempVector3;
26343
+ nativeCollider.getCenterOfMass(localCoM);
26344
+ var transform = this.entity.transform;
26345
+ var worldCoM = DynamicCollider._tempVector3_1;
26346
+ Vector3.transformByQuat(localCoM, transform.worldRotationQuaternion, worldCoM);
26347
+ worldCoM.add(transform.worldPosition);
26348
+ var torque = DynamicCollider._tempVector3_2;
26349
+ Vector3.subtract(position, worldCoM, torque);
26350
+ Vector3.cross(torque, force, torque);
26351
+ nativeCollider.addForce(force);
26352
+ nativeCollider.addTorque(torque);
26353
+ };
26223
26354
  _proto.move = function move(positionOrRotation, rotation) {
26224
26355
  if (!this._isKinematic) {
26225
26356
  console.warn("DynamicCollider: move() is only supported when isKinematic is true.");
@@ -26253,6 +26384,31 @@
26253
26384
  Collider.prototype.addShape.call(this, shape);
26254
26385
  };
26255
26386
  /**
26387
+ * Route per-frame entity → native transform sync to the correct physics API based
26388
+ * on kinematic state.
26389
+ *
26390
+ * PhysX 4.x docs (PxRigidDynamic):
26391
+ * "If you intend to move a kinematic actor with [setGlobalPose] and want
26392
+ * collision detection, use setKinematicTarget() instead."
26393
+ *
26394
+ * setGlobalPose is a teleport: PhysX skips contact detection between the old
26395
+ * and new pose, so two kinematic actors moved onto each other via entity.transform
26396
+ * mutation would NOT produce onCollisionEnter / onCollisionStay events even when
26397
+ * scene.kineKineFilteringMode = eKEEP. Routing the per-frame sync through
26398
+ * IDynamicCollider.move() (which the PhysX backend implements as
26399
+ * setKinematicTarget) tells PhysX the actor is animating to the target during the
26400
+ * next simulate(), enabling sweep contact detection for kine-kine and kine-dynamic
26401
+ * pairs alike.
26402
+ *
26403
+ * @internal
26404
+ */ _proto._syncEntityTransformToNative = function _syncEntityTransformToNative(worldPosition, worldRotation) {
26405
+ if (this._isKinematic) {
26406
+ this._nativeCollider.move(worldPosition, worldRotation);
26407
+ } else {
26408
+ Collider.prototype._syncEntityTransformToNative.call(this, worldPosition, worldRotation);
26409
+ }
26410
+ };
26411
+ /**
26256
26412
  * @internal
26257
26413
  */ _proto._onLateUpdate = function _onLateUpdate() {
26258
26414
  var transform = this.entity.transform;
@@ -26626,6 +26782,8 @@
26626
26782
  return DynamicCollider;
26627
26783
  }(exports.Collider);
26628
26784
  DynamicCollider._tempVector3 = new Vector3();
26785
+ DynamicCollider._tempVector3_1 = new Vector3();
26786
+ DynamicCollider._tempVector3_2 = new Vector3();
26629
26787
  DynamicCollider._tempQuat = new Quaternion();
26630
26788
  __decorate$1([
26631
26789
  ignoreClone
@@ -29720,7 +29878,7 @@
29720
29878
  var spriteMaskVs = "uniform mat4 camera_VPMat;\n\nattribute vec3 POSITION;\nattribute vec2 TEXCOORD_0;\n\nvarying vec2 v_uv;\n\nvoid main()\n{\n gl_Position = camera_VPMat * vec4(POSITION, 1.0);\n v_uv = TEXCOORD_0;\n}\n"; // eslint-disable-line
29721
29879
  var spriteFs = "#include <common>\nuniform sampler2D renderer_SpriteTexture;\n\nvarying vec2 v_uv;\nvarying vec4 v_color;\n\nvoid main()\n{\n vec4 baseColor = texture2DSRGB(renderer_SpriteTexture, v_uv);\n gl_FragColor = baseColor * v_color;\n}\n"; // eslint-disable-line
29722
29880
  var spriteVs = "uniform mat4 renderer_MVPMat;\n\nattribute vec3 POSITION;\nattribute vec2 TEXCOORD_0;\nattribute vec4 COLOR_0;\n\nvarying vec2 v_uv;\nvarying vec4 v_color;\n\nvoid main()\n{\n gl_Position = renderer_MVPMat * vec4(POSITION, 1.0);\n\n v_uv = TEXCOORD_0;\n v_color = COLOR_0;\n}\n"; // eslint-disable-line
29723
- var textFs = "uniform sampler2D renderElement_TextTexture;\nuniform vec2 renderElement_TextTextureSize;\nuniform vec4 renderer_OutlineColor;\nuniform float renderer_OutlineWidth;\n\nuniform vec4 renderer_UIRectClipRect;\nuniform float renderer_UIRectClipEnabled;\nuniform vec4 renderer_UIRectClipSoftness;\nuniform float renderer_UIRectClipHardClip;\n\nvarying vec2 v_uv;\nvarying vec4 v_color;\nvarying vec2 v_worldPosition;\n\nfloat getUIRectClipAlpha()\n{\n vec4 edgeDistance = vec4(\n v_worldPosition.x - renderer_UIRectClipRect.x,\n v_worldPosition.y - renderer_UIRectClipRect.y,\n renderer_UIRectClipRect.z - v_worldPosition.x,\n renderer_UIRectClipRect.w - v_worldPosition.y\n );\n vec4 hardClipFactor = step(vec4(0.0), edgeDistance);\n vec4 softness = max(renderer_UIRectClipSoftness, vec4(1e-5));\n vec4 softClipFactor = clamp(edgeDistance / softness, 0.0, 1.0);\n vec4 useSoftness = step(vec4(1e-5), renderer_UIRectClipSoftness);\n vec4 clipFactor = mix(hardClipFactor, softClipFactor, useSoftness);\n return clipFactor.x * clipFactor.y * clipFactor.z * clipFactor.w;\n}\n\nfloat sampleCoverage(vec2 uv)\n{\n vec4 c = texture2D(renderElement_TextTexture, uv);\n #ifdef GRAPHICS_API_WEBGL2\n return c.r;\n #else\n return c.a;\n #endif\n}\n\nvoid main()\n{\n float rectClipAlpha = 1.0;\n if (renderer_UIRectClipEnabled > 0.5) {\n rectClipAlpha = getUIRectClipAlpha();\n }\n\n float coverage = sampleCoverage(v_uv);\n vec4 finalColor;\n\n if (renderer_OutlineWidth > 0.0) {\n vec2 texelSize = 1.0 / renderElement_TextTextureSize;\n vec2 step = texelSize * renderer_OutlineWidth;\n float outlineCoverage = coverage;\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( step.x, 0.0)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2(-step.x, 0.0)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( 0.0, step.y)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( 0.0, -step.y)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( step.x * 0.7071, step.y * 0.7071)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2(-step.x * 0.7071, step.y * 0.7071)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( step.x * 0.7071, -step.y * 0.7071)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2(-step.x * 0.7071, -step.y * 0.7071)));\n\n vec3 rgb = mix(renderer_OutlineColor.rgb, v_color.rgb, coverage);\n float alpha = max(coverage * v_color.a, outlineCoverage * renderer_OutlineColor.a);\n finalColor = vec4(rgb, alpha);\n } else {\n finalColor = vec4(v_color.rgb, v_color.a * coverage);\n }\n\n finalColor.a *= rectClipAlpha;\n if (renderer_UIRectClipEnabled > 0.5 && renderer_UIRectClipHardClip > 0.5 && finalColor.a < 0.001) {\n discard;\n }\n gl_FragColor = finalColor;\n}\n"; // eslint-disable-line
29881
+ var textFs = "uniform sampler2D renderElement_TextTexture;\nuniform vec2 renderElement_TextTextureSize;\nuniform vec4 renderer_OutlineColor;\nuniform float renderer_OutlineWidth;\n\nuniform vec4 renderer_UIRectClipRect;\nuniform float renderer_UIRectClipEnabled;\nuniform vec4 renderer_UIRectClipSoftness;\nuniform float renderer_UIRectClipHardClip;\n\nvarying vec2 v_uv;\nvarying vec4 v_color;\nvarying vec2 v_worldPosition;\n\nfloat getUIRectClipAlpha()\n{\n vec4 edgeDistance = vec4(\n v_worldPosition.x - renderer_UIRectClipRect.x,\n v_worldPosition.y - renderer_UIRectClipRect.y,\n renderer_UIRectClipRect.z - v_worldPosition.x,\n renderer_UIRectClipRect.w - v_worldPosition.y\n );\n vec4 hardClipFactor = step(vec4(0.0), edgeDistance);\n vec4 softness = max(renderer_UIRectClipSoftness, vec4(1e-5));\n vec4 softClipFactor = clamp(edgeDistance / softness, 0.0, 1.0);\n vec4 useSoftness = step(vec4(1e-5), renderer_UIRectClipSoftness);\n vec4 clipFactor = mix(hardClipFactor, softClipFactor, useSoftness);\n return clipFactor.x * clipFactor.y * clipFactor.z * clipFactor.w;\n}\n\nfloat sampleCoverage(vec2 uv)\n{\n vec4 c = texture2D(renderElement_TextTexture, uv);\n #ifdef GRAPHICS_API_WEBGL2\n return c.r;\n #else\n return c.a;\n #endif\n}\n\nvoid main()\n{\n float rectClipAlpha = 1.0;\n if (renderer_UIRectClipEnabled > 0.5) {\n rectClipAlpha = getUIRectClipAlpha();\n }\n\n float coverage = sampleCoverage(v_uv);\n vec4 finalColor;\n\n if (renderer_OutlineWidth > 0.0) {\n vec2 texelSize = 1.0 / renderElement_TextTextureSize;\n vec2 step = texelSize * renderer_OutlineWidth;\n float outlineCoverage = coverage;\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( step.x, 0.0)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2(-step.x, 0.0)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( 0.0, step.y)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( 0.0, -step.y)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( step.x * 0.7071, step.y * 0.7071)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2(-step.x * 0.7071, step.y * 0.7071)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2( step.x * 0.7071, -step.y * 0.7071)));\n outlineCoverage = max(outlineCoverage, sampleCoverage(v_uv + vec2(-step.x * 0.7071, -step.y * 0.7071)));\n\n vec3 rgb = mix(renderer_OutlineColor.rgb, v_color.rgb, coverage);\n float alpha = max(coverage, outlineCoverage * renderer_OutlineColor.a) * v_color.a;\n finalColor = vec4(rgb, alpha);\n } else {\n finalColor = vec4(v_color.rgb, v_color.a * coverage);\n }\n\n finalColor.a *= rectClipAlpha;\n if (renderer_UIRectClipEnabled > 0.5 && renderer_UIRectClipHardClip > 0.5 && finalColor.a < 0.001) {\n discard;\n }\n gl_FragColor = finalColor;\n}\n"; // eslint-disable-line
29724
29882
  var textVs = "uniform mat4 renderer_MVPMat;\nuniform mat4 renderer_ModelMat;\n\nattribute vec3 POSITION;\nattribute vec2 TEXCOORD_0;\nattribute vec4 COLOR_0;\n\nvarying vec2 v_uv;\nvarying vec4 v_color;\nvarying vec2 v_worldPosition;\n\nvoid main()\n{\n gl_Position = renderer_MVPMat * vec4(POSITION, 1.0);\n\n v_uv = TEXCOORD_0;\n v_color = COLOR_0;\n v_worldPosition = POSITION.xy;\n}\n"; // eslint-disable-line
29725
29883
  var trailFs = "#include <common>\n\nvarying vec2 v_uv;\nvarying vec4 v_color;\n\nuniform vec4 material_BaseColor;\n\n#ifdef MATERIAL_HAS_BASETEXTURE\n uniform sampler2D material_BaseTexture;\n#endif\n\nuniform mediump vec3 material_EmissiveColor;\n#ifdef MATERIAL_HAS_EMISSIVETEXTURE\n uniform sampler2D material_EmissiveTexture;\n#endif\n\nvoid main() {\n vec4 color = material_BaseColor * v_color;\n\n #ifdef MATERIAL_HAS_BASETEXTURE\n color *= texture2DSRGB(material_BaseTexture, v_uv);\n #endif\n\n // Emissive\n vec3 emissiveRadiance = material_EmissiveColor;\n #ifdef MATERIAL_HAS_EMISSIVETEXTURE\n emissiveRadiance *= texture2DSRGB(material_EmissiveTexture, v_uv).rgb;\n #endif\n\n color.rgb += emissiveRadiance;\n\n gl_FragColor = color;\n}\n\n"; // eslint-disable-line
29726
29884
  var trailVs = "attribute vec4 a_PositionBirthTime; // xyz: World position, w: Birth time (used by CPU only)\nattribute vec4 a_CornerTangent; // x: Corner (-1 or 1), yzw: Tangent direction\nattribute float a_Distance; // Absolute cumulative distance (written once per point)\n\nuniform vec4 renderer_TrailParams; // x: TextureMode (0: Stretch, 1: Tile), y: TextureScaleX, z: TextureScaleY\nuniform vec2 renderer_DistanceParams; // x: HeadDistance, y: TailDistance\nuniform vec3 camera_Position;\nuniform mat4 camera_ViewMat;\nuniform mat4 camera_ProjMat;\nuniform vec2 renderer_WidthCurve[4]; // Width curve (4 keyframes max: x=time, y=value)\nuniform vec4 renderer_ColorKeys[4]; // Color gradient (x=time, yzw=rgb)\nuniform vec2 renderer_AlphaKeys[4]; // Alpha gradient (x=time, y=alpha)\nuniform vec4 renderer_CurveMaxTime; // x: colorMaxTime, y: alphaMaxTime, z: widthMaxTime\n\nvarying vec2 v_uv;\nvarying vec4 v_color;\n\n#include <particle_common>\n\nvoid main() {\n vec3 position = a_PositionBirthTime.xyz;\n float corner = a_CornerTangent.x;\n vec3 tangent = a_CornerTangent.yzw;\n\n // Distance-based relative position: 0=head(newest), 1=tail(oldest)\n float distFromHead = renderer_DistanceParams.x - a_Distance;\n float totalDist = renderer_DistanceParams.x - renderer_DistanceParams.y;\n float relativePos = totalDist > 0.0 ? distFromHead / totalDist : 0.0;\n\n // Billboard: expand perpendicular to tangent and view direction\n vec3 toCamera = normalize(camera_Position - position);\n vec3 right = cross(tangent, toCamera);\n float rightLenSq = dot(right, right);\n if (rightLenSq < 0.000001) {\n right = cross(tangent, vec3(0.0, 1.0, 0.0));\n rightLenSq = dot(right, right);\n if (rightLenSq < 0.000001) {\n right = cross(tangent, vec3(1.0, 0.0, 0.0));\n rightLenSq = dot(right, right);\n }\n }\n right = right * inversesqrt(rightLenSq);\n\n float width = evaluateParticleCurve(renderer_WidthCurve, min(relativePos, renderer_CurveMaxTime.z));\n vec3 worldPosition = position + right * width * 0.5 * corner;\n\n gl_Position = camera_ProjMat * camera_ViewMat * vec4(worldPosition, 1.0);\n\n // u = position along trail (affected by textureMode), v = corner side.\n float u = renderer_TrailParams.x == 0.0 ? relativePos : distFromHead;\n float v = corner * 0.5 + 0.5;\n v_uv = vec2(u * renderer_TrailParams.y, v * renderer_TrailParams.z);\n\n v_color = evaluateParticleGradient(renderer_ColorKeys, renderer_CurveMaxTime.x, renderer_AlphaKeys, renderer_CurveMaxTime.y, relativePos);\n}\n"; // eslint-disable-line
@@ -56172,7 +56330,7 @@
56172
56330
  ], EXT_texture_webp);
56173
56331
 
56174
56332
  //@ts-ignore
56175
- var version = "0.0.0-experimental-2.0-game.10";
56333
+ var version = "0.0.0-experimental-2.0-game.12";
56176
56334
  console.log("Galacean Engine Version: " + version);
56177
56335
  for(var key in CoreObjects){
56178
56336
  Loader.registerClass(key, CoreObjects[key]);