@galacean/engine 2.0.0-alpha.25 → 2.0.0-alpha.26

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
@@ -6414,6 +6414,12 @@
6414
6414
  case TextureFormat.ETC2_RGB:
6415
6415
  case TextureFormat.ETC2_RGBA8:
6416
6416
  case TextureFormat.ASTC_4x4:
6417
+ case TextureFormat.ASTC_5x5:
6418
+ case TextureFormat.ASTC_6x6:
6419
+ case TextureFormat.ASTC_8x8:
6420
+ case TextureFormat.ASTC_10x10:
6421
+ case TextureFormat.ASTC_12x12:
6422
+ case TextureFormat.ETC2_RGBA5:
6417
6423
  return true;
6418
6424
  default:
6419
6425
  return false;
@@ -6947,7 +6953,7 @@
6947
6953
  _this = ReferResource.call(this, engine) || this, _this._charInfoMap = {}, _this._space = 1, _this._curX = 1, _this._curY = 1, _this._nextY = 1;
6948
6954
  _this.isGCIgnored = true;
6949
6955
  var format = engine._hardwareRenderer.isWebGL2 ? TextureFormat.R8 : TextureFormat.Alpha8;
6950
- var texture = new Texture2D(engine, 512, 512, format, false);
6956
+ var texture = new Texture2D(engine, 512, 512, format, false, false);
6951
6957
  texture.filterMode = TextureFilterMode.Bilinear;
6952
6958
  texture.isGCIgnored = true;
6953
6959
  _this.texture = texture;
@@ -9888,7 +9894,8 @@
9888
9894
  var texture_sheet_animation_module = "#if defined(RENDERER_TSA_FRAME_CURVE) || defined(RENDERER_TSA_FRAME_RANDOM_CURVES)\n uniform float renderer_TSACycles;\n uniform vec3 renderer_TSATillingParams; // x:subU y:subV z:tileCount\n uniform vec2 renderer_TSAFrameMaxCurve[4]; // x:time y:value\n\n #ifdef RENDERER_TSA_FRAME_RANDOM_CURVES\n uniform vec2 renderer_TSAFrameMinCurve[4]; // x:time y:value\n #endif\n#endif\n\nvec2 computeParticleUV(in vec2 uv, in float normalizedAge) {\n #if defined(RENDERER_TSA_FRAME_CURVE) || defined(RENDERER_TSA_FRAME_RANDOM_CURVES)\n float scaledNormalizedAge = normalizedAge * renderer_TSACycles;\n float cycleNormalizedAge = scaledNormalizedAge - floor(scaledNormalizedAge);\n float normalizedFrame = evaluateParticleCurve(renderer_TSAFrameMaxCurve, cycleNormalizedAge);\n #ifdef RENDERER_TSA_FRAME_RANDOM_CURVES\n normalizedFrame = mix(evaluateParticleCurve(renderer_TSAFrameMinCurve, cycleNormalizedAge), normalizedFrame, a_Random1.x);\n #endif\n\n float frame = floor(normalizedFrame * renderer_TSATillingParams.z);\n\n float tileRow = frame * renderer_TSATillingParams.x;\n float tileRowIndex = floor(tileRow);\n uv.x += tileRow - tileRowIndex;\n uv.y += tileRowIndex * renderer_TSATillingParams.y;\n #endif\n \n return uv;\n}\n"; // eslint-disable-line
9889
9895
  var force_over_lifetime_module = "#if defined(RENDERER_FOL_CONSTANT_MODE) || defined(RENDERER_FOL_CURVE_MODE)\n #define _FOL_MODULE_ENABLED\n#endif\n\n#ifdef _FOL_MODULE_ENABLED\n uniform int renderer_FOLSpace;\n\n #ifdef RENDERER_FOL_CONSTANT_MODE\n uniform vec3 renderer_FOLMaxConst;\n\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n uniform vec3 renderer_FOLMinConst;\n #endif\n\n #endif\n\n #ifdef RENDERER_FOL_CURVE_MODE\n uniform vec2 renderer_FOLMaxGradientX[4];\n uniform vec2 renderer_FOLMaxGradientY[4];\n uniform vec2 renderer_FOLMaxGradientZ[4];\n\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n uniform vec2 renderer_FOLMinGradientX[4];\n uniform vec2 renderer_FOLMinGradientY[4];\n uniform vec2 renderer_FOLMinGradientZ[4];\n #endif\n #endif\n\n // (tHat - t1) * (tHat - t1) * (tHat - t1) * (a2 - a1) / ((t2 - t1) * 6.0) + a1 * (tHat - t1) * (tHat - t1) * 0.5 + v1 * (tHat - t1);\n // to = tHat - t1; tr = t2 - t1\n float computeDisplacementIntegral(in float to, in float tr, in float a1, in float a2, in float v1) {\n return to * to * to * (a2 - a1) / (tr * 6.0) + a1 * to * to * 0.5 + v1 * to;\n }\n\n float evaluateForceParticleCurveCumulative(in vec2 keys[4], in float normalizedAge, out float velocityCumulative) {\n float cumulativeValue = 0.0;\n velocityCumulative = 0.0;\n\n for (int i = 1; i < 4; i++){\n vec2 key = keys[i];\n vec2 lastKey = keys[i - 1];\n float timeRange = (key.x - lastKey.x) * a_ShapePositionStartLifeTime.w;\n\n if (key.x >= normalizedAge){\n float timeOffset = (normalizedAge - lastKey.x) * a_ShapePositionStartLifeTime.w;\n cumulativeValue += computeDisplacementIntegral(timeOffset, timeRange, lastKey.y, key.y, velocityCumulative);\n\n float finalAcceleration = mix(lastKey.y, key.y, timeOffset / timeRange);\n velocityCumulative += 0.5 * timeOffset * (finalAcceleration + lastKey.y);\n break;\n } else { \n cumulativeValue += computeDisplacementIntegral(timeRange, timeRange, lastKey.y, key.y, velocityCumulative);\n velocityCumulative += 0.5 * timeRange * (lastKey.y + key.y);\n }\n }\n return cumulativeValue;\n }\n\n vec3 computeForcePositionOffset(in float normalizedAge, in float age, out vec3 velocityOffset) {\n vec3 forcePosition;\n\n #if defined(RENDERER_FOL_CONSTANT_MODE)\n vec3 forceAcceleration = renderer_FOLMaxConst;\n\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n forceAcceleration = mix(renderer_FOLMinConst, forceAcceleration, vec3(a_Random2.x, a_Random2.y, a_Random2.z));\n #endif\n\n velocityOffset = forceAcceleration * age;\n\n forcePosition = 0.5 * forceAcceleration * age * age;\n #elif defined(RENDERER_FOL_CURVE_MODE)\n forcePosition = vec3(\n evaluateForceParticleCurveCumulative(renderer_FOLMaxGradientX, normalizedAge, velocityOffset.x),\n evaluateForceParticleCurveCumulative(renderer_FOLMaxGradientY, normalizedAge, velocityOffset.y),\n evaluateForceParticleCurveCumulative(renderer_FOLMaxGradientZ, normalizedAge, velocityOffset.z)\n );\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n vec3 minVelocityOffset;\n\n forcePosition = vec3(\n mix(evaluateForceParticleCurveCumulative(renderer_FOLMinGradientX, normalizedAge, minVelocityOffset.x), forcePosition.x, a_Random2.x),\n mix(evaluateForceParticleCurveCumulative(renderer_FOLMinGradientY, normalizedAge, minVelocityOffset.y), forcePosition.y, a_Random2.y),\n mix(evaluateForceParticleCurveCumulative(renderer_FOLMinGradientZ, normalizedAge, minVelocityOffset.z), forcePosition.z, a_Random2.z)\n );\n\n velocityOffset = mix(minVelocityOffset, velocityOffset, vec3(a_Random2.x, a_Random2.y, a_Random2.z));\n #endif\n #endif\n return forcePosition;\n }\n#endif"; // eslint-disable-line
9890
9896
  var limit_velocity_over_lifetime_module = "#ifdef RENDERER_LVL_MODULE_ENABLED\n uniform int renderer_LVLSpace;\n uniform float renderer_LVLDampen;\n\n // Scalar limit\n #ifndef RENDERER_LVL_SEPARATE_AXES\n #ifdef RENDERER_LVL_SPEED_CONSTANT_MODE\n uniform float renderer_LVLSpeedMaxConst;\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n uniform float renderer_LVLSpeedMinConst;\n #endif\n #endif\n #ifdef RENDERER_LVL_SPEED_CURVE_MODE\n uniform vec2 renderer_LVLSpeedMaxCurve[4];\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n uniform vec2 renderer_LVLSpeedMinCurve[4];\n #endif\n #endif\n #endif\n\n // Per-axis limit\n #ifdef RENDERER_LVL_SEPARATE_AXES\n #ifdef RENDERER_LVL_SPEED_CONSTANT_MODE\n uniform vec3 renderer_LVLSpeedMaxConstVector;\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n uniform vec3 renderer_LVLSpeedMinConstVector;\n #endif\n #endif\n #ifdef RENDERER_LVL_SPEED_CURVE_MODE\n uniform vec2 renderer_LVLSpeedXMaxCurve[4];\n uniform vec2 renderer_LVLSpeedYMaxCurve[4];\n uniform vec2 renderer_LVLSpeedZMaxCurve[4];\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n uniform vec2 renderer_LVLSpeedXMinCurve[4];\n uniform vec2 renderer_LVLSpeedYMinCurve[4];\n uniform vec2 renderer_LVLSpeedZMinCurve[4];\n #endif\n #endif\n #endif\n\n // Drag curve\n #ifdef RENDERER_LVL_DRAG_CURVE_MODE\n uniform vec2 renderer_LVLDragMaxCurve[4];\n #ifdef RENDERER_LVL_DRAG_IS_RANDOM_TWO\n uniform vec2 renderer_LVLDragMinCurve[4];\n #endif\n #endif\n\n float evaluateLVLDrag(float normalizedAge, float dragRand) {\n #ifdef RENDERER_LVL_DRAG_CURVE_MODE\n float dragMax = evaluateParticleCurve(renderer_LVLDragMaxCurve, normalizedAge);\n #ifdef RENDERER_LVL_DRAG_IS_RANDOM_TWO\n float dragMin = evaluateParticleCurve(renderer_LVLDragMinCurve, normalizedAge);\n return mix(dragMin, dragMax, dragRand);\n #else\n return dragMax;\n #endif\n #else\n return mix(renderer_LVLDragConstant.x, renderer_LVLDragConstant.y, dragRand);\n #endif\n }\n\n vec3 applyLVLSpeedLimitTF(vec3 velocity, float normalizedAge, float limitRand, float effectiveDampen) {\n #ifdef RENDERER_LVL_SEPARATE_AXES\n vec3 limitSpeed;\n #ifdef RENDERER_LVL_SPEED_CONSTANT_MODE\n limitSpeed = renderer_LVLSpeedMaxConstVector;\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n limitSpeed = mix(renderer_LVLSpeedMinConstVector, limitSpeed, limitRand);\n #endif\n #endif\n #ifdef RENDERER_LVL_SPEED_CURVE_MODE\n limitSpeed = vec3(\n evaluateParticleCurve(renderer_LVLSpeedXMaxCurve, normalizedAge),\n evaluateParticleCurve(renderer_LVLSpeedYMaxCurve, normalizedAge),\n evaluateParticleCurve(renderer_LVLSpeedZMaxCurve, normalizedAge)\n );\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n vec3 minLimitSpeed = vec3(\n evaluateParticleCurve(renderer_LVLSpeedXMinCurve, normalizedAge),\n evaluateParticleCurve(renderer_LVLSpeedYMinCurve, normalizedAge),\n evaluateParticleCurve(renderer_LVLSpeedZMinCurve, normalizedAge)\n );\n limitSpeed = mix(minLimitSpeed, limitSpeed, limitRand);\n #endif\n #endif\n\n vec3 absVel = abs(velocity);\n vec3 excess = max(absVel - limitSpeed, vec3(0.0));\n velocity = sign(velocity) * (absVel - excess * effectiveDampen);\n #else\n float limitSpeed;\n #ifdef RENDERER_LVL_SPEED_CONSTANT_MODE\n limitSpeed = renderer_LVLSpeedMaxConst;\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n limitSpeed = mix(renderer_LVLSpeedMinConst, limitSpeed, limitRand);\n #endif\n #endif\n #ifdef RENDERER_LVL_SPEED_CURVE_MODE\n limitSpeed = evaluateParticleCurve(renderer_LVLSpeedMaxCurve, normalizedAge);\n #ifdef RENDERER_LVL_SPEED_IS_RANDOM_TWO\n float minLimitSpeed = evaluateParticleCurve(renderer_LVLSpeedMinCurve, normalizedAge);\n limitSpeed = mix(minLimitSpeed, limitSpeed, limitRand);\n #endif\n #endif\n\n float speed = length(velocity);\n if (speed > limitSpeed && speed > 0.0) {\n float excess = speed - limitSpeed;\n velocity = velocity * ((speed - excess * effectiveDampen) / speed);\n }\n #endif\n return velocity;\n }\n\n#endif\n"; // eslint-disable-line
