Parcourir la source

Merge pull request #132 from michael-korbas/postProcess-master

Post processes
deltakosh il y a 11 ans
Parent
commit
68ee6d7a5a

+ 102 - 10
Babylon/Cameras/babylon.camera.js

@@ -5,7 +5,7 @@ var BABYLON = BABYLON || {};
 (function () {
     BABYLON.Camera = function (name, position, scene) {
         BABYLON.Node.call(this, scene);
-
+        
         this.name = name;
         this.id = name;
         this.position = position;
@@ -24,7 +24,8 @@ var BABYLON = BABYLON || {};
         this.animations = [];
 
         // Postprocesses
-        this.postProcesses = [];
+        this._postProcesses = [];
+        this._postProcessesTakenIndices = [];
 
         // Viewport
         this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
@@ -125,7 +126,7 @@ var BABYLON = BABYLON || {};
         var check = this._cache.mode === this.mode
              && this._cache.minZ === this.minZ
              && this._cache.maxZ === this.maxZ;
-
+             
         if (!check) {
             return false;
         }
@@ -151,18 +152,109 @@ var BABYLON = BABYLON || {};
     // Controls
     BABYLON.Camera.prototype.attachControl = function (canvas) {
     };
-
+    
     BABYLON.Camera.prototype.detachControl = function (canvas) {
     };
 
     BABYLON.Camera.prototype._update = function () {
     };
+    
+    BABYLON.Camera.prototype.attachPostProcess = function (postProcess, insertAt) {
+        if (!postProcess._reusable && this._postProcesses.indexOf(postProcess) > -1) {
+            console.error("You're trying to reuse a post process not defined as reusable.");
+            return;
+        }
+
+        if (!insertAt || insertAt < 0) {
+            this._postProcesses.push(postProcess);
+            this._postProcessesTakenIndices.push(this._postProcesses.length - 1);
+
+            return this._postProcesses.length - 1;
+        }
+
+        var add = 0;
+
+        if (this._postProcesses[insertAt]) {
+
+            var start = this._postProcesses.length - 1;
+
+
+            for (var i = start; i >= insertAt + 1; --i) {
+                this._postProcesses[i + 1] = this._postProcesses[i];
+            }
+
+            add = 1;
+        }
+
+        for (var i = 0; i < this._postProcessesTakenIndices.length; ++i) {
+            if (this._postProcessesTakenIndices[i] < insertAt) {
+                continue;
+            }
+
+            var start = this._postProcessesTakenIndices.length - 1;
+            for (var j = start; j >= i; --j) {
+                this._postProcessesTakenIndices[j + 1] = this._postProcessesTakenIndices[j] + add;
+            }
+            this._postProcessesTakenIndices[i] = insertAt;
+            break;
+        }
+
+        if (!add && this._postProcessesTakenIndices.indexOf(insertAt) == -1) {
+            this._postProcessesTakenIndices.push(insertAt);
+        }
+
+        result = insertAt + add;
+
+        this._postProcesses[result] = postProcess;
+
+        return result;
+    };
+
+    BABYLON.Camera.prototype.detachPostProcess = function (postProcess, atIndices) {
+        var result = [];
+
+
+        if (!atIndices) {
+
+            var length = this._postProcesses.length;
+
+            for (var i = 0; i < length; i++) {
+
+                if (this._postProcesses[i] !== postProcess) {
+                    continue;
+                }
+
+                delete this._postProcesses[i];
+
+                var index = this._postProcessesTakenIndices.indexOf(i);
+                this._postProcessesTakenIndices.splice(index, 1);
+            }
+
+        }
+        else {
+            atIndices = (atIndices instanceof Array) ? atIndices : [atIndices];
+            for (var i = 0; i < atIndices.length; i++) {
+                var foundPostProcess = this._postProcesses[atIndices[i]];
+
+                if (foundPostProcess !== postProcess) {
+                    result.push(i);
+                    continue;
+                }
+
+                delete this._postProcesses[atIndices[i]];
+
+                var index = this._postProcessesTakenIndices.indexOf(atIndices[i]);
+                this._postProcessesTakenIndices.splice(index, 1);
+            }
+        }
+        return result;
+    };
 
     BABYLON.Camera.prototype.getWorldMatrix = function () {
         if (!this._worldMatrix) {
             this._worldMatrix = BABYLON.Matrix.Identity();
         }
-
+        
         var viewMatrix = this.getViewMatrix();
 
         viewMatrix.invertToRef(this._worldMatrix);
@@ -186,7 +278,7 @@ var BABYLON = BABYLON || {};
         if (!this._worldMatrix) {
             this._worldMatrix = BABYLON.Matrix.Identity();
         }
-
+        
         this._computedViewMatrix.invertToRef(this._worldMatrix);
 
         this._worldMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._computedViewMatrix);
@@ -195,7 +287,7 @@ var BABYLON = BABYLON || {};
 
         return this._computedViewMatrix;
     };
-
+    
     BABYLON.Camera.prototype._computeViewMatrix = function (force) {
         if (!force && this._isSynchronizedViewMatrix()) {
             return this._computedViewMatrix;
@@ -226,10 +318,10 @@ var BABYLON = BABYLON || {};
         // Remove from scene
         var index = this._scene.cameras.indexOf(this);
         this._scene.cameras.splice(index, 1);
-
+        
         // Postprocesses
-        while (this.postProcesses.length) {
-            this.postProcesses[0].dispose();
+        for (var i = 0; i < this._postProcessesTakenIndices.length; ++i) {
+            this._postProcesses[this._postProcessesTakenIndices[i]].dispose(this);
         }
     };
 })();

+ 2 - 2
Babylon/PostProcess/babylon.blackAndWhitePostProcess.js

@@ -3,8 +3,8 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.BlackAndWhitePostProcess = function (name, ratio, camera, samplingMode) {
-        BABYLON.PostProcess.call(this, name, "blackAndWhite", null, null, ratio, camera, samplingMode);
+    BABYLON.BlackAndWhitePostProcess = function (name, ratio, camera, samplingMode, engine, reusable) {
+        BABYLON.PostProcess.call(this, name, "blackAndWhite", null, null, ratio, camera, samplingMode, engine, reusable);
     };
     
     BABYLON.BlackAndWhitePostProcess.prototype = Object.create(BABYLON.PostProcess.prototype);

+ 2 - 2
Babylon/PostProcess/babylon.blurPostProcess.js

@@ -3,13 +3,13 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.BlurPostProcess = function (name, direction, blurWidth, ratio, camera, samplingMode) {
+    BABYLON.BlurPostProcess = function (name, direction, blurWidth, ratio, camera, samplingMode, engine, reusable) {
         
         if (samplingMode === undefined) {
             samplingMode = BABYLON.Texture.BILINEAR_SAMPLINGMODE;
         }
 
-        BABYLON.PostProcess.call(this, name, "blur", ["screenSize", "direction", "blurWidth"], null, ratio, camera, samplingMode);
+        BABYLON.PostProcess.call(this, name, "blur", ["screenSize", "direction", "blurWidth"], null, ratio, camera, samplingMode, engine, reusable);
 
         this.direction = direction;
         this.blurWidth = blurWidth;

+ 2 - 2
Babylon/PostProcess/babylon.convolutionPostProcess.js

@@ -3,8 +3,8 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.ConvolutionPostProcess = function (name, kernelMatrix, ratio, camera, samplingMode) {
-        BABYLON.PostProcess.call(this, name, "convolution", ["kernelMatrix"], null, ratio, camera, samplingMode);
+    BABYLON.ConvolutionPostProcess = function (name, kernelMatrix, ratio, camera, samplingMode, engine, reusable) {
+        BABYLON.PostProcess.call(this, name, "convolution", ["kernelMatrix"], null, ratio, camera, samplingMode, engine, reusable);
         
         this.kernelMatrix = kernelMatrix;
         var that = this;

+ 2 - 2
Babylon/PostProcess/babylon.fxaaPostProcess.js

@@ -3,8 +3,8 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.FxaaPostProcess = function (name, ratio, camera, samplingMode) {
-        BABYLON.PostProcess.call(this, name, "fxaa", ["texelSize"], null, ratio, camera, samplingMode);
+    BABYLON.FxaaPostProcess = function (name, ratio, camera, samplingMode, engine, reusable) {
+        BABYLON.PostProcess.call(this, name, "fxaa", ["texelSize"], null, ratio, camera, samplingMode, engine, reusable);
     };
     
     BABYLON.FxaaPostProcess.prototype = Object.create(BABYLON.PostProcess.prototype);

+ 2 - 2
Babylon/PostProcess/babylon.passPostProcess.js

@@ -3,8 +3,8 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.PassPostProcess = function (name, ratio, camera, samplingMode) {
-        BABYLON.PostProcess.call(this, name, "pass", null, null, ratio, camera, samplingMode);
+    BABYLON.PassPostProcess = function (name, ratio, camera, samplingMode, engine, reusable) {
+        BABYLON.PostProcess.call(this, name, "pass", null, null, ratio, camera, samplingMode, engine, reusable);
     };
     
     BABYLON.PassPostProcess.prototype = Object.create(BABYLON.PostProcess.prototype);

+ 60 - 21
Babylon/PostProcess/babylon.postProcess.js

@@ -3,16 +3,29 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.PostProcess = function (name, fragmentUrl, parameters, samplers, ratio, camera, samplingMode) {
+    BABYLON.PostProcess = function (name, fragmentUrl, parameters, samplers, ratio, camera, samplingMode, engine, reusable) {
         this.name = name;
-        this._camera = camera;
-        this._scene = camera.getScene();
-        camera.postProcesses.push(this);
-        this._engine = this._scene.getEngine();
+
+        if (camera != null) {
+            console.warn("Adding a camera in a post process is deprecated");
+
+            this._camera = camera;
+            this._scene = camera.getScene();
+            camera.attachPostProcess(this);
+            this._engine = this._scene.getEngine();
+        }
+        else {
+            this._engine = engine;
+        }
+
         this._renderRatio = ratio;
         this.width = -1;
         this.height = -1;
         this.renderTargetSamplingMode = samplingMode ? samplingMode : BABYLON.Texture.NEAREST_SAMPLINGMODE;
+        this._reusable = reusable || false;
+
+        this._textures = new BABYLON.Tools.SmartArray(2);
+        this._currentRenderTextureInd = 0;
 
         samplers = samplers || [];
         samplers.push("textureSampler");
@@ -27,25 +40,46 @@ var BABYLON = BABYLON || {};
     BABYLON.PostProcess.prototype.onApply = null;
     BABYLON.PostProcess.prototype._onDispose = null;
     BABYLON.PostProcess.prototype.onSizeChanged = null;
-    BABYLON.PostProcess.prototype.activate = function () {
+    BABYLON.PostProcess.prototype.onActivate = null;
+    BABYLON.PostProcess.prototype.activate = function (camera) {
+        camera = camera || this._camera;
+
+        var scene = camera.getScene();
         var desiredWidth = this._engine._renderingCanvas.width * this._renderRatio;
         var desiredHeight = this._engine._renderingCanvas.height * this._renderRatio;
         if (this.width !== desiredWidth || this.height !== desiredHeight) {
-            if (this._texture) {
-                this._engine._releaseTexture(this._texture);
-                this._texture = null;
+            if (this._textures.length > 0) {
+                for (var i = 0; i < this._textures.length; i++) {
+                    this._engine._releaseTexture(this._textures.data[i]);
+                }
+                this._textures.reset();
             }
             this.width = desiredWidth;
             this.height = desiredHeight;
-            this._texture = this._engine.createRenderTargetTexture({ width: this.width, height: this.height }, { generateMipMaps: false, generateDepthBuffer: this._camera.postProcesses.indexOf(this) === 0, samplingMode: this.renderTargetSamplingMode });
+            this._textures.push(this._engine.createRenderTargetTexture({ width: this.width, height: this.height }, { generateMipMaps: false, generateDepthBuffer: camera._postProcesses.indexOf(this) === camera._postProcessesTakenIndices[0], samplingMode: this.renderTargetSamplingMode }));
+
+            if (this._reusable) {
+                this._textures.push(this._engine.createRenderTargetTexture({ width: this.width, height: this.height }, { generateMipMaps: false, generateDepthBuffer: camera._postProcesses.indexOf(this) === camera._postProcessesTakenIndices[0], samplingMode: this.renderTargetSamplingMode }));
+            }
+
             if (this.onSizeChanged) {
                 this.onSizeChanged();
             }
+
         }
-        this._engine.bindFramebuffer(this._texture);
+
+        this._engine.bindFramebuffer(this._textures.data[this._currentRenderTextureInd]);
         
+        if (this.onActivate) {
+            this.onActivate(camera);
+        }
+
         // Clear
-        this._engine.clear(this._scene.clearColor, this._scene.autoClear || this._scene.forceWireframe, true);
+        this._engine.clear(scene.clearColor, scene.autoClear || scene.forceWireframe, true);
+
+        if (this._reusable) {
+            this._currentRenderTextureInd = (this._currentRenderTextureInd + 1) % 2;
+        }
     };
 
     BABYLON.PostProcess.prototype.apply = function () {
@@ -61,7 +95,7 @@ var BABYLON = BABYLON || {};
         this._engine.setDepthWrite(false);
 
         // Texture
-        this._effect._bindTexture("textureSampler", this._texture);
+        this._effect._bindTexture("textureSampler", this._textures.data[this._currentRenderTextureInd]);
         
         // Parameters
         if (this.onApply) {
@@ -71,19 +105,24 @@ var BABYLON = BABYLON || {};
         return this._effect;
     };
 
-    BABYLON.PostProcess.prototype.dispose = function () {
+    BABYLON.PostProcess.prototype.dispose = function (camera) {
+        camera = camera || this._camera;
+
         if (this._onDispose) {
             this._onDispose();
         }
-        if (this._texture) {
-            this._engine._releaseTexture(this._texture);
-            this._texture = null;
+        if (this._textures.length > 0) {
+            for (var i = 0; i < this._textures.length; i++) {
+                this._engine._releaseTexture(this._textures[i]);
+            }
+            this._textures.reset();
         }
         
-        var index = this._camera.postProcesses.indexOf(this);
-        this._camera.postProcesses.splice(index, 1);
-        if (index == 0 && this._camera.postProcesses.length > 0) {
-            this._camera.postProcesses[0].width = -1; // invalidate frameBuffer to hint the postprocess to create a depth buffer
+        camera.detachPostProcess(this);
+
+        var index = camera._postProcesses.indexOf(this);
+        if (index === camera._postProcessesTakenIndices[0] && camera._postProcessesTakenIndices.length > 0) {
+            this._camera._postProcesses[camera._postProcessesTakenIndices[0]].width = -1; // invalidate frameBuffer to hint the postprocess to create a depth buffer
         }
     };
 

+ 9 - 9
Babylon/PostProcess/babylon.postProcessManager.js

@@ -31,32 +31,32 @@ var BABYLON = BABYLON || {};
 
     // Methods
     BABYLON.PostProcessManager.prototype._prepareFrame = function () {
-        var postProcesses = this._scene.activeCamera.postProcesses;
+        var postProcesses = this._scene.activeCamera._postProcesses;
         
         if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
             return;
         }
-
-        postProcesses[0].activate();
+        
+        postProcesses[this._scene.activeCamera._postProcessesTakenIndices[0]].activate(this._scene.activeCamera);
     };
     
     BABYLON.PostProcessManager.prototype._finalizeFrame = function () {
-        var postProcesses = this._scene.activeCamera.postProcesses;
-        
+        var postProcesses = this._scene.activeCamera._postProcesses;
+        var postProcessesTakenIndices = this._scene.activeCamera._postProcessesTakenIndices;
         if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
             return;
         }
 
         var engine = this._scene.getEngine();
         
-        for (var index = 0; index < postProcesses.length; index++) {            
-            if (index < postProcesses.length - 1) {
-                postProcesses[index + 1].activate();
+        for (var index = 0; index < postProcessesTakenIndices.length; index++) {
+            if (postProcessesTakenIndices[index] < postProcessesTakenIndices.length - 1) {
+                postProcesses[postProcessesTakenIndices[index + 1]].activate(this._scene.activeCamera);
             } else {
                 engine.restoreDefaultFramebuffer();
             }
 
-            var effect = postProcesses[index].apply();
+            var effect = postProcesses[postProcessesTakenIndices[index]].apply();
 
             if (effect) {
                 // VBOs

+ 8 - 3
Babylon/PostProcess/babylon.refractionPostProcess.js

@@ -3,15 +3,20 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.RefractionPostProcess = function (name, refractionTextureUrl, color, depth, colorLevel, ratio, camera, samplingMode) {
-        BABYLON.PostProcess.call(this, name, "refraction", ["baseColor", "depth", "colorLevel"], ["refractionSampler"], ratio, camera, samplingMode);
+    BABYLON.RefractionPostProcess = function (name, refractionTextureUrl, color, depth, colorLevel, ratio, camera, samplingMode, engine, reusable) {
+        BABYLON.PostProcess.call(this, name, "refraction", ["baseColor", "depth", "colorLevel"], ["refractionSampler"], ratio, camera, samplingMode, engine, reusable);
 
         this.color = color;
         this.depth = depth;
         this.colorLevel = colorLevel;
-        this._refRexture = new BABYLON.Texture(refractionTextureUrl, camera.getScene());
+        this._refRexture = null;
         
         var that = this;
+
+        this.onActivate = function (camera) {
+            that._refRexture = this._refRexture || new BABYLON.Texture(refractionTextureUrl, camera.getScene());
+        };
+
         this.onApply = function (effect) {
             effect.setColor3("baseColor", that.color);
             effect.setFloat("depth", that.depth);