Browse Source

Fix multiply mode for particles

David Catuhe 7 years ago
parent
commit
a4abbefc7c

File diff suppressed because it is too large
+ 2197 - 2137
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 24 - 10
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 24 - 10
dist/preview release/babylon.no-module.max.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.worker.js


File diff suppressed because it is too large
+ 24 - 10
dist/preview release/es6.js


+ 174 - 3
dist/preview release/viewer/babylon.viewer.d.ts

@@ -515,10 +515,167 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
+    /**
+        * The current state of the model
+        */
+    export enum ModelState {
+            INIT = 0,
+            LOADING = 1,
+            LOADED = 2,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7
+    }
+    /**
+        * The viewer model is a container for all assets representing a sngle loaded model.
+        */
+    export class ViewerModel implements BABYLON.IDisposable {
+            /**
+                * The loader used to load this model.
+                */
+            loader: BABYLON.ISceneLoaderPlugin | BABYLON.ISceneLoaderPluginAsync;
+            /**
+                * This model's root mesh (the parent of all other meshes).
+                * This mesh does not(!) exist in the meshes array.
+                */
+            rootMesh: BABYLON.AbstractMesh;
+            /**
+                * ParticleSystems connected to this model
+                */
+            particleSystems: Array<BABYLON.IParticleSystem>;
+            /**
+                * Skeletons defined in this model
+                */
+            skeletons: Array<BABYLON.Skeleton>;
+            /**
+                * The current model animation.
+                * On init, this will be undefined.
+                */
+            currentAnimation: IModelAnimation;
+            /**
+                * Observers registered here will be executed when the model is done loading
+                */
+            onLoadedObservable: BABYLON.Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed when the loader notified of a progress event
+                */
+            onLoadProgressObservable: BABYLON.Observable<BABYLON.SceneLoaderProgressEvent>;
+            /**
+                * Observers registered here will be executed when the loader notified of an error.
+                */
+            onLoadErrorObservable: BABYLON.Observable<{
+                    message: string;
+                    exception: any;
+            }>;
+            /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: BABYLON.Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed every time the model is being configured.
+                * This can be used to extend the model's configuration without extending the class itself
+                */
+            onAfterConfigure: BABYLON.Observable<ViewerModel>;
+            /**
+                * The current model state (loaded, error, etc)
+                */
+            state: ModelState;
+            /**
+                * A loadID provided by the modelLoader, unique to ths (Abstract)Viewer instance.
+                */
+            loadId: number;
+            loadInfo: BABYLON.GLTF2.IAsset;
+            constructor(_observablesManager: ObservablesManager, modelConfiguration: IModelConfiguration, _configurationContainer?: ConfigurationContainer | undefined);
+            shadowsRenderedAfterLoad: boolean;
+            getViewerId(): string | undefined;
+            /**
+             * Set whether this model is enabled or not.
+             */
+            enabled: boolean;
+            loaderDone: boolean;
+            /**
+                * Add a mesh to this model.
+                * Any mesh that has no parent will be provided with the root mesh as its new parent.
+                *
+                * @param mesh the new mesh to add
+                * @param triggerLoaded should this mesh trigger the onLoaded observable. Used when adding meshes manually.
+                */
+            addMesh(mesh: BABYLON.AbstractMesh, triggerLoaded?: boolean): Promise<ViewerModel> | undefined;
+            /**
+                * get the list of meshes (excluding the root mesh)
+                */
+            readonly meshes: BABYLON.AbstractMesh[];
+            /**
+             * (Re-)set the model's entire configuration
+             * @param newConfiguration the new configuration to replace the new one
+             */
+            configuration: IModelConfiguration;
+            /**
+                * Update the current configuration with new values.
+                * Configuration will not be overwritten, but merged with the new configuration.
+                * Priority is to the new configuration
+                * @param newConfiguration the configuration to be merged into the current configuration;
+                */
+            updateConfiguration(newConfiguration: Partial<IModelConfiguration>): void;
+            /**
+                * Add a new animation group to this model.
+                * @param animationGroup the new animation group to be added
+                */
+            addAnimationGroup(animationGroup: BABYLON.AnimationGroup): void;
+            /**
+                * Get the ModelAnimation array
+                */
+            getAnimations(): Array<IModelAnimation>;
+            /**
+                * Get the animations' names. Using the names you can play a specific animation.
+                */
+            getAnimationNames(): Array<string>;
+            /**
+                * Get an animation by the provided name. Used mainly when playing n animation.
+                * @param name the name of the animation to find
+                */
+            protected _getAnimationByName(name: string): BABYLON.Nullable<IModelAnimation>;
+            /**
+                * Choose an initialized animation using its name and start playing it
+                * @param name the name of the animation to play
+                * @returns The model aniamtion to be played.
+                */
+            playAnimation(name: string): IModelAnimation;
+            setCurrentAnimationByName(name: string): IModelAnimation;
+            /**
+                * Apply a material configuration to a material
+                * @param material BABYLON.Material to apply configuration to
+                * @hidden
+                */
+            _applyModelMaterialConfiguration(material: BABYLON.Material): void;
+            /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: BABYLON.Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
+                * Will remove this model from the viewer (but NOT dispose it).
+                */
+            remove(): void;
+            /**
+                * Dispose this model, including all of its associated assets.
+                */
+            dispose(): void;
+    }
 }
 declare module BabylonViewer {
     /**
-        * Animation play mode enum - is the animation looping or playing once
+        * BABYLON.Animation play mode enum - is the animation looping or playing once
         */
     export const enum AnimationPlayMode {
             ONCE = 0,
@@ -600,7 +757,7 @@ declare module BabylonViewer {
                 */
             readonly currentFrame: number;
             /**
-                * Animation's FPS value
+                * BABYLON.Animation's FPS value
                 */
             readonly fps: number;
             /**
@@ -767,7 +924,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1401,6 +1558,20 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 181 - 2
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -566,7 +566,169 @@ declare module 'babylonjs-viewer/loader/modelLoader' {
 }
 
 declare module 'babylonjs-viewer/model/viewerModel' {
-    
+    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, AbstractMesh, Observable, SceneLoaderProgressEvent, IParticleSystem, Skeleton, IDisposable, Nullable, Animation, Material } from "babylonjs";
+    import { GLTF2 } from "babylonjs-loaders";
+    import { IModelConfiguration } from "babylonjs-viewer/configuration/interfaces/modelConfiguration";
+    import { IModelAnimation } from "babylonjs-viewer/model/modelAnimation";
+    import { ObservablesManager } from "babylonjs-viewer/managers/observablesManager";
+    import { ConfigurationContainer } from "babylonjs-viewer/configuration/configurationContainer";
+    /**
+        * The current state of the model
+        */
+    export enum ModelState {
+            INIT = 0,
+            LOADING = 1,
+            LOADED = 2,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7
+    }
+    /**
+        * The viewer model is a container for all assets representing a sngle loaded model.
+        */
+    export class ViewerModel implements IDisposable {
+            /**
+                * The loader used to load this model.
+                */
+            loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync;
+            /**
+                * This model's root mesh (the parent of all other meshes).
+                * This mesh does not(!) exist in the meshes array.
+                */
+            rootMesh: AbstractMesh;
+            /**
+                * ParticleSystems connected to this model
+                */
+            particleSystems: Array<IParticleSystem>;
+            /**
+                * Skeletons defined in this model
+                */
+            skeletons: Array<Skeleton>;
+            /**
+                * The current model animation.
+                * On init, this will be undefined.
+                */
+            currentAnimation: IModelAnimation;
+            /**
+                * Observers registered here will be executed when the model is done loading
+                */
+            onLoadedObservable: Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed when the loader notified of a progress event
+                */
+            onLoadProgressObservable: Observable<SceneLoaderProgressEvent>;
+            /**
+                * Observers registered here will be executed when the loader notified of an error.
+                */
+            onLoadErrorObservable: Observable<{
+                    message: string;
+                    exception: any;
+            }>;
+            /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed every time the model is being configured.
+                * This can be used to extend the model's configuration without extending the class itself
+                */
+            onAfterConfigure: Observable<ViewerModel>;
+            /**
+                * The current model state (loaded, error, etc)
+                */
+            state: ModelState;
+            /**
+                * A loadID provided by the modelLoader, unique to ths (Abstract)Viewer instance.
+                */
+            loadId: number;
+            loadInfo: GLTF2.IAsset;
+            constructor(_observablesManager: ObservablesManager, modelConfiguration: IModelConfiguration, _configurationContainer?: ConfigurationContainer | undefined);
+            shadowsRenderedAfterLoad: boolean;
+            getViewerId(): string | undefined;
+            /**
+             * Set whether this model is enabled or not.
+             */
+            enabled: boolean;
+            loaderDone: boolean;
+            /**
+                * Add a mesh to this model.
+                * Any mesh that has no parent will be provided with the root mesh as its new parent.
+                *
+                * @param mesh the new mesh to add
+                * @param triggerLoaded should this mesh trigger the onLoaded observable. Used when adding meshes manually.
+                */
+            addMesh(mesh: AbstractMesh, triggerLoaded?: boolean): Promise<ViewerModel> | undefined;
+            /**
+                * get the list of meshes (excluding the root mesh)
+                */
+            readonly meshes: AbstractMesh[];
+            /**
+             * (Re-)set the model's entire configuration
+             * @param newConfiguration the new configuration to replace the new one
+             */
+            configuration: IModelConfiguration;
+            /**
+                * Update the current configuration with new values.
+                * Configuration will not be overwritten, but merged with the new configuration.
+                * Priority is to the new configuration
+                * @param newConfiguration the configuration to be merged into the current configuration;
+                */
+            updateConfiguration(newConfiguration: Partial<IModelConfiguration>): void;
+            /**
+                * Add a new animation group to this model.
+                * @param animationGroup the new animation group to be added
+                */
+            addAnimationGroup(animationGroup: AnimationGroup): void;
+            /**
+                * Get the ModelAnimation array
+                */
+            getAnimations(): Array<IModelAnimation>;
+            /**
+                * Get the animations' names. Using the names you can play a specific animation.
+                */
+            getAnimationNames(): Array<string>;
+            /**
+                * Get an animation by the provided name. Used mainly when playing n animation.
+                * @param name the name of the animation to find
+                */
+            protected _getAnimationByName(name: string): Nullable<IModelAnimation>;
+            /**
+                * Choose an initialized animation using its name and start playing it
+                * @param name the name of the animation to play
+                * @returns The model aniamtion to be played.
+                */
+            playAnimation(name: string): IModelAnimation;
+            setCurrentAnimationByName(name: string): IModelAnimation;
+            /**
+                * Apply a material configuration to a material
+                * @param material Material to apply configuration to
+                * @hidden
+                */
+            _applyModelMaterialConfiguration(material: Material): void;
+            /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
+                * Will remove this model from the viewer (but NOT dispose it).
+                */
+            remove(): void;
+            /**
+                * Dispose this model, including all of its associated assets.
+                */
+            dispose(): void;
+    }
 }
 
 declare module 'babylonjs-viewer/model/modelAnimation' {
@@ -823,13 +985,14 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
+    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1500,6 +1663,22 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
+declare module 'babylonjs-viewer/optimizer/custom/extended' {
+    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';

+ 69 - 1
src/Particles/babylon.IParticleSystem.ts

@@ -396,6 +396,74 @@ module BABYLON {
          * You must use addEmitRateGradient and removeEmitRateGradient to udpate this list
          * @returns the list of emit rate gradients
          */
-        getEmitRateGradients(): Nullable<Array<FactorGradient>>;                        
+        getEmitRateGradients(): Nullable<Array<FactorGradient>>;                    
+        
+
+        /**
+         * Creates a Point Emitter for the particle system (emits directly from the emitter position)
+         * @param direction1 Particles are emitted between the direction1 and direction2 from within the box
+         * @param direction2 Particles are emitted between the direction1 and direction2 from within the box
+         * @returns the emitter
+         */
+        createPointEmitter(direction1: Vector3, direction2: Vector3): PointParticleEmitter;
+
+        /**
+         * Creates a Hemisphere Emitter for the particle system (emits along the hemisphere radius)
+         * @param radius The radius of the hemisphere to emit from
+         * @param radiusRange The range of the hemisphere to emit from [0-1] 0 Surface Only, 1 Entire Radius
+         * @returns the emitter
+         */
+        createHemisphericEmitter(radius: number, radiusRange: number): HemisphericParticleEmitter;
+
+        /**
+         * Creates a Sphere Emitter for the particle system (emits along the sphere radius)
+         * @param radius The radius of the sphere to emit from
+         * @param radiusRange The range of the sphere to emit from [0-1] 0 Surface Only, 1 Entire Radius
+         * @returns the emitter
+         */
+        createSphereEmitter(radius: number, radiusRange: number): SphereParticleEmitter;
+
+        /**
+         * Creates a Directed Sphere Emitter for the particle system (emits between direction1 and direction2)
+         * @param radius The radius of the sphere to emit from
+         * @param direction1 Particles are emitted between the direction1 and direction2 from within the sphere
+         * @param direction2 Particles are emitted between the direction1 and direction2 from within the sphere
+         * @returns the emitter
+         */
+        createDirectedSphereEmitter(radius: number, direction1:Vector3, direction2: Vector3): SphereDirectedParticleEmitter;
+
+        /**
+         * Creates a Cylinder Emitter for the particle system (emits from the cylinder to the particle position)
+         * @param radius The radius of the emission cylinder
+         * @param height The height of the emission cylinder
+         * @param radiusRange The range of emission [0-1] 0 Surface only, 1 Entire Radius
+         * @param directionRandomizer How much to randomize the particle direction [0-1]
+         * @returns the emitter
+         */
+        createCylinderEmitter(radius: number, height: number, radiusRange: number, directionRandomizer: number): CylinderParticleEmitter;
+
+        /**
+         * Creates a Cone Emitter for the particle system (emits from the cone to the particle position)
+         * @param radius The radius of the cone to emit from
+         * @param angle The base angle of the cone
+         * @returns the emitter
+         */
+        createConeEmitter(radius: number, angle: number): ConeParticleEmitter;
+
+        /**
+         * Creates a Box Emitter for the particle system. (emits between direction1 and direction2 from withing the box defined by minEmitBox and maxEmitBox)
+         * @param direction1 Particles are emitted between the direction1 and direction2 from within the box
+         * @param direction2 Particles are emitted between the direction1 and direction2 from within the box
+         * @param minEmitBox Particles are emitted from the box between minEmitBox and maxEmitBox
+         * @param maxEmitBox  Particles are emitted from the box between minEmitBox and maxEmitBox
+         * @returns the emitter
+         */
+        createBoxEmitter(direction1: Vector3, direction2: Vector3, minEmitBox: Vector3, maxEmitBox: Vector3): BoxParticleEmitter;   
+        
+        /**
+         * Get hosting scene
+         * @returns the scene
+         */
+        getScene(): Scene;
     }  
 }

+ 8 - 0
src/Particles/babylon.baseParticleSystem.ts

@@ -231,6 +231,14 @@ module BABYLON {
 
             this._reset();
         }
+        
+        /**
+         * Get hosting scene
+         * @returns the scene
+         */
+        public getScene(): Scene {
+            return this._scene;
+        }    
 
         /**
          * You can use gravity if you want to give an orientation to your particles.

+ 4 - 0
src/Particles/babylon.gpuParticleSystem.ts

@@ -803,6 +803,10 @@
                 defines = "\n#define CLIPPLANE4";
             }
 
+            if (this.blendMode === ParticleSystem.BLENDMODE_MULTIPLY) {
+                defines = "\n#define BLENDMULTIPLYMODE";
+            }
+
             if (this._isBillboardBased) {
                 defines += "\n#define BILLBOARD";
 

+ 9 - 2
src/Particles/babylon.particleHelper.ts

@@ -13,10 +13,17 @@ module BABYLON {
          * @param emitter defines the emitter to use
          * @param capacity defines the system capacity (default is 500 particles)
          * @param scene defines the hosting scene
+         * @param useGPU defines if a GPUParticleSystem must be created (default is false)
          * @returns the new Particle system
          */
-        public static CreateDefault(emitter: Nullable<AbstractMesh | Vector3>, capacity = 500, scene?: Scene): ParticleSystem {
-            var system = new ParticleSystem("default system", capacity, scene!);
+        public static CreateDefault(emitter: Nullable<AbstractMesh | Vector3>, capacity = 500, scene?: Scene, useGPU = false): IParticleSystem {
+            var system: IParticleSystem;
+            
+            if (useGPU) {
+                system= new GPUParticleSystem("default system", {capacity: capacity}, scene!);
+            } else {
+                system= new ParticleSystem("default system", capacity, scene!);
+            }
         
             system.emitter = emitter;
             system.particleTexture = new Texture("https://www.babylonjs.com/assets/Flare.png", system.getScene());

+ 4 - 10
src/Particles/babylon.particleSystem.ts

@@ -43,16 +43,6 @@
             this._onDisposeObserver = this.onDisposeObservable.add(callback);
         }
 
-
-
-        /**
-         * Get hosting scene
-         * @returns the scene
-         */
-        public getScene(): Scene {
-            return this._scene;
-        }    
-
         private _particles = new Array<Particle>();
         private _epsilon: number;
         private _capacity: number;
@@ -1104,6 +1094,10 @@
                 defines.push("#define ANIMATESHEET");
             }
 
+            if (this.blendMode === ParticleSystem.BLENDMODE_MULTIPLY) {
+                defines.push("#define BLENDMULTIPLYMODE");
+            }
+
             if (this._isBillboardBased) {
                 defines.push("#define BILLBOARD");
 

+ 6 - 1
src/Shaders/gpuRenderParticles.fragment.fx

@@ -17,7 +17,12 @@ out vec4 outFragColor;
 
 void main() {
 	#include<clipPlaneFragment> 
-  	outFragColor = texture(textureSampler, vUV) * vColor;
+	vec4 textureColor = texture(textureSampler, vUV);
+  	outFragColor = textureColor * vColor;
+
+	#ifdef BLENDMULTIPLYMODE
+	outFragColor.rgb += vec3(1.0 - textureColor.a);
+	#endif	  
 
 // Apply image processing if relevant. As this applies in linear space, 
 // We first move from gamma to linear.

+ 5 - 0
src/Shaders/particles.fragment.fx

@@ -16,8 +16,13 @@ void main(void) {
 	#include<clipPlaneFragment>
 
 	vec4 baseColor = texture2D(diffuseSampler, vUV);
+	float alpha = baseColor.a;
 	baseColor = (baseColor * textureMask + (vec4(1., 1., 1., 1.) - textureMask)) * vColor;
 
+	#ifdef BLENDMULTIPLYMODE
+	baseColor.rgb += vec3(1.0 - alpha);
+	#endif
+
 // Apply image processing if relevant. As this applies in linear space, 
 // We first move from gamma to linear.
 #ifdef IMAGEPROCESSINGPOSTPROCESS