Browse Source

prepass is layer compatible & cleaner with outputs

Benjamin Guignabert 4 years ago
parent
commit
3e6506adc2

+ 1 - 1
src/PostProcesses/RenderPipeline/Pipelines/ssao2RenderingPipeline.ts

@@ -190,7 +190,7 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
      * @param cameras The array of cameras that the rendering pipeline will be attached to
      * @param forceGeometryBuffer Set to true if you want to use the legacy geometry buffer renderer
      */
-    constructor(name: string, scene: Scene, ratio: any, cameras?: Camera[], forceGeometryBuffer = true) {
+    constructor(name: string, scene: Scene, ratio: any, cameras?: Camera[], forceGeometryBuffer = false) {
         super(scene.getEngine(), name);
 
         this._scene = scene;

+ 1 - 1
src/PostProcesses/motionBlurPostProcess.ts

@@ -106,7 +106,7 @@ export class MotionBlurPostProcess extends PostProcess {
      * @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: true)
      * @param forceGeometryBuffer If this post process should use geometry buffer instead of prepass (default: false)
      */
-    constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false, forceGeometryBuffer = true) {
+    constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false, forceGeometryBuffer = false) {
         super(name, "motionBlur", ["motionStrength", "motionScale", "screenSize", "inverseViewProjection", "prevViewProjection"], ["velocitySampler"], options, camera, samplingMode, engine, reusable, "#define GEOMETRY_SUPPORTED\n#define SAMPLES 64.0\n#define OBJECT_BASED", textureType, undefined, null, blockCompilation);
 
         this._forceGeometryBuffer = forceGeometryBuffer;

+ 1 - 0
src/PostProcesses/postProcess.ts

@@ -304,6 +304,7 @@ export class PostProcess {
     */
     public restoreDefaultInputTexture() {
         this._forcedOutputTexture = null;
+        this.markTextureDirty();
     }
 
     /**

+ 1 - 1
src/PostProcesses/screenSpaceReflectionPostProcess.ts

@@ -73,7 +73,7 @@ export class ScreenSpaceReflectionPostProcess extends PostProcess {
      * @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: true)
      * @param forceGeometryBuffer If this post process should use geometry buffer instead of prepass (default: false)
      */
-    constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false, forceGeometryBuffer = true) {
+    constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false, forceGeometryBuffer = false) {
         super(name, "screenSpaceReflection", [
             "projection", "view", "threshold", "reflectionSpecularFalloffExponent", "strength", "step", "roughnessFactor"
         ], [

+ 79 - 37
src/Rendering/prePassRenderer.ts

@@ -10,6 +10,7 @@ import { Color4 } from "../Maths/math.color";
 import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
 import { Nullable } from "../types";
 import { AbstractMesh } from '../Meshes/abstractMesh';
+import { Camera } from '../Cameras/camera';
 import { Material } from '../Materials/material';
 import { SubMesh } from '../Meshes/subMesh';
 import { GeometryBufferRenderer } from '../Rendering/geometryBufferRenderer';
@@ -108,6 +109,8 @@ export class PrePassRenderer {
 
     private _enabled: boolean = false;
 
+    private _needsComposition = false;
+
     /**
      * Indicates if the prepass is enabled
      */
@@ -213,7 +216,6 @@ export class PrePassRenderer {
         }
 
         this.imageProcessingPostProcess = new ImageProcessingPostProcess("sceneCompositionPass", 1, null, undefined, this._engine);
-        this.imageProcessingPostProcess.autoClear = false;
     }
 
     /**
@@ -257,28 +259,48 @@ export class PrePassRenderer {
     /**
      * @hidden
      */
-    public _beforeCameraDraw() {
+    public _beforeCameraDraw(camera: Camera) {
         if (this._isDirty) {
             this._update();
         }
 
+        if (!this._enabled) {
+            return;
+        }
+
         if (this._geometryBuffer) {
             this._geometryBuffer.renderList!.length = 0;
         }
 
-        this._bindFrameBuffer();
+        this._setupOutputForCamera(camera);
     }
 
     /**
      * @hidden
      */
-    public _afterCameraDraw() {
+    public _afterCameraDraw(camera: Camera) {
         if (this._enabled) {
-            const firstCameraPP = this._scene.activeCamera && this._scene.activeCamera._getFirstPostProcess();
-            if (firstCameraPP && this._postProcesses.length) {
-                this._scene.postProcessManager._prepareFrame();
+            this._scene.postProcessManager._prepareFrame();
+            const firstCameraPP = camera && camera._getFirstPostProcess();
+            let outputTexture = firstCameraPP ? firstCameraPP.inputTexture : null
+
+            // Build post process chain for this prepass post draw
+            let postProcessChain = this._postProcesses;
+            if (this._needsComposition) {
+                postProcessChain = postProcessChain.concat([this.imageProcessingPostProcess]);
+            }
+
+            // Activates the chain
+            if (postProcessChain.length) {
+                this._scene.postProcessManager._prepareFrame(this.prePassRT.getInternalTexture()!, postProcessChain);
+            }
+
+            // Renders the post process chain 
+            this._scene.postProcessManager.directRender(postProcessChain, outputTexture);
+
+            if (!outputTexture) {
+                this._engine.restoreDefaultFramebuffer();
             }
-            this._scene.postProcessManager.directRender(this._postProcesses, firstCameraPP ? firstCameraPP.inputTexture : null);
         }
     }
 
@@ -292,7 +314,6 @@ export class PrePassRenderer {
             this.prePassRT.resize({ width: requiredWidth, height: requiredHeight });
 
             this._updateGeometryBufferLayout();
-            this._bindPostProcessChain();
         }
     }
 
@@ -441,20 +462,6 @@ export class PrePassRenderer {
             this._createCompositionEffect();
         }
 
-        let isIPPAlreadyPresent = false;
-        if (this._scene.activeCamera?._postProcesses) {
-            for (let i = 0; i < this._scene.activeCamera._postProcesses.length; i++) {
-                if (this._scene.activeCamera._postProcesses[i]?.getClassName() === "ImageProcessingPostProcess") {
-                    isIPPAlreadyPresent = true;
-                }
-            }
-
-        }
-
-        if (!isIPPAlreadyPresent && !this.disableGammaTransform) {
-            this._postProcesses.push(this.imageProcessingPostProcess);
-        }
-        this._bindPostProcessChain();
         this._setState(true);
     }
 
@@ -478,28 +485,63 @@ export class PrePassRenderer {
         this.mrtCount = 1;
     }
 
+    // private _bindPostProcessChain() {
+    //     if (this._postProcesses.length) {
+    //         this._postProcesses[0].inputTexture = this.prePassRT.getInternalTexture()!;
+    //     } else {
+    //         const pp = this._scene.activeCamera?._getFirstPostProcess();
+    //         if (pp) {
+    //             pp.inputTexture = this.prePassRT.getInternalTexture()!;
+    //         }
+    //     }
+    // }
+
     private _resetPostProcessChain() {
         this._postProcesses = [];
-        if (this.imageProcessingPostProcess) {
-            this.imageProcessingPostProcess.restoreDefaultInputTexture();
-        }
+    }
 
-        for (let i = 0; i < this._effectConfigurations.length; i++) {
-            if (this._effectConfigurations[i].postProcess) {
-                this._effectConfigurations[i].postProcess!.restoreDefaultInputTexture();
-            }
+    private _setupOutputForCamera(camera: Camera) {
+        // Here we search for an image composition post process
+        // If no ipp if found, we use the prepass built-in
+        // We also set the framebuffer to the input texture of the first post process that is to come
+        const secondaryCamera = this._scene.activeCameras && this._scene.activeCameras.length && this._scene.activeCameras.indexOf(camera) !== 0;
+        this._needsComposition = !this._cameraHasImageProcessing(camera) && !this.disableGammaTransform && !secondaryCamera;
+        const firstCameraPP = camera && camera._getFirstPostProcess();
+        const firstPrePassPP = this._postProcesses && this._postProcesses[0];
+        let firstPP = null;
+
+        this.imageProcessingPostProcess.restoreDefaultInputTexture();
+
+        // Setting the prepassRT as input texture of the first PP
+        if (firstPrePassPP) {
+            firstPrePassPP.inputTexture = this.prePassRT.getInternalTexture()!;
+            firstPP = firstPrePassPP;
+        } else if (this._needsComposition) {
+            this.imageProcessingPostProcess.inputTexture = this.prePassRT.getInternalTexture()!;
+            firstPP = this.imageProcessingPostProcess;
+        } else if (firstCameraPP) {
+            firstCameraPP.inputTexture = this.prePassRT.getInternalTexture()!;
+            firstPP = firstCameraPP;
+        }
+        
+        if (firstPP) {
+            firstPP.autoClear = false;
         }
+
+        this._bindFrameBuffer();
     }
 
-    private _bindPostProcessChain() {
-        if (this._postProcesses.length) {
-            this._postProcesses[0].inputTexture = this.prePassRT.getInternalTexture()!;
-        } else {
-            const pp = this._scene.activeCamera?._getFirstPostProcess();
-            if (pp) {
-                pp.inputTexture = this.prePassRT.getInternalTexture()!;
+    private _cameraHasImageProcessing(camera: Camera): boolean {
+        let isIPPAlreadyPresent = false;
+        if (camera._postProcesses) {
+            for (let i = 0; i < camera._postProcesses.length; i++) {
+                if (camera._postProcesses[i]?.getClassName() === "ImageProcessingPostProcess") {
+                    isIPPAlreadyPresent = true;
+                }
             }
         }
+
+        return isIPPAlreadyPresent;
     }
 
     /**

+ 5 - 4
src/Rendering/prePassRendererSceneComponent.ts

@@ -7,6 +7,7 @@ import { AbstractMesh } from "../Meshes/abstractMesh";
 import { SubMesh } from "../Meshes/subMesh";
 import { _InstancesBatch } from "../Meshes/mesh";
 import { Effect } from "../Materials/effect";
+import { Camera } from '../Cameras/camera';
 
 declare module "../abstractScene" {
     export interface AbstractScene {
@@ -104,15 +105,15 @@ export class PrePassRendererSceneComponent implements ISceneComponent {
         this.scene._afterRenderingMeshStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGMESH_PREPASS, this, this._afterRenderingMeshStage);
     }
 
-    private _beforeCameraDraw() {
+    private _beforeCameraDraw(camera: Camera) {
         if (this.scene.prePassRenderer) {
-            this.scene.prePassRenderer._beforeCameraDraw();
+            this.scene.prePassRenderer._beforeCameraDraw(camera);
         }
     }
 
-    private _afterCameraDraw() {
+    private _afterCameraDraw(camera: Camera) {
         if (this.scene.prePassRenderer) {
-            this.scene.prePassRenderer._afterCameraDraw();
+            this.scene.prePassRenderer._afterCameraDraw(camera);
         }
     }
 

+ 2 - 2
src/sceneComponent.ts

@@ -72,8 +72,8 @@ export class SceneComponentConstants {
     public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER = 0;
     public static readonly STEP_AFTERCAMERADRAW_LENSFLARESYSTEM = 1;
     public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER_DRAW = 2;
-    public static readonly STEP_AFTERCAMERADRAW_LAYER = 3;
-    public static readonly STEP_AFTERCAMERADRAW_PREPASS = 4;
+    public static readonly STEP_AFTERCAMERADRAW_PREPASS = 3;
+    public static readonly STEP_AFTERCAMERADRAW_LAYER = 4;
 
     public static readonly STEP_AFTERRENDER_AUDIO = 0;