Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix particle scale mode issue #14276

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 40 additions & 19 deletions cocos/particle/particle-culler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ 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 _rol_mat = new Mat4();
const _scale_mat = new Mat4();
const _pos_mat = new Mat4();
const _trans_mat = new Mat4();
const _rol_scale_mat = new Mat4();

const _anim_module = [
'_colorOverLifetimeModule',
Expand Down Expand Up @@ -129,8 +134,23 @@ 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.fromTranslation(_pos_mat, _node_pos);
Mat4.fromQuat(_rol_mat, _node_rol);
Mat4.fromScaling(_scale_mat, _node_scale);
Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat);
zxx43 marked this conversation as resolved.
Show resolved Hide resolved
Mat4.multiply(_trans_mat, _pos_mat, _rol_scale_mat);
}

for (let i = 0; i < count; ++i) {
Expand All @@ -155,8 +175,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);
Expand Down Expand Up @@ -187,6 +207,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);
Expand All @@ -197,20 +219,22 @@ export class ParticleCuller {
default:
break;
}
Mat4.fromTranslation(_pos_mat, _node_pos);
Mat4.fromQuat(_rol_mat, _node_rol);
Mat4.fromScaling(_scale_mat, _node_scale);
Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat);
Mat4.multiply(_trans_mat, _pos_mat, _rol_scale_mat);

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.invert(this._localMat, _trans_mat);
this._localMat.m12 = 0;
zxx43 marked this conversation as resolved.
Show resolved Hide resolved
this._localMat.m13 = 0;
this._localMat.m14 = 0;
this._localMat.m15 = 1;
}

for (let i = 0; i < particleLst.length; ++i) {
Expand All @@ -229,10 +253,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;
Expand Down Expand Up @@ -271,7 +292,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);
Expand Down
39 changes: 35 additions & 4 deletions cocos/particle/particle-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')!;

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
104 changes: 82 additions & 22 deletions cocos/particle/renderer/particle-system-renderer-cpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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';
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -166,17 +173,24 @@ 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,
CC_USE_VERTICAL_BILLBOARD: false,
};
this._trailDefines = {
CC_USE_WORLD_SPACE: true,
CC_USE_WORLD_SCALE: true,
CC_USE_LINE: false,
// CC_DRAW_WIRE_FRAME: true, // <wireframe debug>
};
}
Expand Down Expand Up @@ -335,11 +349,50 @@ export default class ParticleSystemRendererCPU 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);
zxx43 marked this conversation as resolved.
Show resolved Hide resolved
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);
}
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);

pass.setUniform(this._uTransformHandle, _tempWorldTrans);
if (this._trailMat) {
this._trailMat.passes[0].setUniform(this._uTransTrailHandle, _tempWorldTrans);
}
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);

pass.setUniform(this._uTransformHandle, _tempWorldTrans);
if (this._trailMat) {
this._trailMat.passes[0].setUniform(this._uTransTrailHandle, _tempWorldTrans);
}
break;
}
pass.setUniform(this._uScaleHandle, this._node_scale);
Expand All @@ -352,7 +405,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);
Expand All @@ -371,15 +423,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;
}
}

Expand Down Expand Up @@ -408,10 +456,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;
Expand Down Expand Up @@ -661,10 +706,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;
Expand Down Expand Up @@ -716,8 +768,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<Material>('default-trail-material');
_matInsInfo.owner = this._particleSystem;
_matInsInfo.subModelIdx = 1;
Expand All @@ -726,9 +783,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();
}
}
}

Expand Down
Loading