9891
- var particle_feedback_simulation = "// Transform Feedback update shader for particle simulation.\n// Update order: VOL/FOL → Dampen → Drag → Position.\n// Runs once per particle per frame (no rasterization).\n\n// Previous frame TF data\nattribute vec3 a_FeedbackPosition;\nattribute vec3 a_FeedbackVelocity;\n\n// Per-particle instance data\nattribute vec4 a_ShapePositionStartLifeTime;\nattribute vec4 a_DirectionTime;\nattribute vec3 a_StartSize;\nattribute float a_StartSpeed;\nattribute vec4 a_Random0;\nattribute vec4 a_Random1;\nattribute vec3 a_SimulationWorldPosition;\nattribute vec4 a_SimulationWorldRotation;\nattribute vec4 a_Random2;\n\n// Uniforms\nuniform float renderer_CurrentTime;\nuniform float renderer_DeltaTime;\nuniform vec3 renderer_Gravity;\nuniform vec2 renderer_LVLDragConstant;\nuniform vec3 renderer_WorldPosition;\nuniform vec4 renderer_WorldRotation;\nuniform int renderer_SimulationSpace;\n\n// TF outputs\nvarying vec3 v_FeedbackPosition;\nvarying vec3 v_FeedbackVelocity;\n\n#include <particle_common>\n#include <velocity_over_lifetime_module>\n#include <force_over_lifetime_module>\n#include <limit_velocity_over_lifetime_module>\n\n// Get VOL instantaneous velocity at normalizedAge\nvec3 getVOLVelocity(float normalizedAge) {\n vec3 vel = vec3(0.0);\n #ifdef _VOL_MODULE_ENABLED\n #ifdef RENDERER_VOL_CONSTANT_MODE\n vel = renderer_VOLMaxConst;\n #ifdef RENDERER_VOL_IS_RANDOM_TWO\n vel = mix(renderer_VOLMinConst, vel, a_Random1.yzw);\n #endif\n #endif\n #ifdef RENDERER_VOL_CURVE_MODE\n vel = vec3(\n evaluateParticleCurve(renderer_VOLMaxGradientX, normalizedAge),\n evaluateParticleCurve(renderer_VOLMaxGradientY, normalizedAge),\n evaluateParticleCurve(renderer_VOLMaxGradientZ, normalizedAge)\n );\n #ifdef RENDERER_VOL_IS_RANDOM_TWO\n vec3 minVel = vec3(\n evaluateParticleCurve(renderer_VOLMinGradientX, normalizedAge),\n evaluateParticleCurve(renderer_VOLMinGradientY, normalizedAge),\n evaluateParticleCurve(renderer_VOLMinGradientZ, normalizedAge)\n );\n vel = mix(minVel, vel, a_Random1.yzw);\n #endif\n #endif\n #endif\n return vel;\n}\n\n// Get FOL instantaneous acceleration at normalizedAge\nvec3 getFOLAcceleration(float normalizedAge) {\n vec3 acc = vec3(0.0);\n #ifdef _FOL_MODULE_ENABLED\n #ifdef RENDERER_FOL_CONSTANT_MODE\n acc = renderer_FOLMaxConst;\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n acc = mix(renderer_FOLMinConst, acc, vec3(a_Random2.x, a_Random2.y, a_Random2.z));\n #endif\n #endif\n #ifdef RENDERER_FOL_CURVE_MODE\n acc = vec3(\n evaluateParticleCurve(renderer_FOLMaxGradientX, normalizedAge),\n evaluateParticleCurve(renderer_FOLMaxGradientY, normalizedAge),\n evaluateParticleCurve(renderer_FOLMaxGradientZ, normalizedAge)\n );\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n vec3 minAcc = vec3(\n evaluateParticleCurve(renderer_FOLMinGradientX, normalizedAge),\n evaluateParticleCurve(renderer_FOLMinGradientY, normalizedAge),\n evaluateParticleCurve(renderer_FOLMinGradientZ, normalizedAge)\n );\n acc = mix(minAcc, acc, vec3(a_Random2.x, a_Random2.y, a_Random2.z));\n #endif\n #endif\n #endif\n return acc;\n}\n\nvoid main() {\n float age = renderer_CurrentTime - a_DirectionTime.w;\n float lifetime = a_ShapePositionStartLifeTime.w;\n float normalizedAge = age / lifetime;\n // Clamp to age on the first TF pass: particles emitted mid-frame have age < dt,\n // so using the full dt would over-integrate. Subsequent passes are unaffected (age >= dt).\n float dt = min(renderer_DeltaTime, age);\n\n // normalizedAge < 0.0: stale TF slot whose startTime is from a previous playback (e.g. after StopEmittingAndClear).\n if (normalizedAge >= 1.0 || normalizedAge < 0.0) {\n v_FeedbackPosition = a_FeedbackPosition;\n v_FeedbackVelocity = a_FeedbackVelocity;\n gl_Position = vec4(0.0);\n return;\n }\n\n vec4 worldRotation;\n if (renderer_SimulationSpace == 0) {\n worldRotation = renderer_WorldRotation;\n } else {\n worldRotation = a_SimulationWorldRotation;\n }\n vec4 invWorldRotation = quaternionConjugate(worldRotation);\n\n // Read previous frame state (initialized by CPU on particle birth)\n vec3 localVelocity = a_FeedbackVelocity;\n\n // =====================================================\n // Step 1: Apply velocity module deltas (VOL + FOL + Gravity)\n // =====================================================\n\n // Gravity (world space)\n vec3 gravityDelta = renderer_Gravity * a_Random0.x * dt;\n\n // VOL instantaneous velocity (animated velocity, not persisted)\n vec3 volLocal = vec3(0.0);\n vec3 volWorld = vec3(0.0);\n #ifdef _VOL_MODULE_ENABLED\n vec3 vol = getVOLVelocity(normalizedAge);\n if (renderer_VOLSpace == 0) {\n volLocal = vol;\n } else {\n volWorld = vol;\n }\n #endif\n\n // FOL acceleration → velocity delta (always persisted, like gravity)\n vec3 folDeltaLocal = vec3(0.0);\n #ifdef _FOL_MODULE_ENABLED\n vec3 folAcc = getFOLAcceleration(normalizedAge);\n vec3 folVelDelta = folAcc * dt;\n if (renderer_FOLSpace == 0) {\n folDeltaLocal = folVelDelta;\n } else {\n // World FOL: convert to local and persist, same as gravity\n folDeltaLocal = rotationByQuaternions(folVelDelta, invWorldRotation);\n }\n #endif\n\n // Gravity and FOL contribute to base velocity (persisted, subject to dampen/drag).\n vec3 gravityLocal = rotationByQuaternions(gravityDelta, invWorldRotation);\n localVelocity += folDeltaLocal + gravityLocal;\n\n // =====================================================\n // Step 2 & 3: Dampen (Limit Velocity) + Drag\n // VOL must be projected into the LVL target space so that\n // limit/drag see the full velocity regardless of VOL.space vs LVL.space.\n // =====================================================\n #ifdef RENDERER_LVL_MODULE_ENABLED\n // Precompute VOL in both spaces\n vec3 volAsLocal = volLocal + rotationByQuaternions(volWorld, invWorldRotation);\n vec3 volAsWorld = rotationByQuaternions(volLocal, worldRotation) + volWorld;\n\n float limitRand = a_Random2.w;\n float dampen = renderer_LVLDampen;\n // Frame-rate independent dampen (30fps as reference)\n float effectiveDampen = 1.0 - pow(1.0 - dampen, dt * 30.0);\n\n if (renderer_LVLSpace == 0) {\n // Local space: total = base + all VOL projected to local\n vec3 totalLocal = localVelocity + volAsLocal;\n vec3 dampenedTotal = applyLVLSpeedLimitTF(totalLocal, normalizedAge, limitRand, effectiveDampen);\n localVelocity = dampenedTotal - volAsLocal;\n } else {\n // World space: total = rotated base + all VOL projected to world\n vec3 totalWorld = rotationByQuaternions(localVelocity, worldRotation) + volAsWorld;\n vec3 dampenedTotal = applyLVLSpeedLimitTF(totalWorld, normalizedAge, limitRand, effectiveDampen);\n localVelocity = rotationByQuaternions(dampenedTotal - volAsWorld, invWorldRotation);\n }\n\n // Drag: same space as dampen\n {\n float dragCoeff = evaluateLVLDrag(normalizedAge, a_Random2.w);\n if (dragCoeff > 0.0) {\n vec3 totalVel;\n if (renderer_LVLSpace == 0) {\n totalVel = localVelocity + volAsLocal;\n } else {\n totalVel = rotationByQuaternions(localVelocity, worldRotation) + volAsWorld;\n }\n float velMagSqr = dot(totalVel, totalVel);\n float velMag = sqrt(velMagSqr);\n\n float drag = dragCoeff;\n\n #ifdef RENDERER_LVL_DRAG_MULTIPLY_SIZE\n float maxDim = max(a_StartSize.x, max(a_StartSize.y, a_StartSize.z));\n float radius = maxDim * 0.5;\n drag *= 3.14159265 * radius * radius;\n #endif\n\n #ifdef RENDERER_LVL_DRAG_MULTIPLY_VELOCITY\n drag *= velMagSqr;\n #endif\n\n if (velMag > 0.0) {\n float newVelMag = max(0.0, velMag - drag * dt);\n vec3 draggedTotal = totalVel * (newVelMag / velMag);\n if (renderer_LVLSpace == 0) {\n localVelocity = draggedTotal - volAsLocal;\n } else {\n localVelocity = rotationByQuaternions(draggedTotal - volAsWorld, invWorldRotation);\n }\n }\n }\n }\n #endif\n\n // =====================================================\n // Step 4: Integrate position in simulation space\n // Local mode: position in local space, velocity rotated to local\n // World mode: position in world space, velocity rotated to world\n // =====================================================\n // FOL is now fully in localVelocity (both local and world-space FOL).\n // Only VOL overlay needs to be added here.\n vec3 totalVelocity;\n if (renderer_SimulationSpace == 0) {\n // Local: integrate in local space\n totalVelocity = localVelocity + volLocal\n + rotationByQuaternions(volWorld, invWorldRotation);\n } else {\n // World: integrate in world space\n totalVelocity = rotationByQuaternions(localVelocity + volLocal, worldRotation) + volWorld;\n }\n vec3 position = a_FeedbackPosition + totalVelocity * dt;\n\n v_FeedbackPosition = position;\n v_FeedbackVelocity = localVelocity;\n gl_Position = vec4(0.0);\n}\n"; // eslint-disable-line
9897
+ var noise_module = "#ifdef RENDERER_NOISE_MODULE_ENABLED\n\n#include <noise_common>\n#include <noise_simplex_3D>\n\nuniform vec4 renderer_NoiseParams; // xyz = strength (constant mode only), w = frequency\nuniform vec4 renderer_NoiseOctaveParams; // x = scrollSpeed, y = octaveCount, z = octaveIntensityMultiplier, w = octaveFrequencyMultiplier\n\n#ifdef RENDERER_NOISE_STRENGTH_CURVE\n uniform vec2 renderer_NoiseStrengthMaxCurveX[4];\n #ifdef RENDERER_NOISE_IS_SEPARATE\n uniform vec2 renderer_NoiseStrengthMaxCurveY[4];\n uniform vec2 renderer_NoiseStrengthMaxCurveZ[4];\n #endif\n #ifdef RENDERER_NOISE_STRENGTH_IS_RANDOM_TWO\n uniform vec2 renderer_NoiseStrengthMinCurveX[4];\n #ifdef RENDERER_NOISE_IS_SEPARATE\n uniform vec2 renderer_NoiseStrengthMinCurveY[4];\n uniform vec2 renderer_NoiseStrengthMinCurveZ[4];\n #endif\n #endif\n#else\n #ifdef RENDERER_NOISE_STRENGTH_IS_RANDOM_TWO\n uniform vec3 renderer_NoiseStrengthMinConst;\n #endif\n#endif\n\nvec3 sampleSimplexNoise3D(vec3 coord) {\n float axisOffset = 100.0;\n return vec3(\n simplex(vec3(coord.z, coord.y, coord.x)),\n simplex(vec3(coord.x + axisOffset, coord.z, coord.y)),\n simplex(vec3(coord.y, coord.x + axisOffset, coord.z))\n );\n}\n\nvec3 computeNoiseDisplacement(vec3 currentPosition, float normalizedAge) {\n vec3 coord = currentPosition * renderer_NoiseParams.w\n + vec3(renderer_CurrentTime * renderer_NoiseOctaveParams.x);\n\n int octaveCount = int(renderer_NoiseOctaveParams.y);\n float octaveIntensityMultiplier = renderer_NoiseOctaveParams.z;\n float octaveFrequencyMultiplier = renderer_NoiseOctaveParams.w;\n\n vec3 noiseValue = sampleSimplexNoise3D(coord);\n float totalAmplitude = 1.0;\n\n // Unrolled octave loop (GLSL ES 1.0 requires constant loop bounds)\n if (octaveCount >= 2) {\n float amplitude = octaveIntensityMultiplier;\n totalAmplitude += amplitude;\n noiseValue += amplitude * sampleSimplexNoise3D(coord * octaveFrequencyMultiplier);\n\n if (octaveCount >= 3) {\n amplitude *= octaveIntensityMultiplier;\n totalAmplitude += amplitude;\n noiseValue += amplitude * sampleSimplexNoise3D(coord * octaveFrequencyMultiplier * octaveFrequencyMultiplier);\n }\n }\n\n // Evaluate strength (supports Constant, TwoConstants, Curve, TwoCurves).\n vec3 strength;\n #ifdef RENDERER_NOISE_STRENGTH_CURVE\n float sx = evaluateParticleCurve(renderer_NoiseStrengthMaxCurveX, normalizedAge);\n #ifdef RENDERER_NOISE_STRENGTH_IS_RANDOM_TWO\n sx = mix(evaluateParticleCurve(renderer_NoiseStrengthMinCurveX, normalizedAge), sx, a_Random0.z);\n #endif\n #ifdef RENDERER_NOISE_IS_SEPARATE\n float sy = evaluateParticleCurve(renderer_NoiseStrengthMaxCurveY, normalizedAge);\n float sz = evaluateParticleCurve(renderer_NoiseStrengthMaxCurveZ, normalizedAge);\n #ifdef RENDERER_NOISE_STRENGTH_IS_RANDOM_TWO\n sy = mix(evaluateParticleCurve(renderer_NoiseStrengthMinCurveY, normalizedAge), sy, a_Random0.z);\n sz = mix(evaluateParticleCurve(renderer_NoiseStrengthMinCurveZ, normalizedAge), sz, a_Random0.z);\n #endif\n strength = vec3(sx, sy, sz);\n #else\n strength = vec3(sx);\n #endif\n #else\n strength = renderer_NoiseParams.xyz;\n #ifdef RENDERER_NOISE_STRENGTH_IS_RANDOM_TWO\n strength = mix(renderer_NoiseStrengthMinConst, strength, a_Random0.z);\n #endif\n #endif\n\n return (noiseValue / totalAmplitude) * strength;\n}\n\n#endif\n"; // eslint-disable-line
9898
+ var particle_feedback_simulation = "// Transform Feedback update shader for particle simulation.\n// Update order: VOL/FOL → Dampen → Drag → Position.\n// Runs once per particle per frame (no rasterization).\n\n// Previous frame TF data\nattribute vec3 a_FeedbackPosition;\nattribute vec3 a_FeedbackVelocity;\n\n// Per-particle instance data\nattribute vec4 a_ShapePositionStartLifeTime;\nattribute vec4 a_DirectionTime;\nattribute vec3 a_StartSize;\nattribute float a_StartSpeed;\nattribute vec4 a_Random0;\nattribute vec4 a_Random1;\nattribute vec3 a_SimulationWorldPosition;\nattribute vec4 a_SimulationWorldRotation;\nattribute vec4 a_Random2;\n\n// Uniforms\nuniform float renderer_CurrentTime;\nuniform float renderer_DeltaTime;\nuniform vec3 renderer_Gravity;\nuniform vec2 renderer_LVLDragConstant;\nuniform vec3 renderer_WorldPosition;\nuniform vec4 renderer_WorldRotation;\nuniform int renderer_SimulationSpace;\n\n// TF outputs\nvarying vec3 v_FeedbackPosition;\nvarying vec3 v_FeedbackVelocity;\n\n#include <particle_common>\n#include <velocity_over_lifetime_module>\n#include <force_over_lifetime_module>\n#include <limit_velocity_over_lifetime_module>\n#include <noise_module>\n\n// Get VOL instantaneous velocity at normalizedAge\nvec3 getVOLVelocity(float normalizedAge) {\n vec3 vel = vec3(0.0);\n #ifdef _VOL_MODULE_ENABLED\n #ifdef RENDERER_VOL_CONSTANT_MODE\n vel = renderer_VOLMaxConst;\n #ifdef RENDERER_VOL_IS_RANDOM_TWO\n vel = mix(renderer_VOLMinConst, vel, a_Random1.yzw);\n #endif\n #endif\n #ifdef RENDERER_VOL_CURVE_MODE\n vel = vec3(\n evaluateParticleCurve(renderer_VOLMaxGradientX, normalizedAge),\n evaluateParticleCurve(renderer_VOLMaxGradientY, normalizedAge),\n evaluateParticleCurve(renderer_VOLMaxGradientZ, normalizedAge)\n );\n #ifdef RENDERER_VOL_IS_RANDOM_TWO\n vec3 minVel = vec3(\n evaluateParticleCurve(renderer_VOLMinGradientX, normalizedAge),\n evaluateParticleCurve(renderer_VOLMinGradientY, normalizedAge),\n evaluateParticleCurve(renderer_VOLMinGradientZ, normalizedAge)\n );\n vel = mix(minVel, vel, a_Random1.yzw);\n #endif\n #endif\n #endif\n return vel;\n}\n\n// Get FOL instantaneous acceleration at normalizedAge\nvec3 getFOLAcceleration(float normalizedAge) {\n vec3 acc = vec3(0.0);\n #ifdef _FOL_MODULE_ENABLED\n #ifdef RENDERER_FOL_CONSTANT_MODE\n acc = renderer_FOLMaxConst;\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n acc = mix(renderer_FOLMinConst, acc, vec3(a_Random2.x, a_Random2.y, a_Random2.z));\n #endif\n #endif\n #ifdef RENDERER_FOL_CURVE_MODE\n acc = vec3(\n evaluateParticleCurve(renderer_FOLMaxGradientX, normalizedAge),\n evaluateParticleCurve(renderer_FOLMaxGradientY, normalizedAge),\n evaluateParticleCurve(renderer_FOLMaxGradientZ, normalizedAge)\n );\n #ifdef RENDERER_FOL_IS_RANDOM_TWO\n vec3 minAcc = vec3(\n evaluateParticleCurve(renderer_FOLMinGradientX, normalizedAge),\n evaluateParticleCurve(renderer_FOLMinGradientY, normalizedAge),\n evaluateParticleCurve(renderer_FOLMinGradientZ, normalizedAge)\n );\n acc = mix(minAcc, acc, vec3(a_Random2.x, a_Random2.y, a_Random2.z));\n #endif\n #endif\n #endif\n return acc;\n}\n\nvoid main() {\n float age = renderer_CurrentTime - a_DirectionTime.w;\n float lifetime = a_ShapePositionStartLifeTime.w;\n float normalizedAge = age / lifetime;\n // Clamp to age on the first TF pass: particles emitted mid-frame have age < dt,\n // so using the full dt would over-integrate. Subsequent passes are unaffected (age >= dt).\n float dt = min(renderer_DeltaTime, age);\n\n // normalizedAge < 0.0: stale TF slot whose startTime is from a previous playback (e.g. after StopEmittingAndClear).\n if (normalizedAge >= 1.0 || normalizedAge < 0.0) {\n v_FeedbackPosition = a_FeedbackPosition;\n v_FeedbackVelocity = a_FeedbackVelocity;\n gl_Position = vec4(0.0);\n return;\n }\n\n vec4 worldRotation;\n if (renderer_SimulationSpace == 0) {\n worldRotation = renderer_WorldRotation;\n } else {\n worldRotation = a_SimulationWorldRotation;\n }\n vec4 invWorldRotation = quaternionConjugate(worldRotation);\n\n // Read previous frame state (initialized by CPU on particle birth)\n vec3 localVelocity = a_FeedbackVelocity;\n\n // =====================================================\n // Step 1: Apply velocity module deltas (VOL + FOL + Gravity)\n // =====================================================\n\n // Gravity (world space)\n vec3 gravityDelta = renderer_Gravity * a_Random0.x * dt;\n\n // VOL instantaneous velocity (animated velocity, not persisted)\n vec3 volLocal = vec3(0.0);\n vec3 volWorld = vec3(0.0);\n #ifdef _VOL_MODULE_ENABLED\n vec3 vol = getVOLVelocity(normalizedAge);\n if (renderer_VOLSpace == 0) {\n volLocal = vol;\n } else {\n volWorld = vol;\n }\n #endif\n\n // FOL acceleration → velocity delta (always persisted, like gravity)\n vec3 folDeltaLocal = vec3(0.0);\n #ifdef _FOL_MODULE_ENABLED\n vec3 folAcc = getFOLAcceleration(normalizedAge);\n vec3 folVelDelta = folAcc * dt;\n if (renderer_FOLSpace == 0) {\n folDeltaLocal = folVelDelta;\n } else {\n // World FOL: convert to local and persist, same as gravity\n folDeltaLocal = rotationByQuaternions(folVelDelta, invWorldRotation);\n }\n #endif\n\n // Gravity and FOL contribute to base velocity (persisted, subject to dampen/drag).\n vec3 gravityLocal = rotationByQuaternions(gravityDelta, invWorldRotation);\n localVelocity += folDeltaLocal + gravityLocal;\n\n // =====================================================\n // Step 2 & 3: Dampen (Limit Velocity) + Drag\n // VOL must be projected into the LVL target space so that\n // limit/drag see the full velocity regardless of VOL.space vs LVL.space.\n // =====================================================\n #ifdef RENDERER_LVL_MODULE_ENABLED\n // Precompute VOL in both spaces\n vec3 volAsLocal = volLocal + rotationByQuaternions(volWorld, invWorldRotation);\n vec3 volAsWorld = rotationByQuaternions(volLocal, worldRotation) + volWorld;\n\n float limitRand = a_Random2.w;\n float dampen = renderer_LVLDampen;\n // Frame-rate independent dampen (30fps as reference)\n float effectiveDampen = 1.0 - pow(1.0 - dampen, dt * 30.0);\n\n if (renderer_LVLSpace == 0) {\n // Local space: total = base + all VOL projected to local\n vec3 totalLocal = localVelocity + volAsLocal;\n vec3 dampenedTotal = applyLVLSpeedLimitTF(totalLocal, normalizedAge, limitRand, effectiveDampen);\n localVelocity = dampenedTotal - volAsLocal;\n } else {\n // World space: total = rotated base + all VOL projected to world\n vec3 totalWorld = rotationByQuaternions(localVelocity, worldRotation) + volAsWorld;\n vec3 dampenedTotal = applyLVLSpeedLimitTF(totalWorld, normalizedAge, limitRand, effectiveDampen);\n localVelocity = rotationByQuaternions(dampenedTotal - volAsWorld, invWorldRotation);\n }\n\n // Drag: same space as dampen\n {\n float dragCoeff = evaluateLVLDrag(normalizedAge, a_Random2.w);\n if (dragCoeff > 0.0) {\n vec3 totalVel;\n if (renderer_LVLSpace == 0) {\n totalVel = localVelocity + volAsLocal;\n } else {\n totalVel = rotationByQuaternions(localVelocity, worldRotation) + volAsWorld;\n }\n float velMagSqr = dot(totalVel, totalVel);\n float velMag = sqrt(velMagSqr);\n\n float drag = dragCoeff;\n\n #ifdef RENDERER_LVL_DRAG_MULTIPLY_SIZE\n float maxDim = max(a_StartSize.x, max(a_StartSize.y, a_StartSize.z));\n float radius = maxDim * 0.5;\n drag *= 3.14159265 * radius * radius;\n #endif\n\n #ifdef RENDERER_LVL_DRAG_MULTIPLY_VELOCITY\n drag *= velMagSqr;\n #endif\n\n if (velMag > 0.0) {\n float newVelMag = max(0.0, velMag - drag * dt);\n vec3 draggedTotal = totalVel * (newVelMag / velMag);\n if (renderer_LVLSpace == 0) {\n localVelocity = draggedTotal - volAsLocal;\n } else {\n localVelocity = rotationByQuaternions(draggedTotal - volAsWorld, invWorldRotation);\n }\n }\n }\n }\n #endif\n\n // =====================================================\n // Step 4: Integrate position in simulation space\n // Local mode: position in local space, velocity rotated to local\n // World mode: position in world space, velocity rotated to world\n // =====================================================\n // FOL is now fully in localVelocity (both local and world-space FOL).\n // VOL and Noise overlays are added here (not persisted).\n\n vec3 totalVelocity;\n if (renderer_SimulationSpace == 0) {\n totalVelocity = localVelocity + volLocal + rotationByQuaternions(volWorld, invWorldRotation);\n } else {\n totalVelocity = rotationByQuaternions(localVelocity + volLocal, worldRotation) + volWorld;\n }\n #ifdef RENDERER_NOISE_MODULE_ENABLED\n // Noise velocity overlay (not persisted)\n // computeNoiseDisplacement returns noise * strength (position-scale)\n // Dividing by lifetime converts to velocity so that integration over lifetime\n // recovers the original displacement magnitude\n // Use analytical base position (birth + initial velocity * age) instead of\n // a_FeedbackPosition to avoid feedback loop: position → noise → velocity → position\n vec3 noiseBasePos;\n if (renderer_SimulationSpace == 0) {\n noiseBasePos = a_ShapePositionStartLifeTime.xyz + a_DirectionTime.xyz * a_StartSpeed * age;\n } else {\n noiseBasePos = rotationByQuaternions(\n a_ShapePositionStartLifeTime.xyz + a_DirectionTime.xyz * a_StartSpeed * age,\n worldRotation) + a_SimulationWorldPosition;\n }\n totalVelocity += computeNoiseDisplacement(noiseBasePos, normalizedAge) / lifetime;\n #endif\n vec3 position = a_FeedbackPosition + totalVelocity * dt;\n\n v_FeedbackPosition = position;\n v_FeedbackVelocity = localVelocity;\n gl_Position = vec4(0.0);\n}\n"; // eslint-disable-line
9892
9899
  var sphere_billboard = "#ifdef RENDERER_MODE_SPHERE_BILLBOARD\n\tvec2 corner = a_CornerTextureCoordinate.xy + renderer_PivotOffset.xy;\n\tvec3 sideVector = normalize(cross(camera_Forward, camera_Up));\n\tvec3 upVector = normalize(cross(sideVector, camera_Forward));\n\tcorner *= computeParticleSizeBillboard(a_StartSize.xy, normalizedAge);\n #if defined(RENDERER_ROL_CONSTANT_MODE) || defined(RENDERER_ROL_CURVE_MODE)\n if (renderer_ThreeDStartRotation) {\n vec3 rotation = radians(vec3(a_StartRotation0.xy, computeParticleRotationFloat(a_StartRotation0.z, age, normalizedAge)));\n center += renderer_SizeScale.xzy * rotationByEuler(corner.x * sideVector + corner.y * upVector, rotation);\n } else {\n float rot = radians(computeParticleRotationFloat(a_StartRotation0.x, age, normalizedAge));\n float c = cos(rot);\n float s = sin(rot);\n mat2 rotation = mat2(c, -s, s, c);\n corner = rotation * corner;\n center += renderer_SizeScale.xzy * (corner.x * sideVector + corner.y * upVector);\n }\n #else\n if (renderer_ThreeDStartRotation) {\n center += renderer_SizeScale.xzy * rotationByEuler(corner.x * sideVector + corner.y * upVector, radians(a_StartRotation0));\n } else {\n float c = cos(radians(a_StartRotation0.x));\n float s = sin(radians(a_StartRotation0.x));\n mat2 rotation = mat2(c, -s, s, c);\n corner = rotation * corner;\n center += renderer_SizeScale.xzy * (corner.x * sideVector + corner.y * upVector);\n }\n #endif\n#endif"; // eslint-disable-line
