diff --git a/cocos/particle/particle-culler.ts b/cocos/particle/particle-culler.ts index f3ce82d43fc..00d8c3aec38 100644 --- a/cocos/particle/particle-culler.ts +++ b/cocos/particle/particle-culler.ts @@ -34,9 +34,11 @@ import type { ParticleSystem } from './particle-system'; import { Mode } from './animator/curve-range'; const _node_mat = new Mat4(); -const _node_parent_inv = new Mat4(); const _node_rol = new Quat(); const _node_scale = new Vec3(); +const _node_pos = new Vec3(); +const _trans_mat = new Mat4(); +const _rol_scale_mat = new Mat4(); const _anim_module = [ '_colorOverLifetimeModule', @@ -129,8 +131,20 @@ export class ParticleCuller { node.invalidateChildren(TransformBit.POSITION); if (ps.simulationSpace === Space.World) { - node.getWorldMatrix(_node_mat); - node.getWorldRotation(_node_rol); + ps.node.getWorldPosition(_node_pos); + ps.node.getWorldRotation(_node_rol); + switch (ps.scaleSpace) { + case Space.Local: + ps.node.getScale(_node_scale); + break; + case Space.World: + ps.node.getWorldScale(_node_scale); + break; + default: + break; + } + Mat4.fromRTS(_rol_scale_mat, _node_rol, Vec3.ZERO, _node_scale); + Mat4.fromRTS(_trans_mat, _node_rol, _node_pos, _node_scale); } for (let i = 0; i < count; ++i) { @@ -155,8 +169,8 @@ export class ParticleCuller { Vec3.multiplyScalar(particle.velocity, particle.velocity, curveStartSpeed); if (ps.simulationSpace === Space.World) { - Vec3.transformMat4(particle.position, particle.position, _node_mat); - Vec3.transformQuat(particle.velocity, particle.velocity, _node_rol); + Vec3.transformMat4(particle.position, particle.position, _trans_mat); + Vec3.transformMat4(particle.velocity, particle.velocity, _rol_scale_mat); } Vec3.copy(particle.ultimateVelocity, particle.velocity); @@ -187,6 +201,8 @@ export class ParticleCuller { const ps = this._particleSystem; ps.node.getWorldMatrix(_node_mat); + ps.node.getWorldPosition(_node_pos); + ps.node.getWorldRotation(_node_rol); switch (ps.scaleSpace) { case Space.Local: ps.node.getScale(_node_scale); @@ -197,20 +213,15 @@ export class ParticleCuller { default: break; } + Mat4.fromRTS(_rol_scale_mat, _node_rol, Vec3.ZERO, _node_scale); + Mat4.fromRTS(_trans_mat, _node_rol, _node_pos, _node_scale); this._updateList.forEach((value: IParticleModule, key: string) => { - value.update(ps.simulationSpace, _node_mat); + value.update(ps.simulationSpace, _trans_mat); }); if (ps.simulationSpace === Space.Local) { - const r: Quat = ps.node.getRotation(); - Mat4.fromQuat(this._localMat, r); - this._localMat.transpose(); // just consider rotation, use transpose as invert - } - - if (ps.node.parent) { - ps.node.parent.getWorldMatrix(_node_parent_inv); - _node_parent_inv.invert(); + Mat4.transpose(this._localMat, _rol_scale_mat); } for (let i = 0; i < particleLst.length; ++i) { @@ -229,10 +240,7 @@ export class ParticleCuller { this._gravity.z = 0.0; this._gravity.w = 1.0; if (!approx(gravityFactor, 0.0, EPSILON)) { - if (ps.node.parent) { - this._gravity = this._gravity.transformMat4(_node_parent_inv); - } - this._gravity = this._gravity.transformMat4(this._localMat); + Vec4.transformMat4(this._gravity, this._gravity, this._localMat); p.velocity.x += this._gravity.x; p.velocity.y += this._gravity.y; @@ -271,7 +279,7 @@ export class ParticleCuller { } } - const worldMat = this._particleSystem.node.worldMatrix; + const worldMat = _trans_mat; for (let i = 0; i < this._particlesAll.length; ++i) { const p: Particle = this._particlesAll[i]; Vec3.multiply(size, _node_scale, p.size); diff --git a/cocos/particle/particle-system.ts b/cocos/particle/particle-system.ts index 7f65b61d312..851d005ee90 100644 --- a/cocos/particle/particle-system.ts +++ b/cocos/particle/particle-system.ts @@ -54,6 +54,10 @@ import { NoiseModule } from './animator/noise-module'; const _world_mat = new Mat4(); const _world_rol = new Quat(); +const _trans_mat = new Mat4(); +const _rol_mat = new Mat4(); +const _scale_mat = new Mat4(); +const _rol_scale_mat = new Mat4(); const superMaterials = Object.getOwnPropertyDescriptor(Renderer.prototype, 'sharedMaterials')!; @@ -108,10 +112,24 @@ export class ParticleSystem extends ModelRenderer { * @zh 计算粒子缩放的空间。 */ @type(Space) - @serializable @displayOrder(9) @tooltip('i18n:particle_system.scaleSpace') - public scaleSpace = Space.Local; + public get scaleSpace () { + return this._scaleSpace; + } + + public set scaleSpace (val) { + if (val !== this._scaleSpace) { + this._scaleSpace = val; + if (this.processor) { + this.processor.updateMaterialParams(); + this.processor.updateTrailMaterial(); + } + } + } + + @serializable + public _scaleSpace = Space.Local; /** * @en Whether to modify particle size on XYZ axis. @@ -1321,8 +1339,21 @@ export class ParticleSystem extends ModelRenderer { } if (this._simulationSpace === Space.World) { - this.node.getWorldMatrix(_world_mat); this.node.getWorldRotation(_world_rol); + Quat.normalize(_world_rol, _world_rol); + if (this.scaleSpace === Space.World) { + this.node.getWorldMatrix(_world_mat); + Mat4.fromQuat(_rol_mat, _world_rol); + Mat4.fromScaling(_scale_mat, this.node.getWorldScale()); + Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat); + } else { + Mat4.fromScaling(_scale_mat, this.node.getScale()); + Mat4.fromTranslation(_trans_mat, this.node.getWorldPosition()); + Mat4.fromQuat(_rol_mat, _world_rol); + Mat4.multiply(_world_mat, _rol_mat, _scale_mat); + Mat4.multiply(_world_mat, _trans_mat, _world_mat); + Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat); + } } for (let i = 0; i < count; ++i) { @@ -1351,7 +1382,7 @@ export class ParticleSystem extends ModelRenderer { if (this._simulationSpace === Space.World) { Vec3.transformMat4(particle.position, particle.position, _world_mat); - Vec3.transformQuat(particle.velocity, particle.velocity, _world_rol); + Vec3.transformMat4(particle.velocity, particle.velocity, _rol_scale_mat); } Vec3.copy(particle.ultimateVelocity, particle.velocity); diff --git a/cocos/particle/renderer/particle-system-renderer-cpu.ts b/cocos/particle/renderer/particle-system-renderer-cpu.ts index ee123ed1e1d..74fe7ce8d2e 100644 --- a/cocos/particle/renderer/particle-system-renderer-cpu.ts +++ b/cocos/particle/renderer/particle-system-renderer-cpu.ts @@ -38,13 +38,11 @@ import { Pass } from '../../render-scene'; import { ParticleNoise } from '../noise'; import { NoiseModule } from '../animator/noise-module'; import { isCurveTwoValues } from '../particle-general-function'; -import { Mode } from '../animator/curve-range'; const _tempAttribUV = new Vec3(); const _tempWorldTrans = new Mat4(); -const _tempParentInverse = new Mat4(); const _node_rot = new Quat(); -const _node_euler = new Vec3(); +const _rot_mat = new Mat4(); const _anim_module = [ '_colorOverLifetimeModule', @@ -65,6 +63,8 @@ const _uvs = [ ]; const CC_USE_WORLD_SPACE = 'CC_USE_WORLD_SPACE'; +const CC_USE_WORLD_SCALE = 'CC_USE_WORLD_SCALE'; +const CC_USE_LINE = 'CC_USE_LINE'; const CC_RENDER_MODE = 'CC_RENDER_MODE'; const ROTATION_OVER_TIME_MODULE_ENABLE = 'ROTATION_OVER_TIME_MODULE_ENABLE'; @@ -143,7 +143,12 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas private _frameTile_velLenScale: Vec4; private _tmp_velLenScale: Vec4; private _defaultMat: Material | null = null; + private _trailMat: Material | null = null; + private _world_rot: Quat; private _node_scale: Vec4; + private _scale_local_trans: Mat4; + private _node_pos: Vec3; + private _pos_mat: Mat4; private _attrs: any[]; private _particles: RecyclePool | null = null; private _defaultTrailMat: Material | null = null; @@ -154,6 +159,8 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas private _uScaleHandle = 0; private _uLenHandle = 0; private _uNodeRotHandle = 0; + private _uTransformHandle = 0; + private _uTransTrailHandle = 0; private _alignSpace = AlignmentSpace.View; private _inited = false; private _localMat: Mat4 = new Mat4(); @@ -166,10 +173,15 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas this._frameTile_velLenScale = new Vec4(1, 1, 0, 0); this._tmp_velLenScale = this._frameTile_velLenScale.clone(); + this._world_rot = new Quat(); this._node_scale = new Vec4(); + this._scale_local_trans = new Mat4(); + this._node_pos = new Vec3(); + this._pos_mat = new Mat4(); this._attrs = new Array(7); this._defines = { CC_USE_WORLD_SPACE: true, + CC_USE_WORLD_SCALE: true, CC_USE_BILLBOARD: true, CC_USE_STRETCHED_BILLBOARD: false, CC_USE_HORIZONTAL_BILLBOARD: false, @@ -177,6 +189,8 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas }; this._trailDefines = { CC_USE_WORLD_SPACE: true, + CC_USE_WORLD_SCALE: true, + CC_USE_LINE: false, // CC_DRAW_WIRE_FRAME: true, // }; } @@ -331,15 +345,35 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas } } + private doScale (pass) { + Mat4.fromScaling(this._scale_local_trans, this._node_scale); + this._particleSystem.node.getWorldRotation(this._world_rot); + Quat.normalize(this._world_rot, this._world_rot); + Mat4.multiply(this._scale_local_trans, Mat4.fromQuat(_rot_mat, this._world_rot), this._scale_local_trans); + this._particleSystem.node.getWorldPosition(this._node_pos); + Mat4.fromTranslation(this._pos_mat, this._node_pos); + Mat4.multiply(this._scale_local_trans, this._pos_mat, this._scale_local_trans); + Mat4.copy(_tempWorldTrans, this._scale_local_trans); + + pass.setUniform(this._uTransformHandle, _tempWorldTrans); + if (this._trailMat) { + this._trailMat.passes[0].setUniform(this._uTransTrailHandle, _tempWorldTrans); + } + } + private doUpdateScale (pass) { switch (this._particleSystem.scaleSpace) { case Space.Local: this._particleSystem.node.getScale(this._node_scale); + this.doScale(pass); break; case Space.World: this._particleSystem.node.getWorldScale(this._node_scale); + this.doScale(pass); break; default: + this._particleSystem.node.getScale(this._node_scale); + this.doScale(pass); break; } pass.setUniform(this._uScaleHandle, this._node_scale); @@ -352,7 +386,6 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas if (!ps) { return this._particles!.length; } - ps.node.getWorldMatrix(_tempWorldTrans); const mat: Material | null = ps.getMaterialInstance(0) || this._defaultMat; const pass = mat!.passes[0]; this.doUpdateScale(pass); @@ -371,15 +404,11 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas const useGravity = !ps.gravityModifier.isZero(); if (useGravity) { if (ps.simulationSpace === Space.Local) { - const r: Quat = ps.node.getRotation(); - Mat4.fromQuat(this._localMat, r); - this._localMat.transpose(); // just consider rotation, use transpose as invert - } - - if (ps.node.parent) { - const r: Quat = ps.node.parent.getWorldRotation(); - Mat4.fromQuat(_tempParentInverse, r); - _tempParentInverse.transpose(); + Mat4.invert(this._localMat, _tempWorldTrans); + this._localMat.m12 = 0; + this._localMat.m13 = 0; + this._localMat.m14 = 0; + this._localMat.m15 = 1; } } @@ -408,10 +437,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas this._gravity.z = 0.0; this._gravity.w = 1.0; if (!approx(gravityFactor, 0.0, EPSILON)) { - if (ps.node.parent) { - this._gravity = this._gravity.transformMat4(_tempParentInverse); - } - this._gravity = this._gravity.transformMat4(this._localMat); + Vec4.transformMat4(this._gravity, this._gravity, this._localMat); p.velocity.x += this._gravity.x; p.velocity.y += this._gravity.y; @@ -661,10 +687,17 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas this._defines[CC_USE_WORLD_SPACE] = false; } + if (ps.scaleSpace === Space.World) { + this._defines[CC_USE_WORLD_SCALE] = true; + } else { + this._defines[CC_USE_WORLD_SCALE] = false; + } + const pass = mat.passes[0]; this._uScaleHandle = pass.getHandle('scale'); this._uLenHandle = pass.getHandle('frameTile_velLenScale'); this._uNodeRotHandle = pass.getHandle('nodeRotation'); + this._uTransformHandle = pass.getHandle('worldTrans'); const renderMode = this._renderInfo!.renderMode; const vlenScale = this._frameTile_velLenScale; @@ -716,8 +749,13 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas } else { this._trailDefines[CC_USE_WORLD_SPACE] = false; } - let mat = ps.getMaterialInstance(1); - if (mat === null && this._defaultTrailMat === null) { + if (ps.scaleSpace === Space.World) { + this._trailDefines[CC_USE_WORLD_SCALE] = true; + } else { + this._trailDefines[CC_USE_WORLD_SCALE] = false; + } + this._trailMat = ps.getMaterialInstance(1); + if (this._trailMat === null && this._defaultTrailMat === null) { _matInsInfo.parent = builtinResMgr.get('default-trail-material'); _matInsInfo.owner = this._particleSystem; _matInsInfo.subModelIdx = 1; @@ -726,9 +764,12 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas _matInsInfo.owner = null!; _matInsInfo.subModelIdx = 0; } - mat = mat || this._defaultTrailMat; - mat.recompileShaders(this._trailDefines); - trailModule.updateMaterial(); + this._trailMat = this._trailMat || this._defaultTrailMat; + if (this._trailMat) { + this._uTransTrailHandle = this._trailMat.passes[0].getHandle('worldTrans'); + this._trailMat.recompileShaders(this._trailDefines); + trailModule.updateMaterial(); + } } } diff --git a/cocos/particle/renderer/particle-system-renderer-gpu.ts b/cocos/particle/renderer/particle-system-renderer-gpu.ts index 9333d82902e..7550c0fa4b0 100644 --- a/cocos/particle/renderer/particle-system-renderer-gpu.ts +++ b/cocos/particle/renderer/particle-system-renderer-gpu.ts @@ -42,7 +42,7 @@ const _tempWorldTrans = new Mat4(); const _tempVec4 = new Vec4(); const _world_rot = new Quat(); const _node_rot = new Quat(); -const _node_euler = new Vec3(); +const _rot_mat = new Mat4(); const _sample_num = 32; const _sample_interval = 1.0 / _sample_num; @@ -133,7 +133,11 @@ export default class ParticleSystemRendererGPU extends ParticleSystemRendererBas private _frameTile_velLenScale: Vec4; private _unifrom_velLenScale: Vec4; private _tmp_velLenScale: Vec4; + private _world_rot: Quat; private _node_scale: Vec4; + private _scale_local_trans: Mat4; + private _node_pos: Vec3; + private _pos_mat: Mat4; protected _vertAttrs: Attribute[] = []; protected _defaultMat: Material | null = null; private _particleNum = 0; @@ -162,7 +166,11 @@ export default class ParticleSystemRendererGPU extends ParticleSystemRendererBas this._frameTile_velLenScale = new Vec4(1, 1, 0, 0); this._unifrom_velLenScale = this._frameTile_velLenScale.clone(); this._tmp_velLenScale = this._frameTile_velLenScale.clone(); + this._world_rot = new Quat(); this._node_scale = new Vec4(); + this._scale_local_trans = new Mat4(); + this._node_pos = new Vec3(); + this._pos_mat = new Mat4(); this._defines = { CC_USE_WORLD_SPACE: true, CC_USE_BILLBOARD: true, @@ -294,32 +302,47 @@ export default class ParticleSystemRendererGPU extends ParticleSystemRendererBas switch (this._particleSystem.scaleSpace) { case Space.Local: this._particleSystem.node.getScale(this._node_scale); + Mat4.fromScaling(this._scale_local_trans, this._node_scale); + this._particleSystem.node.getWorldRotation(this._world_rot); + Quat.normalize(this._world_rot, this._world_rot); + Mat4.multiply(this._scale_local_trans, Mat4.fromQuat(_rot_mat, this._world_rot), this._scale_local_trans); + this._particleSystem.node.getWorldPosition(this._node_pos); + Mat4.fromTranslation(this._pos_mat, this._node_pos); + Mat4.multiply(this._scale_local_trans, this._pos_mat, this._scale_local_trans); + Mat4.copy(_tempWorldTrans, this._scale_local_trans); break; case Space.World: this._particleSystem.node.getWorldScale(this._node_scale); + Mat4.fromScaling(this._scale_local_trans, this._node_scale); + this._particleSystem.node.getWorldRotation(this._world_rot); + Quat.normalize(this._world_rot, this._world_rot); + Mat4.multiply(this._scale_local_trans, Mat4.fromQuat(_rot_mat, this._world_rot), this._scale_local_trans); + this._particleSystem.node.getWorldPosition(this._node_pos); + Mat4.fromTranslation(this._pos_mat, this._node_pos); + Mat4.multiply(this._scale_local_trans, this._pos_mat, this._scale_local_trans); + Mat4.copy(_tempWorldTrans, this._scale_local_trans); break; default: + this._particleSystem.node.getScale(this._node_scale); + Mat4.fromScaling(this._scale_local_trans, this._node_scale); + this._particleSystem.node.getWorldRotation(this._world_rot); + Quat.normalize(this._world_rot, this._world_rot); + Mat4.multiply(this._scale_local_trans, Mat4.fromQuat(_rot_mat, this._world_rot), this._scale_local_trans); + this._particleSystem.node.getWorldPosition(this._node_pos); + Mat4.fromTranslation(this._pos_mat, this._node_pos); + Mat4.multiply(this._scale_local_trans, this._pos_mat, this._scale_local_trans); + Mat4.copy(_tempWorldTrans, this._scale_local_trans); break; } + pass.setUniform(pass.getHandle('worldTrans'), _tempWorldTrans); pass.setUniform(pass.getHandle('scale'), this._node_scale); } public updateParticles (dt: number) { + if (EDITOR && !cclegacy.GAME_VIEW) { const mat: Material | null = this._particleSystem.getMaterialInstance(0) || this._defaultMat; - - this._particleSystem.node.getWorldMatrix(_tempWorldTrans); - switch (this._particleSystem.scaleSpace) { - case Space.Local: - this._particleSystem.node.getScale(this._node_scale); - break; - case Space.World: - this._particleSystem.node.getWorldScale(this._node_scale); - break; - default: - break; - } - + this.doUpdateScale(mat?.passes[0]); this.initShaderUniform(mat!); } this._particleNum = this._model!.updateGPUParticles(this._particleNum, this._particleSystem._time, dt); @@ -590,8 +613,6 @@ export default class ParticleSystemRendererGPU extends ParticleSystemRendererBas } const mat: Material | null = ps.getMaterialInstance(0) || this._defaultMat; - ps.node.getWorldMatrix(_tempWorldTrans); - if (ps._simulationSpace === Space.World) { this._defines[CC_USE_WORLD_SPACE] = true; } else { diff --git a/cocos/particle/renderer/trail.ts b/cocos/particle/renderer/trail.ts index e02c073045d..49eb9c473da 100644 --- a/cocos/particle/renderer/trail.ts +++ b/cocos/particle/renderer/trail.ts @@ -47,6 +47,10 @@ const _temp_vec3 = new Vec3(); const _temp_vec3_1 = new Vec3(); const _temp_color = new Color(); +const _trans_mat = new Mat4(); +const _rol_mat = new Mat4(); +const _scale_mat = new Mat4(); + // const barycentric = [1, 0, 0, 0, 1, 0, 0, 0, 1]; // // let _bcIdx = 0; // @@ -452,10 +456,24 @@ export default class TrailModule { public update () { this._trailLifetime = this.lifeTime.evaluate(this._particleSystem._time, 1)!; - if (this.space === Space.World && this._particleSystem._simulationSpace === Space.Local) { + if (this.space === Space.World && (this._particleSystem._simulationSpace === Space.Local || this._particleSystem._simulationSpace === Space.Custom)) { this._needTransform = true; - this._particleSystem.node.getWorldMatrix(_temp_xform); this._particleSystem.node.getWorldRotation(_temp_quat); + Quat.normalize(_temp_quat, _temp_quat); + if (this._particleSystem.scaleSpace === Space.World) { + // this._particleSystem.node.getWorldMatrix(_temp_xform); + Mat4.fromScaling(_scale_mat, this._particleSystem.node.getWorldScale()); + Mat4.fromTranslation(_trans_mat, this._particleSystem.node.getWorldPosition()); + Mat4.fromQuat(_rol_mat, _temp_quat); + Mat4.multiply(_temp_xform, _rol_mat, _scale_mat); + Mat4.multiply(_temp_xform, _trans_mat, _temp_xform); + } else { + Mat4.fromScaling(_scale_mat, this._particleSystem.node.getScale()); + Mat4.fromTranslation(_trans_mat, this._particleSystem.node.getWorldPosition()); + Mat4.fromQuat(_rol_mat, _temp_quat); + Mat4.multiply(_temp_xform, _rol_mat, _scale_mat); + Mat4.multiply(_temp_xform, _trans_mat, _temp_xform); + } } else { this._needTransform = false; } diff --git a/editor/assets/chunks/builtin/internal/particle-common.chunk b/editor/assets/chunks/builtin/internal/particle-common.chunk index 4aba5d57da4..f494b87e0ab 100644 --- a/editor/assets/chunks/builtin/internal/particle-common.chunk +++ b/editor/assets/chunks/builtin/internal/particle-common.chunk @@ -10,6 +10,7 @@ uniform Constants { vec4 frameTile_velLenScale; vec4 scale; vec4 nodeRotation; + mat4 worldTrans; }; #include diff --git a/editor/assets/chunks/builtin/internal/particle-trail.chunk b/editor/assets/chunks/builtin/internal/particle-trail.chunk index c8935315da5..b0ed6e1ccdf 100644 --- a/editor/assets/chunks/builtin/internal/particle-trail.chunk +++ b/editor/assets/chunks/builtin/internal/particle-trail.chunk @@ -16,8 +16,13 @@ vec4 vs_main() { vec4 velocity = vec4(a_texCoord1.xyz, 0); #if !CC_USE_WORLD_SPACE - pos = cc_matWorld * pos; - velocity = cc_matWorld * velocity; + #if CC_USE_LINE + mat4 transMat = cc_matWorld; + #else + mat4 transMat = worldTrans; + #endif + pos = transMat * pos; + velocity.xyz = mat3(transMat) * velocity.xyz; #endif float vertOffset = (a_texCoord.x - 0.5) * a_texCoord.y; diff --git a/editor/assets/chunks/builtin/internal/particle-vs-gpu.chunk b/editor/assets/chunks/builtin/internal/particle-vs-gpu.chunk index bd886efdc58..32de0187ed9 100644 --- a/editor/assets/chunks/builtin/internal/particle-vs-gpu.chunk +++ b/editor/assets/chunks/builtin/internal/particle-vs-gpu.chunk @@ -262,9 +262,9 @@ vec4 gpvs_main () { pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w; #if !CC_USE_WORLD_SPACE - pos = cc_matWorld * pos; + pos = worldTrans * pos; #if CC_RENDER_MODE == RENDER_MODE_STRETCHED_BILLBOARD - velocity = rotateQuat(velocity, u_worldRot); + velocity.xyz = mat3(worldTrans) * velocity.xyz; #endif #endif diff --git a/editor/assets/chunks/builtin/internal/particle-vs-legacy.chunk b/editor/assets/chunks/builtin/internal/particle-vs-legacy.chunk index 1747a562027..4f53ad744c7 100644 --- a/editor/assets/chunks/builtin/internal/particle-vs-legacy.chunk +++ b/editor/assets/chunks/builtin/internal/particle-vs-legacy.chunk @@ -40,9 +40,10 @@ vec4 lpvs_main () { #if !CC_USE_WORLD_SPACE // simulate in world space. apply cc_matWorld matrix on CPU side. - pos = cc_matWorld * pos; + mat4 transMat = worldTrans; + pos = transMat * pos; #if CC_RENDER_MODE == RENDER_MODE_STRETCHED_BILLBOARD - velocity = cc_matWorld * velocity; + velocity.xyz = mat3(transMat) * velocity.xyz; #endif #endif