瀏覽代碼

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

David Catuhe 7 年之前
父節點
當前提交
05f9db3fd5

+ 1 - 0
dist/preview release/what's new.md

@@ -95,6 +95,7 @@
 - Tests for sharpen, chromatic aberration, default pipeline and enable/disable post processes ([trevordev](https://github.com/trevordev))
 - onPointer* callbacks have now the event type as a 3rd variable ([RaananW](https://github.com/RaananW))
 - Lightmap texture in PBR material follow the gammaSpace Flag of the texture ([sebavan](https://github.com/sebavan))
+- Added setTextureFromPostProcessOutput to bind the output of a postprocess into an effect ([trevordev](https://github.com/trevordev))
 - Added support for primitive modes to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
 
 ## Bug fixes

+ 27 - 0
src/Engine/babylon.engine.ts

@@ -5042,6 +5042,24 @@
             if (texture._lodTextureLow) {
                 texture._lodTextureLow.dispose();
             }
+
+            // Set output texture of post process to null if the texture has been released/disposed
+            this.scenes.forEach((scene)=>{
+                scene.postProcesses.forEach((postProcess)=>{
+                    if(postProcess._outputTexture == texture){
+                        postProcess._outputTexture = null;
+                    }
+                });
+                scene.cameras.forEach((camera)=>{
+                    camera._postProcesses.forEach((postProcess)=>{
+                        if(postProcess){
+                            if(postProcess._outputTexture == texture){
+                                postProcess._outputTexture = null;
+                            }
+                        }
+                    });
+                });
+            })
         }
 
         private setProgram(program: WebGLProgram): void {
@@ -5204,6 +5222,15 @@
             this._bindTexture(channel, postProcess ? postProcess._textures.data[postProcess._currentRenderTextureInd] : null);
         }
 
+        /**
+         * Binds the output of the passed in post process to the texture channel specified
+         * @param channel The channel the texture should be bound to
+         * @param postProcess The post process which's output should be bound
+         */
+        public setTextureFromPostProcessOutput(channel: number, postProcess: Nullable<PostProcess>): void {
+            this._bindTexture(channel, postProcess ? postProcess._outputTexture : null);
+        }
+
         public unbindAllTextures(): void {
             for (var channel = 0; channel < this._maxSimultaneousTextures; channel++) {
                 this._activeChannel = channel;

+ 11 - 1
src/Materials/babylon.effect.ts

@@ -947,7 +947,8 @@
         }
 
         /**
-         * Sets a texture to be the input of the specified post process. (To use the output, pass in the next post process in the pipeline)
+         * (Warning! setTextureFromPostProcessOutput may be desired instead)
+         * Sets the input texture of the passed in post process to be input of this effect. (To use the output of the passed in post process use setTextureFromPostProcessOutput)
          * @param channel Name of the sampler variable.
          * @param postProcess Post process to get the input texture from.
          */
@@ -955,6 +956,15 @@
             this._engine.setTextureFromPostProcess(this._samplers.indexOf(channel), postProcess);
         }
 
+        /**
+         * Sets the output texture of the passed in post process to be input of this effect.
+         * @param channel Name of the sampler variable.
+         * @param postProcess Post process to get the output texture from.
+         */
+        public setTextureFromPostProcessOutput(channel: string, postProcess: Nullable<PostProcess>): void {
+            this._engine.setTextureFromPostProcessOutput(this._samplers.indexOf(channel), postProcess);
+        }
+
         /** @ignore */
         public _cacheMatrix(uniformName: string, matrix: Matrix): boolean {
             var cache = this._valueCache[uniformName];

+ 1 - 1
src/PostProcess/babylon.depthOfFieldBlurPostProcess.ts

@@ -29,7 +29,7 @@ module BABYLON {
                 if(imageToBlur != null){
                     effect.setTextureFromPostProcess("textureSampler", imageToBlur);
                 }
-                effect.setTextureFromPostProcess("circleOfConfusionSampler", circleOfConfusion);
+                effect.setTextureFromPostProcessOutput("circleOfConfusionSampler", circleOfConfusion);
                 if(scene.activeCamera){
                     effect.setFloat2('cameraMinMaxZ', scene.activeCamera.minZ, scene.activeCamera.maxZ);
                 }

+ 4 - 9
src/PostProcess/babylon.depthOfFieldEffect.ts

@@ -20,7 +20,6 @@ module BABYLON {
      * The depth of field effect applies a blur to objects that are closer or further from where the camera is focusing.
      */
     export class DepthOfFieldEffect extends PostProcessRenderEffect{
-        private _depthOfFieldPass: PassPostProcess;
         private _circleOfConfusion: CircleOfConfusionPostProcess;
         private _depthOfFieldBlurX: Array<DepthOfFieldBlurPostProcess>;
         private _depthOfFieldBlurY: Array<DepthOfFieldBlurPostProcess>;
@@ -81,9 +80,6 @@ module BABYLON {
             }, true);
             // Circle of confusion value for each pixel is used to determine how much to blur that pixel
             this._circleOfConfusion = new BABYLON.CircleOfConfusionPostProcess("circleOfConfusion", depthTexture, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
-            // Capture circle of confusion texture
-            this._depthOfFieldPass = new PassPostProcess("depthOfFieldPass", 1.0, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
-            this._depthOfFieldPass.autoClear = false;
 
             // Create a pyramid of blurred images (eg. fullSize 1/4 blur, half size 1/2 blur, quarter size 3/4 blur, eith size 4/4 blur)
             // Blur the image but do not blur on sharp far to near distance changes to avoid bleeding artifacts 
@@ -111,20 +107,20 @@ module BABYLON {
             }
             var adjustedKernelSize = kernelSize/Math.pow(2, blurCount-1);
             for(var i = 0;i<blurCount;i++){
-                var blurY = new DepthOfFieldBlurPostProcess("verticle blur", scene, new Vector2(0, 1.0), adjustedKernelSize, 1.0/Math.pow(2, i), null, this._depthOfFieldPass, i == 0 ? this._circleOfConfusion : null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
+                var blurY = new DepthOfFieldBlurPostProcess("verticle blur", scene, new Vector2(0, 1.0), adjustedKernelSize, 1.0/Math.pow(2, i), null, this._circleOfConfusion, i == 0 ? this._circleOfConfusion : null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
                 blurY.autoClear = false;
-                var blurX = new DepthOfFieldBlurPostProcess("horizontal blur", scene, new Vector2(1.0, 0), adjustedKernelSize, 1.0/Math.pow(2, i), null,  this._depthOfFieldPass, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
+                var blurX = new DepthOfFieldBlurPostProcess("horizontal blur", scene, new Vector2(1.0, 0), adjustedKernelSize, 1.0/Math.pow(2, i), null,  this._circleOfConfusion, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
                 blurX.autoClear = false;
                 this._depthOfFieldBlurY.push(blurY);
                 this._depthOfFieldBlurX.push(blurX);
             }
 
             // Merge blurred images with original image based on circleOfConfusion
-            this._depthOfFieldMerge = new DepthOfFieldMergePostProcess("depthOfFieldMerge", this._circleOfConfusion, this._depthOfFieldPass, this._depthOfFieldBlurY.slice(1), 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
+            this._depthOfFieldMerge = new DepthOfFieldMergePostProcess("depthOfFieldMerge", this._circleOfConfusion, this._circleOfConfusion, this._depthOfFieldBlurX, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType, blockCompilation);
             this._depthOfFieldMerge.autoClear = false;
             
             // Set all post processes on the effect.
-            this._effects= [this._circleOfConfusion, this._depthOfFieldPass];
+            this._effects= [this._circleOfConfusion];
             for(var i=0;i<this._depthOfFieldBlurX.length;i++){
                 this._effects.push(this._depthOfFieldBlurY[i]);
                 this._effects.push(this._depthOfFieldBlurX[i]);
@@ -144,7 +140,6 @@ module BABYLON {
          * @param camera The camera to dispose the effect on.
          */
         public disposeEffects(camera:Camera){
-            this._depthOfFieldPass.dispose(camera);
             this._circleOfConfusion.dispose(camera);
             this._depthOfFieldBlurX.forEach(element => {
                 element.dispose(camera);

+ 5 - 5
src/PostProcess/babylon.depthOfFieldMergePostProcess.ts

@@ -18,12 +18,12 @@ module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, original: PostProcess, circleOfConfusion: PostProcess, private blurSteps: Array<PostProcess>, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
-            super(name, "depthOfFieldMerge", [], ["circleOfConfusionSampler", "originalSampler", "blurStep1", "blurStep2"], options, camera, samplingMode, engine, reusable, null, textureType, undefined, null, true);
+            super(name, "depthOfFieldMerge", [], ["circleOfConfusionSampler", "blurStep0", "blurStep1", "blurStep2"], options, camera, samplingMode, engine, reusable, null, textureType, undefined, null, true);
             this.onApplyObservable.add((effect: Effect) => {
-                effect.setTextureFromPostProcess("circleOfConfusionSampler", circleOfConfusion);
-                effect.setTextureFromPostProcess("originalSampler", original);
+                effect.setTextureFromPostProcessOutput("circleOfConfusionSampler", circleOfConfusion);
+                effect.setTextureFromPostProcess("textureSampler", original);
                 blurSteps.forEach((step,index)=>{
-                    effect.setTextureFromPostProcess("blurStep"+(index+1), step);
+                    effect.setTextureFromPostProcessOutput("blurStep"+(blurSteps.length-index-1), step);
                 });
             });
 
@@ -43,7 +43,7 @@ module BABYLON {
          */
         public updateEffect(defines: Nullable<string> = null, uniforms: Nullable<string[]> = null, samplers: Nullable<string[]> = null, indexParameters?: any,
             onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void) {
-            super.updateEffect(defines ? defines : "#define BLUR_LEVEL "+this.blurSteps.length+"\n", uniforms, samplers, indexParameters, onCompiled, onError);
+            super.updateEffect(defines ? defines : "#define BLUR_LEVEL "+(this.blurSteps.length-1)+"\n", uniforms, samplers, indexParameters, onCompiled, onError);
         }
     }
 }

+ 9 - 1
src/PostProcess/babylon.postProcess.ts

@@ -14,6 +14,12 @@
         * Height of the texture to apply the post process on
         */
         public height = -1;
+
+        /**
+        * Internal, reference to the location where this postprocess was output to. (Typically the texture on the next postprocess in the chain)
+        */
+        public _outputTexture: Nullable<InternalTexture> = null;
+
         /**
         * Sampling mode used by the shader
         * See https://doc.babylonjs.com/classes/3.1/texture
@@ -350,8 +356,9 @@
          * @param camera The camera that will be used in the post process. This camera will be used when calling onActivateObservable.
          * @param sourceTexture The source texture to be inspected to get the width and height if not specified in the post process constructor. (default: null)
          * @param forceDepthStencil If true, a depth and stencil buffer will be generated. (default: false)
+         * @returns The target texture that was bound to be written to. 
          */
-        public activate(camera: Nullable<Camera>, sourceTexture: Nullable<InternalTexture> = null, forceDepthStencil?: boolean): void {
+        public activate(camera: Nullable<Camera>, sourceTexture: Nullable<InternalTexture> = null, forceDepthStencil?: boolean): InternalTexture {
             camera = camera || this._camera;
 
             var scene = camera.getScene();
@@ -461,6 +468,7 @@
             if (this._reusable) {
                 this._currentRenderTextureInd = (this._currentRenderTextureInd + 1) % 2;
             }
+            return target;
         }
 
 

+ 4 - 3
src/PostProcess/babylon.postProcessManager.ts

@@ -147,8 +147,10 @@
             var engine = this._scene.getEngine();
 
             for (var index = 0, len = postProcesses.length; index < len; index++) {
+                var pp = postProcesses[index];
+
                 if (index < len - 1) {
-                    postProcesses[index + 1].activate(camera, targetTexture);
+                    pp._outputTexture = postProcesses[index + 1].activate(camera, targetTexture);
                 } else {
                     if (targetTexture) {
                         engine.bindFramebuffer(targetTexture, faceIndex, undefined, undefined, forceFullscreenViewport);
@@ -160,8 +162,7 @@
                 if (doNotPresent) {
                     break;
                 }
-
-                var pp = postProcesses[index];
+                
                 var effect = pp.apply();
 
                 if (effect) {

+ 12 - 10
src/Shaders/depthOfFieldMerge.fragment.fx

@@ -1,7 +1,7 @@
 // samplers
 uniform sampler2D textureSampler;
-uniform sampler2D originalSampler;
 uniform sampler2D circleOfConfusionSampler;
+uniform sampler2D blurStep0;
 
 #if BLUR_LEVEL > 0
 uniform sampler2D blurStep1;
@@ -14,31 +14,33 @@ varying vec2 vUV;
 
 void main(void)
 {
+    gl_FragColor = texture2D(textureSampler, vUV);
+
     float coc = texture2D(circleOfConfusionSampler, vUV).r;
-    vec4 original = texture2D(originalSampler, vUV);
+    vec4 original = texture2D(textureSampler, vUV);
 #if BLUR_LEVEL == 0
-    vec4 blurred1 = texture2D(textureSampler, vUV);
-    gl_FragColor = mix(original, blurred1, coc);
+    vec4 blurred0 = texture2D(blurStep0, vUV);
+    gl_FragColor = mix(original, blurred0, coc);
 #endif
 #if BLUR_LEVEL == 1
+    vec4 blurred0 = texture2D(blurStep0, vUV);   
     vec4 blurred1 = texture2D(blurStep1, vUV);
-    vec4 blurred2 = texture2D(textureSampler, vUV);    
     if(coc < 0.5){
         gl_FragColor = mix(original, blurred1, coc/0.5);
     }else{
-        gl_FragColor = mix(blurred1, blurred2, (coc-0.5)/0.5);
+        gl_FragColor = mix(blurred1, blurred0, (coc-0.5)/0.5);
     }
 #endif
 #if BLUR_LEVEL == 2
+    vec4 blurred0 = texture2D(blurStep0, vUV);
     vec4 blurred1 = texture2D(blurStep1, vUV);
     vec4 blurred2 = texture2D(blurStep2, vUV);
-    vec4 blurred3 = texture2D(textureSampler, vUV);
     if(coc < 0.33){
-        gl_FragColor = mix(original, blurred1, coc/0.33);
+        gl_FragColor = mix(original, blurred2, coc/0.33);
     }else if(coc < 0.66){
-        gl_FragColor = mix(blurred1, blurred2, (coc-0.33)/0.33);
+        gl_FragColor = mix(blurred2, blurred1, (coc-0.33)/0.33);
     }else{
-        gl_FragColor = mix(blurred2, blurred3, (coc-0.66)/0.34);
+        gl_FragColor = mix(blurred1, blurred0, (coc-0.66)/0.34);
     }
 #endif
 }