Kaynağa Gözat

Add support for multiple custom effects depending on the blend mode

Popov72 5 yıl önce
ebeveyn
işleme
e68b1bc2cf

+ 9 - 7
src/Materials/Node/nodeMaterial.ts

@@ -42,6 +42,7 @@ import { MultiplyBlock } from './Blocks/multiplyBlock';
 import { NodeMaterialModes } from './Enums/nodeMaterialModes';
 import { Texture } from '../Textures/texture';
 import { ParticleSystem } from '../../Particles/particleSystem';
+import { BaseParticleSystem } from '../../Particles/baseParticleSystem';
 
 const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };
 
@@ -810,7 +811,7 @@ export class NodeMaterial extends PushMaterial {
         return postProcess;
     }
 
-    private _createEffectForParticles(particleSystem: ParticleSystem, onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, effect?: Effect, defines?: NodeMaterialDefines, dummyMesh?: AbstractMesh) {
+    private _createEffectForParticles(particleSystem: ParticleSystem, blendMode: number, onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, effect?: Effect, defines?: NodeMaterialDefines, dummyMesh?: AbstractMesh) {
         let tempName = this.name + this._buildId;
 
         if (!defines) {
@@ -831,13 +832,13 @@ export class NodeMaterial extends PushMaterial {
 
             Effect.RegisterShader(tempName, this._fragmentCompilationState._builtCompilationString);
 
-            particleSystem.fillDefines(particleSystemDefines, particleSystem.blendMode);
+            particleSystem.fillDefines(particleSystemDefines, blendMode);
 
             particleSystemDefinesJoined = particleSystemDefines.join("\n");
 
             effect = this.getScene().getEngine().createEffectForParticles(tempName, this._fragmentCompilationState.uniforms, this._fragmentCompilationState.samplers, defines.toString() + "\n" + particleSystemDefinesJoined, result?.fallbacks, onCompiled, onError, particleSystem);
 
-            particleSystem.customEffect = effect;
+            particleSystem.setCustomEffect(effect, blendMode);
         }
 
         effect.onBindObservable.add((effect) => {
@@ -853,7 +854,7 @@ export class NodeMaterial extends PushMaterial {
 
             particleSystemDefines.length = 0;
 
-            particleSystem.fillDefines(particleSystemDefines, particleSystem.blendMode);
+            particleSystem.fillDefines(particleSystemDefines, blendMode);
 
             const particleSystemDefinesJoinedCurrent = particleSystemDefines.join("\n");
 
@@ -868,8 +869,8 @@ export class NodeMaterial extends PushMaterial {
                 Effect.RegisterShader(tempName, this._fragmentCompilationState._builtCompilationString);
 
                 effect = this.getScene().getEngine().createEffectForParticles(tempName, this._fragmentCompilationState.uniforms, this._fragmentCompilationState.samplers, defines!.toString() + "\n" + particleSystemDefinesJoined, result?.fallbacks, onCompiled, onError, particleSystem);
-                particleSystem.customEffect = effect;
-                this._createEffectForParticles(particleSystem, onCompiled, onError, effect, defines, dummyMesh); // add the effect.onBindObservable observer
+                particleSystem.setCustomEffect(effect, blendMode);
+                this._createEffectForParticles(particleSystem, blendMode, onCompiled, onError, effect, defines, dummyMesh); // add the effect.onBindObservable observer
                 return;
             }
 
@@ -907,7 +908,8 @@ export class NodeMaterial extends PushMaterial {
      * @param onError defines a function to call when the effect creation has failed
      */
     public createEffectForParticles(particleSystem: ParticleSystem, onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void) {
-        this._createEffectForParticles(particleSystem, onCompiled, onError);
+        this._createEffectForParticles(particleSystem, BaseParticleSystem.BLENDMODE_ONEONE, onCompiled, onError);
+        this._createEffectForParticles(particleSystem, BaseParticleSystem.BLENDMODE_MULTIPLY, onCompiled, onError);
     }
 
     private _processDefines(mesh: AbstractMesh, defines: NodeMaterialDefines, useInstances = false): Nullable<{

+ 22 - 14
src/Particles/particleSystem.ts

@@ -105,7 +105,7 @@ export class ParticleSystem extends BaseParticleSystem implements IDisposable, I
     private _spriteBuffer: Nullable<Buffer>;
     private _indexBuffer: Nullable<DataBuffer>;
     private _effect: Effect;
-    private _customEffect: Nullable<Effect>;
+    private _customEffect: { [blendMode: number] : Nullable<Effect> };
     private _cachedDefines: string;
     private _scaledColorStep = new Color4(0, 0, 0, 0);
     private _colorDiff = new Color4(0, 0, 0, 0);
@@ -214,14 +214,21 @@ export class ParticleSystem extends BaseParticleSystem implements IDisposable, I
     }
 
     /**
-     * Gets or sets the custom effect used to render the particles
+     * Gets the custom effect used to render the particles
+     * @params blendMode Blend mode for which the effect should be retrieved
+     * @returns the effect
      */
-    public get customEffect(): Nullable<Effect> {
-        return this._customEffect;
+    public getCustomEffect(blendMode = 0): Nullable<Effect> {
+        return this._customEffect[blendMode] ?? this._customEffect[0];
     }
 
-    public set customEffect(effect: Nullable<Effect>) {
-        this._customEffect = effect;
+    /**
+     * Sets the custom effect used to render the particles
+     * @params effect The effect to set
+     * @params blendMode Blend mode for which the effect should be set
+     */
+    public setCustomEffect(effect: Nullable<Effect>, blendMode = 0) {
+        this._customEffect[blendMode] = effect;
     }
 
     /** @hidden */
@@ -263,7 +270,7 @@ export class ParticleSystem extends BaseParticleSystem implements IDisposable, I
         // Setup the default processing configuration to the scene.
         this._attachImageProcessingConfiguration(null);
 
-        this._customEffect = customEffect;
+        this._customEffect = { 0: customEffect };
 
         this._scene.particleSystems.push(this);
 
@@ -1663,8 +1670,10 @@ export class ParticleSystem extends BaseParticleSystem implements IDisposable, I
 
     /** @hidden */
     private _getEffect(blendMode: number): Effect {
-        if (this._customEffect) {
-            return this._customEffect;
+        const customEffect = this.getCustomEffect(blendMode);
+
+        if (customEffect) {
+            return customEffect;
         }
 
         var defines: Array<string> = [];
@@ -2027,17 +2036,16 @@ export class ParticleSystem extends BaseParticleSystem implements IDisposable, I
      * @returns the cloned particle system
      */
     public clone(name: string, newEmitter: any): ParticleSystem {
-        var custom: Nullable<Effect> = null;
+        var custom = { ...this._customEffect };
         var program: any = null;
         if (this.customShader != null) {
             program = this.customShader;
             var defines: string = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
-            custom = this._scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
-        } else if (this._customEffect) {
-            custom = this._customEffect;
+            custom[0] = this._scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
         }
-        var result = new ParticleSystem(name, this._capacity, this._scene, custom);
+        var result = new ParticleSystem(name, this._capacity, this._scene, custom[0]);
         result.customShader = program;
+        result._customEffect = custom;
 
         DeepCopier.DeepCopy(this, result, ["particles", "customShader", "noiseTexture", "particleTexture", "onDisposeObservable"]);