David Catuhe 7 سال پیش
والد
کامیت
dcb6eca321

+ 15 - 0
Tools/Gulp/config.json

@@ -26,6 +26,7 @@
             "picking",
             "collisions",
             "particles",
+            "gpuParticles",
             "solidParticles",
             "additionalMeshes",
             "meshBuilder",
@@ -220,6 +221,20 @@
                 "particles.fragment"
             ]
         },
+        "gpuParticles": {
+            "files": [
+                "../../src/Particles/babylon.gpuParticleSystem.js"
+            ],
+            "dependUpon": [
+                "core"
+            ],
+            "shaders": [
+                "gpuRenderParticles.vertex",
+                "gpuRenderParticles.fragment",
+                "gpuUpdateParticles.vertex",
+                "gpuUpdateParticles.fragment"
+            ]
+        },
         "nullEngine": {
             "files": [
                 "../../src/Engine/babylon.nullEngine.js"

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 8450 - 8431
dist/preview release/babylon.d.ts


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 8450 - 8431
dist/preview release/babylon.module.d.ts


+ 46 - 3
src/Engine/babylon.engine.ts

@@ -2421,6 +2421,12 @@
         public _deleteProgram(program: WebGLProgram): void {
             if (program) {
                 program.__SPECTOR_rebuildProgram = null;
+
+                if (program.transformFeedback) {
+                    this.deleteTransformFeedback(program.transformFeedback);
+                    program.transformFeedback = null;
+                }
+
                 this._gl.deleteProgram(program);
             }
         }
@@ -2473,7 +2479,7 @@
             return this._createShaderProgram(vertexShader, fragmentShader, context);
         }
 
-        public createShaderProgram(vertexCode: string, fragmentCode: string, defines: Nullable<string>, context?: WebGLRenderingContext): WebGLProgram {
+        public createShaderProgram(vertexCode: string, fragmentCode: string, defines: Nullable<string>, context?: WebGLRenderingContext, transformFeedbackVaryings: Nullable<string[]> = null): WebGLProgram {
             context = context || this._gl;
 
             this.onBeforeShaderCompilationObservable.notifyObservers(this);
@@ -2482,14 +2488,14 @@
             var vertexShader = compileShader(context, vertexCode, "vertex", defines, shaderVersion);
             var fragmentShader = compileShader(context, fragmentCode, "fragment", defines, shaderVersion);
 
-            let program = this._createShaderProgram(vertexShader, fragmentShader, context);
+            let program = this._createShaderProgram(vertexShader, fragmentShader, context, transformFeedbackVaryings);
 
             this.onAfterShaderCompilationObservable.notifyObservers(this);
 
             return program;
         }
 
-        private _createShaderProgram(vertexShader: WebGLShader, fragmentShader: WebGLShader, context: WebGLRenderingContext): WebGLProgram {
+        private _createShaderProgram(vertexShader: WebGLShader, fragmentShader: WebGLShader, context: WebGLRenderingContext, transformFeedbackVaryings: Nullable<string[]> = null): WebGLProgram {
             var shaderProgram = context.createProgram();
 
             if (!shaderProgram) {
@@ -2499,8 +2505,20 @@
             context.attachShader(shaderProgram, vertexShader);
             context.attachShader(shaderProgram, fragmentShader);
 
+            if (this.webGLVersion > 1 && transformFeedbackVaryings) {
+                let transformFeedback = this.createTransformFeedback();
+
+                this.bindTransformFeedback(transformFeedback);
+                this.setTranformFeedbackVaryings(shaderProgram, transformFeedbackVaryings);
+                shaderProgram.transformFeedback = transformFeedback;
+            }
+
             context.linkProgram(shaderProgram);
 
+            if (this.webGLVersion > 1 && transformFeedbackVaryings) {
+                this.bindTransformFeedback(null);
+            }
+
             var linked = context.getProgramParameter(shaderProgram, context.LINK_STATUS);
 
             if (!linked) {
@@ -5250,6 +5268,31 @@
             return algorithmType === AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE ? this._gl.ANY_SAMPLES_PASSED_CONSERVATIVE : this._gl.ANY_SAMPLES_PASSED;
         }
 
+        // Transform feedback
+        public createTransformFeedback(): WebGLTransformFeedback {
+            return this._gl.createTransformFeedback();
+        }
+
+        public deleteTransformFeedback(value: WebGLTransformFeedback): void {
+            this._gl.deleteTransformFeedback(value);
+        }
+
+        public bindTransformFeedback(value: Nullable<WebGLTransformFeedback>): void {
+            this._gl.bindTransformFeedback(this._gl.TRANSFORM_FEEDBACK, value);
+        }
+
+        public beginTransformFeedback(): void {
+            this._gl.beginTransformFeedback(this._gl.TRIANGLES);
+        }
+
+        public endTransformFeedback(): void {
+            this._gl.endTransformFeedback();
+        }
+
+        public setTranformFeedbackVaryings(program: WebGLProgram, value: string[]): void {
+            this._gl.transformFeedbackVaryings(program, value, this._gl.INTERLEAVED_ATTRIBS);
+        }
+
         // Statics
         public static isSupported(): boolean {
             try {

+ 2 - 1
src/Engine/babylon.nullEngine.ts

@@ -120,7 +120,8 @@
 
         public createShaderProgram(vertexCode: string, fragmentCode: string, defines: string, context?: WebGLRenderingContext): WebGLProgram {
             return {
-                __SPECTOR_rebuildProgram: null,
+                transformFeedback: null,
+                __SPECTOR_rebuildProgram: null
             };
         }
 

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

@@ -13,6 +13,15 @@ interface WebGLRenderingContext {
     texImage3D(target: number, level: number, internalformat: number, width: number, height: number, depth: number, border: number, format: number, type: number, pixels: ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void;
     
     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;
+    createTransformFeedback(): WebGLTransformFeedback;
+    deleteTransformFeedback(transformFeedbac: WebGLTransformFeedback): void;
+    bindTransformFeedback(target: number, transformFeedback: Nullable<WebGLTransformFeedback>): void;
+    beginTransformFeedback(primitiveMode: number): void;
+    endTransformFeedback(): void;
+    transformFeedbackVaryings(program: WebGLProgram, varyings: string[], bufferMode: number): void;
 }
 
 interface ImageBitmap {

+ 6 - 3
src/Materials/babylon.effect.ts

@@ -81,11 +81,12 @@
         public uniformBuffersNames: string[];
         public samplers: string[];
         public defines: any;
-        public fallbacks: EffectFallbacks;
-        public onCompiled: (effect: Effect) => void;
-        public onError: (effect: Effect, errors: string) => void;
+        public fallbacks: Nullable<EffectFallbacks>;
+        public onCompiled: Nullable<(effect: Effect) => void>;
+        public onError: Nullable<(effect: Effect, errors: string) => void>;
         public indexParameters: any;
         public maxSimultaneousLights: number;
+        public transformFeedbackVaryings: Nullable<string[]>;
     }
 
     export class Effect {
@@ -116,6 +117,7 @@
         private _fragmentSourceCode: string;
         private _vertexSourceCodeOverride: string;
         private _fragmentSourceCodeOverride: string;
+        private _transformFeedbackVaryings: Nullable<string[]>;
 
         public _program: WebGLProgram;
         private _valueCache: { [key: string]: any };
@@ -137,6 +139,7 @@
                 this.onCompiled = options.onCompiled;
                 this._fallbacks = options.fallbacks;
                 this._indexParameters = options.indexParameters;  
+                this._transformFeedbackVaryings = options.transformFeedbackVaryings;
 
                 if (options.uniformBuffersNames) {
                     for (var i = 0; i < options.uniformBuffersNames.length; i++) {

+ 22 - 1
src/Particles/babylon.gpuParticleSystem.ts

@@ -5,6 +5,8 @@
         public emitter: Nullable<AbstractMesh | Vector3> = null;       
         public renderingGroupId = 0;        
         public layerMask: number = 0x0FFFFFFF;
+        private _renderingEffect: Effect;
+        private _updateEffect: Effect;
 
         private _scene: Scene;
 
@@ -23,7 +25,26 @@
             this.id = name;
             this._scene = scene || Engine.LastCreatedScene;
 
-            scene.particleSystems.push(this);
+            this._scene.particleSystems.push(this);
+
+            this._renderingEffect = new Effect("gpuRenderParticles", ["position", "age", "life", "velocity"], [], [], this._scene.getEngine());
+
+            let updateEffectOptions: EffectCreationOptions = {
+                attributes: ["position", "age", "life", "velocity"],
+                uniformsNames: [],
+                uniformBuffersNames: [],
+                samplers:[],
+                defines: "",
+                fallbacks: null,  
+                onCompiled: null,
+                onError: null,
+                indexParameters: null,
+                maxSimultaneousLights: 0,                                                      
+                transformFeedbackVaryings: ["outPosition", "outAge", "outLife", "outVelocity"]
+            };
+
+            this._updateEffect = new Effect("gpuUpdateParticles", updateEffectOptions, this._scene.getEngine());
+                                            
         }
 
         public animate(): void {

+ 4 - 0
src/Shaders/gpuRenderParticles.fragment.fx

@@ -0,0 +1,4 @@
+
+void main() {
+  gl_FragColor = vec4(1.0);
+}

+ 12 - 0
src/Shaders/gpuRenderParticles.vertex.fx

@@ -0,0 +1,12 @@
+#version 300 es
+
+// Particles state
+in vec3 position;
+in float age;
+in float life;
+in vec3 velocity;
+
+void main() {
+  gl_PointSize = 1.0;
+  gl_Position = vec4(position, 1.0);
+}

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

@@ -0,0 +1,5 @@
+#version 300 es
+
+void main() {
+  discard;
+}

+ 34 - 0
src/Shaders/gpuUpdateParticles.vertex.fx

@@ -0,0 +1,34 @@
+#version 300 es
+
+uniform float timeDelta;
+
+// Particles state
+in vec3 position;
+in float age;
+in float life;
+in vec3 velocity;
+
+// Output
+out vec3 outPosition;
+out float outAge;
+out float outLife;
+out vec3 outVelocity;
+
+void main() {
+  if (age >= life) {
+    // Create the particle at origin
+    outPosition = vec3(0, 0, 0);
+
+    // Age and life
+    outAge = 0.0;
+    outLife = life;
+
+    // Initial velocity
+    outVelocity = vec3(0, 1, 0);
+  } else {
+    outPosition = position + velocity * timeDelta;
+    outAge = age + timeDelta;
+    outLife = life;
+    outVelocity = velocity;
+  }
+}

+ 1 - 0
src/babylon.mixins.ts

@@ -120,6 +120,7 @@ interface WebGLBuffer {
 }
 
 interface WebGLProgram {
+    transformFeedback: Nullable<WebGLTransformFeedback>;
     __SPECTOR_rebuildProgram: Nullable<(vertexSourceCode: string, fragmentSourceCode: string, onCompiled: (program: WebGLProgram) => void, onError: (message: string) => void) => void>;
 }