9893
9900
  var stretched_billboard = "#ifdef RENDERER_MODE_STRETCHED_BILLBOARD\n\tvec2 corner = a_CornerTextureCoordinate.xy + renderer_PivotOffset.xy;\n\tvec3 velocity = rotationByQuaternions(renderer_SizeScale * localVelocity, worldRotation) + worldVelocity;\n\tvec3 cameraUpVector = normalize(velocity);\n\tvec3 direction = normalize(center - camera_Position);\n\tvec3 sideVector = normalize(cross(direction, normalize(velocity)));\n\n\tsideVector = renderer_SizeScale.xzy * sideVector;\n\tcameraUpVector = length(vec3(renderer_SizeScale.x, 0.0, 0.0)) * cameraUpVector;\n\n\tvec2 size = computeParticleSizeBillboard(a_StartSize.xy, normalizedAge);\n\n\tconst mat2 rotationZHalfPI = mat2(0.0, -1.0, 1.0, 0.0);\n\tcorner = rotationZHalfPI * corner;\n\tcorner.y = corner.y - abs(corner.y);\n\n\tfloat speed = length(velocity); // TODO:\n\tcenter += sign(renderer_SizeScale.x) * (sign(renderer_StretchedBillboardLengthScale) * size.x * corner.x * sideVector\n\t + (speed * renderer_StretchedBillboardSpeedScale + size.y * renderer_StretchedBillboardLengthScale) * corner.y * cameraUpVector);\n#endif"; // eslint-disable-line
9894
9901
  var vertical_billboard = "#ifdef RENDERER_MODE_VERTICAL_BILLBOARD\n\tvec2 corner = a_CornerTextureCoordinate.xy + renderer_PivotOffset.xy; // Billboard模式z轴无效\n\tconst vec3 cameraUpVector = vec3(0.0, 1.0, 0.0);\n\tvec3 sideVector = normalize(cross(camera_Forward, cameraUpVector));\n\n\tfloat rot = radians(computeParticleRotationFloat(a_StartRotation0.x, age, normalizedAge));\n\tfloat c = cos(rot);\n\tfloat s = sin(rot);\n\tmat2 rotation = mat2(c, -s, s, c);\n\tcorner = rotation * corner * cos(0.78539816339744830961566084581988); // TODO:临时缩小cos45,不确定U3D原因\n\tcorner *= computeParticleSizeBillboard(a_StartSize.xy, normalizedAge);\n\tcenter += renderer_SizeScale.xzy * (corner.x * sideVector + corner.y * cameraUpVector);\n#endif"; // eslint-disable-line
@@ -9903,6 +9910,7 @@
9903
9910
  texture_sheet_animation_module: texture_sheet_animation_module,
9904
9911
  force_over_lifetime_module: force_over_lifetime_module,
9905
9912
  limit_velocity_over_lifetime_module: limit_velocity_over_lifetime_module,
9913
+ noise_module: noise_module,
9906
9914
  particle_feedback_simulation: particle_feedback_simulation,
9907
9915
  sphere_billboard: sphere_billboard,
9908
9916
  stretched_billboard: stretched_billboard,
@@ -10742,26 +10750,483 @@
10742
10750
  return ShaderProgram;
10743
10751
  }();
10744
10752
  ShaderProgram._counter = 0;
