Browse Source

adding prepass to render target #1

Benjamin Guignabert 4 years ago
parent
commit
1590aa1585

+ 34 - 0
src/Materials/Textures/prePassRenderTarget.ts

@@ -7,6 +7,7 @@ import { Scene } from "../../scene";
 import { Constants } from "../../Engines/constants";
 import { Constants } from "../../Engines/constants";
 import { PostProcess } from "../../PostProcesses/postProcess";
 import { PostProcess } from "../../PostProcesses/postProcess";
 import { ImageProcessingPostProcess } from "../../PostProcesses/imageProcessingPostProcess";
 import { ImageProcessingPostProcess } from "../../PostProcesses/imageProcessingPostProcess";
+import { PrePassEffectConfiguration } from "../../Rendering/prePassEffectConfiguration";
 
 
 /**
 /**
  * A multi render target designed to render the prepass.
  * A multi render target designed to render the prepass.
@@ -37,6 +38,11 @@ export class PrePassRenderTarget extends MultiRenderTarget {
      */
      */
     public imageProcessingPostProcess: ImageProcessingPostProcess;
     public imageProcessingPostProcess: ImageProcessingPostProcess;
 
 
+    /**
+     * Configuration for prepass effects
+     */
+    public _effectConfigurations: PrePassEffectConfiguration[] = [];
+
     private _prePassRenderer: PrePassRenderer;
     private _prePassRenderer: PrePassRenderer;
 
 
 	/**
 	/**
@@ -139,6 +145,25 @@ export class PrePassRenderTarget extends MultiRenderTarget {
 	}
 	}
 
 
 	/**
 	/**
+	 * Adds an effect configuration to the prepass render target.
+	 * If an effect has already been added, it won't add it twice and will return the configuration
+	 * already present.
+	 * @param cfg the effect configuration
+	 * @return the effect configuration now used by the prepass
+	 */
+	public _addEffectConfiguration(cfg: PrePassEffectConfiguration) : PrePassEffectConfiguration {
+	    // Do not add twice
+	    for (let i = 0; i < this._effectConfigurations.length; i++) {
+	        if (this._effectConfigurations[i].name === cfg.name) {
+	            return this._effectConfigurations[i];
+	        }
+	    }
+
+	    this._effectConfigurations.push(cfg);
+	    return cfg;
+	}
+
+	/**
 	 * Prepares this rt to rebuild attachments according to the current texture layout
 	 * Prepares this rt to rebuild attachments according to the current texture layout
 	 */
 	 */
 	public _reinitializeAttachments() {
 	public _reinitializeAttachments() {
@@ -166,7 +191,9 @@ export class PrePassRenderTarget extends MultiRenderTarget {
 	        this.useGeometryBufferFallback = true;
 	        this.useGeometryBufferFallback = true;
 	    }
 	    }
 
 
+	    const applyByPostProcess = this._scene.imageProcessingConfiguration?.applyByPostProcess;
 	    this.imageProcessingPostProcess = new ImageProcessingPostProcess("prePassComposition", 1, null, undefined, this._engine);
 	    this.imageProcessingPostProcess = new ImageProcessingPostProcess("prePassComposition", 1, null, undefined, this._engine);
+	    this.imageProcessingPostProcess.imageProcessingConfiguration.applyByPostProcess = applyByPostProcess;
 	}
 	}
 
 
 	public _updateGeometryBufferLayout() {
 	public _updateGeometryBufferLayout() {
@@ -255,6 +282,13 @@ export class PrePassRenderTarget extends MultiRenderTarget {
 	 */
 	 */
 	public dispose() {
 	public dispose() {
 		super.dispose();
 		super.dispose();
+
+		for (let i = 0; i < this._effectConfigurations.length; i++) {
+		    if (this._effectConfigurations[i].dispose) {
+		        this._effectConfigurations[i].dispose!();
+		    }
+		}
+
 		if (this.imageProcessingPostProcess) {
 		if (this.imageProcessingPostProcess) {
 	        this.imageProcessingPostProcess.dispose();
 	        this.imageProcessingPostProcess.dispose();
 		}
 		}

+ 23 - 6
src/Materials/Textures/renderTargetTexture.ts

@@ -112,6 +112,12 @@ export class RenderTargetTexture extends Texture {
      */
      */
     public renderSprites = false;
     public renderSprites = false;
     /**
     /**
+    * @hidden
+     * Defines if prepass should be rendered in your texture.
+     * This is automatically set by the prepass renderer
+     */
+    public _renderPrePass = false;
+    /**
      * Define the camera used to render the texture.
      * Define the camera used to render the texture.
      */
      */
     public activeCamera: Nullable<Camera>;
     public activeCamera: Nullable<Camera>;
@@ -133,6 +139,13 @@ export class RenderTargetTexture extends Texture {
     public ignoreCameraViewport: boolean = false;
     public ignoreCameraViewport: boolean = false;
 
 
     private _postProcessManager: Nullable<PostProcessManager>;
     private _postProcessManager: Nullable<PostProcessManager>;
+
+    /**
+     * Post-processes for this render target
+     */
+    public get postProcesses() {
+        return this._postProcesses;
+    }
     private _postProcesses: PostProcess[];
     private _postProcesses: PostProcess[];
     private _resizeObserver: Nullable<Observer<Engine>>;
     private _resizeObserver: Nullable<Observer<Engine>>;
 
 
@@ -849,11 +862,13 @@ export class RenderTargetTexture extends Texture {
         }
         }
 
 
         // Bind
         // Bind
-        if (this._postProcessManager) {
-            this._postProcessManager._prepareFrame(this._texture, this._postProcesses);
-        }
-        else if (!useCameraPostProcess || !scene.postProcessManager._prepareFrame(this._texture)) {
-            this._bindFrameBuffer(faceIndex, layer);
+        if (!this._renderPrePass) {
+            if (this._postProcessManager) {
+                this._postProcessManager._prepareFrame(this._texture, this._postProcesses);
+            }
+            else if (!useCameraPostProcess || !scene.postProcessManager._prepareFrame(this._texture)) {
+                this._bindFrameBuffer(faceIndex, layer);
+            }
         }
         }
 
 
         if (this.is2DArray) {
         if (this.is2DArray) {
@@ -889,7 +904,9 @@ export class RenderTargetTexture extends Texture {
         if (this.onClearObservable.hasObservers()) {
         if (this.onClearObservable.hasObservers()) {
             this.onClearObservable.notifyObservers(engine);
             this.onClearObservable.notifyObservers(engine);
         } else {
         } else {
-            engine.clear(this.clearColor || scene.clearColor, true, true, true);
+            if (!this._renderPrePass) {
+                engine.clear(this.clearColor || scene.clearColor, true, true, true);
+            }
         }
         }
 
 
         if (!this._doNotChangeAspectRatio) {
         if (!this._doNotChangeAspectRatio) {

+ 66 - 64
src/Rendering/prePassRenderer.ts

@@ -6,12 +6,13 @@ import { PostProcess } from "../PostProcesses/postProcess";
 import { Effect } from "../Materials/effect";
 import { Effect } from "../Materials/effect";
 import { _DevTools } from '../Misc/devTools';
 import { _DevTools } from '../Misc/devTools';
 import { Color4 } from "../Maths/math.color";
 import { Color4 } from "../Maths/math.color";
-import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
 import { Nullable } from "../types";
 import { Nullable } from "../types";
 import { AbstractMesh } from '../Meshes/abstractMesh';
 import { AbstractMesh } from '../Meshes/abstractMesh';
 import { Camera } from '../Cameras/camera';
 import { Camera } from '../Cameras/camera';
 import { Material } from '../Materials/material';
 import { Material } from '../Materials/material';
 import { SubMesh } from '../Meshes/subMesh';
 import { SubMesh } from '../Meshes/subMesh';
+import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
+import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
 
 
 /**
 /**
  * Renders a pre pass of the scene
  * Renders a pre pass of the scene
@@ -68,14 +69,9 @@ export class PrePassRenderer {
 
 
     private readonly _clearColor = new Color4(0, 0, 0, 0);
     private readonly _clearColor = new Color4(0, 0, 0, 0);
 
 
-    /**
-     * Configuration for prepass effects
-     */
-    private _effectConfigurations: PrePassEffectConfiguration[] = [];
-
     private _enabled: boolean = false;
     private _enabled: boolean = false;
 
 
-    private _needsCompositionForThisCamera = false;
+    private _needsCompositionForThisPass = false;
 
 
     /**
     /**
      * Indicates if the prepass is enabled
      * Indicates if the prepass is enabled
@@ -101,9 +97,10 @@ export class PrePassRenderer {
 
 
         PrePassRenderer._SceneComponentInitialization(this._scene);
         PrePassRenderer._SceneComponentInitialization(this._scene);
         this.defaultRT = this._createRenderTarget();
         this.defaultRT = this._createRenderTarget();
+        this._setRenderTarget(null);
     }
     }
 
 
-    private _createRenderTarget() : PrePassRenderTarget {
+    public _createRenderTarget() : PrePassRenderTarget {
         const rt = new PrePassRenderTarget("sceneprePassRT", this, { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, 0, this._scene,
         const rt = new PrePassRenderTarget("sceneprePassRT", this, { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, 0, this._scene,
             { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: [] });
             { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: [] });
         rt.samples = 1;
         rt.samples = 1;
@@ -154,12 +151,20 @@ export class PrePassRenderer {
     /**
     /**
      * @hidden
      * @hidden
      */
      */
-    public _beforeCameraDraw(camera: Camera) {
+    public _beforeDraw(camera: Nullable<Camera>, texture: Nullable<RenderTargetTexture>) {
         if (this._isDirty) {
         if (this._isDirty) {
             this._update(this._currentTarget);
             this._update(this._currentTarget);
         }
         }
 
 
         if (!this._enabled) {
         if (!this._enabled) {
+            // Prepass disabled, we render only on 1 color attachment
+            if (texture) {
+                texture._bindFrameBuffer();
+            } else {
+                this._engine.restoreDefaultFramebuffer();
+            }
+            this._engine.restoreSingleAttachment();
+
             return;
             return;
         }
         }
 
 
@@ -168,17 +173,17 @@ export class PrePassRenderer {
             this._currentTarget._geometryBuffer.renderList!.length = 0;
             this._currentTarget._geometryBuffer.renderList!.length = 0;
         }
         }
 
 
-        this._setupOutputForCamera(this._currentTarget, camera);
+        this._setupOutputForThisPass(this._currentTarget, camera, texture ? texture.postProcesses : []);
     }
     }
 
 
     /**
     /**
      * @hidden
      * @hidden
      */
      */
-    public _afterCameraDraw(camera: Camera) {
+    public _afterDraw(camera: Nullable<Camera>, texture: Nullable<RenderTargetTexture>) {
         if (this._enabled) {
         if (this._enabled) {
             this._scene.postProcessManager._prepareFrame();
             this._scene.postProcessManager._prepareFrame();
             const firstCameraPP = camera && camera._getFirstPostProcess();
             const firstCameraPP = camera && camera._getFirstPostProcess();
-            let outputTexture = firstCameraPP ? firstCameraPP.inputTexture : null
+            let outputTexture = firstCameraPP ? firstCameraPP.inputTexture : (texture ? texture.getInternalTexture() : null);
 
 
             // Build post process chain for this prepass post draw
             // Build post process chain for this prepass post draw
             let postProcessChain = this._currentTarget._beforeCompositionPostProcesses;
             let postProcessChain = this._currentTarget._beforeCompositionPostProcesses;
@@ -187,8 +192,8 @@ export class PrePassRenderer {
             if (this._currentTarget !== this.defaultRT) {
             if (this._currentTarget !== this.defaultRT) {
                 postProcessChain = [];
                 postProcessChain = [];
             }
             }
-            
-            if (this._needsCompositionForThisCamera) {
+
+            if (this._needsCompositionForThisPass) {
                 postProcessChain = postProcessChain.concat([this._currentTarget.imageProcessingPostProcess]);
                 postProcessChain = postProcessChain.concat([this._currentTarget.imageProcessingPostProcess]);
             }
             }
 
 
@@ -248,31 +253,22 @@ export class PrePassRenderer {
     }
     }
 
 
     /**
     /**
-     * Adds an effect configuration to the prepass.
+     * Adds an effect configuration to the current prepass render target.
      * If an effect has already been added, it won't add it twice and will return the configuration
      * If an effect has already been added, it won't add it twice and will return the configuration
      * already present.
      * already present.
      * @param cfg the effect configuration
      * @param cfg the effect configuration
      * @return the effect configuration now used by the prepass
      * @return the effect configuration now used by the prepass
      */
      */
-    public addEffectConfiguration(cfg: PrePassEffectConfiguration) : PrePassEffectConfiguration {
-        // Do not add twice
-        for (let i = 0; i < this._effectConfigurations.length; i++) {
-            if (this._effectConfigurations[i].name === cfg.name) {
-                return this._effectConfigurations[i];
-            }
-        }
-
-        this._effectConfigurations.push(cfg);
-        return cfg;
+    public addEffectConfiguration(effectConfiguration: PrePassEffectConfiguration): PrePassEffectConfiguration {
+        return this.getRenderTarget()._addEffectConfiguration(effectConfiguration);
     }
     }
 
 
     private _enable(prePassRenderTarget: PrePassRenderTarget) {
     private _enable(prePassRenderTarget: PrePassRenderTarget) {
-        // TODO : loop over all rts, this function shouldn't be called with prePassRenderTarget
         const previousMrtCount = prePassRenderTarget.mrtCount;
         const previousMrtCount = prePassRenderTarget.mrtCount;
 
 
-        for (let i = 0; i < this._effectConfigurations.length; i++) {
-            if (this._effectConfigurations[i].enabled) {
-                this._enableTextures(prePassRenderTarget, this._effectConfigurations[i].texturesRequired);
+        for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
+            if (prePassRenderTarget._effectConfigurations[i].enabled) {
+                this._enableTextures(prePassRenderTarget, prePassRenderTarget._effectConfigurations[i].texturesRequired);
             }
             }
         }
         }
 
 
@@ -283,15 +279,17 @@ export class PrePassRenderer {
         prePassRenderTarget._updateGeometryBufferLayout();
         prePassRenderTarget._updateGeometryBufferLayout();
         prePassRenderTarget._resetPostProcessChain();
         prePassRenderTarget._resetPostProcessChain();
 
 
-        for (let i = 0; i < this._effectConfigurations.length; i++) {
-            if (this._effectConfigurations[i].enabled) {
-                // TODO : 1 post process per prepass RT to avoid recreating textures if size are differing
-                if (!this._effectConfigurations[i].postProcess && this._effectConfigurations[i].createPostProcess) {
-                    this._effectConfigurations[i].createPostProcess!();
+        for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
+            if (prePassRenderTarget._effectConfigurations[i].enabled) {
+                // TODO : subsurface scattering has 1 scene-wide effect configuration
+                // solution : do not stock postProcess on effectConfiguration, but in the prepassRenderTarget (hashmap configuration => postProcess)
+                // And call createPostProcess whenever the post process does not exist in the RT
+                if (!prePassRenderTarget._effectConfigurations[i].postProcess && prePassRenderTarget._effectConfigurations[i].createPostProcess) {
+                    prePassRenderTarget._effectConfigurations[i].createPostProcess!();
                 }
                 }
 
 
-                if (this._effectConfigurations[i].postProcess) {
-                    prePassRenderTarget._beforeCompositionPostProcesses.push(this._effectConfigurations[i].postProcess!);
+                if (prePassRenderTarget._effectConfigurations[i].postProcess) {
+                    prePassRenderTarget._beforeCompositionPostProcesses.push(prePassRenderTarget._effectConfigurations[i].postProcess!);
                 }
                 }
             }
             }
         }
         }
@@ -308,11 +306,10 @@ export class PrePassRenderer {
     private _disable(prePassRenderTarget: PrePassRenderTarget) {
     private _disable(prePassRenderTarget: PrePassRenderTarget) {
         this._setState(prePassRenderTarget, false);
         this._setState(prePassRenderTarget, false);
 
 
-        // TODO : separate and loop over all rt, this function shouldn't need to be called with prePassRenderTarget
         prePassRenderTarget._resetLayout();
         prePassRenderTarget._resetLayout();
 
 
-        for (let i = 0; i < this._effectConfigurations.length; i++) {
-            this._effectConfigurations[i].enabled = false;
+        for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
+            prePassRenderTarget._effectConfigurations[i].enabled = false;
         }
         }
     }
     }
 
 
@@ -327,27 +324,31 @@ export class PrePassRenderer {
     //     }
     //     }
     // }
     // }
 
 
-    private _setupOutputForCamera(prePassRenderTarget: PrePassRenderTarget, camera: Camera) {
+    private _setupOutputForThisPass(prePassRenderTarget: PrePassRenderTarget, camera: Nullable<Camera>, postProcesses: Nullable<PostProcess>[] = []) {
         // Here we search for an image composition post process
         // Here we search for an image composition post process
         // If no ipp if found, we use the prepass built-in
         // 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
         // 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._needsCompositionForThisCamera = !this._cameraHasImageProcessing(camera) && !this.disableGammaTransform && !secondaryCamera;
-        const firstCameraPP = camera && camera._getFirstPostProcess();
+        // Order is : draw ===> prePassRenderTarget._postProcesses ==> ipp ==> camera._postProcesses
+        const secondaryCamera = camera && this._scene.activeCameras && !!this._scene.activeCameras.length && this._scene.activeCameras.indexOf(camera) !== 0;
+        const postProcessesSource = camera ? camera._postProcesses : postProcesses;
+        this._needsCompositionForThisPass = !this._hasImageProcessing(postProcessesSource) && 
+            !this.disableGammaTransform && 
+            !secondaryCamera;
+        const firstCameraPP = this._getFirstPostProcess(postProcessesSource);
         const firstPrePassPP = prePassRenderTarget._beforeCompositionPostProcesses && prePassRenderTarget._beforeCompositionPostProcesses[0];
         const firstPrePassPP = prePassRenderTarget._beforeCompositionPostProcesses && prePassRenderTarget._beforeCompositionPostProcesses[0];
         let firstPP = null;
         let firstPP = null;
 
 
         prePassRenderTarget.imageProcessingPostProcess.restoreDefaultInputTexture();
         prePassRenderTarget.imageProcessingPostProcess.restoreDefaultInputTexture();
 
 
-        // Setting the defaultRT as input texture of the first PP
+        // Setting the prePassRenderTarget as input texture of the first PP
         if (firstPrePassPP) {
         if (firstPrePassPP) {
-            firstPrePassPP.inputTexture = this.defaultRT.getInternalTexture()!;
+            firstPrePassPP.inputTexture = prePassRenderTarget.getInternalTexture()!;
             firstPP = firstPrePassPP;
             firstPP = firstPrePassPP;
-        } else if (this._needsCompositionForThisCamera) {
-            prePassRenderTarget.imageProcessingPostProcess.inputTexture = this.defaultRT.getInternalTexture()!;
+        } else if (this._needsCompositionForThisPass) {
+            prePassRenderTarget.imageProcessingPostProcess.inputTexture = prePassRenderTarget.getInternalTexture()!;
             firstPP = prePassRenderTarget.imageProcessingPostProcess;
             firstPP = prePassRenderTarget.imageProcessingPostProcess;
         } else if (firstCameraPP) {
         } else if (firstCameraPP) {
-            firstCameraPP.inputTexture = this.defaultRT.getInternalTexture()!;
+            firstCameraPP.inputTexture = prePassRenderTarget.getInternalTexture()!;
             firstPP = firstCameraPP;
             firstPP = firstCameraPP;
         }
         }
         
         
@@ -358,11 +359,11 @@ export class PrePassRenderer {
         this._bindFrameBuffer(prePassRenderTarget);
         this._bindFrameBuffer(prePassRenderTarget);
     }
     }
 
 
-    private _cameraHasImageProcessing(camera: Camera): boolean {
+    private _hasImageProcessing(postProcesses: Nullable<PostProcess>[]): boolean {
         let isIPPAlreadyPresent = false;
         let isIPPAlreadyPresent = false;
-        if (camera._postProcesses) {
-            for (let i = 0; i < camera._postProcesses.length; i++) {
-                if (camera._postProcesses[i]?.getClassName() === "ImageProcessingPostProcess") {
+        if (postProcesses) {
+            for (let i = 0; i < postProcesses.length; i++) {
+                if (postProcesses[i]?.getClassName() === "ImageProcessingPostProcess") {
                     isIPPAlreadyPresent = true;
                     isIPPAlreadyPresent = true;
                 }
                 }
             }
             }
@@ -372,6 +373,19 @@ export class PrePassRenderer {
     }
     }
 
 
     /**
     /**
+     * Internal, gets the first post proces.
+     * @returns the first post process to be run on this camera.
+     */
+    private _getFirstPostProcess(postProcesses: Nullable<PostProcess>[]): Nullable<PostProcess> {
+        for (var ppIndex = 0; ppIndex < postProcesses.length; ppIndex++) {
+            if (postProcesses[ppIndex] !== null) {
+                return postProcesses[ppIndex];
+            }
+        }
+        return null;
+    }
+
+    /**
      * Marks the prepass renderer as dirty, triggering a check if the prepass is necessary for the next rendering.
      * Marks the prepass renderer as dirty, triggering a check if the prepass is necessary for the next rendering.
      */
      */
     public markAsDirty() {
     public markAsDirty() {
@@ -426,12 +440,6 @@ export class PrePassRenderer {
         if (enablePrePass) {
         if (enablePrePass) {
             this._enable(prePassRenderTarget);
             this._enable(prePassRenderTarget);
         }
         }
-
-        if (!this.enabled) {
-            // Prepass disabled, we render only on 1 color attachment
-            this._engine.restoreDefaultFramebuffer();
-            this._engine.restoreSingleAttachment();
-        }
     }
     }
 
 
     private _markAllMaterialsAsPrePassDirty() {
     private _markAllMaterialsAsPrePassDirty() {
@@ -446,12 +454,6 @@ export class PrePassRenderer {
      * Disposes the prepass renderer.
      * Disposes the prepass renderer.
      */
      */
     public dispose() {
     public dispose() {
-        for (let i = 0; i < this._effectConfigurations.length; i++) {
-            if (this._effectConfigurations[i].dispose) {
-                this._effectConfigurations[i].dispose!();
-            }
-        }
-
         for (let i = 0; i < this._renderTargets.length; i++) {
         for (let i = 0; i < this._renderTargets.length; i++) {
             this._renderTargets[i].dispose();
             this._renderTargets[i].dispose();
         }
         }

+ 30 - 3
src/Rendering/prePassRendererSceneComponent.ts

@@ -8,6 +8,8 @@ import { SubMesh } from "../Meshes/subMesh";
 import { _InstancesBatch } from "../Meshes/mesh";
 import { _InstancesBatch } from "../Meshes/mesh";
 import { Effect } from "../Materials/effect";
 import { Effect } from "../Materials/effect";
 import { Camera } from '../Cameras/camera';
 import { Camera } from '../Cameras/camera';
+import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
+import { PrePassRenderTarget } from "../Materials/Textures/prePassRenderTarget";
 
 
 declare module "../abstractScene" {
 declare module "../abstractScene" {
     export interface AbstractScene {
     export interface AbstractScene {
@@ -32,6 +34,12 @@ declare module "../abstractScene" {
     }
     }
 }
 }
 
 
+declare module "../Materials/Textures/renderTargetTexture" {
+    export interface RenderTargetTexture {
+        prePassRenderTarget: PrePassRenderTarget;
+    }
+}
+
 Object.defineProperty(Scene.prototype, "prePassRenderer", {
 Object.defineProperty(Scene.prototype, "prePassRenderer", {
     get: function(this: Scene) {
     get: function(this: Scene) {
         return this._prePassRenderer;
         return this._prePassRenderer;
@@ -100,22 +108,41 @@ export class PrePassRendererSceneComponent implements ISceneComponent {
     public register(): void {
     public register(): void {
         this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_PREPASS, this, this._beforeCameraDraw);
         this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_PREPASS, this, this._beforeCameraDraw);
         this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_PREPASS, this, this._afterCameraDraw);
         this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_PREPASS, this, this._afterCameraDraw);
+        this.scene._beforeRenderTargetDrawStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERTARGETDRAW_PREPASS, this, this._beforeRenderTargetDraw);
+        this.scene._afterRenderTargetDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_PREPASS, this, this._afterRenderTargetDraw);
+
         this.scene._beforeClearStage.registerStep(SceneComponentConstants.STEP_BEFORECLEARSTAGE_PREPASS, this, this._beforeClearStage);
         this.scene._beforeClearStage.registerStep(SceneComponentConstants.STEP_BEFORECLEARSTAGE_PREPASS, this, this._beforeClearStage);
+
         this.scene._beforeRenderingMeshStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERINGMESH_PREPASS, this, this._beforeRenderingMeshStage);
         this.scene._beforeRenderingMeshStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERINGMESH_PREPASS, this, this._beforeRenderingMeshStage);
         this.scene._afterRenderingMeshStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGMESH_PREPASS, this, this._afterRenderingMeshStage);
         this.scene._afterRenderingMeshStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGMESH_PREPASS, this, this._afterRenderingMeshStage);
     }
     }
 
 
+    private _beforeRenderTargetDraw(renderTarget: RenderTargetTexture) {
+        if (this.scene.prePassRenderer) {
+            if (!renderTarget.prePassRenderTarget) {
+                renderTarget.prePassRenderTarget = this.scene.prePassRenderer._createRenderTarget();
+            }
+            this.scene.prePassRenderer._setRenderTarget(renderTarget.prePassRenderTarget);
+            this.scene.prePassRenderer._beforeDraw(null, renderTarget);
+        }
+    }
+
+    private _afterRenderTargetDraw(renderTarget: RenderTargetTexture) {
+        if (this.scene.prePassRenderer) {
+            this.scene.prePassRenderer._afterDraw(null, renderTarget);
+        }
+    }
+
     private _beforeCameraDraw(camera: Camera) {
     private _beforeCameraDraw(camera: Camera) {
         if (this.scene.prePassRenderer) {
         if (this.scene.prePassRenderer) {
-            // TODO choose the right rt
             this.scene.prePassRenderer._setRenderTarget(null);
             this.scene.prePassRenderer._setRenderTarget(null);
-            this.scene.prePassRenderer._beforeCameraDraw(camera);
+            this.scene.prePassRenderer._beforeDraw(camera, null);
         }
         }
     }
     }
 
 
     private _afterCameraDraw(camera: Camera) {
     private _afterCameraDraw(camera: Camera) {
         if (this.scene.prePassRenderer) {
         if (this.scene.prePassRenderer) {
-            this.scene.prePassRenderer._afterCameraDraw(camera);
+            this.scene.prePassRenderer._afterDraw(camera, null);
         }
         }
     }
     }
 
 

+ 4 - 2
src/sceneComponent.ts

@@ -51,7 +51,8 @@ export class SceneComponentConstants {
     public static readonly STEP_BEFORECAMERADRAW_LAYER = 1;
     public static readonly STEP_BEFORECAMERADRAW_LAYER = 1;
     public static readonly STEP_BEFORECAMERADRAW_PREPASS = 2;
     public static readonly STEP_BEFORECAMERADRAW_PREPASS = 2;
 
 
-    public static readonly STEP_BEFORERENDERTARGETDRAW_LAYER = 0;
+    public static readonly STEP_BEFORERENDERTARGETDRAW_PREPASS = 0;
+    public static readonly STEP_BEFORERENDERTARGETDRAW_LAYER = 1;
 
 
     public static readonly STEP_BEFORERENDERINGMESH_PREPASS = 0;
     public static readonly STEP_BEFORERENDERINGMESH_PREPASS = 0;
     public static readonly STEP_BEFORERENDERINGMESH_OUTLINE = 1;
     public static readonly STEP_BEFORERENDERINGMESH_OUTLINE = 1;
@@ -67,7 +68,8 @@ export class SceneComponentConstants {
 
 
     public static readonly STEP_BEFORECLEAR_PROCEDURALTEXTURE = 0;
     public static readonly STEP_BEFORECLEAR_PROCEDURALTEXTURE = 0;
 
 
-    public static readonly STEP_AFTERRENDERTARGETDRAW_LAYER = 0;
+    public static readonly STEP_AFTERRENDERTARGETDRAW_PREPASS = 0;
+    public static readonly STEP_AFTERRENDERTARGETDRAW_LAYER = 1;
 
 
     public static readonly STEP_AFTERCAMERADRAW_PREPASS = 0;
     public static readonly STEP_AFTERCAMERADRAW_PREPASS = 0;
     public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER = 1;
     public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER = 1;