Sfoglia il codice sorgente

effects are now scene wide

Benjamin Guignabert 4 anni fa
parent
commit
0faee707cc

+ 1 - 1
package.json

@@ -112,4 +112,4 @@
         "xhr2": "^0.2.0",
         "xmlbuilder": "15.1.1"
     }
-}
+}

+ 80 - 264
src/Materials/Textures/prePassRenderTarget.ts

@@ -1,44 +1,21 @@
 import { MultiRenderTarget, IMultiRenderTargetOptions } from "./multiRenderTarget";
 import { Engine } from "../../Engines/engine";
-import { GeometryBufferRenderer } from '../../Rendering/geometryBufferRenderer';
-import { PrePassRenderer } from '../../Rendering/prePassRenderer';
-import { Nullable } from "../../types";
+import { RenderTargetTexture } from './renderTargetTexture';
 import { Scene } from "../../scene";
-import { Constants } from "../../Engines/constants";
 import { PostProcess } from "../../PostProcesses/postProcess";
 import { ImageProcessingPostProcess } from "../../PostProcesses/imageProcessingPostProcess";
-import { PrePassEffectConfiguration } from "../../Rendering/prePassEffectConfiguration";
+import { Nullable } from "../../types";
 
 /**
  * A multi render target designed to render the prepass.
  * Prepass is a scene component used to render information in multiple textures
  * alongside with the scene materials rendering.
- * Note : This is an internal class, and you should NOT need to instanciate this. 
+ * Note : This is an internal class, and you should NOT need to instanciate this.
  * Only the `PrePassRenderer` should instanciate this class.
  * It is more likely that you need a regular `MultiRenderTarget`
  */
 export class PrePassRenderTarget extends MultiRenderTarget {
 
-	/**
-	 * Number of textures in the multi render target texture where the scene is directly rendered
-	 */
-	public mrtCount: number = 0;
-
-	/**
-	 * Is rendering on this prepass texture enabled
-	 */
-	public enabled: boolean = false;
-
-	public _mrtFormats: number[] = [];
-	public _mrtLayout: number[];
-    public _textureIndices: number[] = [];
-
-    public _multiRenderAttachments: number[];
-    public _defaultAttachments: number[];
-    public _clearAttachments: number[];
-
-    public _isDirty: boolean = true;
-
     public _beforeCompositionPostProcesses: PostProcess[] = [];
     /**
      * Image processing post process for composition
@@ -46,256 +23,95 @@ export class PrePassRenderTarget extends MultiRenderTarget {
     public imageProcessingPostProcess: ImageProcessingPostProcess;
 
     /**
-     * Configuration for prepass effects
+     * How many samples are used for MSAA of the scene render target
      */
-    public _effectConfigurations: PrePassEffectConfiguration[] = [];
-
-    private _prePassRenderer: PrePassRenderer;
-
-	/**
-	 * How many samples are used for MSAA of the scene render target
-	 */
-	public get samples() {
-	    return this._samples;
-	}
-
-	public set samples(n: number) {
-	    if (!this.imageProcessingPostProcess) {
-	        this._createCompositionEffect();
-	    }
-
-	    this._samples = n;
-	}
-
-	public _engine: Engine;
-	public _scene: Scene;
-
-	public static _textureFormats = [
-	    {
-	        type: Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE,
-	        format: Constants.TEXTURETYPE_HALF_FLOAT,
-	    },
-	    {
-	        type: Constants.PREPASS_POSITION_TEXTURE_TYPE,
-	        format: Constants.TEXTURETYPE_HALF_FLOAT,
-	    },
-	    {
-	        type: Constants.PREPASS_VELOCITY_TEXTURE_TYPE,
-	        format: Constants.TEXTURETYPE_HALF_FLOAT,
-	    },
-	    {
-	        type: Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE,
-	        format: Constants.TEXTURETYPE_UNSIGNED_INT,
-	    },
-	    {
-	        type: Constants.PREPASS_COLOR_TEXTURE_TYPE,
-	        format: Constants.TEXTURETYPE_HALF_FLOAT,
-	    },
-	    {
-	        type: Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE,
-	        format: Constants.TEXTURETYPE_HALF_FLOAT,
-	    },
-	    {
-	        type: Constants.PREPASS_ALBEDO_TEXTURE_TYPE,
-	        format: Constants.TEXTURETYPE_UNSIGNED_INT,
-	    },
-	];
-
-	public _geometryBuffer: Nullable<GeometryBufferRenderer>;
-	public _useGeometryBufferFallback = false;
-	/**
-	 * Uses the geometry buffer renderer as a fallback for non prepass capable effects
-	 */
-	public get useGeometryBufferFallback() : boolean {
-	    return this._useGeometryBufferFallback;
-	}
-
-	public set useGeometryBufferFallback(value: boolean) {
-	    this._useGeometryBufferFallback = value;
-
-	    if (value) {
-	        this._geometryBuffer = this._scene.enableGeometryBufferRenderer();
-
-	        if (!this._geometryBuffer) {
-	            // Not supported
-	            this._useGeometryBufferFallback = false;
-	            return;
-	        }
-
-	        this._geometryBuffer.renderList = [];
-	        this._geometryBuffer._linkPrePassRenderer(this._prePassRenderer);
-	        this._updateGeometryBufferLayout();
-	    } else {
-	        if (this._geometryBuffer) {
-	            this._geometryBuffer._unlinkPrePassRenderer();
-	        }
-	        this._geometryBuffer = null;
-	        this._scene.disableGeometryBufferRenderer();
-	    }
-	}
-
-	/**
-	 * Returns the index of a texture in the multi render target texture array.
-	 * @param type Texture type
-	 * @return The index
-	 */
-	public getIndex(type: number) : number {
-	    return this._textureIndices[type];
-	}
-
-	public constructor(name: string,  prePassRenderer: PrePassRenderer, size: any, count: number, scene: Scene, options?: IMultiRenderTargetOptions | undefined) {
-		super(name, size, count, scene, options);
-		this._prePassRenderer = prePassRenderer;
+    public get samples() {
+        return this._samples;
+    }
 
-		this._resetLayout();
-		this._reinitializeAttachments();
-	}
+    public set samples(n: number) {
+        if (!this.imageProcessingPostProcess) {
+            this._createCompositionEffect();
+        }
 
-	/**
-	 * 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._samples = n;
+    }
 
-	    this._effectConfigurations.push(cfg);
-	    return cfg;
-	}
+    public _engine: Engine;
+    public _scene: Scene;
 
-	/**
-	 * Prepares this rt to rebuild attachments according to the current texture layout
-	 */
-	public _reinitializeAttachments() {
-	    const multiRenderLayout = [];
-	    const clearLayout = [false];
-	    const defaultLayout = [true];
-
-	    for (let i = 0; i < this.mrtCount; i++) {
-	        multiRenderLayout.push(true);
-
-	        if (i > 0) {
-	            clearLayout.push(true);
-	            defaultLayout.push(false);
-	        }
-	    }
-
-	    this._multiRenderAttachments = this._engine.buildTextureLayout(multiRenderLayout);
-	    this._clearAttachments = this._engine.buildTextureLayout(clearLayout);
-	    this._defaultAttachments = this._engine.buildTextureLayout(defaultLayout);
-	}
-
-	public _createCompositionEffect() {
-	    if (this._useGeometryBufferFallback && !this._geometryBuffer) {
-	        // Initializes the link with geometry buffer
-	        this.useGeometryBufferFallback = true;
-	    }
-
-	    const applyByPostProcess = this._scene.imageProcessingConfiguration?.applyByPostProcess;
-	    this.imageProcessingPostProcess = new ImageProcessingPostProcess("prePassComposition", 1, null, undefined, this._engine);
-	    this.imageProcessingPostProcess.imageProcessingConfiguration.applyByPostProcess = applyByPostProcess;
-	}
-
-	public _updateGeometryBufferLayout() {
-	    if (this._geometryBuffer) {
-	        this._geometryBuffer._resetLayout();
-
-	        const texturesActivated = [];
-
-	        for (let i = 0; i < this._mrtLayout.length; i++) {
-	            texturesActivated.push(false);
-	        }
-
-	        this._geometryBuffer._linkInternalTexture(this.getInternalTexture()!);
-
-	        const matches = [
-	            {
-	                prePassConstant: Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE,
-	                geometryBufferConstant: GeometryBufferRenderer.DEPTHNORMAL_TEXTURE_TYPE,
-	            },
-	            {
-	                prePassConstant: Constants.PREPASS_POSITION_TEXTURE_TYPE,
-	                geometryBufferConstant: GeometryBufferRenderer.POSITION_TEXTURE_TYPE,
-	            },
-	            {
-	                prePassConstant: Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE,
-	                geometryBufferConstant: GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE,
-	            },
-	            {
-	                prePassConstant: Constants.PREPASS_VELOCITY_TEXTURE_TYPE,
-	                geometryBufferConstant: GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE,
-	            }
-	        ];
-
-	        // replace textures in the geometryBuffer RT
-	        for (let i = 0; i < matches.length; i++) {
-	            const index = this._mrtLayout.indexOf(matches[i].prePassConstant);
-	            if (index !== -1) {
-	                this._geometryBuffer._forceTextureType(matches[i].geometryBufferConstant, index);
-	                texturesActivated[index] = true;
-	            }
-	        }
-
-	        this._geometryBuffer._setAttachments(this._engine.buildTextureLayout(texturesActivated));
-	    }
-	}
+    /**
+      * Is this render target enabled for prepass rendering
+      */
+    public enabled: boolean = false;
 
-	/**
-	 * Checks that the size of this RT is still adapted to the desired render size.
-	 */
-	public _checkSize() {
-	    var requiredWidth = this._engine.getRenderWidth(true);
-	    var requiredHeight = this._engine.getRenderHeight(true);
-	    var width = this.getRenderWidth();
-	    var height = this.getRenderHeight();
+    /**
+      * Render target associated with this prePassRenderTarget
+      * If this is `null`, it means this prePassRenderTarget is associated with the scene
+      */
+    public renderTargetTexture: Nullable<RenderTargetTexture> = null;
+
+    public constructor(name: string,  renderTargetTexture: Nullable<RenderTargetTexture>, size: any, count: number, scene: Scene, options?: IMultiRenderTargetOptions | undefined) {
+        super(name, size, count, scene, options);
+
+        this.renderTargetTexture = renderTargetTexture;
+        // TODO : poser dans prepassrenderer ?
+        // this._resetLayout();
+        // this._reinitializeAttachments();
+    }
+
+    public _createCompositionEffect() {
+        // TODO : GBR
+        // if (this._useGeometryBufferFallback && !this._geometryBuffer) {
+        //     // Initializes the link with geometry buffer
+        //     this.useGeometryBufferFallback = true;
+        // }
+
+        const applyByPostProcess = this._scene.imageProcessingConfiguration?.applyByPostProcess;
+        this.imageProcessingPostProcess = new ImageProcessingPostProcess("prePassComposition", 1, null, undefined, this._engine);
+        this.imageProcessingPostProcess.imageProcessingConfiguration.applyByPostProcess = applyByPostProcess;
+    }
 
-	    if (width !== requiredWidth || height !== requiredHeight) {
-	        this.resize({ width: requiredWidth, height: requiredHeight });
+    /**
+     * Checks that the size of this RT is still adapted to the desired render size.
+     */
+    public _checkSize() {
+        var requiredWidth = this._engine.getRenderWidth(true);
+        var requiredHeight = this._engine.getRenderHeight(true);
+        var width = this.getRenderWidth();
+        var height = this.getRenderHeight();
 
-	        this._updateGeometryBufferLayout();
-	    }
-	}
+        if (width !== requiredWidth || height !== requiredHeight) {
+            this.resize({ width: requiredWidth, height: requiredHeight });
 
-	/**
-	 * Resets the texture layout within this MRT.
-	 */
-	public _resetLayout() {
-	    for (let i = 0 ; i < PrePassRenderTarget._textureFormats.length; i++) {
-	        this._textureIndices[PrePassRenderTarget._textureFormats[i].type] = -1;
-	    }
+            // TODO : geometry buffer
+            // this._updateGeometryBufferLayout();
+        }
+    }
 
-	    this._textureIndices[Constants.PREPASS_COLOR_TEXTURE_TYPE] = 0;
-	    this._mrtLayout = [Constants.PREPASS_COLOR_TEXTURE_TYPE];
-	    this._mrtFormats = [Constants.TEXTURETYPE_HALF_FLOAT];
-	    this.mrtCount = 1;
-	}
+    /**
+     * Resets the post processes chains applied to this RT.
+     */
+    public _resetPostProcessChain() {
+        this._beforeCompositionPostProcesses = [];
+    }
 
-	/**
-	 * Resets the post processes chains applied to this RT.
-	 */
-	public _resetPostProcessChain() {
-	    this._beforeCompositionPostProcesses = [];
-	}
+    /**
+     * Diposes this render target
+     */
+    public dispose() {
+        super.dispose();
 
-	/**
-	 * Diposes this render target
-	 */
-	public dispose() {
-		super.dispose();
+        if (this._scene.prePassRenderer) {
+            const index = this._scene.prePassRenderer.renderTargets.indexOf(this);
 
-		if (this._scene.prePassRenderer) {
-			this._scene.prePassRenderer.renderTargets.splice(this._scene.prePassRenderer.renderTargets.indexOf(this));
-		}
+            if (index !== -1) {
+                this._scene.prePassRenderer.renderTargets.splice(index, 1);
+            }
+        }
 
-		if (this.imageProcessingPostProcess) {
-	        this.imageProcessingPostProcess.dispose();
-		}
-	}
+        if (this.imageProcessingPostProcess) {
+            this.imageProcessingPostProcess.dispose();
+        }
+    }
 }

+ 3 - 3
src/Materials/materialHelper.ts

@@ -350,10 +350,10 @@ export class MaterialHelper {
 
         if (scene.prePassRenderer && scene.prePassRenderer.enabled && scene.prePassRenderer.getRenderTarget().enabled && canRenderToMRT) {
             defines.PREPASS = true;
-            defines.SCENE_MRT_COUNT = scene.prePassRenderer.getRenderTarget().mrtCount;
+            defines.SCENE_MRT_COUNT = scene.prePassRenderer.mrtCount;
 
             for (let i = 0; i < texturesList.length; i++) {
-                const index = scene.prePassRenderer.getRenderTarget().getIndex(texturesList[i].type);
+                const index = scene.prePassRenderer.getIndex(texturesList[i].type);
                 if (index !== -1) {
                     defines[texturesList[i].define] = true;
                     defines[texturesList[i].index] = index;
@@ -868,7 +868,7 @@ export class MaterialHelper {
 
                 if (matrices) {
                     effect.setMatrices("mBones", matrices);
-                    if (prePassConfiguration && mesh.getScene().prePassRenderer && mesh.getScene().prePassRenderer!.getRenderTarget().getIndex(Constants.PREPASS_VELOCITY_TEXTURE_TYPE)) {
+                    if (prePassConfiguration && mesh.getScene().prePassRenderer && mesh.getScene().prePassRenderer!.getIndex(Constants.PREPASS_VELOCITY_TEXTURE_TYPE)) {
                         if (prePassConfiguration.previousBones[mesh.uniqueId]) {
                             effect.setMatrices("mPreviousBones", prePassConfiguration.previousBones[mesh.uniqueId]);
                         }

+ 2 - 2
src/Materials/prePassConfiguration.ts

@@ -49,8 +49,8 @@ export class PrePassConfiguration {
      * @param isFrozen Is the material frozen
      */
     public bindForSubMesh(effect: Effect, scene: Scene, mesh: Mesh, world: Matrix, isFrozen: boolean): void {
-        if (scene.prePassRenderer && scene.prePassRenderer.enabled) {
-            if (scene.prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_VELOCITY_TEXTURE_TYPE) !== -1) {
+        if (scene.prePassRenderer && scene.prePassRenderer.enabled && scene.prePassRenderer.currentRTisSceneRT) {
+            if (scene.prePassRenderer.getIndex(Constants.PREPASS_VELOCITY_TEXTURE_TYPE) !== -1) {
                 if (!this.previousWorldMatrices[mesh.uniqueId]) {
                     this.previousWorldMatrices[mesh.uniqueId] = Matrix.Identity();
                 }

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

@@ -291,7 +291,7 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
             if (this._forceGeometryBuffer) {
                 effect.setTexture("depthNormalSampler", this._scene.enableGeometryBufferRenderer()!.getGBuffer().textures[0]);
             } else {
-                effect.setTexture("depthNormalSampler", this._prePassRenderer.getRenderTarget().textures[this._prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
+                effect.setTexture("depthNormalSampler", this._prePassRenderer.getRenderTarget().textures[this._prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
             }
             effect.setArray("samplerOffsets", this._samplerOffsets);
         };
@@ -309,7 +309,7 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
             if (this._forceGeometryBuffer) {
                 effect.setTexture("depthNormalSampler", this._scene.enableGeometryBufferRenderer()!.getGBuffer().textures[0]);
             } else {
-                effect.setTexture("depthNormalSampler", this._prePassRenderer.getRenderTarget().textures[this._prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
+                effect.setTexture("depthNormalSampler", this._prePassRenderer.getRenderTarget().textures[this._prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
             }
             effect.setArray("samplerOffsets", this._samplerOffsets);
 
@@ -427,7 +427,7 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
                 effect.setTexture("depthSampler", this._scene.enableGeometryBufferRenderer()!.getGBuffer().textures[0]);
                 effect.setTexture("normalSampler", this._scene.enableGeometryBufferRenderer()!.getGBuffer().textures[1]);
             } else {
-                effect.setTexture("depthNormalSampler", this._prePassRenderer.getRenderTarget().textures[this._prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
+                effect.setTexture("depthNormalSampler", this._prePassRenderer.getRenderTarget().textures[this._prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
             }
             effect.setTexture("randomSampler", this._randomTexture);
         };

+ 2 - 2
src/PostProcesses/motionBlurPostProcess.ts

@@ -233,7 +233,7 @@ export class MotionBlurPostProcess extends PostProcess {
             const velocityIndex = this._geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE);
             effect.setTexture("velocitySampler", this._geometryBufferRenderer.getGBuffer().textures[velocityIndex]);
         } else if (this._prePassRenderer) {
-            const velocityIndex = this._prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_VELOCITY_TEXTURE_TYPE);
+            const velocityIndex = this._prePassRenderer.getIndex(Constants.PREPASS_VELOCITY_TEXTURE_TYPE);
             effect.setTexture("velocitySampler", this._prePassRenderer.getRenderTarget().textures[velocityIndex]);
         }
     }
@@ -259,7 +259,7 @@ export class MotionBlurPostProcess extends PostProcess {
             const depthIndex = this._geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.DEPTHNORMAL_TEXTURE_TYPE);
             effect.setTexture("depthSampler", this._geometryBufferRenderer.getGBuffer().textures[depthIndex]);
         } else if (this._prePassRenderer) {
-            const depthIndex = this._prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE);
+            const depthIndex = this._prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE);
             effect.setTexture("depthSampler", this._prePassRenderer.getRenderTarget().textures[depthIndex]);
         }
     }

+ 3 - 3
src/PostProcesses/screenSpaceReflectionPostProcess.ts

@@ -121,9 +121,9 @@ export class ScreenSpaceReflectionPostProcess extends PostProcess {
                 effect.setTexture("reflectivitySampler", geometryBufferRenderer.getGBuffer().textures[roughnessIndex]);
             } else {
                 // Samplers
-                const positionIndex = prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_POSITION_TEXTURE_TYPE);
-                const roughnessIndex = prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE);
-                const normalIndex = prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE);
+                const positionIndex = prePassRenderer.getIndex(Constants.PREPASS_POSITION_TEXTURE_TYPE);
+                const roughnessIndex = prePassRenderer.getIndex(Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE);
+                const normalIndex = prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE);
 
                 effect.setTexture("normalSampler", prePassRenderer.getRenderTarget().textures[normalIndex]);
                 effect.setTexture("positionSampler", prePassRenderer.getRenderTarget().textures[positionIndex]);

+ 3 - 3
src/PostProcesses/subSurfaceScatteringPostProcess.ts

@@ -38,9 +38,9 @@ export class SubSurfaceScatteringPostProcess extends PostProcess {
             var texelSize = this.texelSize;
             effect.setFloat("metersPerUnit", scene.subSurfaceConfiguration.metersPerUnit);
             effect.setFloat2("texelSize", texelSize.x, texelSize.y);
-            effect.setTexture("irradianceSampler", scene.prePassRenderer.getRenderTarget().textures[scene.prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE)]);
-            effect.setTexture("depthSampler", scene.prePassRenderer.getRenderTarget().textures[scene.prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
-            effect.setTexture("albedoSampler", scene.prePassRenderer.getRenderTarget().textures[scene.prePassRenderer.getRenderTarget().getIndex(Constants.PREPASS_ALBEDO_TEXTURE_TYPE)]);
+            effect.setTexture("irradianceSampler", scene.prePassRenderer.getRenderTarget().textures[scene.prePassRenderer.getIndex(Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE)]);
+            effect.setTexture("depthSampler", scene.prePassRenderer.getRenderTarget().textures[scene.prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
+            effect.setTexture("albedoSampler", scene.prePassRenderer.getRenderTarget().textures[scene.prePassRenderer.getIndex(Constants.PREPASS_ALBEDO_TEXTURE_TYPE)]);
             effect.setFloat2("viewportSize",
                 Math.tan(scene.activeCamera!.fov / 2) * scene.getEngine().getAspectRatio(scene.activeCamera!, true),
                 Math.tan(scene.activeCamera!.fov / 2));

+ 290 - 94
src/Rendering/prePassRenderer.ts

@@ -13,6 +13,7 @@ import { Material } from '../Materials/material';
 import { SubMesh } from '../Meshes/subMesh';
 import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
 import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
+import { GeometryBufferRenderer } from '../Rendering/geometryBufferRenderer';
 
 /**
  * Renders a pre pass of the scene
@@ -42,13 +43,74 @@ export class PrePassRenderer {
     private _engine: Engine;
 
     /**
+     * Number of textures in the multi render target texture where the scene is directly rendered
+     */
+    public mrtCount: number = 0;
+
+    public _mrtFormats: number[] = [];
+    public _mrtLayout: number[];
+    public _textureIndices: number[] = [];
+
+    public _multiRenderAttachments: number[];
+    public _defaultAttachments: number[];
+    public _clearAttachments: number[];
+
+    /**
+     * Returns the index of a texture in the multi render target texture array.
+     * @param type Texture type
+     * @return The index
+     */
+    public getIndex(type: number) : number {
+        return this._textureIndices[type];
+    }
+
+    private static _textureFormats = [
+        {
+            type: Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE,
+            format: Constants.TEXTURETYPE_HALF_FLOAT,
+        },
+        {
+            type: Constants.PREPASS_POSITION_TEXTURE_TYPE,
+            format: Constants.TEXTURETYPE_HALF_FLOAT,
+        },
+        {
+            type: Constants.PREPASS_VELOCITY_TEXTURE_TYPE,
+            format: Constants.TEXTURETYPE_HALF_FLOAT,
+        },
+        {
+            type: Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE,
+            format: Constants.TEXTURETYPE_UNSIGNED_INT,
+        },
+        {
+            type: Constants.PREPASS_COLOR_TEXTURE_TYPE,
+            format: Constants.TEXTURETYPE_HALF_FLOAT,
+        },
+        {
+            type: Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE,
+            format: Constants.TEXTURETYPE_HALF_FLOAT,
+        },
+        {
+            type: Constants.PREPASS_ALBEDO_TEXTURE_TYPE,
+            format: Constants.TEXTURETYPE_UNSIGNED_INT,
+        },
+    ];
+
+    private _isDirty: boolean = true;
+
+    /**
      * The render target where the scene is directly rendered
      */
     public defaultRT: PrePassRenderTarget;
 
     /**
-     * Returns the prepass render target for the rendering pass. 
-     * If we are currently rendering a render target, it returns the PrePassRenderTarget 
+     * TODO : public ?
+     * Configuration for prepass effects
+     */
+    private _effectConfigurations: PrePassEffectConfiguration[] = [];
+
+    /**
+     * Returns the prepass render target for the rendering pass.
+     * If we are currently rendering a render target, it returns the PrePassRenderTarget
      * associated with that render target. Otherwise, it returns the scene default PrePassRenderTarget
      */
     public getRenderTarget(): PrePassRenderTarget {
@@ -63,6 +125,47 @@ export class PrePassRenderer {
         }
     }
 
+    /**
+     * Returns true if the currently rendered prePassRenderTarget is the one
+     * associated with the scene.
+     */
+    public get currentRTisSceneRT(): boolean {
+        return this._currentTarget === this.defaultRT;
+    }
+
+    public _geometryBuffer: Nullable<GeometryBufferRenderer>;
+    public _useGeometryBufferFallback = false;
+    /**
+     * Uses the geometry buffer renderer as a fallback for non prepass capable effects
+     */
+    public get useGeometryBufferFallback() : boolean {
+        return this._useGeometryBufferFallback;
+    }
+
+    public set useGeometryBufferFallback(value: boolean) {
+        this._useGeometryBufferFallback = value;
+
+        if (value) {
+            this._geometryBuffer = this._scene.enableGeometryBufferRenderer();
+
+            if (!this._geometryBuffer) {
+                // Not supported
+                this._useGeometryBufferFallback = false;
+                return;
+            }
+
+            this._geometryBuffer.renderList = [];
+            this._geometryBuffer._linkPrePassRenderer(this);
+            this._updateGeometryBufferLayout();
+        } else {
+            if (this._geometryBuffer) {
+                this._geometryBuffer._unlinkPrePassRenderer();
+            }
+            this._geometryBuffer = null;
+            this._scene.disableGeometryBufferRenderer();
+        }
+    }
+
     private _currentTarget: PrePassRenderTarget;
 
     /**
@@ -99,12 +202,12 @@ export class PrePassRenderer {
         this._engine = scene.getEngine();
 
         PrePassRenderer._SceneComponentInitialization(this._scene);
-        this.defaultRT = this._createRenderTarget("sceneprePassRT");
+        this.defaultRT = this._createRenderTarget("sceneprePassRT", null);
         this._setRenderTarget(null);
     }
 
-    public _createRenderTarget(name: string) : PrePassRenderTarget {
-        const rt = new PrePassRenderTarget(name, this, { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, 0, this._scene,
+    public _createRenderTarget(name: string, renderTargetTexture: Nullable<RenderTargetTexture>) : PrePassRenderTarget {
+        const rt = new PrePassRenderTarget(name, renderTargetTexture, { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, 0, this._scene,
             { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: [] });
         rt.samples = 1;
 
@@ -127,9 +230,9 @@ export class PrePassRenderer {
     public bindAttachmentsForEffect(effect: Effect, subMesh: SubMesh) {
         if (this.enabled && this._currentTarget.enabled) {
             if (effect._multiTarget) {
-                this._engine.bindAttachments(this._currentTarget._multiRenderAttachments);
+                this._engine.bindAttachments(this._multiRenderAttachments);
             } else {
-                this._engine.bindAttachments(this._currentTarget._defaultAttachments);
+                this._engine.bindAttachments(this._defaultAttachments);
 
                 // TODO : geometry buffer renderer
                 // if (this._geometryBuffer) {
@@ -142,12 +245,86 @@ export class PrePassRenderer {
         }
     }
 
+    private _reinitializeAttachments() {
+        const multiRenderLayout = [];
+        const clearLayout = [false];
+        const defaultLayout = [true];
+
+        for (let i = 0; i < this.mrtCount; i++) {
+            multiRenderLayout.push(true);
+
+            if (i > 0) {
+                clearLayout.push(true);
+                defaultLayout.push(false);
+            }
+        }
+
+        this._multiRenderAttachments = this._engine.buildTextureLayout(multiRenderLayout);
+        this._clearAttachments = this._engine.buildTextureLayout(clearLayout);
+        this._defaultAttachments = this._engine.buildTextureLayout(defaultLayout);
+    }
+
+    private _resetLayout() {
+        for (let i = 0 ; i < PrePassRenderer._textureFormats.length; i++) {
+            this._textureIndices[PrePassRenderer._textureFormats[i].type] = -1;
+        }
+
+        this._textureIndices[Constants.PREPASS_COLOR_TEXTURE_TYPE] = 0;
+        this._mrtLayout = [Constants.PREPASS_COLOR_TEXTURE_TYPE];
+        this._mrtFormats = [Constants.TEXTURETYPE_HALF_FLOAT];
+        this.mrtCount = 1;
+    }
+
+    private _updateGeometryBufferLayout() {
+        if (this._geometryBuffer) {
+            this._geometryBuffer._resetLayout();
+
+            const texturesActivated = [];
+
+            for (let i = 0; i < this._mrtLayout.length; i++) {
+                texturesActivated.push(false);
+            }
+
+            this._geometryBuffer._linkInternalTexture(this.defaultRT.getInternalTexture()!);
+
+            const matches = [
+                {
+                    prePassConstant: Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE,
+                    geometryBufferConstant: GeometryBufferRenderer.DEPTHNORMAL_TEXTURE_TYPE,
+                },
+                {
+                    prePassConstant: Constants.PREPASS_POSITION_TEXTURE_TYPE,
+                    geometryBufferConstant: GeometryBufferRenderer.POSITION_TEXTURE_TYPE,
+                },
+                {
+                    prePassConstant: Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE,
+                    geometryBufferConstant: GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE,
+                },
+                {
+                    prePassConstant: Constants.PREPASS_VELOCITY_TEXTURE_TYPE,
+                    geometryBufferConstant: GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE,
+                }
+            ];
+
+            // replace textures in the geometryBuffer RT
+            for (let i = 0; i < matches.length; i++) {
+                const index = this._mrtLayout.indexOf(matches[i].prePassConstant);
+                if (index !== -1) {
+                    this._geometryBuffer._forceTextureType(matches[i].geometryBufferConstant, index);
+                    texturesActivated[index] = true;
+                }
+            }
+
+            this._geometryBuffer._setAttachments(this._engine.buildTextureLayout(texturesActivated));
+        }
+    }
+
     /**
      * Restores attachments for single texture draw.
      */
     public restoreAttachments() {
-        if (this.enabled && this._currentTarget._defaultAttachments) {
-            this._engine.bindAttachments(this._currentTarget._defaultAttachments);
+        if (this.enabled && this._defaultAttachments) {
+            this._engine.bindAttachments(this._defaultAttachments);
         }
     }
 
@@ -157,11 +334,11 @@ export class PrePassRenderer {
     public _beforeDraw(camera: Nullable<Camera>, texture: Nullable<RenderTargetTexture>) {
         let postProcesses = undefined;
         if (texture) {
-            postProcesses = texture.postProcesses || texture.activeCamera?._postProcesses || [];       
-        } 
+            postProcesses = texture.postProcesses || texture.activeCamera?._postProcesses || [];
+        }
 
-        if (this._currentTarget._isDirty) {
-            this._update(this._currentTarget, postProcesses);
+        if (this._isDirty) {
+            this._update();
         }
 
         if (!this._enabled || !this._currentTarget.enabled) {
@@ -178,8 +355,8 @@ export class PrePassRenderer {
         }
 
         // TODO : handle geometry buffer renderer fallback
-        if (this._currentTarget._geometryBuffer) {
-            this._currentTarget._geometryBuffer.renderList!.length = 0;
+        if (this._geometryBuffer) {
+            this._geometryBuffer.renderList!.length = 0;
         }
 
         this._setupOutputForThisPass(this._currentTarget, camera, postProcesses);
@@ -211,7 +388,7 @@ export class PrePassRenderer {
                 this._scene.postProcessManager._prepareFrame(this._currentTarget.getInternalTexture()!, postProcessChain);
             }
 
-            // Renders the post process chain 
+            // Renders the post process chain
             this._scene.postProcessManager.directRender(postProcessChain, outputTexture);
 
             if (!outputTexture) {
@@ -221,18 +398,19 @@ export class PrePassRenderer {
     }
 
     /**
-     * Clears the render target (in the sense of settings pixels to the scene clear color value)
+     * Clears the current prepass render target (in the sense of settings pixels to the scene clear color value)
+     * @hidden
      */
     public _clear() {
         if (this._enabled && this._currentTarget.enabled) {
             this._bindFrameBuffer(this._currentTarget);
 
             // Clearing other attachment with 0 on all other attachments
-            this._engine.bindAttachments(this._currentTarget._clearAttachments);
+            this._engine.bindAttachments(this._clearAttachments);
             this._engine.clear(this._clearColor, true, false, false);
 
             // Regular clear color with the scene clear color of the 1st attachment
-            this._engine.bindAttachments(this._currentTarget._defaultAttachments);
+            this._engine.bindAttachments(this._defaultAttachments);
             this._engine.clear(this._scene.clearColor,
                 this._scene.autoClear || this._scene.forceWireframe || this._scene.forcePointsCloud,
                 this._scene.autoClearDepthAndStencil,
@@ -250,74 +428,88 @@ export class PrePassRenderer {
         }
     }
 
-    private _setState(prePassRenderTarget: PrePassRenderTarget, enabled: boolean) {
+    private _setState(enabled: boolean) {
         this._enabled = enabled;
 
-        prePassRenderTarget.enabled = enabled;
+        // TODO : enable/disable per texture
+        for (let i = 0; i < this.renderTargets.length; i++) {
+            const prePassRenderTarget = this.renderTargets[i];
+
+            prePassRenderTarget.enabled = enabled;
 
-        if (prePassRenderTarget.imageProcessingPostProcess) {
-            prePassRenderTarget.imageProcessingPostProcess.imageProcessingConfiguration.applyByPostProcess = enabled;
+            if (prePassRenderTarget.imageProcessingPostProcess) {
+                prePassRenderTarget.imageProcessingPostProcess.imageProcessingConfiguration.applyByPostProcess = enabled;
+            }
         }
     }
 
     /**
-     * Adds an effect configuration to the current prepass render target.
+     * 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(effectConfiguration: PrePassEffectConfiguration): PrePassEffectConfiguration {
-        return this.getRenderTarget()._addEffectConfiguration(effectConfiguration);
-    }
-
-    private _enable(prePassRenderTarget: PrePassRenderTarget) {
-        const previousMrtCount = prePassRenderTarget.mrtCount;
-
-        for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
-            if (prePassRenderTarget._effectConfigurations[i].enabled) {
-                this._enableTextures(prePassRenderTarget, prePassRenderTarget._effectConfigurations[i].texturesRequired);
+    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];
             }
         }
 
-        if (prePassRenderTarget.mrtCount !== previousMrtCount) {
-            prePassRenderTarget.updateCount(prePassRenderTarget.mrtCount, { types: prePassRenderTarget._mrtFormats });
-        }
+        this._effectConfigurations.push(cfg);
+        return cfg;
+    }
 
-        prePassRenderTarget._updateGeometryBufferLayout();
-        prePassRenderTarget._resetPostProcessChain();
+    private _enable() {
+        const previousMrtCount = this.mrtCount;
 
-        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 (prePassRenderTarget._effectConfigurations[i].postProcess) {
-                    prePassRenderTarget._beforeCompositionPostProcesses.push(prePassRenderTarget._effectConfigurations[i].postProcess!);
-                }
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            if (this._effectConfigurations[i].enabled) {
+                this._enableTextures(this._effectConfigurations[i].texturesRequired);
             }
         }
 
-        prePassRenderTarget._reinitializeAttachments();
+        for (let i = 0; i < this.renderTargets.length; i++) {
+            if (this.mrtCount !== previousMrtCount) {
+                this.renderTargets[i].updateCount(this.mrtCount, { types: this._mrtFormats });
+            }
+            // TODO : gbr
+            this._updateGeometryBufferLayout();
+            this.renderTargets[i]._resetPostProcessChain();
+
+            for (let j = 0; j < this._effectConfigurations.length; j++) {
+                if (this._effectConfigurations[j].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 (!this._effectConfigurations[j].postProcess && this._effectConfigurations[j].createPostProcess) {
+                        this._effectConfigurations[j].createPostProcess!();
+                    }
+
+                    if (this._effectConfigurations[j].postProcess) {
+                        this.renderTargets[i]._beforeCompositionPostProcesses.push(this._effectConfigurations[j].postProcess!);
+                    }
+                }
+            }
 
-        if (!prePassRenderTarget.imageProcessingPostProcess) {
-            prePassRenderTarget._createCompositionEffect();
+            if (!this.renderTargets[i].imageProcessingPostProcess) {
+                this.renderTargets[i]._createCompositionEffect();
+            }
         }
 
-        this._setState(prePassRenderTarget, true);
+        this._reinitializeAttachments();
+        this._setState(true);
     }
 
-    private _disable(prePassRenderTarget: PrePassRenderTarget) {
-        this._setState(prePassRenderTarget, false);
+    private _disable() {
+        this._setState(false);
 
-        prePassRenderTarget._resetLayout();
+        this._resetLayout();
 
-        for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
-            prePassRenderTarget._effectConfigurations[i].enabled = false;
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            this._effectConfigurations[i].enabled = false;
         }
     }
 
@@ -339,8 +531,8 @@ export class PrePassRenderer {
         // 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 && 
+        this._needsCompositionForThisPass = !this._hasImageProcessing(postProcessesSource) &&
+            !this.disableGammaTransform &&
             !secondaryCamera;
         const firstCameraPP = this._getFirstPostProcess(postProcessesSource);
         const firstPrePassPP = prePassRenderTarget._beforeCompositionPostProcesses && prePassRenderTarget._beforeCompositionPostProcesses[0];
@@ -359,7 +551,7 @@ export class PrePassRenderer {
             firstCameraPP.inputTexture = prePassRenderTarget.getInternalTexture()!;
             firstPP = firstCameraPP;
         }
-        
+
         if (firstPP) {
             firstPP.autoClear = false;
         }
@@ -397,30 +589,28 @@ export class PrePassRenderer {
      * Marks the prepass renderer as dirty, triggering a check if the prepass is necessary for the next rendering.
      */
     public markAsDirty() {
-        for (let i = 0; i < this.renderTargets.length; i++) {
-            this.renderTargets[i]._isDirty = true;
-        }
+        this._isDirty = true;
     }
 
     /**
      * Enables a texture on the MultiRenderTarget for prepass
      */
-    private _enableTextures(prePassRenderTarget: PrePassRenderTarget, types: number[]) {
+    private _enableTextures(types: number[]) {
         for (let i = 0; i < types.length; i++) {
             let type = types[i];
 
-            if (prePassRenderTarget._textureIndices[type] === -1) {
-                prePassRenderTarget._textureIndices[type] = prePassRenderTarget._mrtLayout.length;
-                prePassRenderTarget._mrtLayout.push(type);
+            if (this._textureIndices[type] === -1) {
+                this._textureIndices[type] = this._mrtLayout.length;
+                this._mrtLayout.push(type);
 
-                prePassRenderTarget._mrtFormats.push(PrePassRenderTarget._textureFormats[type].format);
-                prePassRenderTarget.mrtCount++;
+                this._mrtFormats.push(PrePassRenderer._textureFormats[type].format);
+                this.mrtCount++;
             }
         }
     }
 
-    private _update(prePassRenderTarget: PrePassRenderTarget, forcePostProcesses?: PostProcess[]) {
-        this._disable(prePassRenderTarget);
+    private _update() {
+        this._disable();
         let enablePrePass = false;
 
         for (let i = 0; i < this._scene.materials.length; i++) {
@@ -431,32 +621,38 @@ export class PrePassRenderer {
 
         let postProcesses;
 
-        if (forcePostProcesses) {
-            postProcesses = forcePostProcesses;
-        } else {
-            const camera = this._scene.activeCamera;
-            if (!camera) {
-                return;
+        for (let i = 0; i < this.renderTargets.length; i++) {
+            if (this.renderTargets[i].renderTargetTexture) {
+                postProcesses = this.renderTargets[i].renderTargetTexture!.activeCamera?._postProcesses;
+            } else {
+                const camera = this._scene.activeCamera;
+                if (!camera) {
+                    continue;
+                }
+
+                postProcesses = camera._postProcesses;
             }
 
-            postProcesses = camera._postProcesses;
-        }
+            if (!postProcesses) {
+                continue;
+            }
 
-        postProcesses = (<Nullable<PostProcess[]>>postProcesses.filter((pp) => { return pp != null; }));
+            postProcesses = (<Nullable<PostProcess[]>>postProcesses.filter((pp) => { return pp != null; }));
 
-        if (postProcesses) {
-            for (let i = 0; i < postProcesses.length; i++) {
-                if (postProcesses[i].setPrePassRenderer(this)) {
-                    enablePrePass = true;
+            if (postProcesses) {
+                for (let i = 0; i < postProcesses.length; i++) {
+                    if (postProcesses[i].setPrePassRenderer(this)) {
+                        enablePrePass = true;
+                    }
                 }
             }
         }
 
         this._markAllMaterialsAsPrePassDirty();
-        prePassRenderTarget._isDirty = false;
+        this._isDirty = false;
 
         if (enablePrePass) {
-            this._enable(prePassRenderTarget);
+            this._enable();
         }
     }
 
@@ -473,13 +669,13 @@ export class PrePassRenderer {
      */
     public dispose() {
         for (let i = this.renderTargets.length - 1; i >= 0; i--) {
+            this.renderTargets[i].dispose();
+        }
 
-            for (let j = 0; j < this.renderTargets[i]._effectConfigurations.length; j++) {
-                if (this.renderTargets[i]._effectConfigurations[j].dispose) {
-                    this.renderTargets[i]._effectConfigurations[j].dispose!();
-                }
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            if (this._effectConfigurations[i].dispose) {
+                this._effectConfigurations[i].dispose!();
             }
-            this.renderTargets[i].dispose();
         }
     }
 

+ 3 - 3
src/Rendering/prePassRendererSceneComponent.ts

@@ -108,8 +108,8 @@ export class PrePassRendererSceneComponent implements ISceneComponent {
     public register(): void {
         this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_PREPASS, this, this._beforeCameraDraw);
         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._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);
 
@@ -120,7 +120,7 @@ export class PrePassRendererSceneComponent implements ISceneComponent {
     private _beforeRenderTargetDraw(renderTarget: RenderTargetTexture) {
         if (this.scene.prePassRenderer) {
             if (!renderTarget._prePassRenderTarget) {
-                renderTarget._prePassRenderTarget = this.scene.prePassRenderer._createRenderTarget(renderTarget.name + "_prePassRTT");
+                renderTarget._prePassRenderTarget = this.scene.prePassRenderer._createRenderTarget(renderTarget.name + "_prePassRTT", renderTarget);
             }
             this.scene.prePassRenderer._setRenderTarget(renderTarget._prePassRenderTarget);
             this.scene.prePassRenderer._clear();