10753
+ function _array_like_to_array$2(arr, len) {
10754
+ if (len == null || len > arr.length) len = arr.length;
10755
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
10756
+ return arr2;
10757
+ }
10758
+ function _unsupported_iterable_to_array$2(o, minLen) {
10759
+ if (!o) return;
10760
+ if (typeof o === "string") return _array_like_to_array$2(o, minLen);
10761
+ var n = Object.prototype.toString.call(o).slice(8, -1);
10762
+ if (n === "Object" && o.constructor) n = o.constructor.name;
10763
+ if (n === "Map" || n === "Set") return Array.from(n);
10764
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$2(o, minLen);
10765
+ }
10766
+ function _create_for_of_iterator_helper_loose$2(o, allowArrayLike) {
10767
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
10768
+ if (it) return (it = it.call(o)).next.bind(it);
10769
+ // Fallback for engines without symbol support
10770
+ if (Array.isArray(o) || (it = _unsupported_iterable_to_array$2(o)) || allowArrayLike && o && typeof o.length === "number") {
10771
+ if (it) o = it;
10772
+ var i = 0;
10773
+ return function() {
10774
+ if (i >= o.length) return {
10775
+ done: true
10776
+ };
10777
+ return {
10778
+ done: false,
10779
+ value: o[i++]
10780
+ };
10781
+ };
10782
+ }
10783
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
10784
+ }
10785
+ /**
10786
+ * Directive types for shader preprocessor instructions.
10787
+ */ var ShaderPreprocessorDirective = /*#__PURE__*/ function(ShaderPreprocessorDirective) {
10788
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["Text"] = 0] = "Text";
10789
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["IfDef"] = 1] = "IfDef";
10790
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["IfNdef"] = 2] = "IfNdef";
10791
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["IfCmp"] = 3] = "IfCmp";
10792
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["IfExpr"] = 4] = "IfExpr";
10793
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["Else"] = 5] = "Else";
10794
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["Endif"] = 6] = "Endif";
10795
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["Define"] = 7] = "Define";
10796
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["DefineVal"] = 8] = "DefineVal";
10797
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["DefineFunc"] = 9] = "DefineFunc";
10798
+ ShaderPreprocessorDirective[ShaderPreprocessorDirective["Undef"] = 10] = "Undef";
10799
+ return ShaderPreprocessorDirective;
10800
+ }({});
10801
+ /**
10802
+ * @internal
10803
+ */ var ShaderMacroProcessor = /*#__PURE__*/ function() {
10804
+ function ShaderMacroProcessor() {}
10805
+ /**
10806
+ * Evaluate a flat instruction array with active macros.
10807
+ * Macros are expanded immediately when text chunks are collected,
10808
+ * using the current macro state at that point (conforming to GLSL/C99 §6.10 standard).
10809
+ * @param instructions - Pre-parsed instruction array
10810
+ * @param macros - Active runtime macros
10811
+ * @returns Pure GLSL string with all conditionals resolved and macros expanded
10812
+ */ ShaderMacroProcessor.evaluate = function evaluate(instructions, macros) {
10813
+ var valueMacros = ShaderMacroProcessor._valueMacros;
10814
+ var funcMacros = ShaderMacroProcessor._funcMacros;
10815
+ var shaderChunks = ShaderMacroProcessor._shaderChunks;
10816
+ valueMacros.clear();
10817
+ funcMacros.clear();
10818
+ shaderChunks.length = 0;
10819
+ for(var _iterator = _create_for_of_iterator_helper_loose$2(macros), _step; !(_step = _iterator()).done;){
10820
+ var _step_value = _step.value, name = _step_value[0], value = _step_value[1];
10821
+ valueMacros.set(name, value);
10822
+ }
10823
+ ShaderMacroProcessor._macroFirstCharsDirty = true;
10824
+ var index = 0;
10825
+ var length = instructions.length;
10826
+ while(index < length){
10827
+ var instruction = instructions[index];
10828
+ switch(instruction[0]){
10829
+ case ShaderPreprocessorDirective.Text:
10830
+ // Immediately expand macros using current macro state (GLSL/C99 conformant)
10831
+ shaderChunks.push(ShaderMacroProcessor._expandChunk(instruction[1], valueMacros, funcMacros));
10832
+ index++;
10833
+ break;
10834
+ case ShaderPreprocessorDirective.IfDef:
10835
+ {
10836
+ var name1 = instruction[1];
10837
+ index = valueMacros.has(name1) || funcMacros.has(name1) ? index + 1 : instruction[2];
10838
+ break;
10839
+ }
10840
+ case ShaderPreprocessorDirective.IfNdef:
10841
+ {
10842
+ var name2 = instruction[1];
10843
+ index = !valueMacros.has(name2) && !funcMacros.has(name2) ? index + 1 : instruction[2];
10844
+ break;
10845
+ }
10846
+ case ShaderPreprocessorDirective.IfCmp:
10847
+ {
10848
+ var name3 = instruction[1];
10849
+ var val = valueMacros.get(name3);
10850
+ var matched = val !== undefined && ShaderMacroProcessor._compareValues(Number(val) || 0, instruction[2], instruction[3]);
10851
+ index = matched ? index + 1 : instruction[4];
10852
+ break;
10853
+ }
10854
+ case ShaderPreprocessorDirective.IfExpr:
10855
+ index = ShaderMacroProcessor._evalCondition(instruction[1], valueMacros, funcMacros) ? index + 1 : instruction[2];
10856
+ break;
10857
+ case ShaderPreprocessorDirective.Else:
10858
+ index = instruction[1];
10859
+ break;
10860
+ case ShaderPreprocessorDirective.Endif:
10861
+ index++;
10862
+ break;
10863
+ case ShaderPreprocessorDirective.Define:
10864
+ valueMacros.set(instruction[1], "");
10865
+ index++;
10866
+ break;
10867
+ case ShaderPreprocessorDirective.DefineVal:
10868
+ valueMacros.set(instruction[1], instruction[2]);
10869
+ ShaderMacroProcessor._macroFirstCharsDirty = true;
10870
+ index++;
10871
+ break;
10872
+ case ShaderPreprocessorDirective.DefineFunc:
10873
+ funcMacros.set(instruction[1], {
10874
+ params: instruction[2],
10875
+ body: instruction[3]
10876
+ });
10877
+ ShaderMacroProcessor._macroFirstCharsDirty = true;
10878
+ index++;
10879
+ break;
10880
+ case ShaderPreprocessorDirective.Undef:
10881
+ valueMacros.delete(instruction[1]);
10882
+ funcMacros.delete(instruction[1]);
10883
+ index++;
10884
+ break;
10885
+ default:
10886
+ index++;
10887
+ break;
10888
+ }
10889
+ }
10890
+ return ShaderMacroProcessor._concatChunks(shaderChunks);
10891
+ };
10892
+ /**
10893
+ * Expand macros in a single text chunk using the current macro state.
10894
+ * Returns the chunk as-is if no expandable macros exist.
10895
+ */ ShaderMacroProcessor._expandChunk = function _expandChunk(chunk, valueMacros, funcMacros) {
10896
+ // Fast path: no expandable macros at this point
10897
+ if (funcMacros.size === 0) {
10898
+ var hasExpandable = false;
10899
+ for(var _iterator = _create_for_of_iterator_helper_loose$2(valueMacros), _step; !(_step = _iterator()).done;){
10900
+ var _step_value = _step.value, val = _step_value[1];
10901
+ if (val !== "") {
10902
+ hasExpandable = true;
10903
+ break;
10904
+ }
10905
+ }
10906
+ if (!hasExpandable) return chunk;
10907
+ }
10908
+ // Rebuild first-char filter if macros changed
10909
+ if (ShaderMacroProcessor._macroFirstCharsDirty) {
10910
+ var macroFirstChars = ShaderMacroProcessor._macroFirstChars;
10911
+ macroFirstChars.clear();
10912
+ for(var _iterator1 = _create_for_of_iterator_helper_loose$2(valueMacros.keys()), _step1; !(_step1 = _iterator1()).done;){
10913
+ var name = _step1.value;
10914
+ macroFirstChars.add(name.charCodeAt(0));
10915
+ }
10916
+ for(var _iterator2 = _create_for_of_iterator_helper_loose$2(funcMacros.keys()), _step2; !(_step2 = _iterator2()).done;){
10917
+ var name1 = _step2.value;
10918
+ macroFirstChars.add(name1.charCodeAt(0));
10919
+ }
10920
+ ShaderMacroProcessor._macroFirstCharsDirty = false;
10921
+ }
10922
+ var macroFirstChars1 = ShaderMacroProcessor._macroFirstChars;
10923
+ var expandedNames = ShaderMacroProcessor._expandedNames;
10924
+ var out = ShaderMacroProcessor._out;
10925
+ out.length = 0;
10926
+ var len = chunk.length;
10927
+ var i = 0;
10928
+ while(i < len){
10929
+ var cc = chunk.charCodeAt(i);
10930
+ if (ShaderMacroProcessor._isIdentifierStart(cc)) {
10931
+ var start = i;
10932
+ i++;
10933
+ while(i < len && ShaderMacroProcessor._isIdentifierPart(chunk.charCodeAt(i)))i++;
10934
+ // Fast path: first char not in any macro name
10935
+ if (!macroFirstChars1.has(chunk.charCodeAt(start))) {
10936
+ out.push(chunk.substring(start, i));
10937
+ continue;
10938
+ }
10939
+ var name2 = chunk.substring(start, i);
10940
+ // Try function macro
10941
+ var func = funcMacros.get(name2);
10942
+ if (func) {
10943
+ var lookAhead = i;
10944
+ while(lookAhead < len && (chunk.charCodeAt(lookAhead) === 32 /* space */ || chunk.charCodeAt(lookAhead) === 9))lookAhead++;
10945
+ if (lookAhead < len && chunk.charCodeAt(lookAhead) === 40 /* '(' */ ) {
10946
+ var args = ShaderMacroProcessor._parseFuncArgs(chunk, lookAhead);
10947
+ if (args) {
10948
+ i = args.end;
10949
+ var expanded = ShaderMacroProcessor._expandFuncBody(func, args.values);
10950
+ expandedNames.clear();
10951
+ expandedNames.add(name2);
10952
+ out.push(ShaderMacroProcessor._recursiveExpandMacro(expanded, valueMacros, funcMacros, expandedNames));
10953
+ continue;
10954
+ }
10955
+ }
10956
+ }
10957
+ // Try value macro
10958
+ var val1 = valueMacros.get(name2);
10959
+ if (val1 !== undefined && val1 !== "") {
10960
+ expandedNames.clear();
10961
+ expandedNames.add(name2);
10962
+ out.push(ShaderMacroProcessor._recursiveExpandMacro(val1, valueMacros, funcMacros, expandedNames));
10963
+ continue;
10964
+ }
10965
+ out.push(name2);
10966
+ continue;
10967
+ }
10968
+ // Batch collect non-identifier characters
10969
+ var batchStart = i;
10970
+ while(i < len && !ShaderMacroProcessor._isIdentifierStart(chunk.charCodeAt(i)))i++;
10971
+ out.push(chunk.substring(batchStart, i));
10972
+ }
10973
+ return out.join("");
10974
+ };
10975
+ /**
10976
+ * Recursively expand macro substitution results until no more macros remain.
10977
+ * @param macroExpansion - Intermediate text from a macro substitution that may contain further macro references
10978
+ * @param valueMacros - Current value macro definitions
10979
+ * @param funcMacros - Current function macro definitions
10980
+ * @param expandedNames - Macro names already on the expansion chain, prevents circular references (C99 §6.10.3.4)
10981
+ */ ShaderMacroProcessor._recursiveExpandMacro = function _recursiveExpandMacro(macroExpansion, valueMacros, funcMacros, expandedNames) {
10982
+ if (macroExpansion.length === 0) return macroExpansion;
10983
+ var len = macroExpansion.length;
10984
+ var out = [];
10985
+ var i = 0;
10986
+ while(i < len){
10987
+ var cc = macroExpansion.charCodeAt(i);
10988
+ if (ShaderMacroProcessor._isIdentifierStart(cc)) {
10989
+ var start = i;
10990
+ i++;
10991
+ while(i < len && ShaderMacroProcessor._isIdentifierPart(macroExpansion.charCodeAt(i)))i++;
10992
+ var name = macroExpansion.substring(start, i);
10993
+ // Skip already-expanded names (circular reference prevention)
10994
+ // Skip GL_ prefixed names (reserved GLSL built-ins, charCodes: G=71, L=76, _=95)
10995
+ if (expandedNames.has(name) || name.charCodeAt(0) === 71 && name.charCodeAt(1) === 76 && name.charCodeAt(2) === 95) {
10996
+ out.push(name);
10997
+ continue;
10998
+ }
10999
+ var func = funcMacros.get(name);
11000
+ if (func) {
11001
+ var lookAhead = i;
11002
+ while(lookAhead < len && (macroExpansion.charCodeAt(lookAhead) === 32 /* space */ || macroExpansion.charCodeAt(lookAhead) === 9))lookAhead++;
11003
+ if (lookAhead < len && macroExpansion.charCodeAt(lookAhead) === 40 /* '(' */ ) {
11004
+ var args = ShaderMacroProcessor._parseFuncArgs(macroExpansion, lookAhead);
11005
+ if (args) {
11006
+ i = args.end;
11007
+ expandedNames.add(name);
11008
+ out.push(ShaderMacroProcessor._recursiveExpandMacro(ShaderMacroProcessor._expandFuncBody(func, args.values), valueMacros, funcMacros, expandedNames));
11009
+ expandedNames.delete(name);
11010
+ continue;
11011
+ }
11012
+ }
11013
+ }
11014
+ var val = valueMacros.get(name);
11015
+ if (val !== undefined && val !== "") {
11016
+ expandedNames.add(name);
11017
+ out.push(ShaderMacroProcessor._recursiveExpandMacro(val, valueMacros, funcMacros, expandedNames));
11018
+ expandedNames.delete(name);
11019
+ continue;
11020
+ }
11021
+ out.push(name);
11022
+ continue;
11023
+ }
11024
+ // Batch collect non-identifier characters
11025
+ var batchStart = i;
11026
+ while(i < len && !ShaderMacroProcessor._isIdentifierStart(macroExpansion.charCodeAt(i)))i++;
11027
+ out.push(macroExpansion.substring(batchStart, i));
11028
+ }
11029
+ return out.join("");
11030
+ };
11031
+ /**
11032
+ * Substitute function macro params in body.
11033
+ */ ShaderMacroProcessor._expandFuncBody = function _expandFuncBody(func, args) {
11034
+ if (func.params.length === 0 || args.length !== func.params.length) return func.body;
11035
+ var result = func.body;
11036
+ for(var i = 0; i < func.params.length; i++){
11037
+ result = ShaderMacroProcessor._replaceWord(result, func.params[i], args[i]);
11038
+ }
11039
+ return result;
11040
+ };
11041
+ /**
11042
+ * Evaluate a compound condition tree.
11043
+ */ ShaderMacroProcessor._evalCondition = function _evalCondition(cond, valueMacros, funcMacros) {
11044
+ switch(cond.t){
11045
+ case "def":
11046
+ return valueMacros.has(cond.m) || funcMacros.has(cond.m);
11047
+ case "ndef":
11048
+ return !valueMacros.has(cond.m) && !funcMacros.has(cond.m);
11049
+ case "cmp":
11050
+ {
11051
+ var val = valueMacros.get(cond.m);
11052
+ if (val === undefined) return false;
11053
+ return ShaderMacroProcessor._compareValues(Number(val) || 0, cond.op, cond.v);
11054
+ }
11055
+ case "and":
11056
+ return ShaderMacroProcessor._evalCondition(cond.l, valueMacros, funcMacros) && ShaderMacroProcessor._evalCondition(cond.r, valueMacros, funcMacros);
11057
+ case "or":
11058
+ return ShaderMacroProcessor._evalCondition(cond.l, valueMacros, funcMacros) || ShaderMacroProcessor._evalCondition(cond.r, valueMacros, funcMacros);
11059
+ case "not":
11060
+ return !ShaderMacroProcessor._evalCondition(cond.c, valueMacros, funcMacros);
11061
+ case "bool":
11062
+ return cond.v;
11063
+ }
11064
+ };
11065
+ /**
11066
+ * Evaluate a comparison operator.
11067
+ */ ShaderMacroProcessor._compareValues = function _compareValues(numVal, op, value) {
11068
+ switch(op){
11069
+ case "==":
11070
+ return numVal === value;
11071
+ case "!=":
11072
+ return numVal !== value;
11073
+ case ">":
11074
+ return numVal > value;
11075
+ case "<":
11076
+ return numVal < value;
11077
+ case ">=":
11078
+ return numVal >= value;
11079
+ case "<=":
11080
+ return numVal <= value;
11081
+ default:
11082
+ return false;
11083
+ }
11084
+ };
11085
+ /**
11086
+ * Parse function macro call arguments.
11087
+ * Returns reusable static result object to avoid allocation.
11088
+ */ ShaderMacroProcessor._parseFuncArgs = function _parseFuncArgs(text, openParen) {
11089
+ var result = ShaderMacroProcessor._parsedFuncArgs;
11090
+ result.values.length = 0;
11091
+ var level = 1;
11092
+ var argStart = openParen + 1;
11093
+ var k = argStart;
11094
+ var len = text.length;
11095
+ while(k < len && level > 0){
11096
+ var cc = text.charCodeAt(k);
11097
+ if (cc === 40 /* '(' */ ) {
11098
+ level++;
11099
+ } else if (cc === 41 /* ')' */ ) {
11100
+ if (--level === 0) {
11101
+ var arg = text.substring(argStart, k).trim();
11102
+ if (arg.length > 0 || result.values.length > 0) result.values.push(arg);
11103
+ result.end = k + 1;
11104
+ return result;
11105
+ }
11106
+ } else if (cc === 44 /* ',' */ && level === 1) {
11107
+ result.values.push(text.substring(argStart, k).trim());
11108
+ argStart = k + 1;
11109
+ }
11110
+ k++;
11111
+ }
11112
+ return null;
11113
+ };
11114
+ /**
11115
+ * Replace all whole-word occurrences of `word` in `text` with `replacement`.
11116
+ */ ShaderMacroProcessor._replaceWord = function _replaceWord(text, word, replacement) {
11117
+ var wLen = word.length;
11118
+ var parts = ShaderMacroProcessor._replaceWordParts;
11119
+ parts.length = 0;
11120
+ var start = 0;
11121
+ var idx = text.indexOf(word, start);
11122
+ while(idx !== -1){
11123
+ if (idx > 0 && ShaderMacroProcessor._isIdentifierPart(text.charCodeAt(idx - 1))) {
11124
+ idx = text.indexOf(word, idx + 1);
11125
+ continue;
11126
+ }
11127
+ var afterIdx = idx + wLen;
11128
+ if (afterIdx < text.length && ShaderMacroProcessor._isIdentifierPart(text.charCodeAt(afterIdx))) {
11129
+ idx = text.indexOf(word, idx + 1);
11130
+ continue;
11131
+ }
11132
+ parts.push(text.substring(start, idx));
11133
+ parts.push(replacement);
11134
+ start = afterIdx;
11135
+ idx = text.indexOf(word, start);
11136
+ }
11137
+ if (start === 0) return text;
11138
+ parts.push(text.substring(start));
11139
+ return parts.join("");
11140
+ };
11141
+ /**
11142
+ * Concatenate shader chunks with consecutive blank lines collapsed to a single newline.
11143
+ */ ShaderMacroProcessor._concatChunks = function _concatChunks(shaderChunks) {
11144
+ var out = ShaderMacroProcessor._out;
11145
+ out.length = 0;
11146
+ var lastNewline = false;
11147
+ for(var p = 0; p < shaderChunks.length; p++){
11148
+ var text = shaderChunks[p];
11149
+ var len = text.length;
11150
+ var i = 0;
11151
+ while(i < len){
11152
+ if (text.charCodeAt(i) === 10 /* \n */ ) {
11153
+ if (!lastNewline) {
11154
+ out.push("\n");
11155
+ lastNewline = true;
11156
+ }
11157
+ i++;
11158
+ while(i < len){
11159
+ var c = text.charCodeAt(i);
11160
+ if (c === 32 /* space */ || c === 9 /* tab */ || c === 10 /* \n */ ) i++;
11161
+ else break;
11162
+ }
11163
+ } else {
11164
+ var batchStart = i;
11165
+ while(i < len && text.charCodeAt(i) !== 10 /* \n */ )i++;
11166
+ out.push(text.substring(batchStart, i));
11167
+ lastNewline = false;
11168
+ }
11169
+ }
11170
+ }
11171
+ return out.join("");
11172
+ };
11173
+ /**
11174
+ * Check if char code is a valid identifier start.
11175
+ * Matches: [A-Z] | [a-z] | _
11176
+ */ ShaderMacroProcessor._isIdentifierStart = function _isIdentifierStart(charCode) {
11177
+ return charCode >= 65 && charCode <= 90 || charCode >= 97 && charCode <= 122 || charCode === 95;
11178
+ };
11179
+ /**
11180
+ * Check if char code is a valid identifier part.
11181
+ * Matches: [A-Z] | [a-z] | [0-9] | _
11182
+ */ ShaderMacroProcessor._isIdentifierPart = function _isIdentifierPart(charCode) {
11183
+ return charCode >= 65 && charCode <= 90 || charCode >= 97 && charCode <= 122 || charCode >= 48 && charCode <= 57 || charCode === 95;
11184
+ };
11185
+ return ShaderMacroProcessor;
11186
+ }();
11187
+ ShaderMacroProcessor._valueMacros = new Map();
11188
+ ShaderMacroProcessor._funcMacros = new Map();
11189
+ ShaderMacroProcessor._shaderChunks = [];
11190
+ ShaderMacroProcessor._out = [];
11191
+ ShaderMacroProcessor._expandedNames = new Set();
11192
+ ShaderMacroProcessor._macroFirstChars = new Set();
11193
+ ShaderMacroProcessor._macroFirstCharsDirty = true;
11194
+ ShaderMacroProcessor._replaceWordParts = [];
11195
+ ShaderMacroProcessor._parsedFuncArgs = {
11196
+ values: [],
11197
+ end: 0
11198
+ };
10745
11199
  var precisionStr = "\n #ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n precision highp int;\n #else\n precision mediump float;\n precision mediump int;\n #endif\n ";
