David Catuhe 7 роки тому
батько
коміт
acf8b4b2f0

+ 53 - 32
dist/preview release/babylon.d.ts

@@ -4364,6 +4364,7 @@ declare module BABYLON {
         setStencilOperationDepthFail(operation: number): void;
         setStencilOperationPass(operation: number): void;
         setDitheringState(value: boolean): void;
+        setRasterizerState(value: boolean): void;
         /**
          * stop executing a render loop function and remove it from the execution array
          * @param {Function} [renderFunction] the function to be removed. If not provided all functions will be removed.
@@ -4670,9 +4671,10 @@ declare module BABYLON {
         createTransformFeedback(): WebGLTransformFeedback;
         deleteTransformFeedback(value: WebGLTransformFeedback): void;
         bindTransformFeedback(value: Nullable<WebGLTransformFeedback>): void;
-        beginTransformFeedback(): void;
+        beginTransformFeedback(usePoints?: boolean): void;
         endTransformFeedback(): void;
         setTranformFeedbackVaryings(program: WebGLProgram, value: string[]): void;
+        bindTransformFeedbackBuffer(value: Nullable<WebGLBuffer>): void;
         static isSupported(): boolean;
     }
 }
@@ -4746,6 +4748,7 @@ declare module BABYLON {
 }
 
 interface WebGLRenderingContext {
+    readonly RASTERIZER_DISCARD: number;
     readonly TEXTURE_3D: number;
     readonly TEXTURE_2D_ARRAY: number;
     readonly TEXTURE_WRAP_R: number;
@@ -4755,6 +4758,7 @@ interface WebGLRenderingContext {
     compressedTexImage3D(target: number, level: number, internalformat: number, width: number, height: number, depth: number, border: number, data: ArrayBufferView, offset?: number, length?: number): void;
     readonly TRANSFORM_FEEDBACK: number;
     readonly INTERLEAVED_ATTRIBS: number;
+    readonly TRANSFORM_FEEDBACK_BUFFER: number;
     createTransformFeedback(): WebGLTransformFeedback;
     deleteTransformFeedback(transformFeedbac: WebGLTransformFeedback): void;
     bindTransformFeedback(target: number, transformFeedback: Nullable<WebGLTransformFeedback>): void;
@@ -13284,17 +13288,34 @@ declare module BABYLON {
         emitter: Nullable<AbstractMesh | Vector3>;
         renderingGroupId: number;
         layerMask: number;
-        private _renderingEffect;
+        private _capacity;
+        private _renderEffect;
         private _updateEffect;
+        private _updateBuffer;
+        private _updateVAO;
+        private _updateVertexBuffers;
+        private _renderBuffer;
+        private _renderVAO;
+        private _renderVertexBuffers;
+        private _sourceVAO;
+        private _targetVAO;
+        private _sourceBuffer;
+        private _targetBuffer;
         private _scene;
+        private _engine;
+        private _currentRenderId;
+        private _started;
         /**
         * An event triggered when the system is disposed.
         * @type {BABYLON.Observable}
         */
         onDisposeObservable: Observable<GPUParticleSystem>;
         isStarted(): boolean;
+        start(): void;
+        stop(): void;
         constructor(name: string, capacity: number, scene: Scene);
         animate(): void;
+        private _initialize();
         render(): number;
         rebuild(): void;
         dispose(): void;
@@ -14227,6 +14248,36 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class ReflectionProbe {
+        name: string;
+        private _scene;
+        private _renderTargetTexture;
+        private _projectionMatrix;
+        private _viewMatrix;
+        private _target;
+        private _add;
+        private _attachedMesh;
+        invertYAxis: boolean;
+        position: Vector3;
+        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
+        samples: number;
+        refreshRate: number;
+        getScene(): Scene;
+        readonly cubeTexture: RenderTargetTexture;
+        readonly renderList: Nullable<AbstractMesh[]>;
+        attachToMesh(mesh: AbstractMesh): void;
+        /**
+         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
+         *
+         * @param renderingGroupId The rendering group id corresponding to its index
+         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
+         */
+        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
+        dispose(): void;
+    }
+}
+
+declare module BABYLON {
     class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         constructor(name: string, options: number | PostProcessOptions, rigCameras: Camera[], samplingMode?: number, engine?: Engine, reusable?: boolean);
@@ -14753,36 +14804,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class ReflectionProbe {
-        name: string;
-        private _scene;
-        private _renderTargetTexture;
-        private _projectionMatrix;
-        private _viewMatrix;
-        private _target;
-        private _add;
-        private _attachedMesh;
-        invertYAxis: boolean;
-        position: Vector3;
-        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
-        samples: number;
-        refreshRate: number;
-        getScene(): Scene;
-        readonly cubeTexture: RenderTargetTexture;
-        readonly renderList: Nullable<AbstractMesh[]>;
-        attachToMesh(mesh: AbstractMesh): void;
-        /**
-         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
-         *
-         * @param renderingGroupId The rendering group id corresponding to its index
-         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
-         */
-        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
-        dispose(): void;
-    }
-}
-
-declare module BABYLON {
     class BoundingBoxRenderer {
         frontColor: Color3;
         backColor: Color3;

+ 53 - 32
dist/preview release/babylon.module.d.ts

@@ -4369,6 +4369,7 @@ declare module BABYLON {
         setStencilOperationDepthFail(operation: number): void;
         setStencilOperationPass(operation: number): void;
         setDitheringState(value: boolean): void;
+        setRasterizerState(value: boolean): void;
         /**
          * stop executing a render loop function and remove it from the execution array
          * @param {Function} [renderFunction] the function to be removed. If not provided all functions will be removed.
@@ -4675,9 +4676,10 @@ declare module BABYLON {
         createTransformFeedback(): WebGLTransformFeedback;
         deleteTransformFeedback(value: WebGLTransformFeedback): void;
         bindTransformFeedback(value: Nullable<WebGLTransformFeedback>): void;
-        beginTransformFeedback(): void;
+        beginTransformFeedback(usePoints?: boolean): void;
         endTransformFeedback(): void;
         setTranformFeedbackVaryings(program: WebGLProgram, value: string[]): void;
+        bindTransformFeedbackBuffer(value: Nullable<WebGLBuffer>): void;
         static isSupported(): boolean;
     }
 }
@@ -4751,6 +4753,7 @@ declare module BABYLON {
 }
 
 interface WebGLRenderingContext {
+    readonly RASTERIZER_DISCARD: number;
     readonly TEXTURE_3D: number;
     readonly TEXTURE_2D_ARRAY: number;
     readonly TEXTURE_WRAP_R: number;
@@ -4760,6 +4763,7 @@ interface WebGLRenderingContext {
     compressedTexImage3D(target: number, level: number, internalformat: number, width: number, height: number, depth: number, border: number, data: ArrayBufferView, offset?: number, length?: number): void;
     readonly TRANSFORM_FEEDBACK: number;
     readonly INTERLEAVED_ATTRIBS: number;
+    readonly TRANSFORM_FEEDBACK_BUFFER: number;
     createTransformFeedback(): WebGLTransformFeedback;
     deleteTransformFeedback(transformFeedbac: WebGLTransformFeedback): void;
     bindTransformFeedback(target: number, transformFeedback: Nullable<WebGLTransformFeedback>): void;
@@ -13289,17 +13293,34 @@ declare module BABYLON {
         emitter: Nullable<AbstractMesh | Vector3>;
         renderingGroupId: number;
         layerMask: number;
-        private _renderingEffect;
+        private _capacity;
+        private _renderEffect;
         private _updateEffect;
+        private _updateBuffer;
+        private _updateVAO;
+        private _updateVertexBuffers;
+        private _renderBuffer;
+        private _renderVAO;
+        private _renderVertexBuffers;
+        private _sourceVAO;
+        private _targetVAO;
+        private _sourceBuffer;
+        private _targetBuffer;
         private _scene;
+        private _engine;
+        private _currentRenderId;
+        private _started;
         /**
         * An event triggered when the system is disposed.
         * @type {BABYLON.Observable}
         */
         onDisposeObservable: Observable<GPUParticleSystem>;
         isStarted(): boolean;
+        start(): void;
+        stop(): void;
         constructor(name: string, capacity: number, scene: Scene);
         animate(): void;
+        private _initialize();
         render(): number;
         rebuild(): void;
         dispose(): void;
@@ -14232,6 +14253,36 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class ReflectionProbe {
+        name: string;
+        private _scene;
+        private _renderTargetTexture;
+        private _projectionMatrix;
+        private _viewMatrix;
+        private _target;
+        private _add;
+        private _attachedMesh;
+        invertYAxis: boolean;
+        position: Vector3;
+        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
+        samples: number;
+        refreshRate: number;
+        getScene(): Scene;
+        readonly cubeTexture: RenderTargetTexture;
+        readonly renderList: Nullable<AbstractMesh[]>;
+        attachToMesh(mesh: AbstractMesh): void;
+        /**
+         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
+         *
+         * @param renderingGroupId The rendering group id corresponding to its index
+         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
+         */
+        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
+        dispose(): void;
+    }
+}
+
+declare module BABYLON {
     class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         constructor(name: string, options: number | PostProcessOptions, rigCameras: Camera[], samplingMode?: number, engine?: Engine, reusable?: boolean);
@@ -14758,36 +14809,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class ReflectionProbe {
-        name: string;
-        private _scene;
-        private _renderTargetTexture;
-        private _projectionMatrix;
-        private _viewMatrix;
-        private _target;
-        private _add;
-        private _attachedMesh;
-        invertYAxis: boolean;
-        position: Vector3;
-        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
-        samples: number;
-        refreshRate: number;
-        getScene(): Scene;
-        readonly cubeTexture: RenderTargetTexture;
-        readonly renderList: Nullable<AbstractMesh[]>;
-        attachToMesh(mesh: AbstractMesh): void;
-        /**
-         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
-         *
-         * @param renderingGroupId The rendering group id corresponding to its index
-         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
-         */
-        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
-        dispose(): void;
-    }
-}
-
-declare module BABYLON {
     class BoundingBoxRenderer {
         frontColor: Color3;
         backColor: Color3;

+ 14 - 2
src/Engine/babylon.engine.ts

@@ -1447,6 +1447,14 @@
             }
         }
 
+        public setRasterizerState(value: boolean): void {
+            if (value) {
+                this._gl.disable(this._gl.RASTERIZER_DISCARD);
+            } else {
+                this._gl.enable(this._gl.RASTERIZER_DISCARD);
+            }
+        }        
+
         /**
          * stop executing a render loop function and remove it from the execution array
          * @param {Function} [renderFunction] the function to be removed. If not provided all functions will be removed.
@@ -5281,8 +5289,8 @@
             this._gl.bindTransformFeedback(this._gl.TRANSFORM_FEEDBACK, value);
         }
 
-        public beginTransformFeedback(): void {
-            this._gl.beginTransformFeedback(this._gl.TRIANGLES);
+        public beginTransformFeedback(usePoints: boolean = true): void {
+            this._gl.beginTransformFeedback(usePoints ? this._gl.POINTS : this._gl.TRIANGLES);
         }
 
         public endTransformFeedback(): void {
@@ -5293,6 +5301,10 @@
             this._gl.transformFeedbackVaryings(program, value, this._gl.INTERLEAVED_ATTRIBS);
         }
 
+        public bindTransformFeedbackBuffer(value: Nullable<WebGLBuffer>): void {
+            this._gl.bindBufferBase(this._gl.TRANSFORM_FEEDBACK_BUFFER, 0, value);
+        }
+
         // Statics
         public static isSupported(): boolean {
             try {

+ 2 - 0
src/Engine/babylon.webgl2.ts

@@ -4,6 +4,7 @@
 // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
 
 interface WebGLRenderingContext {
+    readonly RASTERIZER_DISCARD: number;
     readonly TEXTURE_3D: number;
     readonly TEXTURE_2D_ARRAY: number;
     readonly TEXTURE_WRAP_R: number;
@@ -16,6 +17,7 @@ interface WebGLRenderingContext {
 
     readonly TRANSFORM_FEEDBACK: number;
     readonly INTERLEAVED_ATTRIBS: number;
+    readonly TRANSFORM_FEEDBACK_BUFFER: number;
     createTransformFeedback(): WebGLTransformFeedback;
     deleteTransformFeedback(transformFeedbac: WebGLTransformFeedback): void;
     bindTransformFeedback(target: number, transformFeedback: Nullable<WebGLTransformFeedback>): void;

+ 132 - 7
src/Particles/babylon.gpuParticleSystem.ts

@@ -4,11 +4,28 @@
         public id: string;
         public emitter: Nullable<AbstractMesh | Vector3> = null;       
         public renderingGroupId = 0;        
-        public layerMask: number = 0x0FFFFFFF;
-        private _renderingEffect: Effect;
+        public layerMask: number = 0x0FFFFFFF; // TODO
+        private _capacity: number;
+        private _renderEffect: Effect;
         private _updateEffect: Effect;
 
+        private _updateBuffer: Buffer;
+        private _updateVAO: WebGLVertexArrayObject;
+        private _updateVertexBuffers: {[key: string]: VertexBuffer} = {};
+        private _renderBuffer: Buffer;
+        private _renderVAO: WebGLVertexArrayObject;
+        private _renderVertexBuffers: {[key: string]: VertexBuffer} = {};
+
+        private _sourceVAO: WebGLVertexArrayObject;
+        private _targetVAO: WebGLVertexArrayObject;
+        private _sourceBuffer: Buffer;
+        private _targetBuffer: Buffer;
+
         private _scene: Scene;
+        private _engine: Engine;
+
+        private _currentRenderId = -1;    
+        private _started = true;    
 
         /**
         * An event triggered when the system is disposed.
@@ -16,18 +33,27 @@
         */
         public onDisposeObservable = new Observable<GPUParticleSystem>();
 
-
         public isStarted(): boolean {
-            return false;
+            return this._started;
+        }     
+
+        public start(): void {
+            this._started = true;
+        }
+
+        public stop(): void {
+            this._started = false;
         }        
 
         constructor(public name: string, capacity: number, scene: Scene) {
             this.id = name;
             this._scene = scene || Engine.LastCreatedScene;
+            this._capacity = capacity;
+            this._engine = this._scene.getEngine();
 
             this._scene.particleSystems.push(this);
 
-            this._renderingEffect = new Effect("gpuRenderParticles", ["position", "age", "life", "velocity"], [], [], this._scene.getEngine());
+            this._renderEffect = new Effect("gpuRenderParticles", ["position", "age", "life", "velocity"], [], [], this._scene.getEngine());
 
             let updateEffectOptions: EffectCreationOptions = {
                 attributes: ["position", "age", "life", "velocity"],
@@ -43,15 +69,112 @@
                 transformFeedbackVaryings: ["outPosition", "outAge", "outLife", "outVelocity"]
             };
 
-            this._updateEffect = new Effect("gpuUpdateParticles", updateEffectOptions, this._scene.getEngine());
-                                            
+            this._updateEffect = new Effect("gpuUpdateParticles", updateEffectOptions, this._scene.getEngine());   
         }
 
         public animate(): void {
+            // Do nothing
+        }
+        
+        private _initialize(): void {
+            if (this._renderVAO) {
+                return;
+            }
+
+            var data = new Array<float>();
+            for (var particleIndex = 0; particleIndex < this._capacity; particleIndex++) {
+              // position
+              data.push(0.0);
+              data.push(0.0);
+              data.push(0.0);
+          
+              var life = 1 + Math.random() * 10; // TODO: var
+              data.push(life + 1); // create the particle as a dead one to create a new one at start
+              data.push(life);
+          
+              // velocity
+              data.push(0.0);
+              data.push(0.0);
+              data.push(0.0);
+            }
 
+            // Update VAO
+            this._updateBuffer = new Buffer(this._scene.getEngine(), data, false, 0);
+            this._updateVertexBuffers["position"] = this._updateBuffer.createVertexBuffer("position", 0, 3, 3);
+            this._updateVertexBuffers["age"] = this._updateBuffer.createVertexBuffer("age", 3, 1, 1);
+            this._updateVertexBuffers["life"] = this._updateBuffer.createVertexBuffer("life", 4, 1, 1);
+            this._updateVertexBuffers["velocity"] = this._updateBuffer.createVertexBuffer("velocity", 5, 3, 3);
+           
+            this._updateVAO = this._engine.recordVertexArrayObject(this._updateVertexBuffers, null, this._updateEffect);
+            this._engine.bindArrayBuffer(null);
+
+            // Render VAO
+            this._renderBuffer = new Buffer(this._scene.getEngine(), data, false, 0);
+            this._renderVertexBuffers["position"] = this._renderBuffer.createVertexBuffer("position", 0, 3, 3);
+            this._renderVertexBuffers["age"] = this._renderBuffer.createVertexBuffer("age", 3, 1, 1);
+            this._renderVertexBuffers["life"] = this._renderBuffer.createVertexBuffer("life", 4, 1, 1);
+            this._renderVertexBuffers["velocity"] = this._renderBuffer.createVertexBuffer("velocity", 5, 3, 3);
+           
+            this._renderVAO = this._engine.recordVertexArrayObject(this._renderVertexBuffers, null, this._renderEffect);  
+            this._engine.bindArrayBuffer(null);          
+
+            // Links
+            this._sourceVAO = this._updateVAO;
+            this._targetVAO = this._renderVAO;
+
+            this._sourceBuffer = this._updateBuffer;
+            this._targetBuffer = this._renderBuffer;
         }
 
         public render(): number {
+            if (!this.emitter || !this._updateEffect.isReady() || !this._renderEffect.isReady() ) {
+                return 0;
+            }
+
+            // Get everything ready to render
+            this. _initialize();
+            
+            if (this._currentRenderId === this._scene.getRenderId()) {
+                return 0;
+            }
+
+            this._currentRenderId = this._scene.getRenderId();            
+
+            // Enable update effect
+            this._engine.enableEffect(this._updateEffect);
+            this._engine.setState(false);            
+
+            // Bind source VAO
+            this._engine.bindVertexArrayObject(this._sourceVAO, null);
+
+            // Update
+            this._engine.bindTransformFeedbackBuffer(this._targetBuffer.getBuffer());
+            this._engine.setRasterizerState(false);
+            this._engine.beginTransformFeedback();
+            this._engine.drawPointClouds(0, this._capacity);
+            this._engine.endTransformFeedback();
+            this._engine.setRasterizerState(true);
+            this._engine.bindTransformFeedbackBuffer(null);
+
+            // Enable render effect
+            this._engine.enableEffect(this._renderEffect);
+
+            // Bind source VAO
+            this._engine.bindVertexArrayObject(this._targetVAO, null);
+
+            // Render
+            this._engine.drawPointClouds(0, this._capacity);            
+
+            // Switch VAOs
+            let tmpVAO = this._sourceVAO;
+            this._sourceVAO = this._targetVAO;
+            this._targetVAO = tmpVAO;
+
+            // Switch buffers
+            let tmpBuffer = this._sourceBuffer;
+            this._sourceBuffer = this._targetBuffer;
+            this._targetBuffer = tmpBuffer;            
+
             return 0;
         }
 
@@ -65,6 +188,8 @@
                 this._scene.particleSystems.splice(index, 1);
             }
 
+            //TODO: this._dataBuffer.dispose();
+
             // Callback
             this.onDisposeObservable.notifyObservers(this);
             this.onDisposeObservable.clear();