10746
11200
  /**
10747
11201
  * Shader pass containing vertex and fragment source.
10748
11202
  */ var ShaderPass = /*#__PURE__*/ function(ShaderPart) {
10749
11203
  _inherits$2(ShaderPass, ShaderPart);
10750
- function ShaderPass(nameOrVertexSource, vertexSourceOrFragmentSource, fragmentSourceOrTags, tags) {
11204
+ function ShaderPass(nameOrVertexSource, vertexSourceOrFragmentSourceOrInstructions, fragmentSourceOrTags, tagsOrPlatformTarget, tags) {
10751
11205
  var _this;
10752
11206
  _this = ShaderPart.call(this) || this, /** @internal */ _this._shaderPassId = 0, /** @internal */ _this._renderStateDataMap = {}, /** @internal */ _this._shaderProgramPools = [];
10753
11207
  _this._shaderPassId = ShaderPass._shaderPassCounter++;
10754
- if (typeof fragmentSourceOrTags === "string") {
11208
+ if (Array.isArray(vertexSourceOrFragmentSourceOrInstructions)) {
11209
+ // Instructions overload: (name, vertexInst, fragInst, platformTarget, tags?)
10755
11210
  _this._name = nameOrVertexSource;
10756
- _this._vertexSource = vertexSourceOrFragmentSource;
10757
- _this._fragmentSource = fragmentSourceOrTags;
11211
+ _this._vertexShaderInstructions = vertexSourceOrFragmentSourceOrInstructions;
11212
+ _this._fragmentShaderInstructions = fragmentSourceOrTags;
11213
+ _this._platformTarget = tagsOrPlatformTarget;
10758
11214
  tags = _extends$2({
10759
11215
  pipelineStage: PipelineStage.Forward
10760
11216
  }, tags);
11217
+ } else if (typeof fragmentSourceOrTags === "string") {
11218
+ // Named overload: (name, vertexSource, fragmentSource, tags?)
11219
+ _this._name = nameOrVertexSource;
11220
+ _this._vertexSource = vertexSourceOrFragmentSourceOrInstructions;
11221
+ _this._fragmentSource = fragmentSourceOrTags;
11222
+ tags = _extends$2({
11223
+ pipelineStage: PipelineStage.Forward
11224
+ }, tagsOrPlatformTarget);
10761
11225
  } else {
11226
+ // Unnamed overload: (vertexSource, fragmentSource, tags?)
10762
11227
  _this._name = "Default";
10763
11228
  _this._vertexSource = nameOrVertexSource;
10764
- _this._fragmentSource = vertexSourceOrFragmentSource;
11229
+ _this._fragmentSource = vertexSourceOrFragmentSourceOrInstructions;
10765
11230
  tags = _extends$2({
10766
11231
  pipelineStage: PipelineStage.Forward
10767
11232
  }, fragmentSourceOrTags);
@@ -10797,15 +11262,16 @@
10797
11262
  shaderProgramPools.length = 0;
10798
11263
  };
10799
11264
  _proto._getCanonicalShaderProgram = function _getCanonicalShaderProgram(engine, macroCollection) {
10800
- if (this._platformTarget != undefined) {
10801
- return this._getShaderLabProgram(engine, macroCollection);
10802
- }
10803
- var _ShaderFactory_compilePlatformSource = ShaderFactory.compilePlatformSource(engine, macroCollection, this._vertexSource, this._fragmentSource), vertexSource = _ShaderFactory_compilePlatformSource.vertexSource, fragmentSource = _ShaderFactory_compilePlatformSource.fragmentSource;
11265
+ var _ref = this._platformTarget != undefined ? this._compileShaderLabSource(engine, macroCollection) : this._compilePlatformSource(engine, macroCollection), vertexSource = _ref.vertexSource, fragmentSource = _ref.fragmentSource;
10804
11266
  return new ShaderProgram(engine, vertexSource, fragmentSource);
10805
11267
  };
10806
- _proto._getShaderLabProgram = function _getShaderLabProgram(engine, macroCollection) {
11268
+ _proto._compilePlatformSource = function _compilePlatformSource(engine, macroCollection) {
11269
+ return ShaderFactory.compilePlatformSource(engine, macroCollection, this._vertexSource, this._fragmentSource);
11270
+ };
11271
+ _proto._compileShaderLabSource = function _compileShaderLabSource(engine, macroCollection) {
10807
11272
  var isWebGL2 = engine._hardwareRenderer.isWebGL2;
10808
- var shaderMacroList = new Array();
11273
+ var shaderMacroList = ShaderPass._shaderMacroList;
11274
+ shaderMacroList.length = 0;
10809
11275
  ShaderMacro._getMacrosElements(macroCollection, shaderMacroList);
10810
11276
  shaderMacroList.push(ShaderMacro.getByName(isWebGL2 ? "GRAPHICS_API_WEBGL2" : "GRAPHICS_API_WEBGL1"));
10811
11277
  if (engine._hardwareRenderer.canIUse(GLCapabilityType.shaderTextureLod)) {
@@ -10814,23 +11280,31 @@
10814
11280
  if (engine._hardwareRenderer.canIUse(GLCapabilityType.standardDerivatives)) {
10815
11281
  shaderMacroList.push(ShaderMacro.getByName("HAS_DERIVATIVES"));
10816
11282
  }
10817
- var noIncludeVertex = ShaderFactory.parseIncludes(this._vertexSource);
10818
- var noIncludeFrag = ShaderFactory.parseIncludes(this._fragmentSource);
10819
- noIncludeVertex = Shader._shaderLab._parseMacros(noIncludeVertex, shaderMacroList);
10820
- noIncludeFrag = Shader._shaderLab._parseMacros(noIncludeFrag, shaderMacroList);
11283
+ var macroMap = ShaderPass._macroMap;
11284
+ macroMap.clear();
11285
+ for(var i = 0, n = shaderMacroList.length; i < n; i++){
11286
+ var macro = shaderMacroList[i];
11287
+ var _macro_value;
11288
+ macroMap.set(macro.name, (_macro_value = macro.value) != null ? _macro_value : "");
11289
+ }
11290
+ var vertexSource = ShaderMacroProcessor.evaluate(this._vertexShaderInstructions, macroMap);
11291
+ var fragmentSource = ShaderMacroProcessor.evaluate(this._fragmentShaderInstructions, macroMap);
10821
11292
  if (isWebGL2 && this._platformTarget === ShaderLanguage.GLSLES100) {
10822
- noIncludeVertex = ShaderFactory.convertTo300(noIncludeVertex);
10823
- noIncludeFrag = ShaderFactory.convertTo300(noIncludeFrag, true);
11293
+ vertexSource = ShaderFactory.convertTo300(vertexSource);
11294
+ fragmentSource = ShaderFactory.convertTo300(fragmentSource, true);
10824
11295
  }
10825
11296
  var versionStr = isWebGL2 ? "#version 300 es" : "#version 100";
10826
- var vertexSource = " " + versionStr + "\n " + noIncludeVertex + "\n ";
10827
- var fragmentSource = " " + versionStr + "\n " + (isWebGL2 ? "" : ShaderFactory._shaderExtension) + "\n " + precisionStr + "\n " + noIncludeFrag + "\n ";
10828
- return new ShaderProgram(engine, vertexSource, fragmentSource);
11297
+ return {
11298
+ vertexSource: " " + versionStr + "\n " + vertexSource + "\n ",
11299
+ fragmentSource: " " + versionStr + "\n " + (isWebGL2 ? "" : ShaderFactory._shaderExtension) + "\n " + precisionStr + "\n " + fragmentSource + "\n "
11300
+ };
10829
11301
  };
10830
11302
  return ShaderPass;
10831
11303
  }(ShaderPart);
10832
11304
  /** @internal */ ShaderPass._shaderPassCounter = 0;
10833
11305
  /** @internal */ ShaderPass._shaderRootPath = "shaders://root/";
11306
+ ShaderPass._shaderMacroList = [];
11307
+ ShaderPass._macroMap = new Map();
10834
11308
  /**
10835
11309
  * Sub shader.
10836
11310
  */ var SubShader = /*#__PURE__*/ function(ShaderPart) {
@@ -11571,36 +12045,14 @@
11571
12045
  var subShaderList = shaderSource.subShaders.map(function(subShaderSource) {
11572
12046
  var passList = subShaderSource.passes.map(function(passSource) {
11573
12047
  if (passSource.isUsePass) {
11574
- var _Shader_find_subShaders_find, _Shader_find;
11575
- var _passSource_name_split = passSource.name.split("/"), shaderName = _passSource_name_split[0], subShaderName = _passSource_name_split[1], passName = _passSource_name_split[2];
11576
- return (_Shader_find = Shader.find(shaderName)) == null ? void 0 : (_Shader_find_subShaders_find = _Shader_find.subShaders.find(function(subShader) {
11577
- return subShader.name === subShaderName;
11578
- })) == null ? void 0 : _Shader_find_subShaders_find.passes.find(function(pass) {
11579
- return pass.name === passName;
11580
- });
12048
+ return Shader._resolveUsePass(passSource.name);
11581
12049
  }
11582
12050
  var shaderPassSource = Shader._shaderLab._parseShaderPass(passSource.contents, passSource.vertexEntry, passSource.fragmentEntry, vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget, new URL(fragmentSourceOrPath != null ? fragmentSourceOrPath : "", ShaderPass._shaderRootPath).href);
11583
12051
  if (!shaderPassSource) {
11584
12052
  throw 'Shader pass "' + shaderSource.name + "." + subShaderSource.name + "." + passSource.name + '" parse failed, please check the shader source code.';
11585
12053
  }
11586
- var shaderPass = new ShaderPass(passSource.name, shaderPassSource.vertex, shaderPassSource.fragment, passSource.tags);
11587
- shaderPass._platformTarget = vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget;
11588
- var _passSource_renderStates = passSource.renderStates, constantMap = _passSource_renderStates.constantMap, variableMap = _passSource_renderStates.variableMap;
11589
- // Compatible shader lab no render state use material `renderState` to modify render state
11590
- if (Object.keys(constantMap).length > 0 || Object.keys(variableMap).length > 0) {
11591
- // Parse const render state
11592
- var renderState = new RenderState();
11593
- for(var k in constantMap){
11594
- Shader._applyConstRenderStates(renderState, +k, constantMap[k]);
11595
- }
11596
- shaderPass._renderState = renderState;
11597
- // Parse variable render state
11598
- var renderStateDataMap = {};
11599
- for(var k1 in variableMap){
11600
- renderStateDataMap[k1] = ShaderProperty.getByName(variableMap[k1]);
11601
- }
11602
- shaderPass._renderStateDataMap = renderStateDataMap;
11603
- }
12054
+ var shaderPass = new ShaderPass(passSource.name, shaderPassSource.vertexShaderInstructions, shaderPassSource.fragmentShaderInstructions, vertexSourceOrShaderPassesOrSubShadersOrPlatformTarget, passSource.tags);
12055
+ Shader._applyRenderStates(shaderPass, passSource.renderStates.constantMap, passSource.renderStates.variableMap, false);
11604
12056
  return shaderPass;
11605
12057
  });
11606
12058
  return new SubShader(subShaderSource.name, passList, subShaderSource.tags);
@@ -11645,6 +12097,29 @@
11645
12097
  };
11646
12098
  /**
11647
12099
  * @internal
12100
+ */ Shader._createFromPrecompiled = function _createFromPrecompiled(data) {
12101
+ var shaderMap = Shader._shaderMap;
12102
+ if (shaderMap[data.name]) {
12103
+ console.error('Shader named "' + data.name + '" already exists.');
12104
+ return;
12105
+ }
12106
+ var subShaderList = data.subShaders.map(function(subData) {
12107
+ var passList = subData.passes.map(function(passData) {
12108
+ if (passData.isUsePass) {
12109
+ return Shader._resolveUsePass(passData.name);
12110
+ }
12111
+ var shaderPass = new ShaderPass(passData.name, passData.vertexShaderInstructions, passData.fragmentShaderInstructions, data.platformTarget, passData.tags);
12112
+ Shader._applyRenderStates(shaderPass, passData.renderStates.constantMap, passData.renderStates.variableMap, true);
12113
+ return shaderPass;
12114
+ });
12115
+ return new SubShader(subData.name, passList, subData.tags);
12116
+ });
12117
+ var shader = new Shader(data.name, subShaderList);
12118
+ shaderMap[data.name] = shader;
12119
+ return shader;
12120
+ };
12121
+ /**
12122
+ * @internal
11648
12123
  */ Shader._clear = function _clear(engine) {
11649
12124
  var shaderMap = Shader._shaderMap;
11650
12125
  for(var key in shaderMap){
@@ -11665,6 +12140,34 @@
11665
12140
  }
11666
12141
  }
11667
12142
  };
12143
+ Shader._resolveUsePass = function _resolveUsePass(passName) {
12144
+ var _Shader_find_subShaders_find, _Shader_find;
12145
+ var _passName_split = passName.split("/"), shaderName = _passName_split[0], subShaderName = _passName_split[1], passNamePart = _passName_split[2];
12146
+ return (_Shader_find = Shader.find(shaderName)) == null ? void 0 : (_Shader_find_subShaders_find = _Shader_find.subShaders.find(function(subShader) {
12147
+ return subShader.name === subShaderName;
12148
+ })) == null ? void 0 : _Shader_find_subShaders_find.passes.find(function(pass) {
12149
+ return pass.name === passNamePart;
12150
+ });
12151
+ };
12152
+ Shader._applyRenderStates = function _applyRenderStates(shaderPass, constantMap, variableMap, deserializeColor) {
12153
+ if (Object.keys(constantMap).length > 0 || Object.keys(variableMap).length > 0) {
12154
+ var renderState = new RenderState();
12155
+ for(var k in constantMap){
12156
+ var value = constantMap[k];
12157
+ if (deserializeColor && Array.isArray(value)) {
12158
+ Shader._applyConstRenderStates(renderState, +k, new Color(value[0], value[1], value[2], value[3]));
12159
+ } else {
12160
+ Shader._applyConstRenderStates(renderState, +k, value);
12161
+ }
12162
+ }
12163
+ shaderPass._renderState = renderState;
12164
+ var renderStateDataMap = {};
12165
+ for(var k1 in variableMap){
12166
+ renderStateDataMap[k1] = ShaderProperty.getByName(variableMap[k1]);
12167
+ }
12168
+ shaderPass._renderStateDataMap = renderStateDataMap;
12169
+ }
12170
+ };
11668
12171
  Shader._applyConstRenderStates = function _applyConstRenderStates(renderState, key, value) {
11669
12172
  switch(key){
11670
12173
  case RenderStateElementKey.BlendStateEnabled0:
@@ -14082,7 +14585,15 @@
14082
14585
  */ _proto._getInvViewProjMat = function _getInvViewProjMat() {
14083
14586
  if (this._isInvViewProjDirty.flag) {
14084
14587
  this._isInvViewProjDirty.flag = false;
14085
- Matrix.multiply(this._entity.transform.worldMatrix, this._getInverseProjectionMatrix(), this._invViewProjMat);
14588
+ var matrix = this._invViewProjMat;
14589
+ if (this._isCustomViewMatrix) {
14590
+ Matrix.invert(this.viewMatrix, matrix);
14591
+ } else {
14592
+ // Ignore scale, consistent with viewMatrix getter
14593
+ var transform = this._entity.transform;
14594
+ Matrix.rotationTranslation(transform.worldRotationQuaternion, transform.worldPosition, matrix);
14595
+ }
14596
+ matrix.multiply(this._getInverseProjectionMatrix());
14086
14597
  }
14087
14598
  return this._invViewProjMat;
14088
14599
  };
@@ -27250,7 +27761,7 @@
27250
27761
  deepClone
27251
27762
  ], Skin.prototype, "inverseBindMatrices", void 0);
27252
27763
  __decorate$1([
27253
- ignoreClone
27764
+ deepClone
27254
27765
  ], Skin.prototype, "_skinMatrices", void 0);
27255
27766
  __decorate$1([
27256
27767
  ignoreClone
@@ -28241,7 +28752,10 @@
28241
28752
  _proto._setActiveComponents = function _setActiveComponents(isActive, activeChangeFlag) {
28242
28753
  var activeChangedComponents = this._activeChangedComponents;
28243
28754
  for(var i = 0, length = activeChangedComponents.length; i < length; ++i){
28244
- activeChangedComponents[i]._setActive(isActive, activeChangeFlag);
28755
+ var component = activeChangedComponents[i];
28756
+ // Skip components whose scene was already cleared by an earlier callback's removeChild
28757
+ if (!isActive && !component._entity._scene) continue;
28758
+ component._setActive(isActive, activeChangeFlag);
28245
28759
  }
28246
28760
  this._scene._componentsManager.putActiveChangedTempList(activeChangedComponents);
28247
28761
  this._activeChangedComponents = null;
@@ -28261,18 +28775,19 @@
28261
28775
  }
28262
28776
  };
28263
28777
  _proto._setInActiveInHierarchy = function _setInActiveInHierarchy(activeChangedComponents, activeChangeFlag) {
28778
+ // Children-first, reverse traversal for safe removeChild during callbacks
28779
+ var children = this._children;
28780
+ for(var i = children.length - 1; i >= 0; i--){
28781
+ var child = children[i];
28782
+ child.isActive && child._setInActiveInHierarchy(activeChangedComponents, activeChangeFlag);
28783
+ }
28264
28784
  activeChangeFlag & ActiveChangeFlag.Hierarchy && (this._isActiveInHierarchy = false);
28265
28785
  activeChangeFlag & ActiveChangeFlag.Scene && (this._isActiveInScene = false);
28266
28786
  var components = this._components;
28267
- for(var i = 0, n = components.length; i < n; i++){
28268
- var component = components[i];
28787
+ for(var i1 = 0, n = components.length; i1 < n; i1++){
28788
+ var component = components[i1];
28269
28789
  component.enabled && activeChangedComponents.push(component);
28270
28790
  }
28271
- var children = this._children;
28272
- for(var i1 = 0, n1 = children.length; i1 < n1; i1++){
28273
- var child = children[i1];
28274
- child.isActive && child._setInActiveInHierarchy(activeChangedComponents, activeChangeFlag);
28275
- }
28276
28791
  };
28277
28792
  _proto._setSiblingIndex = function _setSiblingIndex(sibling, target) {
28278
28793
  target = Math.min(target, sibling.length - 1);
@@ -31137,7 +31652,7 @@
31137
31652
  var depthOnlyFs = "void main() {\n}"; // eslint-disable-line
31138
31653
  var depthOnlyVs = "#define MATERIAL_OMIT_NORMAL\n#include <common>\n#include <common_vert>\n#include <blendShape_input>\nuniform mat4 camera_VPMat;\n\n\nvoid main() {\n\n #include <begin_position_vert>\n #include <blendShape_vert>\n #include <skinning_vert>\n #include <position_vert>\n\n}\n"; // eslint-disable-line
31139
31654
  var particleFs = "#include <common>\n\nvarying vec4 v_Color;\nvarying vec2 v_TextureCoordinate;\nuniform sampler2D material_BaseTexture;\nuniform vec4 material_BaseColor;\n \nuniform mediump vec3 material_EmissiveColor;\n#ifdef MATERIAL_HAS_EMISSIVETEXTURE\n uniform sampler2D material_EmissiveTexture;\n#endif\n\n#ifdef RENDERER_MODE_MESH\n\tvarying vec4 v_MeshColor;\n#endif\n\nvoid main() {\n\tvec4 color = material_BaseColor * v_Color;\n\n\t#if defined(RENDERER_MODE_MESH) && defined(RENDERER_ENABLE_VERTEXCOLOR)\n\t\tcolor *= v_MeshColor;\n\t#endif\n\n\t#ifdef MATERIAL_HAS_BASETEXTURE\n\t\tcolor *= texture2DSRGB(material_BaseTexture, v_TextureCoordinate);\n\t#endif\n\t\n\t// Emissive\n\tvec3 emissiveRadiance = material_EmissiveColor;\n\t#ifdef MATERIAL_HAS_EMISSIVETEXTURE\n\t\temissiveRadiance *= texture2DSRGB(material_EmissiveTexture, v_TextureCoordinate).rgb;\n\t#endif\n\n\tcolor.rgb += emissiveRadiance;\n\n\tgl_FragColor = color;\n}"; // eslint-disable-line
31140
- var particleVs = "#if defined(RENDERER_MODE_SPHERE_BILLBOARD) || defined(RENDERER_MODE_STRETCHED_BILLBOARD) || defined(RENDERER_MODE_HORIZONTAL_BILLBOARD) || defined(RENDERER_MODE_VERTICAL_BILLBOARD)\n attribute vec4 a_CornerTextureCoordinate;\n#endif\n\n#ifdef RENDERER_MODE_MESH\n attribute vec3 POSITION;\n #ifdef RENDERER_ENABLE_VERTEXCOLOR\n attribute vec4 COLOR_0;\n #endif\n attribute vec2 TEXCOORD_0;\n varying vec4 v_MeshColor;\n#endif\n\nattribute vec4 a_ShapePositionStartLifeTime;\nattribute vec4 a_DirectionTime;\nattribute vec4 a_StartColor;\nattribute vec3 a_StartSize;\nattribute vec3 a_StartRotation0;\nattribute float a_StartSpeed;\n\n//#if defined(COLOR_OVER_LIFETIME) || defined(RENDERER_COL_RANDOM_GRADIENTS) || defined(RENDERER_SOL_RANDOM_CURVES) || defined(RENDERER_SOL_RANDOM_CURVES_SEPARATE) || defined(ROTATION_OVER_LIFE_TIME_RANDOM_CONSTANTS) || defined(ROTATION_OVER_LIFETIME_RANDOM_CURVES)\n attribute vec4 a_Random0;\n//#endif\n\n#if defined(RENDERER_TSA_FRAME_RANDOM_CURVES) || defined(RENDERER_VOL_IS_RANDOM_TWO)\n attribute vec4 a_Random1; // x:texture sheet animation random\n#endif\n\n#if defined(RENDERER_FOL_CONSTANT_MODE) || defined(RENDERER_FOL_CURVE_MODE) || defined(RENDERER_LVL_MODULE_ENABLED)\n attribute vec4 a_Random2;\n#endif\n\nattribute vec3 a_SimulationWorldPosition;\nattribute vec4 a_SimulationWorldRotation;\n\n#ifdef RENDERER_TRANSFORM_FEEDBACK\n attribute vec3 a_FeedbackPosition;\n attribute vec3 a_FeedbackVelocity;\n#endif\n\nvarying vec4 v_Color;\n#ifdef MATERIAL_HAS_BASETEXTURE\n attribute vec4 a_SimulationUV;\n varying vec2 v_TextureCoordinate;\n#endif\n\nuniform float renderer_CurrentTime;\nuniform vec3 renderer_Gravity;\nuniform vec3 renderer_WorldPosition;\nuniform vec4 renderer_WorldRotation;\nuniform bool renderer_ThreeDStartRotation;\nuniform int renderer_ScalingMode;\nuniform vec3 renderer_PositionScale;\nuniform vec3 renderer_SizeScale;\nuniform vec3 renderer_PivotOffset;\n\nuniform mat4 camera_ViewMat;\nuniform mat4 camera_ProjMat;\n\n#ifdef RENDERER_MODE_STRETCHED_BILLBOARD\n uniform vec3 camera_Position;\n#endif\nuniform vec3 camera_Forward; // TODO:只有几种广告牌模式需要用\nuniform vec3 camera_Up;\n\nuniform float renderer_StretchedBillboardLengthScale;\nuniform float renderer_StretchedBillboardSpeedScale;\nuniform int renderer_SimulationSpace;\n\n#include <particle_common>\n#include <velocity_over_lifetime_module>\n#include <force_over_lifetime_module>\n#include <color_over_lifetime_module>\n#include <size_over_lifetime_module>\n#include <rotation_over_lifetime_module>\n#include <texture_sheet_animation_module>\n\nvec3 computeParticlePosition(in vec3 startVelocity, in float age, in float normalizedAge, vec3 gravityVelocity, vec4 worldRotation, inout vec3 localVelocity, inout vec3 worldVelocity) {\n vec3 startPosition = startVelocity * age;\n\n vec3 finalPosition;\n vec3 localPositionOffset = startPosition;\n vec3 worldPositionOffset;\n\n #ifdef _VOL_MODULE_ENABLED\n vec3 lifeVelocity; \n vec3 velocityPositionOffset = computeVelocityPositionOffset(normalizedAge, age, lifeVelocity);\n if (renderer_VOLSpace == 0) {\n localVelocity += lifeVelocity;\n localPositionOffset += velocityPositionOffset;\n } else {\n worldVelocity += lifeVelocity;\n worldPositionOffset += velocityPositionOffset;\n }\n #endif\n\n #ifdef _FOL_MODULE_ENABLED\n vec3 forceVelocity;\n vec3 forcePositionOffset = computeForcePositionOffset(normalizedAge, age, forceVelocity);\n if (renderer_FOLSpace == 0) {\n localVelocity += forceVelocity;\n localPositionOffset += forcePositionOffset;\n } else {\n worldVelocity += forceVelocity;\n worldPositionOffset += forcePositionOffset;\n }\n #endif\n\n finalPosition = rotationByQuaternions(a_ShapePositionStartLifeTime.xyz + localPositionOffset, worldRotation) + worldPositionOffset;\n\n if (renderer_SimulationSpace == 0) {\n finalPosition = finalPosition + renderer_WorldPosition;\n } else if (renderer_SimulationSpace == 1) {\n\t finalPosition = finalPosition + a_SimulationWorldPosition;\n\t}\n\n finalPosition += 0.5 * gravityVelocity * age;\n\n return finalPosition;\n}\n\nvoid main() {\n float age = renderer_CurrentTime - a_DirectionTime.w;\n float normalizedAge = age / a_ShapePositionStartLifeTime.w;\n // normalizedAge >= 0.0: skip stale TF slots whose startTime is from a previous playback (e.g. after StopEmittingAndClear).\n if (normalizedAge >= 0.0 && normalizedAge < 1.0) {\n vec4 worldRotation;\n if (renderer_SimulationSpace == 0) {\n worldRotation = renderer_WorldRotation;\n } else {\n worldRotation = a_SimulationWorldRotation;\n }\n\n vec3 localVelocity;\n vec3 worldVelocity;\n\n #ifdef RENDERER_TRANSFORM_FEEDBACK\n // Transform Feedback mode: position in simulation space (local or world).\n // Local: transform to world; World: use directly.\n vec3 center;\n if (renderer_SimulationSpace == 0) {\n center = rotationByQuaternions(a_FeedbackPosition, worldRotation) + renderer_WorldPosition;\n } else if (renderer_SimulationSpace == 1) {\n center = a_FeedbackPosition;\n }\n localVelocity = a_FeedbackVelocity;\n worldVelocity = vec3(0.0);\n\n #ifdef _VOL_MODULE_ENABLED\n vec3 instantVOLVelocity;\n computeVelocityPositionOffset(normalizedAge, age, instantVOLVelocity);\n if (renderer_VOLSpace == 0) {\n localVelocity += instantVOLVelocity;\n } else {\n worldVelocity += instantVOLVelocity;\n }\n #endif\n #else\n // Original analytical path\n vec3 startVelocity = a_DirectionTime.xyz * a_StartSpeed;\n vec3 gravityVelocity = renderer_Gravity * a_Random0.x * age;\n localVelocity = startVelocity;\n worldVelocity = gravityVelocity;\n vec3 center = computeParticlePosition(startVelocity, age, normalizedAge, gravityVelocity, worldRotation, localVelocity, worldVelocity);\n #endif\n\n #include <sphere_billboard>\n #include <stretched_billboard>\n #include <horizontal_billboard>\n #include <vertical_billboard>\n #include <particle_mesh>\n\n gl_Position = camera_ProjMat * camera_ViewMat * vec4(center, 1.0);\n v_Color = computeParticleColor(a_StartColor, normalizedAge);\n\n #ifdef MATERIAL_HAS_BASETEXTURE\n vec2 simulateUV;\n #if defined(RENDERER_MODE_SPHERE_BILLBOARD) || defined(RENDERER_MODE_STRETCHED_BILLBOARD) || defined(RENDERER_MODE_HORIZONTAL_BILLBOARD) || defined(RENDERER_MODE_VERTICAL_BILLBOARD)\n simulateUV = a_CornerTextureCoordinate.zw * a_SimulationUV.xy + a_SimulationUV.zw;\n v_TextureCoordinate = computeParticleUV(simulateUV, normalizedAge);\n #endif\n #ifdef RENDERER_MODE_MESH\n simulateUV = a_SimulationUV.zw + TEXCOORD_0 * a_SimulationUV.xy;\n v_TextureCoordinate = computeParticleUV(simulateUV, normalizedAge);\n #endif\n #endif\n } else {\n\t gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Discard use out of X(-1,1),Y(-1,1),Z(0,1)\n }\n}"; // eslint-disable-line
31655
+ var particleVs = "#if defined(RENDERER_MODE_SPHERE_BILLBOARD) || defined(RENDERER_MODE_STRETCHED_BILLBOARD) || defined(RENDERER_MODE_HORIZONTAL_BILLBOARD) || defined(RENDERER_MODE_VERTICAL_BILLBOARD)\n attribute vec4 a_CornerTextureCoordinate;\n#endif\n\n#ifdef RENDERER_MODE_MESH\n attribute vec3 POSITION;\n #ifdef RENDERER_ENABLE_VERTEXCOLOR\n attribute vec4 COLOR_0;\n #endif\n attribute vec2 TEXCOORD_0;\n varying vec4 v_MeshColor;\n#endif\n\nattribute vec4 a_ShapePositionStartLifeTime;\nattribute vec4 a_DirectionTime;\nattribute vec4 a_StartColor;\nattribute vec3 a_StartSize;\nattribute vec3 a_StartRotation0;\nattribute float a_StartSpeed;\n\n//#if defined(COLOR_OVER_LIFETIME) || defined(RENDERER_COL_RANDOM_GRADIENTS) || defined(RENDERER_SOL_RANDOM_CURVES) || defined(RENDERER_SOL_RANDOM_CURVES_SEPARATE) || defined(ROTATION_OVER_LIFE_TIME_RANDOM_CONSTANTS) || defined(ROTATION_OVER_LIFETIME_RANDOM_CURVES)\n attribute vec4 a_Random0;\n//#endif\n\n#if defined(RENDERER_TSA_FRAME_RANDOM_CURVES) || defined(RENDERER_VOL_IS_RANDOM_TWO)\n attribute vec4 a_Random1; // x:texture sheet animation random\n#endif\n\n#if defined(RENDERER_FOL_CONSTANT_MODE) || defined(RENDERER_FOL_CURVE_MODE) || defined(RENDERER_LVL_MODULE_ENABLED)\n attribute vec4 a_Random2;\n#endif\n\nattribute vec3 a_SimulationWorldPosition;\nattribute vec4 a_SimulationWorldRotation;\n\n#ifdef RENDERER_TRANSFORM_FEEDBACK\n attribute vec3 a_FeedbackPosition;\n attribute vec3 a_FeedbackVelocity;\n#endif\n\nvarying vec4 v_Color;\n#ifdef MATERIAL_HAS_BASETEXTURE\n attribute vec4 a_SimulationUV;\n varying vec2 v_TextureCoordinate;\n#endif\n\nuniform float renderer_CurrentTime;\nuniform vec3 renderer_Gravity;\nuniform vec3 renderer_WorldPosition;\nuniform vec4 renderer_WorldRotation;\nuniform bool renderer_ThreeDStartRotation;\nuniform int renderer_ScalingMode;\nuniform vec3 renderer_PositionScale;\nuniform vec3 renderer_SizeScale;\nuniform vec3 renderer_PivotOffset;\n\nuniform mat4 camera_ViewMat;\nuniform mat4 camera_ProjMat;\n\n#ifdef RENDERER_MODE_STRETCHED_BILLBOARD\n uniform vec3 camera_Position;\n#endif\nuniform vec3 camera_Forward; // TODO:只有几种广告牌模式需要用\nuniform vec3 camera_Up;\n\nuniform float renderer_StretchedBillboardLengthScale;\nuniform float renderer_StretchedBillboardSpeedScale;\nuniform int renderer_SimulationSpace;\n\n#include <particle_common>\n#include <velocity_over_lifetime_module>\n#include <force_over_lifetime_module>\n#include <color_over_lifetime_module>\n#include <size_over_lifetime_module>\n#include <rotation_over_lifetime_module>\n#include <texture_sheet_animation_module>\n#include <noise_module>\n\nvec3 computeParticlePosition(in vec3 startVelocity, in float age, in float normalizedAge, vec3 gravityVelocity, vec4 worldRotation, inout vec3 localVelocity, inout vec3 worldVelocity) {\n vec3 startPosition = startVelocity * age;\n\n vec3 finalPosition;\n vec3 localPositionOffset = startPosition;\n vec3 worldPositionOffset;\n\n #ifdef _VOL_MODULE_ENABLED\n vec3 lifeVelocity; \n vec3 velocityPositionOffset = computeVelocityPositionOffset(normalizedAge, age, lifeVelocity);\n if (renderer_VOLSpace == 0) {\n localVelocity += lifeVelocity;\n localPositionOffset += velocityPositionOffset;\n } else {\n worldVelocity += lifeVelocity;\n worldPositionOffset += velocityPositionOffset;\n }\n #endif\n\n #ifdef _FOL_MODULE_ENABLED\n vec3 forceVelocity;\n vec3 forcePositionOffset = computeForcePositionOffset(normalizedAge, age, forceVelocity);\n if (renderer_FOLSpace == 0) {\n localVelocity += forceVelocity;\n localPositionOffset += forcePositionOffset;\n } else {\n worldVelocity += forceVelocity;\n worldPositionOffset += forcePositionOffset;\n }\n #endif\n\n finalPosition = rotationByQuaternions(a_ShapePositionStartLifeTime.xyz + localPositionOffset, worldRotation) + worldPositionOffset;\n\n if (renderer_SimulationSpace == 0) {\n finalPosition = finalPosition + renderer_WorldPosition;\n } else if (renderer_SimulationSpace == 1) {\n\t finalPosition = finalPosition + a_SimulationWorldPosition;\n\t}\n\n finalPosition += 0.5 * gravityVelocity * age;\n\n return finalPosition;\n}\n\nvoid main() {\n float age = renderer_CurrentTime - a_DirectionTime.w;\n float normalizedAge = age / a_ShapePositionStartLifeTime.w;\n // normalizedAge >= 0.0: skip stale TF slots whose startTime is from a previous playback (e.g. after StopEmittingAndClear).\n if (normalizedAge >= 0.0 && normalizedAge < 1.0) {\n vec4 worldRotation;\n if (renderer_SimulationSpace == 0) {\n worldRotation = renderer_WorldRotation;\n } else {\n worldRotation = a_SimulationWorldRotation;\n }\n\n vec3 localVelocity;\n vec3 worldVelocity;\n\n #ifdef RENDERER_TRANSFORM_FEEDBACK\n // Transform Feedback mode: position in simulation space (local or world).\n // Local: transform to world; World: use directly.\n vec3 center;\n if (renderer_SimulationSpace == 0) {\n center = rotationByQuaternions(a_FeedbackPosition, worldRotation) + renderer_WorldPosition;\n } else if (renderer_SimulationSpace == 1) {\n center = a_FeedbackPosition;\n }\n localVelocity = a_FeedbackVelocity;\n worldVelocity = vec3(0.0);\n\n #ifdef _VOL_MODULE_ENABLED\n vec3 instantVOLVelocity;\n computeVelocityPositionOffset(normalizedAge, age, instantVOLVelocity);\n if (renderer_VOLSpace == 0) {\n localVelocity += instantVOLVelocity;\n } else {\n worldVelocity += instantVOLVelocity;\n }\n #endif\n #else\n // Original analytical path\n vec3 startVelocity = a_DirectionTime.xyz * a_StartSpeed;\n vec3 gravityVelocity = renderer_Gravity * a_Random0.x * age;\n localVelocity = startVelocity;\n worldVelocity = gravityVelocity;\n vec3 center = computeParticlePosition(startVelocity, age, normalizedAge, gravityVelocity, worldRotation, localVelocity, worldVelocity);\n #endif\n\n #include <sphere_billboard>\n #include <stretched_billboard>\n #include <horizontal_billboard>\n #include <vertical_billboard>\n #include <particle_mesh>\n\n gl_Position = camera_ProjMat * camera_ViewMat * vec4(center, 1.0);\n v_Color = computeParticleColor(a_StartColor, normalizedAge);\n\n #ifdef MATERIAL_HAS_BASETEXTURE\n vec2 simulateUV;\n #if defined(RENDERER_MODE_SPHERE_BILLBOARD) || defined(RENDERER_MODE_STRETCHED_BILLBOARD) || defined(RENDERER_MODE_HORIZONTAL_BILLBOARD) || defined(RENDERER_MODE_VERTICAL_BILLBOARD)\n simulateUV = a_CornerTextureCoordinate.zw * a_SimulationUV.xy + a_SimulationUV.zw;\n v_TextureCoordinate = computeParticleUV(simulateUV, normalizedAge);\n #endif\n #ifdef RENDERER_MODE_MESH\n simulateUV = a_SimulationUV.zw + TEXCOORD_0 * a_SimulationUV.xy;\n v_TextureCoordinate = computeParticleUV(simulateUV, normalizedAge);\n #endif\n #endif\n } else {\n\t gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Discard use out of X(-1,1),Y(-1,1),Z(0,1)\n }\n}"; // eslint-disable-line
31141
31656
  var pbrSpecularFs = "#include <common>\n#include <camera_declare>\n\n#include <FogFragmentDeclaration>\n\n#include <uv_share>\n#include <normal_share>\n#include <color_share>\n#include <worldpos_share>\n\n#include <light_frag_define>\n\n\n#include <pbr_frag_define>\n#include <pbr_helper>\n\nvoid main() {\n #include <pbr_frag>\n #include <FogFragment>\n}\n"; // eslint-disable-line
31142
31657
  var pbrFs = "#include <common>\n#include <camera_declare>\n#include <transform_declare>\n\n#include <FogFragmentDeclaration>\n#include <PositionClipSpaceDeclaration>\n\n#include <uv_share>\n#include <normal_share>\n#include <color_share>\n#include <worldpos_share>\n\n#include <light_frag_define>\n\n#include <pbr_frag_define>\n#include <pbr_helper>\n\nvoid main() {\n #include <pbr_frag>\n #include <FogFragment>\n}\n"; // eslint-disable-line
31143
31658
  var pbrVs = "#include <common>\n#include <common_vert>\n#include <blendShape_input>\n#include <uv_share>\n#include <color_share>\n#include <normal_share>\n#include <worldpos_share>\n\n#include <ShadowVertexDeclaration>\n#include <FogVertexDeclaration>\n#include <PositionClipSpaceDeclaration>\n\nvoid main() {\n\n #include <begin_position_vert>\n #include <begin_normal_vert>\n #include <blendShape_vert>\n #include <skinning_vert>\n #include <uv_vert>\n #include <color_vert>\n #include <normal_vert>\n #include <worldpos_vert>\n #include <position_vert>\n\n #include <ShadowVertex>\n #include <FogVertex>\n #include <PositionClipSpaceVertex>\n}\n"; // eslint-disable-line
@@ -33572,38 +34087,6 @@
33572
34087
  Scene._fogColorProperty = ShaderProperty.getByName("scene_FogColor");
33573
34088
  Scene._fogParamsProperty = ShaderProperty.getByName("scene_FogParams");
33574
34089
  Scene._prefilterdDFGProperty = ShaderProperty.getByName("scene_PrefilteredDFG");
33575
- function _array_like_to_array$2(arr, len) {
33576
- if (len == null || len > arr.length) len = arr.length;
33577
- for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
33578
- return arr2;
33579
- }
33580
- function _unsupported_iterable_to_array$2(o, minLen) {
33581
- if (!o) return;
33582
- if (typeof o === "string") return _array_like_to_array$2(o, minLen);
33583
- var n = Object.prototype.toString.call(o).slice(8, -1);
33584
- if (n === "Object" && o.constructor) n = o.constructor.name;
33585
- if (n === "Map" || n === "Set") return Array.from(n);
33586
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$2(o, minLen);
33587
- }
33588
- function _create_for_of_iterator_helper_loose$2(o, allowArrayLike) {
33589
- var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
33590
- if (it) return (it = it.call(o)).next.bind(it);
33591
- // Fallback for engines without symbol support
33592
- if (Array.isArray(o) || (it = _unsupported_iterable_to_array$2(o)) || allowArrayLike && o && typeof o.length === "number") {
33593
- if (it) o = it;
33594
- var i = 0;
33595
- return function() {
33596
- if (i >= o.length) return {
33597
- done: true
33598
- };
33599
- return {
33600
- done: false,
33601
- value: o[i++]
33602
- };
33603
- };
33604
- }
33605
- throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
33606
- }
33607
34090
  /**
33608
34091
  * Script class, used for logic writing.
33609
34092
  */ var Script = /*#__PURE__*/ function(Component) {
@@ -37928,7 +38411,7 @@
37928
38411
  _inherits$2(ParticleRenderer, Renderer);
37929
38412
  function ParticleRenderer(entity) {
37930
38413
  var _this;
37931
- _this = Renderer.call(this, entity) || this, /** Specifies how much particles stretch depending on their velocity. */ _this.velocityScale = 0, /** How much are the particles stretched in their direction of motion, defined as the length of the particle compared to its width. */ _this.lengthScale = 2, /** The pivot of particle. */ _this.pivot = new Vector3(), /** @internal */ _this._generatorBounds = new BoundingBox(), /** @internal */ _this._transformedBounds = new BoundingBox();
38414
+ _this = Renderer.call(this, entity) || this, /** Specifies how much particles stretch depending on their velocity. */ _this.velocityScale = 0, /** How much are the particles stretched in their direction of motion, defined as the length of the particle compared to its width. */ _this.lengthScale = 2, /** The pivot of particle. */ _this.pivot = new Vector3(), /** @internal */ _this._generatorBounds = new BoundingBox(), /** @internal */ _this._transformedBounds = new BoundingBox(), _this._renderMode = ParticleRenderMode.Billboard;
37932
38415
  _this._onGeneratorParamsChanged = _this._onGeneratorParamsChanged.bind(_this);
37933
38416
  _this.generator = new ParticleGenerator(_this);
37934
38417
  _this._currentRenderModeMacro = ParticleRenderer._billboardModeMacro;
@@ -38527,6 +39010,7 @@
38527
39010
  ParticleRandomSubSeeds[ParticleRandomSubSeeds["GravityModifier"] = 2759560269] = "GravityModifier";
38528
39011
  ParticleRandomSubSeeds[ParticleRandomSubSeeds["ForceOverLifetime"] = 3875246972] = "ForceOverLifetime";
38529
39012
  ParticleRandomSubSeeds[ParticleRandomSubSeeds["LimitVelocityOverLifetime"] = 3047300990] = "LimitVelocityOverLifetime";
39013
+ ParticleRandomSubSeeds[ParticleRandomSubSeeds["Noise"] = 4105357473] = "Noise";
38530
39014
  return ParticleRandomSubSeeds;
38531
39015
  }({});
38532
39016
  /**
@@ -39902,7 +40386,7 @@
39902
40386
  return;
39903
40387
  }
39904
40388
  this._enabled = value;
39905
- this._generator._setTransformFeedback(value);
40389
+ this._generator._setTransformFeedback();
39906
40390
  this._generator._renderer._onGeneratorParamsChanged();
39907
40391
  }
39908
40392
  }
@@ -40841,6 +41325,297 @@
40841
41325
  __decorate$1([
40842
41326
  ignoreClone
40843
41327
  ], TextureSheetAnimationModule.prototype, "_onTilingChanged", null);
41328
+ /**
41329
+ * Noise module for particle system.
41330
+ * Adds simplex noise-based turbulence displacement to particles.
41331
+ */ var NoiseModule = /*#__PURE__*/ function(ParticleGeneratorModule) {
41332
+ _inherits$2(NoiseModule, ParticleGeneratorModule);
41333
+ function NoiseModule(generator) {
41334
+ var _this;
41335
+ _this = ParticleGeneratorModule.call(this, generator) || this, /** @internal */ _this._noiseRand = new Rand(0, ParticleRandomSubSeeds.Noise), _this._noiseParams = new Vector4(), _this._noiseOctaveParams = new Vector4(), _this._strengthMinConst = new Vector3(), _this._scrollSpeed = 0, _this._separateAxes = false, _this._frequency = 0.5, _this._octaveCount = 1, _this._octaveIntensityMultiplier = 0.5, _this._octaveFrequencyMultiplier = 2.0;
41336
+ _this.strengthX = new ParticleCompositeCurve(1);
41337
+ _this.strengthY = new ParticleCompositeCurve(1);
41338
+ _this.strengthZ = new ParticleCompositeCurve(1);
41339
+ return _this;
41340
+ }
41341
+ var _proto = NoiseModule.prototype;
41342
+ /**
41343
+ * @internal
41344
+ */ _proto._updateShaderData = function _updateShaderData(shaderData) {
41345
+ var enabledMacro = null;
41346
+ var strengthCurveMacro = null;
41347
+ var strengthIsRandomTwoMacro = null;
41348
+ var separateAxesMacro = null;
41349
+ if (this.enabled) {
41350
+ enabledMacro = NoiseModule._enabledMacro;
41351
+ var strengthX = this._strengthX;
41352
+ var strengthY = this._strengthY;
41353
+ var strengthZ = this._strengthZ;
41354
+ var separateAxes = this._separateAxes;
41355
+ // Determine strength curve mode (following SOL pattern)
41356
+ var isRandomCurveMode = separateAxes ? strengthX.mode === ParticleCurveMode.TwoCurves && strengthY.mode === ParticleCurveMode.TwoCurves && strengthZ.mode === ParticleCurveMode.TwoCurves : strengthX.mode === ParticleCurveMode.TwoCurves;
41357
+ var isCurveMode = isRandomCurveMode || (separateAxes ? strengthX.mode === ParticleCurveMode.Curve && strengthY.mode === ParticleCurveMode.Curve && strengthZ.mode === ParticleCurveMode.Curve : strengthX.mode === ParticleCurveMode.Curve);
41358
+ var isRandomConstMode = separateAxes ? strengthX.mode === ParticleCurveMode.TwoConstants && strengthY.mode === ParticleCurveMode.TwoConstants && strengthZ.mode === ParticleCurveMode.TwoConstants : strengthX.mode === ParticleCurveMode.TwoConstants;
41359
+ // noiseParams.w = frequency (always needed)
41360
+ var noiseParams = this._noiseParams;
41361
+ if (isCurveMode) {
41362
+ // Curve/TwoCurves: encode curve data as float arrays
41363
+ shaderData.setFloatArray(NoiseModule._strengthMaxCurveXProperty, strengthX.curveMax._getTypeArray());
41364
+ if (separateAxes) {
41365
+ shaderData.setFloatArray(NoiseModule._strengthMaxCurveYProperty, strengthY.curveMax._getTypeArray());
41366
+ shaderData.setFloatArray(NoiseModule._strengthMaxCurveZProperty, strengthZ.curveMax._getTypeArray());
41367
+ }
41368
+ if (isRandomCurveMode) {
41369
+ shaderData.setFloatArray(NoiseModule._strengthMinCurveXProperty, strengthX.curveMin._getTypeArray());
41370
+ if (separateAxes) {
41371
+ shaderData.setFloatArray(NoiseModule._strengthMinCurveYProperty, strengthY.curveMin._getTypeArray());
41372
+ shaderData.setFloatArray(NoiseModule._strengthMinCurveZProperty, strengthZ.curveMin._getTypeArray());
41373
+ }
41374
+ strengthIsRandomTwoMacro = NoiseModule._strengthIsRandomTwoMacro;
41375
+ }
41376
+ strengthCurveMacro = NoiseModule._strengthCurveMacro;
41377
+ // xyz unused in curve mode, just set frequency
41378
+ noiseParams.set(0, 0, 0, this._frequency);
41379
+ } else {
41380
+ // Constant/TwoConstants: pack strength into noiseParams.xyz
41381
+ if (separateAxes) {
41382
+ noiseParams.set(strengthX.constantMax, strengthY.constantMax, strengthZ.constantMax, this._frequency);
41383
+ } else {
41384
+ var s = strengthX.constantMax;
41385
+ noiseParams.set(s, s, s, this._frequency);
41386
+ }
41387
+ if (isRandomConstMode) {
41388
+ var minConst = this._strengthMinConst;
41389
+ if (separateAxes) {
41390
+ minConst.set(strengthX.constantMin, strengthY.constantMin, strengthZ.constantMin);
41391
+ } else {
41392
+ var sMin = strengthX.constantMin;
41393
+ minConst.set(sMin, sMin, sMin);
41394
+ }
41395
+ shaderData.setVector3(NoiseModule._strengthMinConstProperty, minConst);
41396
+ strengthIsRandomTwoMacro = NoiseModule._strengthIsRandomTwoMacro;
41397
+ }
41398
+ }
41399
+ shaderData.setVector4(NoiseModule._noiseProperty, noiseParams);
41400
+ if (separateAxes) {
41401
+ separateAxesMacro = NoiseModule._separateAxesMacro;
41402
+ }
41403
+ var noiseOctaveParams = this._noiseOctaveParams;
41404
+ noiseOctaveParams.set(this._scrollSpeed, this._octaveCount, this._octaveIntensityMultiplier, this._octaveFrequencyMultiplier);
41405
+ shaderData.setVector4(NoiseModule._noiseOctaveProperty, noiseOctaveParams);
41406
+ }
41407
+ this._enabledModuleMacro = this._enableMacro(shaderData, this._enabledModuleMacro, enabledMacro);
41408
+ this._strengthCurveModeMacro = this._enableMacro(shaderData, this._strengthCurveModeMacro, strengthCurveMacro);
41409
+ this._strengthIsRandomTwoModeMacro = this._enableMacro(shaderData, this._strengthIsRandomTwoModeMacro, strengthIsRandomTwoMacro);
41410
+ this._separateAxesModeMacro = this._enableMacro(shaderData, this._separateAxesModeMacro, separateAxesMacro);
41411
+ };
41412
+ /**
41413
+ * @internal
41414
+ */ _proto._resetRandomSeed = function _resetRandomSeed(seed) {
41415
+ this._noiseRand.reset(seed, ParticleRandomSubSeeds.Noise);
41416
+ };
41417
+ _create_class$2(NoiseModule, [
41418
+ {
41419
+ key: "separateAxes",
41420
+ get: /**
41421
+ * Specifies whether the strength is separate on each axis, when disabled, only `strength` is used.
41422
+ */ function get() {
41423
+ return this._separateAxes;
41424
+ },
41425
+ set: function set(value) {
41426
+ if (value !== this._separateAxes) {
41427
+ this._separateAxes = value;
41428
+ this._generator._renderer._onGeneratorParamsChanged();
41429
+ }
41430
+ }
41431
+ },
41432
+ {
41433
+ key: "strengthX",
41434
+ get: /**
41435
+ * Noise strength. When `separateAxes` is disabled, applies to all axes.
41436
+ * When `separateAxes` is enabled, applies only to x axis.
41437
+ */ function get() {
41438
+ return this._strengthX;
41439
+ },
41440
+ set: function set(value) {
41441
+ var lastValue = this._strengthX;
41442
+ if (value !== lastValue) {
41443
+ this._strengthX = value;
41444
+ this._onCompositeCurveChange(lastValue, value);
41445
+ }
41446
+ }
41447
+ },
41448
+ {
41449
+ key: "strengthY",
41450
+ get: /**
41451
+ * Noise strength for y axis, used when `separateAxes` is enabled.
41452
+ */ function get() {
41453
+ return this._strengthY;
41454
+ },
41455
+ set: function set(value) {
41456
+ var lastValue = this._strengthY;
41457
+ if (value !== lastValue) {
41458
+ this._strengthY = value;
41459
+ this._onCompositeCurveChange(lastValue, value);
41460
+ }
41461
+ }
41462
+ },
41463
+ {
41464
+ key: "strengthZ",
41465
+ get: /**
41466
+ * Noise strength for z axis, used when `separateAxes` is enabled.
41467
+ */ function get() {
41468
+ return this._strengthZ;
41469
+ },
41470
+ set: function set(value) {
41471
+ var lastValue = this._strengthZ;
41472
+ if (value !== lastValue) {
41473
+ this._strengthZ = value;
41474
+ this._onCompositeCurveChange(lastValue, value);
41475
+ }
41476
+ }
41477
+ },
41478
+ {
41479
+ key: "frequency",
41480
+ get: /**
41481
+ * Noise spatial frequency.
41482
+ */ function get() {
41483
+ return this._frequency;
41484
+ },
41485
+ set: function set(value) {
41486
+ value = Math.max(1e-6, value);
41487
+ if (value !== this._frequency) {
41488
+ this._frequency = value;
41489
+ this._generator._renderer._onGeneratorParamsChanged();
41490
+ }
41491
+ }
41492
+ },
41493
+ {
41494
+ key: "scrollSpeed",
41495
+ get: /**
41496
+ * Noise field scroll speed over time.
41497
+ */ function get() {
41498
+ return this._scrollSpeed;
41499
+ },
41500
+ set: function set(value) {
41501
+ if (value !== this._scrollSpeed) {
41502
+ this._scrollSpeed = value;
41503
+ this._generator._renderer._onGeneratorParamsChanged();
41504
+ }
41505
+ }
41506
+ },
41507
+ {
41508
+ key: "octaveCount",
41509
+ get: /**
41510
+ * Number of noise octave layers (1-3).
41511
+ */ function get() {
41512
+ return this._octaveCount;
41513
+ },
41514
+ set: function set(value) {
41515
+ value = Math.max(1, Math.min(3, Math.floor(value)));
41516
+ if (value !== this._octaveCount) {
41517
+ this._octaveCount = value;
41518
+ this._generator._renderer._onGeneratorParamsChanged();
41519
+ }
41520
+ }
41521
+ },
41522
+ {
41523
+ key: "octaveIntensityMultiplier",
41524
+ get: /**
41525
+ * Intensity multiplier for each successive octave, only effective when `octaveCount` > 1.
41526
+ * Each layer's contribution is scaled by this factor relative to the previous layer, range [0, 1].
41527
+ */ function get() {
41528
+ return this._octaveIntensityMultiplier;
41529
+ },
41530
+ set: function set(value) {
41531
+ value = Math.max(0, Math.min(1, value));
41532
+ if (value !== this._octaveIntensityMultiplier) {
41533
+ this._octaveIntensityMultiplier = value;
41534
+ this._generator._renderer._onGeneratorParamsChanged();
41535
+ }
41536
+ }
41537
+ },
41538
+ {
41539
+ key: "octaveFrequencyMultiplier",
41540
+ get: /**
41541
+ * Frequency multiplier for each successive octave, only effective when `octaveCount` > 1.
41542
+ * Each layer samples at this multiple of the previous layer's frequency, range [1, 4].
41543
+ */ function get() {
41544
+ return this._octaveFrequencyMultiplier;
41545
+ },
41546
+ set: function set(value) {
41547
+ value = Math.max(1, Math.min(4, value));
41548
+ if (value !== this._octaveFrequencyMultiplier) {
41549
+ this._octaveFrequencyMultiplier = value;
41550
+ this._generator._renderer._onGeneratorParamsChanged();
41551
+ }
41552
+ }
41553
+ },
41554
+ {
41555
+ key: "enabled",
41556
+ get: function get() {
41557
+ return this._enabled;
41558
+ },
41559
+ set: function set(value) {
41560
+ if (value !== this._enabled) {
41561
+ if (value && !this._generator._renderer.engine._hardwareRenderer.isWebGL2) {
41562
+ return;
41563
+ }
41564
+ this._enabled = value;
41565
+ this._generator._setTransformFeedback();
41566
+ this._generator._renderer._onGeneratorParamsChanged();
41567
+ }
41568
+ }
41569
+ }
41570
+ ]);
41571
+ return NoiseModule;
41572
+ }(ParticleGeneratorModule);
41573
+ NoiseModule._enabledMacro = ShaderMacro.getByName("RENDERER_NOISE_MODULE_ENABLED");
41574
+ NoiseModule._strengthCurveMacro = ShaderMacro.getByName("RENDERER_NOISE_STRENGTH_CURVE");
41575
+ NoiseModule._strengthIsRandomTwoMacro = ShaderMacro.getByName("RENDERER_NOISE_STRENGTH_IS_RANDOM_TWO");
41576
+ NoiseModule._separateAxesMacro = ShaderMacro.getByName("RENDERER_NOISE_IS_SEPARATE");
41577
+ NoiseModule._noiseProperty = ShaderProperty.getByName("renderer_NoiseParams");
41578
+ NoiseModule._noiseOctaveProperty = ShaderProperty.getByName("renderer_NoiseOctaveParams");
41579
+ NoiseModule._strengthMinConstProperty = ShaderProperty.getByName("renderer_NoiseStrengthMinConst");
41580
+ NoiseModule._strengthMaxCurveXProperty = ShaderProperty.getByName("renderer_NoiseStrengthMaxCurveX");
41581
+ NoiseModule._strengthMaxCurveYProperty = ShaderProperty.getByName("renderer_NoiseStrengthMaxCurveY");
41582
+ NoiseModule._strengthMaxCurveZProperty = ShaderProperty.getByName("renderer_NoiseStrengthMaxCurveZ");
41583
+ NoiseModule._strengthMinCurveXProperty = ShaderProperty.getByName("renderer_NoiseStrengthMinCurveX");
41584
+ NoiseModule._strengthMinCurveYProperty = ShaderProperty.getByName("renderer_NoiseStrengthMinCurveY");
41585
+ NoiseModule._strengthMinCurveZProperty = ShaderProperty.getByName("renderer_NoiseStrengthMinCurveZ");
41586
+ __decorate$1([
41587
+ ignoreClone
41588
+ ], NoiseModule.prototype, "_enabledModuleMacro", void 0);
41589
+ __decorate$1([
41590
+ ignoreClone
41591
+ ], NoiseModule.prototype, "_strengthCurveModeMacro", void 0);
41592
+ __decorate$1([
41593
+ ignoreClone
41594
+ ], NoiseModule.prototype, "_strengthIsRandomTwoModeMacro", void 0);
41595
+ __decorate$1([
41596
+ ignoreClone
41597
+ ], NoiseModule.prototype, "_separateAxesModeMacro", void 0);
41598
+ __decorate$1([
41599
+ ignoreClone
41600
+ ], NoiseModule.prototype, "_noiseRand", void 0);
41601
+ __decorate$1([
41602
+ ignoreClone
41603
+ ], NoiseModule.prototype, "_noiseParams", void 0);
41604
+ __decorate$1([
41605
+ ignoreClone
41606
+ ], NoiseModule.prototype, "_noiseOctaveParams", void 0);
41607
+ __decorate$1([
41608
+ ignoreClone
41609
+ ], NoiseModule.prototype, "_strengthMinConst", void 0);
41610
+ __decorate$1([
41611
+ deepClone
41612
+ ], NoiseModule.prototype, "_strengthX", void 0);
41613
+ __decorate$1([
41614
+ deepClone
41615
+ ], NoiseModule.prototype, "_strengthY", void 0);
41616
+ __decorate$1([
41617
+ deepClone
41618
+ ], NoiseModule.prototype, "_strengthZ", void 0);
40844
41619
  /**
40845
41620
  * Velocity over lifetime module.
40846
41621
  */ var VelocityOverLifetimeModule = /*#__PURE__*/ function(ParticleGeneratorModule) {
@@ -41046,6 +41821,7 @@
41046
41821
  this.forceOverLifetime = new ForceOverLifetimeModule(this);
41047
41822
  this.sizeOverLifetime = new SizeOverLifetimeModule(this);
41048
41823
  this.limitVelocityOverLifetime = new LimitVelocityOverLifetimeModule(this);
41824
+ this.noise = new NoiseModule(this);
41049
41825
  this.emission.enabled = true;
41050
41826
  }
41051
41827
  var _proto = ParticleGenerator.prototype;
@@ -41353,6 +42129,7 @@
41353
42129
  this.sizeOverLifetime._updateShaderData(shaderData);
41354
42130
  this.rotationOverLifetime._updateShaderData(shaderData);
41355
42131
  this.colorOverLifetime._updateShaderData(shaderData);
42132
+ this.noise._updateShaderData(shaderData);
41356
42133
  };
41357
42134
  /**
41358
42135
  * @internal
@@ -41366,16 +42143,19 @@
41366
42143
  this.limitVelocityOverLifetime._resetRandomSeed(seed);
41367
42144
  this.rotationOverLifetime._resetRandomSeed(seed);
41368
42145
  this.colorOverLifetime._resetRandomSeed(seed);
42146
+ this.noise._resetRandomSeed(seed);
41369
42147
  };
41370
42148
  /**
41371
42149
  * @internal
41372
- */ _proto._setTransformFeedback = function _setTransformFeedback(enabled) {
41373
- this._useTransformFeedback = enabled;
42150
+ */ _proto._setTransformFeedback = function _setTransformFeedback() {
42151
+ var needed = this.limitVelocityOverLifetime.enabled || this.noise.enabled;
42152
+ if (needed === this._useTransformFeedback) return;
42153
+ this._useTransformFeedback = needed;
41374
42154
  // Switching TF mode invalidates all active particle state: feedback buffers and instance
41375
42155
  // buffer layout are incompatible between the two paths. Clear rather than show a one-frame
41376
42156
  // jump; new particles will fill in naturally from the next emit cycle.
41377
42157
  this._clearActiveParticles();
41378
- if (enabled) {
42158
+ if (needed) {
41379
42159
  if (!this._feedbackSimulator) {
41380
42160
  this._feedbackSimulator = new ParticleTransformFeedbackSimulator(this._renderer.engine);
41381
42161
  }
@@ -41425,9 +42205,7 @@
41425
42205
  /**
41426
42206
  * @internal
41427
42207
  */ _proto._cloneTo = function _cloneTo(target) {
41428
- if (target.limitVelocityOverLifetime.enabled) {
41429
- target._setTransformFeedback(true);
41430
- }
42208
+ target._setTransformFeedback();
41431
42209
  };
41432
42210
  /**
41433
42211
  * @internal
@@ -41589,10 +42367,6 @@
41589
42367
  // Start rotation
41590
42368
  var startRotationRand = main._startRotationRand, flipRotation = main.flipRotation;
41591
42369
  var isFlip = flipRotation > startRotationRand.random();
41592
- // @todo:None-Mesh mode should inverse the rotation, maybe should unify it
41593
- if (this._renderer.renderMode !== ParticleRenderMode.Mesh) {
41594
- isFlip = !isFlip;
41595
- }
41596
42370
  var rotationZ = main.startRotationZ.evaluate(undefined, startRotationRand.random());
41597
42371
  if (main.startRotation3D) {
41598
42372
  var rotationX = main.startRotationX.evaluate(undefined, startRotationRand.random());
@@ -41618,7 +42392,9 @@
41618
42392
  if (colorOverLifetime.enabled && colorOverLifetime.color.mode === ParticleGradientMode.TwoGradients) {
41619
42393
  instanceVertices[offset + 20] = colorOverLifetime._colorGradientRand.random();
41620
42394
  }
41621
- // instanceVertices[offset + 21] = rand.random();
42395
+ if (this.noise.enabled) {
42396
+ instanceVertices[offset + 21] = this.noise._noiseRand.random();
42397
+ }
41622
42398
  var rotationOverLifetime = this.rotationOverLifetime;
41623
42399
  if (rotationOverLifetime.enabled && rotationOverLifetime.rotationZ.mode === ParticleCurveMode.TwoConstants) {
41624
42400
  instanceVertices[offset + 22] = rotationOverLifetime._rotationRand.random();
@@ -41906,6 +42682,21 @@
41906
42682
  out.transform(rotateMat);
41907
42683
  min.add(worldOffsetMin);
41908
42684
  max.add(worldOffsetMax);
42685
+ // Noise module impact: noise output is normalized to [-1, 1],
42686
+ // max displacement = |strength_max|
42687
+ var noise = this.noise;
42688
+ if (noise.enabled) {
42689
+ var noiseMaxX, noiseMaxY, noiseMaxZ;
42690
+ if (noise.separateAxes) {
42691
+ noiseMaxX = Math.abs(noise.strengthX._getMax());
42692
+ noiseMaxY = Math.abs(noise.strengthY._getMax());
42693
+ noiseMaxZ = Math.abs(noise.strengthZ._getMax());
42694
+ } else {
42695
+ noiseMaxX = noiseMaxY = noiseMaxZ = Math.abs(noise.strengthX._getMax());
42696
+ }
42697
+ min.set(min.x - noiseMaxX, min.y - noiseMaxY, min.z - noiseMaxZ);
42698
+ max.set(max.x + noiseMaxX, max.y + noiseMaxY, max.z + noiseMaxZ);
42699
+ }
41909
42700
  min.add(worldPosition);
41910
42701
  max.add(worldPosition);
41911
42702
  };
@@ -42003,6 +42794,9 @@
42003
42794
  __decorate$1([
42004
42795
  deepClone
42005
42796
  ], ParticleGenerator.prototype, "textureSheetAnimation", void 0);
42797
+ __decorate$1([
42798
+ deepClone
42799
+ ], ParticleGenerator.prototype, "noise", void 0);
42006
42800
  __decorate$1([
42007
42801
  ignoreClone
42008
42802
  ], ParticleGenerator.prototype, "_playTime", void 0);
@@ -44196,6 +44990,7 @@
44196
44990
  MeshShape: MeshShape,
44197
44991
  MeshTopology: MeshTopology,
44198
44992
  ModelMesh: ModelMesh,
44993
+ NoiseModule: NoiseModule,
44199
44994
  OverflowMode: OverflowMode,
44200
44995
  PBRMaterial: PBRMaterial,
44201
44996
  ParticleCompositeCurve: ParticleCompositeCurve,
@@ -45386,7 +46181,7 @@
45386
46181
  };
45387
46182
  case TextureFormat.ETC2_RGBA5:
45388
46183
  return {
45389
- internalFormat: GLCompressedTextureInternalFormat.RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
46184
+ internalFormat: isSRGBColorSpace ? GLCompressedTextureInternalFormat.SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : GLCompressedTextureInternalFormat.RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
45390
46185
  isCompressed: true
45391
46186
  };
45392
46187
  case TextureFormat.ETC2_RGBA8:
@@ -45421,27 +46216,27 @@
45421
46216
  };
45422
46217
  case TextureFormat.ASTC_5x5:
45423
46218
  return {
45424
- internalFormat: GLCompressedTextureInternalFormat.RGBA_ASTC_5X5_KHR,
46219
+ internalFormat: isSRGBColorSpace ? GLCompressedTextureInternalFormat.SRGB8_ALPHA8_ASTC_5X5_KHR : GLCompressedTextureInternalFormat.RGBA_ASTC_5X5_KHR,
45425
46220
  isCompressed: true
45426
46221
  };
45427
46222
  case TextureFormat.ASTC_6x6:
45428
46223
  return {
45429
- internalFormat: GLCompressedTextureInternalFormat.RGBA_ASTC_6X6_KHR,
46224
+ internalFormat: isSRGBColorSpace ? GLCompressedTextureInternalFormat.SRGB8_ALPHA8_ASTC_6X6_KHR : GLCompressedTextureInternalFormat.RGBA_ASTC_6X6_KHR,
45430
46225
  isCompressed: true
45431
46226
  };
45432
46227
  case TextureFormat.ASTC_8x8:
45433
46228
  return {
45434
- internalFormat: GLCompressedTextureInternalFormat.RGBA_ASTC_8X8_KHR,
46229
+ internalFormat: isSRGBColorSpace ? GLCompressedTextureInternalFormat.SRGB8_ALPHA8_ASTC_8X8_KHR : GLCompressedTextureInternalFormat.RGBA_ASTC_8X8_KHR,
45435
46230
  isCompressed: true
45436
46231
  };
45437
46232
  case TextureFormat.ASTC_10x10:
45438
46233
  return {
45439
- internalFormat: GLCompressedTextureInternalFormat.RGBA_ASTC_10X10_KHR,
46234
+ internalFormat: isSRGBColorSpace ? GLCompressedTextureInternalFormat.SRGB8_ALPHA8_ASTC_10X10_KHR : GLCompressedTextureInternalFormat.RGBA_ASTC_10X10_KHR,
45440
46235
  isCompressed: true
45441
46236
  };
45442
46237
  case TextureFormat.ASTC_12x12:
45443
46238
  return {
45444
- internalFormat: GLCompressedTextureInternalFormat.RGBA_ASTC_12X12_KHR,
46239
+ internalFormat: isSRGBColorSpace ? GLCompressedTextureInternalFormat.SRGB8_ALPHA8_ASTC_12X12_KHR : GLCompressedTextureInternalFormat.RGBA_ASTC_12X12_KHR,
45445
46240
  isCompressed: true
45446
46241
  };
45447
46242
  case TextureFormat.Depth:
@@ -51701,16 +52496,11 @@
51701
52496
  var isDefaultScene = scene === index;
51702
52497
  var sceneNodes = sceneInfo.nodes || [];
51703
52498
  var sceneRoot;
51704
- if (sceneNodes.length === 1) {
51705
- sceneRoot = context.get(GLTFParserType.Entity, sceneNodes[0]);
51706
- } else {
51707
- sceneRoot = new Entity(engine, "GLTF_ROOT");
51708
- // @ts-ignore
51709
- sceneRoot._markAsTemplate(glTFResource);
51710
- for(var i = 0; i < sceneNodes.length; i++){
51711
- var childEntity = context.get(GLTFParserType.Entity, sceneNodes[i]);
51712
- sceneRoot.addChild(childEntity);
51713
- }
52499
+ sceneRoot = new Entity(engine, "GLTF_ROOT");
52500
+ // @ts-ignore
52501
+ sceneRoot._markAsTemplate(glTFResource);
52502
+ for(var i = 0; i < sceneNodes.length; i++){
52503
+ sceneRoot.addChild(context.get(GLTFParserType.Entity, sceneNodes[i]));
51714
52504
  }
51715
52505
  if (isDefaultScene) {
51716
52506
  glTFResource._defaultSceneRoot = sceneRoot;
@@ -53233,6 +54023,15 @@
53233
54023
  _proto.load = function load(item, resourceManager) {
53234
54024
  var _this = this;
53235
54025
  var url = item.url;
54026
+ if (url.endsWith(".gsp")) {
54027
+ // @ts-ignore
54028
+ return resourceManager._request(url, _extends({}, item, {
54029
+ type: "json"
54030
+ })).then(function(data) {
54031
+ // @ts-ignore - _createFromPrecompiled is @internal
54032
+ return Shader._createFromPrecompiled(data);
54033
+ });
54034
+ }
53236
54035
  // @ts-ignore
53237
54036
  return resourceManager._request(url, _extends({}, item, {
53238
54037
  type: "text"
@@ -53256,8 +54055,7 @@
53256
54055
  ShaderLoader._builtinRegex = /^\s*\/\/\s*@builtin\s+(\w+)/;
53257
54056
  ShaderLoader = __decorate([
53258
54057
  resourceLoader(AssetType.Shader, [
53259
- "gs",
53260
- "gsl"
54058
+ "shader"
53261
54059
  ])
53262
54060
  ], ShaderLoader);
53263
54061
  var PhysicsMaterialLoader = /*#__PURE__*/ function(Loader) {
@@ -53968,7 +54766,7 @@
53968
54766
  ], EXT_texture_webp);
53969
54767
 
53970
54768
  //@ts-ignore
53971
- var version = "2.0.0-alpha.25";
54769
+ var version = "2.0.0-alpha.26";
53972
54770
  console.log("Galacean Engine Version: " + version);
53973
54771
  for(var key in CoreObjects){
53974
54772
  Loader.registerClass(key, CoreObjects[key]);
@@ -54132,6 +54930,7 @@
54132
54930
  exports.MeshShape = MeshShape;
54133
54931
  exports.MeshTopology = MeshTopology;
54134
54932
  exports.ModelMesh = ModelMesh;
54933
+ exports.NoiseModule = NoiseModule;
54135
54934
  exports.OverflowMode = OverflowMode;
54136
54935
  exports.PBRMaterial = PBRMaterial;
54137
54936
  exports.ParserContext = ParserContext;