Browse Source

Merge pull request #8747 from CraigFeldspar/prepass

Prepass adjustments
David Catuhe 5 years ago
parent
commit
abef7fa4d5

+ 2 - 2
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx

@@ -246,8 +246,8 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                     <CheckBoxLineComponent label="Scattering Enabled" target={material.subSurface} propertyName="isScatteringEnabled"
                         onValueChanged={() => this.forceUpdate()}
                         onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    { (material.subSurface as any).isScatteringEnabled && material.getScene().prePassRenderer &&
-                        <SliderLineComponent label="Meters per unit" target={ material.getScene().prePassRenderer!.subSurfaceConfiguration } propertyName="metersPerUnit" minimum={0.01} maximum={2} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    { (material.subSurface as any).isScatteringEnabled && material.getScene().prePassRenderer && material.getScene().subSurfaceConfiguration &&
+                        <SliderLineComponent label="Meters per unit" target={ material.getScene().subSurfaceConfiguration! } propertyName="metersPerUnit" minimum={0.01} maximum={2} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     }
                     <CheckBoxLineComponent label="Refraction Enabled" target={material.subSurface} propertyName="isRefractionEnabled"
                         onValueChanged={() => this.forceUpdate()}

+ 28 - 12
src/Engines/constants.ts

@@ -486,22 +486,38 @@ export class Constants {
     public static readonly SCENELOADER_DETAILED_LOGGING = 3;
 
     /**
-     * Prepass texture index for color
+     * Constant used to retrieve the irradiance texture index in the textures array in the prepass
+     * using getIndex(Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE)
      */
-    public static readonly PREPASS_COLOR_INDEX = 0;
-
+    public static readonly PREPASS_IRRADIANCE_TEXTURE_TYPE = 0;
     /**
-     * Prepass texture index for irradiance
+     * Constant used to retrieve the position texture index in the textures array in the prepass
+     * using getIndex(Constants.PREPASS_POSITION_TEXTURE_INDEX)
      */
-    public static readonly PREPASS_IRRADIANCE_INDEX = 1;
-
+    public static readonly PREPASS_POSITION_TEXTURE_TYPE = 1;
     /**
-     * Prepass texture index for depth + normal
+     * Constant used to retrieve the velocity texture index in the textures array in the prepass
+     * using getIndex(Constants.PREPASS_VELOCITY_TEXTURE_INDEX)
      */
-    public static readonly PREPASS_DEPTHNORMAL_INDEX = 2;
-
+    public static readonly PREPASS_VELOCITY_TEXTURE_TYPE = 2;
+    /**
+     * Constant used to retrieve the reflectivity texture index in the textures array in the prepass
+     * using the getIndex(Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE)
+     */
+    public static readonly PREPASS_REFLECTIVITY_TEXTURE_TYPE = 3;
+    /**
+     * Constant used to retrieve the lit color texture index in the textures array in the prepass
+     * using the getIndex(Constants.PREPASS_COLOR_TEXTURE_TYPE)
+     */
+    public static readonly PREPASS_COLOR_TEXTURE_TYPE = 4;
+    /**
+     * Constant used to retrieve depth + normal index in the textures array in the prepass
+     * using the getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)
+     */
+    public static readonly PREPASS_DEPTHNORMAL_TEXTURE_TYPE = 5;
     /**
-     * Prepass texture index for albedo
+     * Constant used to retrieve albedo index in the textures array in the prepass
+     * using the getIndex(Constants.PREPASS_ALBEDO_TEXTURE_TYPE)
      */
-    public static readonly PREPASS_ALBEDO_INDEX = 3;
-}
+    public static readonly PREPASS_ALBEDO_TEXTURE_TYPE = 6;
+}

+ 13 - 3
src/Materials/PBR/pbrBaseMaterial.ts

@@ -164,6 +164,12 @@ export class PBRMaterialDefines extends MaterialDefines
     public THIN_INSTANCES = false;
 
     public PREPASS = false;
+    public PREPASS_IRRADIANCE = false;
+    public PREPASS_IRRADIANCE_INDEX = -1;
+    public PREPASS_ALBEDO = false;
+    public PREPASS_ALBEDO_INDEX = -1;
+    public PREPASS_DEPTHNORMAL = false;
+    public PREPASS_DEPTHNORMAL_INDEX = -1;
     public SCENE_MRT_COUNT = 0;
 
     public NUM_BONE_INFLUENCERS = 0;
@@ -2232,11 +2238,15 @@ export abstract class PBRBaseMaterial extends PushMaterial {
      */
     public setPrePassRenderer(prePassRenderer: PrePassRenderer): boolean {
         if (this.subSurface.isScatteringEnabled) {
-            prePassRenderer.subSurfaceConfiguration.enabled = true;
-            prePassRenderer.materialsShouldRenderIrradiance = true;
+            let subSurfaceConfiguration = this.getScene().enableSubSurfaceForPrePass();
+            if (subSurfaceConfiguration) {
+                subSurfaceConfiguration.enabled = true;
+            }
+
+            return true;
         }
 
-        return true;
+        return false;
     }
 
     /**

+ 4 - 4
src/Materials/PBR/pbrSubSurfaceConfiguration.ts

@@ -80,22 +80,22 @@ export class PBRSubSurfaceConfiguration {
      * Useful for better scattering in the skins or foliages.
      */
     public get scatteringDiffusionProfile() : Nullable<Color3> {
-        if (!this._scene.prePassRenderer) {
+        if (!this._scene.subSurfaceConfiguration) {
             return null;
         }
 
-        return this._scene.prePassRenderer.subSurfaceConfiguration.ssDiffusionProfileColors[this._scatteringDiffusionProfileIndex];
+        return this._scene.subSurfaceConfiguration.ssDiffusionProfileColors[this._scatteringDiffusionProfileIndex];
     }
 
     public set scatteringDiffusionProfile(c: Nullable<Color3>) {
-        if (!this._scene.enablePrePassRenderer()) {
+        if (!this._scene.enableSubSurfaceForPrePass()) {
             // Not supported
             return;
         }
 
         // addDiffusionProfile automatically checks for doubles
         if (c) {
-            this._scatteringDiffusionProfileIndex = this._scene.prePassRenderer!.subSurfaceConfiguration.addDiffusionProfile(c);
+            this._scatteringDiffusionProfileIndex = this._scene.subSurfaceConfiguration!.addDiffusionProfile(c);
         }
     }
 

+ 44 - 18
src/Materials/Textures/multiRenderTarget.ts

@@ -138,22 +138,9 @@ export class MultiRenderTarget extends RenderTargetTexture {
             return;
         }
 
-        var types = [];
-        var samplingModes = [];
-
-        for (var i = 0; i < count; i++) {
-            if (options && options.types && options.types[i] !== undefined) {
-                types.push(options.types[i]);
-            } else {
-                types.push(options && options.defaultType ? options.defaultType : Constants.TEXTURETYPE_UNSIGNED_INT);
-            }
-
-            if (options && options.samplingModes && options.samplingModes[i] !== undefined) {
-                samplingModes.push(options.samplingModes[i]);
-            } else {
-                samplingModes.push(Texture.BILINEAR_SAMPLINGMODE);
-            }
-        }
+        var types: number[] = [];
+        var samplingModes: number[] = [];
+        this._initTypes(count, types, samplingModes, options);
 
         var generateDepthBuffer = !options || options.generateDepthBuffer === undefined ? true : options.generateDepthBuffer;
         var generateStencilBuffer = !options || options.generateStencilBuffer === undefined ? false : options.generateStencilBuffer;
@@ -175,11 +162,31 @@ export class MultiRenderTarget extends RenderTargetTexture {
         this._createTextures();
     }
 
+    private _initTypes(count: number, types: number[], samplingModes: number[], options?: IMultiRenderTargetOptions) {
+        for (var i = 0; i < count; i++) {
+            if (options && options.types && options.types[i] !== undefined) {
+                types.push(options.types[i]);
+            } else {
+                types.push(options && options.defaultType ? options.defaultType : Constants.TEXTURETYPE_UNSIGNED_INT);
+            }
+
+            if (options && options.samplingModes && options.samplingModes[i] !== undefined) {
+                samplingModes.push(options.samplingModes[i]);
+            } else {
+                samplingModes.push(Texture.BILINEAR_SAMPLINGMODE);
+            }
+        }
+    }
+
     /** @hidden */
-    public _rebuild(): void {
+    public _rebuild(forceFullRebuild: boolean = false): void {
         this.releaseInternalTextures();
         this._createInternalTextures();
 
+        if (forceFullRebuild) {
+            this._createTextures();
+        }
+
         for (var i = 0; i < this._internalTextures.length; i++) {
             var texture = this._textures[i];
             texture._texture = this._internalTextures[i];
@@ -226,7 +233,7 @@ export class MultiRenderTarget extends RenderTargetTexture {
 
     /**
      * Resize all the textures in the multi render target.
-     * Be carrefull as it will recreate all the data in the new texture.
+     * Be careful as it will recreate all the data in the new texture.
      * @param size Define the new size
      */
     public resize(size: any) {
@@ -234,6 +241,25 @@ export class MultiRenderTarget extends RenderTargetTexture {
         this._rebuild();
     }
 
+    /**
+     * Changes the number of render targets in this MRT
+     * Be careful as it will recreate all the data in the new texture.
+     * @param count new texture count
+     * @param options Specifies texture types and sampling modes for new textures
+     */
+    public updateCount(count: number, options?: IMultiRenderTargetOptions) {
+        this._multiRenderTargetOptions.textureCount = count;
+        this._count = count;
+
+        const types: number[] = [];
+        const samplingModes: number[] = [];
+
+        this._initTypes(count, types, samplingModes, options);
+        this._multiRenderTargetOptions.types = types;
+        this._multiRenderTargetOptions.samplingModes = samplingModes;
+        this._rebuild(true);
+    }
+
     protected unbindFrameBuffer(engine: Engine, faceIndex: number): void {
         engine.unBindMultiColorAttachmentFramebuffer(this._internalTextures, this.isCube, () => {
             this.onAfterRenderObservable.notifyObservers(faceIndex);

+ 26 - 1
src/Materials/materialHelper.ts

@@ -8,6 +8,7 @@ import { AbstractMesh } from "../Meshes/abstractMesh";
 import { Mesh } from "../Meshes/mesh";
 import { VertexBuffer } from "../Meshes/buffer";
 import { Light } from "../Lights/light";
+import { Constants } from "../Engines/constants";
 
 import { UniformBuffer } from "./uniformBuffer";
 import { Effect, IEffectCreationOptions } from "./effect";
@@ -304,9 +305,33 @@ export class MaterialHelper {
     public static PrepareDefinesForPrePass(scene: Scene, defines: any, canRenderToMRT: boolean) {
         var previousPrePass = defines.PREPASS;
 
-        if (scene.prePassRenderer && canRenderToMRT) {
+        if (scene.prePassRenderer && scene.prePassRenderer.enabled && canRenderToMRT) {
             defines.PREPASS = true;
             defines.SCENE_MRT_COUNT = scene.prePassRenderer.mrtCount;
+
+            const irradianceIndex = scene.prePassRenderer.getIndex(Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE);
+            if (irradianceIndex !== -1) {
+                defines.PREPASS_IRRADIANCE = true;
+                defines.PREPASS_IRRADIANCE_INDEX = irradianceIndex;
+            } else {
+                defines.PREPASS_IRRADIANCE = false;
+            }
+
+            const albedoIndex = scene.prePassRenderer.getIndex(Constants.PREPASS_ALBEDO_TEXTURE_TYPE);
+            if (albedoIndex !== -1) {
+                defines.PREPASS_ALBEDO = true;
+                defines.PREPASS_ALBEDO_INDEX = albedoIndex;
+            } else {
+                defines.PREPASS_ALBEDO = false;
+            }
+
+            const depthNormalIndex = scene.prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE);
+            if (depthNormalIndex !== -1) {
+                defines.PREPASS_DEPTHNORMAL = true;
+                defines.PREPASS_DEPTHNORMAL_INDEX = depthNormalIndex;
+            } else {
+                defines.PREPASS_DEPTHNORMAL = false;
+            }
         } else {
             defines.PREPASS = false;
         }

+ 6 - 0
src/Materials/standardMaterial.ts

@@ -126,6 +126,12 @@ export class StandardMaterialDefines extends MaterialDefines implements IImagePr
     public ALPHABLEND = true;
 
     public PREPASS = false;
+    public PREPASS_IRRADIANCE = false;
+    public PREPASS_IRRADIANCE_INDEX = -1;
+    public PREPASS_ALBEDO = false;
+    public PREPASS_ALBEDO_INDEX = -1;
+    public PREPASS_DEPTHNORMAL = false;
+    public PREPASS_DEPTHNORMAL_INDEX = -1;
     public SCENE_MRT_COUNT = 0;
 
     public RGBDLIGHTMAP = false;

+ 15 - 6
src/PostProcesses/RenderPipeline/Pipelines/ssao2RenderingPipeline.ts

@@ -12,6 +12,8 @@ import { PassPostProcess } from "../../../PostProcesses/passPostProcess";
 import { Scene } from "../../../scene";
 import { _TypeStore } from '../../../Misc/typeStore';
 import { EngineStore } from '../../../Engines/engineStore';
+import { SSAO2Configuration } from "../../../Rendering/ssao2Configuration";
+import { PrePassRenderer } from "../../../Rendering/prePassRenderer";
 import { Constants } from "../../../Engines/constants";
 
 import "../../../PostProcesses/RenderPipeline/postProcessRenderPipelineManagerSceneComponent";
@@ -19,8 +21,6 @@ import "../../../PostProcesses/RenderPipeline/postProcessRenderPipelineManagerSc
 import "../../../Shaders/ssao2.fragment";
 import "../../../Shaders/ssaoCombine.fragment";
 
-declare type PrePassRenderer = import("../../../Rendering/prePassRenderer").PrePassRenderer;
-
 /**
  * Render pipeline to produce ssao effect
  */
@@ -119,6 +119,8 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
     */
     private _sampleSphere: number[];
 
+    private _ssao2PrePassConfiguration: SSAO2Configuration;
+
     /**
     * Blur filter offsets
     */
@@ -267,6 +269,7 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
         }
 
         this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
+        this._ssao2PrePassConfiguration.enabled = false;
 
         super.dispose();
     }
@@ -293,7 +296,7 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
             if (this._forceGeometryBuffer) {
                 effect.setTexture("depthNormalSampler", this._scene.enableGeometryBufferRenderer()!.getGBuffer().textures[0]);
             } else {
-                effect.setTexture("depthNormalSampler", this._prePassRenderer.prePassRT.textures[Constants.PREPASS_DEPTHNORMAL_INDEX]);
+                effect.setTexture("depthNormalSampler", this._prePassRenderer.prePassRT.textures[this._prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
             }
             effect.setArray("samplerOffsets", this._samplerOffsets);
         };
@@ -311,7 +314,7 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
             if (this._forceGeometryBuffer) {
                 effect.setTexture("depthNormalSampler", this._scene.enableGeometryBufferRenderer()!.getGBuffer().textures[0]);
             } else {
-                effect.setTexture("depthNormalSampler", this._prePassRenderer.prePassRT.textures[Constants.PREPASS_DEPTHNORMAL_INDEX]);
+                effect.setTexture("depthNormalSampler", this._prePassRenderer.prePassRT.textures[this._prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
             }
             effect.setArray("samplerOffsets", this._samplerOffsets);
 
@@ -429,7 +432,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.prePassRT.textures[Constants.PREPASS_DEPTHNORMAL_INDEX]);
+                effect.setTexture("depthNormalSampler", this._prePassRenderer.prePassRT.textures[this._prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
             }
             effect.setTexture("randomSampler", this._randomTexture);
         };
@@ -512,7 +515,13 @@ export class SSAO2RenderingPipeline extends PostProcessRenderPipeline {
      * @returns true if the pre pass is needed.
      */
     public setPrePassRenderer(prePassRenderer: PrePassRenderer): boolean {
-        prePassRenderer.materialsShouldRenderGeometry = prePassRenderer.materialsShouldRenderGeometry || true;
+        let cfg = this._ssao2PrePassConfiguration;
+        if (!cfg) {
+            cfg = new SSAO2Configuration();
+        }
+
+        cfg.enabled = true;
+        this._ssao2PrePassConfiguration = prePassRenderer.addEffectConfiguration(cfg);
         return true;
     }
 }

+ 9 - 9
src/PostProcesses/subSurfaceScatteringPostProcess.ts

@@ -31,22 +31,22 @@ export class SubSurfaceScatteringPostProcess extends PostProcess {
         this.updateEffect();
 
         this.onApplyObservable.add((effect: Effect) => {
-            if (!scene.prePassRenderer) {
-                Logger.Error("PrePass needs to be enabled for subsurface scattering.");
+            if (!scene.prePassRenderer || !scene.subSurfaceConfiguration) {
+                Logger.Error("PrePass and subsurface configuration needs to be enabled for subsurface scattering.");
                 return;
             }
             var texelSize = this.texelSize;
-            effect.setFloat("metersPerUnit", scene.prePassRenderer.subSurfaceConfiguration.metersPerUnit);
+            effect.setFloat("metersPerUnit", scene.subSurfaceConfiguration.metersPerUnit);
             effect.setFloat2("texelSize", texelSize.x, texelSize.y);
-            effect.setTexture("irradianceSampler", scene.prePassRenderer.prePassRT.textures[1]);
-            effect.setTexture("depthSampler", scene.prePassRenderer.prePassRT.textures[2]);
-            effect.setTexture("albedoSampler", scene.prePassRenderer.prePassRT.textures[3]);
+            effect.setTexture("irradianceSampler", scene.prePassRenderer.prePassRT.textures[scene.prePassRenderer.getIndex(Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE)]);
+            effect.setTexture("depthSampler", scene.prePassRenderer.prePassRT.textures[scene.prePassRenderer.getIndex(Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE)]);
+            effect.setTexture("albedoSampler", scene.prePassRenderer.prePassRT.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));
-            effect.setArray3("diffusionS", scene.prePassRenderer.subSurfaceConfiguration.ssDiffusionS);
-            effect.setArray("diffusionD", scene.prePassRenderer.subSurfaceConfiguration.ssDiffusionD);
-            effect.setArray("filterRadii", scene.prePassRenderer.subSurfaceConfiguration.ssFilterRadii);
+            effect.setArray3("diffusionS", scene.subSurfaceConfiguration.ssDiffusionS);
+            effect.setArray("diffusionD", scene.subSurfaceConfiguration.ssDiffusionD);
+            effect.setArray("filterRadii", scene.subSurfaceConfiguration.ssFilterRadii);
         });
     }
 }

+ 1 - 0
src/Rendering/index.ts

@@ -6,6 +6,7 @@ export * from "./geometryBufferRenderer";
 export * from "./geometryBufferRendererSceneComponent";
 export * from "./prePassRenderer";
 export * from "./prePassRendererSceneComponent";
+export * from "./subSurfaceSceneComponent";
 export * from "./outlineRenderer";
 export * from "./renderingGroup";
 export * from "./renderingManager";

+ 11 - 3
src/Rendering/prePassEffectConfiguration.ts

@@ -5,9 +5,17 @@ import { PostProcess } from "../PostProcesses/postProcess";
  */
 export interface PrePassEffectConfiguration {
     /**
+     * Name of the effect
+     */
+    name: string;
+    /**
      * Post process to attach for this effect
      */
-    postProcess: PostProcess;
+    postProcess?: PostProcess;
+    /**
+     * Textures required in the MRT
+     */
+    texturesRequired: number[];
     /**
      * Is the effect enabled
      */
@@ -17,7 +25,7 @@ export interface PrePassEffectConfiguration {
      */
     dispose(): void;
     /**
-     * Disposes the effect configuration
+     * Creates the associated post process
      */
-    createPostProcess: () => PostProcess;
+    createPostProcess?: () => PostProcess;
 }

+ 153 - 27
src/Rendering/prePassRenderer.ts

@@ -5,10 +5,10 @@ import { Constants } from "../Engines/constants";
 import { ImageProcessingPostProcess } from "../PostProcesses/imageProcessingPostProcess";
 import { PostProcess } from "../PostProcesses/postProcess";
 import { Effect } from "../Materials/effect";
+import { Logger } from '../Misc/logger';
 import { _DevTools } from '../Misc/devTools';
 import { Color4 } from "../Maths/math.color";
-import { SubSurfaceConfiguration } from "./subSurfaceConfiguration";
-
+import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
 /**
  * Renders a pre pass of the scene
  * This means every mesh in the scene will be rendered to a render target texture
@@ -21,6 +21,39 @@ export class PrePassRenderer {
         throw _DevTools.WarnImport("PrePassRendererSceneComponent");
     }
 
+    private _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 _textureIndices: number[] = [];
+
     private _scene: Scene;
     private _engine: Engine;
     private _isDirty: boolean = false;
@@ -28,18 +61,13 @@ export class PrePassRenderer {
     /**
      * Number of textures in the multi render target texture where the scene is directly rendered
      */
-    public readonly mrtCount: number = 4;
+    public mrtCount: number = 0;
 
     /**
      * The render target where the scene is directly rendered
      */
     public prePassRT: MultiRenderTarget;
-    private _mrtTypes = [
-        Constants.TEXTURETYPE_HALF_FLOAT, // Original color
-        Constants.TEXTURETYPE_HALF_FLOAT, // Irradiance
-        Constants.TEXTURETYPE_HALF_FLOAT, // Depth (world units)
-        Constants.TEXTURETYPE_UNSIGNED_INT // Albedo
-    ];
+
     private _multiRenderAttachments: number[];
     private _defaultAttachments: number[];
     private _clearAttachments: number[];
@@ -54,9 +82,9 @@ export class PrePassRenderer {
     public imageProcessingPostProcess: ImageProcessingPostProcess;
 
     /**
-     * Configuration for sub surface scattering post process
+     * Configuration for prepass effects
      */
-    public subSurfaceConfiguration: SubSurfaceConfiguration;
+    private _effectConfigurations: PrePassEffectConfiguration[] = [];
 
     /**
      * Should materials render their geometry on the MRT
@@ -68,6 +96,9 @@ export class PrePassRenderer {
      */
     public materialsShouldRenderIrradiance: boolean = false;
 
+    private _mrtFormats: number[] = [];
+    private _mrtLayout: number[];
+
     private _enabled: boolean = false;
 
     /**
@@ -102,7 +133,7 @@ export class PrePassRenderer {
 
         PrePassRenderer._SceneComponentInitialization(this._scene);
 
-        this.subSurfaceConfiguration = new SubSurfaceConfiguration(this._scene);
+        this._resetLayout();
     }
 
     private _initializeAttachments() {
@@ -124,11 +155,9 @@ export class PrePassRenderer {
 
     private _createCompositionEffect() {
         this.prePassRT = new MultiRenderTarget("sceneprePassRT", { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, this.mrtCount, this._scene,
-            { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: this._mrtTypes });
+            { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: this._mrtFormats });
         this.prePassRT.samples = 1;
 
-        this._initializeAttachments();
-
         this.imageProcessingPostProcess = new ImageProcessingPostProcess("sceneCompositionPass", 1, null, undefined, this._engine);
         this.imageProcessingPostProcess.autoClear = false;
     }
@@ -230,17 +259,77 @@ export class PrePassRenderer {
         }
     }
 
+    private _checkTextureType(type: number) : boolean {
+        if (type < 0 || type >= this._textureFormats.length) {
+            Logger.Error("PrePassRenderer : Unknown texture type");
+            return false;
+        }
+
+        return true;
+
+    }
+
+    /**
+     * Adds an effect configuration to the prepass.
+     * 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;
+    }
+
+    /**
+     * 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 {
+        if (!this._checkTextureType(type)) {
+            return -1;
+        }
+
+        return this._textureIndices[type];
+    }
+
     private _enable() {
-        this._resetPostProcessChain();
+        const previousMrtCount = this.mrtCount;
 
-        if (this.subSurfaceConfiguration.enabled) {
-            if (!this.subSurfaceConfiguration.postProcess) {
-                this.subSurfaceConfiguration.createPostProcess();
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            if (this._effectConfigurations[i].enabled) {
+                this._enableTextures(this._effectConfigurations[i].texturesRequired);
             }
+        }
 
-            this._postProcesses.push(this.subSurfaceConfiguration.postProcess);
+        if (this.prePassRT && this.mrtCount !== previousMrtCount) {
+            this.prePassRT.updateCount(this.mrtCount, { types: this._mrtFormats });
         }
 
+        this._resetPostProcessChain();
+
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            if (this._effectConfigurations[i].enabled) {
+                if (!this._effectConfigurations[i].postProcess && this._effectConfigurations[i].createPostProcess) {
+                    this._effectConfigurations[i].createPostProcess!();
+                }
+
+                if (this._effectConfigurations[i].postProcess) {
+                    this._postProcesses.push(this._effectConfigurations[i].postProcess!);
+                }
+            }
+        }
+
+        this._initializeAttachments();
+
         if (!this.imageProcessingPostProcess) {
             this._createCompositionEffect();
         }
@@ -252,9 +341,22 @@ export class PrePassRenderer {
 
     private _disable() {
         this._setState(false);
-        this.subSurfaceConfiguration.enabled = false;
-        this.materialsShouldRenderGeometry = false;
-        this.materialsShouldRenderIrradiance = false;
+        this._resetLayout();
+
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            this._effectConfigurations[i].enabled = false;
+        }
+    }
+
+    private _resetLayout() {
+        for (let i = 0 ; i < this._textureFormats.length; i++) {
+            this._textureIndices[this._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 _resetPostProcessChain() {
@@ -263,8 +365,10 @@ export class PrePassRenderer {
             this.imageProcessingPostProcess.restoreDefaultInputTexture();
         }
 
-        if (this.subSurfaceConfiguration.postProcess) {
-            this.subSurfaceConfiguration.postProcess.restoreDefaultInputTexture();
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            if (this._effectConfigurations[i].postProcess) {
+                this._effectConfigurations[i].postProcess!.restoreDefaultInputTexture();
+            }
         }
     }
 
@@ -279,11 +383,30 @@ export class PrePassRenderer {
         this._isDirty = true;
     }
 
+    /**
+     * Enables a texture on the MultiRenderTarget for prepass
+     */
+    private _enableTextures(types: number[]) {
+        for (let i = 0; i < types.length; i++) {
+            let type = types[i];
+            if (!this._checkTextureType(type)) {
+                return;
+            }
+
+            if (this._textureIndices[type] === -1) {
+                this._textureIndices[type] = this._mrtLayout.length;
+                this._mrtLayout.push(type);
+
+                this._mrtFormats.push(this._textureFormats[type].format);
+                this.mrtCount++;
+            }
+        }
+    }
+
     private _update() {
         this._disable();
         let enablePrePass = false;
 
-        // Subsurface scattering
         for (let i = 0; i < this._scene.materials.length; i++) {
             if (this._scene.materials[i].setPrePassRenderer(this)) {
                 enablePrePass = true;
@@ -312,8 +435,11 @@ export class PrePassRenderer {
      * Disposes the prepass renderer.
      */
     public dispose() {
+        for (let i = 0; i < this._effectConfigurations.length; i++) {
+            this._effectConfigurations[i].dispose();
+        }
+
         this.imageProcessingPostProcess.dispose();
-        this.subSurfaceConfiguration.dispose();
         this.prePassRT.dispose();
     }
 

+ 2 - 57
src/Rendering/prePassRendererSceneComponent.ts

@@ -1,25 +1,9 @@
 import { Nullable } from "../types";
 import { Scene } from "../scene";
-import { ISceneSerializableComponent, SceneComponentConstants } from "../sceneComponent";
+import { ISceneComponent, SceneComponentConstants } from "../sceneComponent";
 import { PrePassRenderer } from "./prePassRenderer";
-import { AbstractScene } from "../abstractScene";
-import { Color3 } from "../Maths/math.color";
 import { Logger } from "../Misc/logger";
 
-// Adds the parser to the scene parsers.
-AbstractScene.AddParser(SceneComponentConstants.NAME_PREPASSRENDERER, (parsedData: any, scene: Scene) => {
-    // Diffusion profiles
-    if (parsedData.ssDiffusionProfileColors !== undefined && parsedData.ssDiffusionProfileColors !== null) {
-        scene.enablePrePassRenderer();
-        if (scene.prePassRenderer) {
-            for (var index = 0, cache = parsedData.ssDiffusionProfileColors.length; index < cache; index++) {
-                var color = parsedData.ssDiffusionProfileColors[index];
-                scene.prePassRenderer.subSurfaceConfiguration.addDiffusionProfile(new Color3(color.r, color.g, color.b));
-            }
-        }
-    }
-});
-
 declare module "../abstractScene" {
     export interface AbstractScene {
         /** @hidden (Backing field) */
@@ -86,7 +70,7 @@ Scene.prototype.disablePrePassRenderer = function(): void {
  * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
  * in several rendering techniques.
  */
-export class PrePassRendererSceneComponent implements ISceneSerializableComponent {
+export class PrePassRendererSceneComponent implements ISceneComponent {
     /**
      * The component name helpful to identify the component in the list of scene components.
      */
@@ -133,45 +117,6 @@ export class PrePassRendererSceneComponent implements ISceneSerializableComponen
     }
 
     /**
-     * Serializes the component data to the specified json object
-     * @param serializationObject The object to serialize to
-     */
-    public serialize(serializationObject: any): void {
-        if (!this.scene.prePassRenderer) {
-            return;
-        }
-
-        const ssDiffusionProfileColors = this.scene.prePassRenderer.subSurfaceConfiguration.ssDiffusionProfileColors;
-        serializationObject.ssDiffusionProfileColors = [];
-
-        for (let i = 0; i < ssDiffusionProfileColors.length; i++) {
-            serializationObject.ssDiffusionProfileColors.push({ r: ssDiffusionProfileColors[i].r,
-                                                                g: ssDiffusionProfileColors[i].g,
-                                                                b: ssDiffusionProfileColors[i].b });
-        }
-    }
-
-    /**
-     * Adds all the elements from the container to the scene
-     * @param container the container holding the elements
-     */
-    public addFromContainer(container: AbstractScene): void {
-        // Nothing to do
-    }
-
-    /**
-     * Removes all the elements in the container from the scene
-     * @param container contains the elements to remove
-     * @param dispose if the removed element should be disposed (default: false)
-     */
-    public removeFromContainer(container: AbstractScene, dispose?: boolean): void {
-        // Make sure nothing will be serialized
-        if (this.scene.prePassRenderer) {
-            this.scene.prePassRenderer.subSurfaceConfiguration.clearAllDiffusionProfiles();
-        }
-    }
-
-    /**
      * Rebuilds the elements related to this component in case of
      * context lost for instance.
      */

+ 41 - 0
src/Rendering/ssao2Configuration.ts

@@ -0,0 +1,41 @@
+import { Constants } from "../Engines/constants";
+import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
+import { _DevTools } from '../Misc/devTools';
+
+/**
+ * Contains all parameters needed for the prepass to perform
+ * screen space subsurface scattering
+ */
+export class SSAO2Configuration implements PrePassEffectConfiguration {
+    /**
+     * Is subsurface enabled
+     */
+    public enabled = false;
+
+    /**
+     * Name of the configuration
+     */
+    public name = "ssao2";
+
+    /**
+     * Textures that should be present in the MRT for this effect to work
+     */
+    public readonly texturesRequired: number[] = [
+        Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE
+    ];
+
+    /**
+     * Builds a ssao2 configuration object
+     * @param scene The scene
+     */
+    constructor() {
+
+    }
+
+    /**
+     * Disposes the configuration
+     */
+    public dispose() {
+        // pass
+    }
+}

+ 26 - 0
src/Rendering/subSurfaceConfiguration.ts

@@ -2,12 +2,21 @@ import { Logger } from "../Misc/logger";
 import { Scene } from "../scene";
 import { Color3 } from "../Maths/math.color";
 import { SubSurfaceScatteringPostProcess } from "../PostProcesses/subSurfaceScatteringPostProcess";
+import { SceneComponentConstants } from "../sceneComponent";
 import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
+import { _DevTools } from '../Misc/devTools';
+import { Constants } from "../Engines/constants";
+
 /**
  * Contains all parameters needed for the prepass to perform
  * screen space subsurface scattering
  */
 export class SubSurfaceConfiguration implements PrePassEffectConfiguration {
+    /** @hidden */
+    public static _SceneComponentInitialization: (scene: Scene) => void = (_) => {
+        throw _DevTools.WarnImport("PrePassRendererSceneComponent");
+    }
+
     private _ssDiffusionS: number[] = [];
     private _ssFilterRadii: number[] = [];
     private _ssDiffusionD: number[] = [];
@@ -44,6 +53,11 @@ export class SubSurfaceConfiguration implements PrePassEffectConfiguration {
     public enabled = false;
 
     /**
+     * Name of the configuration
+     */
+    public name = SceneComponentConstants.NAME_SUBSURFACE;
+
+    /**
      * Diffusion profile colors for subsurface scattering
      * You can add one diffusion color using `addDiffusionProfile` on `scene.prePassRenderer`
      * See ...
@@ -57,6 +71,16 @@ export class SubSurfaceConfiguration implements PrePassEffectConfiguration {
      */
     public metersPerUnit: number = 1;
 
+    /**
+     * Textures that should be present in the MRT for this effect to work
+     */
+    public readonly texturesRequired: number[] = [
+        Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE,
+        Constants.PREPASS_ALBEDO_TEXTURE_TYPE,
+        Constants.PREPASS_COLOR_TEXTURE_TYPE,
+        Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE,
+    ];
+
     private _scene: Scene;
 
     /**
@@ -67,6 +91,8 @@ export class SubSurfaceConfiguration implements PrePassEffectConfiguration {
         // Adding default diffusion profile
         this.addDiffusionProfile(new Color3(1, 1, 1));
         this._scene = scene;
+
+        SubSurfaceConfiguration._SceneComponentInitialization(this._scene);
     }
 
     /**

+ 181 - 0
src/Rendering/subSurfaceSceneComponent.ts

@@ -0,0 +1,181 @@
+import { Nullable } from "../types";
+import { Scene } from "../scene";
+import { ISceneSerializableComponent, SceneComponentConstants } from "../sceneComponent";
+import { SubSurfaceConfiguration } from "./subSurfaceConfiguration";
+import { AbstractScene } from "../abstractScene";
+import { Color3 } from "../Maths/math.color";
+
+// Adds the parser to the scene parsers.
+AbstractScene.AddParser(SceneComponentConstants.NAME_SUBSURFACE, (parsedData: any, scene: Scene) => {
+    // Diffusion profiles
+    if (parsedData.ssDiffusionProfileColors !== undefined && parsedData.ssDiffusionProfileColors !== null) {
+        scene.enableSubSurfaceForPrePass();
+        if (scene.subSurfaceConfiguration) {
+            for (var index = 0, cache = parsedData.ssDiffusionProfileColors.length; index < cache; index++) {
+                var color = parsedData.ssDiffusionProfileColors[index];
+                scene.subSurfaceConfiguration.addDiffusionProfile(new Color3(color.r, color.g, color.b));
+            }
+        }
+    }
+});
+
+declare module "../abstractScene" {
+    export interface AbstractScene {
+        /** @hidden (Backing field) */
+        _subSurfaceConfiguration: Nullable<SubSurfaceConfiguration>;
+
+        /**
+         * Gets or Sets the current prepass renderer associated to the scene.
+         */
+        subSurfaceConfiguration: Nullable<SubSurfaceConfiguration>;
+
+        /**
+         * Enables the subsurface effect for prepass
+         * @returns the SubSurfaceConfiguration
+         */
+        enableSubSurfaceForPrePass(): Nullable<SubSurfaceConfiguration>;
+
+        /**
+         * Disables the subsurface effect for prepass
+         */
+        disableSubSurfaceForPrePass(): void;
+    }
+}
+
+Object.defineProperty(Scene.prototype, "subSurfaceConfiguration", {
+    get: function(this: Scene) {
+        return this._subSurfaceConfiguration;
+    },
+    set: function(this: Scene, value: Nullable<SubSurfaceConfiguration>) {
+        if (value) {
+            if (this.enablePrePassRenderer()) {
+                    this._subSurfaceConfiguration = value;
+            }
+        }
+    },
+    enumerable: true,
+    configurable: true
+});
+
+Scene.prototype.enableSubSurfaceForPrePass = function(): Nullable<SubSurfaceConfiguration> {
+    if (this._subSurfaceConfiguration) {
+        return this._subSurfaceConfiguration;
+    }
+
+    const prePassRenderer = this.enablePrePassRenderer();
+    if (prePassRenderer) {
+        this._subSurfaceConfiguration = new SubSurfaceConfiguration(this);
+        prePassRenderer.addEffectConfiguration(this._subSurfaceConfiguration);
+        return this._subSurfaceConfiguration;
+    }
+
+    return null;
+
+};
+
+Scene.prototype.disableSubSurfaceForPrePass = function(): void {
+    if (!this._subSurfaceConfiguration) {
+        return;
+    }
+
+    this._subSurfaceConfiguration.dispose();
+    this._subSurfaceConfiguration = null;
+};
+
+/**
+ * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
+ * in several rendering techniques.
+ */
+export class SubSurfaceSceneComponent implements ISceneSerializableComponent {
+    /**
+     * The component name helpful to identify the component in the list of scene components.
+     */
+    public readonly name = SceneComponentConstants.NAME_PREPASSRENDERER;
+
+    /**
+     * The scene the component belongs to.
+     */
+    public scene: Scene;
+
+    /**
+     * Creates a new instance of the component for the given scene
+     * @param scene Defines the scene to register the component in
+     */
+    constructor(scene: Scene) {
+        this.scene = scene;
+    }
+
+    /**
+     * Registers the component in a given scene
+     */
+    public register(): void {
+    }
+
+    /**
+     * Serializes the component data to the specified json object
+     * @param serializationObject The object to serialize to
+     */
+    public serialize(serializationObject: any): void {
+        if (!this.scene.subSurfaceConfiguration) {
+            return;
+        }
+
+        const ssDiffusionProfileColors = this.scene.subSurfaceConfiguration.ssDiffusionProfileColors;
+        serializationObject.ssDiffusionProfileColors = [];
+
+        for (let i = 0; i < ssDiffusionProfileColors.length; i++) {
+            serializationObject.ssDiffusionProfileColors.push({ r: ssDiffusionProfileColors[i].r,
+                                                                g: ssDiffusionProfileColors[i].g,
+                                                                b: ssDiffusionProfileColors[i].b });
+        }
+    }
+
+    /**
+     * Adds all the elements from the container to the scene
+     * @param container the container holding the elements
+     */
+    public addFromContainer(container: AbstractScene): void {
+        // Nothing to do
+    }
+
+    /**
+     * Removes all the elements in the container from the scene
+     * @param container contains the elements to remove
+     * @param dispose if the removed element should be disposed (default: false)
+     */
+    public removeFromContainer(container: AbstractScene, dispose?: boolean): void {
+        // Make sure nothing will be serialized
+        if (!this.scene.prePassRenderer) {
+            return;
+        }
+
+        if (this.scene.subSurfaceConfiguration) {
+            this.scene.subSurfaceConfiguration.clearAllDiffusionProfiles();
+        }
+    }
+
+    /**
+     * Rebuilds the elements related to this component in case of
+     * context lost for instance.
+     */
+    public rebuild(): void {
+        // Nothing to do for this component
+    }
+
+    /**
+     * Disposes the component and the associated ressources
+     */
+    public dispose(): void {
+        // Nothing to do for this component
+    }
+
+}
+
+SubSurfaceConfiguration._SceneComponentInitialization = (scene: Scene) => {
+    // Register the G Buffer component to the scene.
+    let component = scene._getComponent(SceneComponentConstants.NAME_SUBSURFACE) as SubSurfaceSceneComponent;
+    if (!component) {
+        component = new SubSurfaceSceneComponent(scene);
+        scene._addComponent(component);
+    }
+};

+ 13 - 4
src/Shaders/default.fragment.fx

@@ -481,10 +481,19 @@ color.rgb = max(color.rgb, 0.);
 
 #define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR
 #ifdef PREPASS
-    gl_FragData[0] = color; // Lit without irradiance
-    gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0); // Irradiance
-    gl_FragData[2] = vec4(vViewPos.z, (view * vec4(normalW, 0.0)).rgb); // Linear depth + normal
-    gl_FragData[3] = vec4(0.0, 0.0, 0.0, 1.0); // albedo, for pre and post scatter
+    gl_FragData[0] = color; // We can't split irradiance on std material
+
+    #ifdef PREPASS_IRRADIANCE
+        gl_FragData[PREPASS_IRRADIANCE_INDEX] = vec4(0.0, 0.0, 0.0, 1.0); //  We can't split irradiance on std material
+    #endif
+
+    #ifdef PREPASS_DEPTHNORMAL
+    	gl_FragData[PREPASS_DEPTHNORMAL_INDEX] = vec4(vViewPos.z, (view * vec4(normalW, 0.0)).rgb); // Linear depth + normal
+    #endif
+
+    #ifdef PREPASS_ALBEDO
+        gl_FragData[PREPASS_ALBEDO_INDEX] = vec4(0.0, 0.0, 0.0, 1.0); // We can't split albedo on std material
+    #endif
 #endif
 	gl_FragColor = color;
 

+ 22 - 15
src/Shaders/pbr.fragment.fx

@@ -502,26 +502,33 @@ void main(void) {
     #define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR
 
 #ifdef PREPASS
-    vec3 irradiance = finalDiffuse;
-    #ifndef UNLIT
-        #ifdef REFLECTION
-            irradiance += finalIrradiance;
+    #ifdef PREPASS_IRRADIANCE
+        vec3 irradiance = finalDiffuse;
+        #ifndef UNLIT
+            #ifdef REFLECTION
+                irradiance += finalIrradiance;
+            #endif
+        #endif
+
+        vec3 sqAlbedo = sqrt(surfaceAlbedo); // for pre and post scatter
+        gl_FragData[0] = vec4(finalColor.rgb - irradiance, finalColor.a); // Split irradiance from final color
+        irradiance /= sqAlbedo;
+        
+        #ifndef SS_SCATTERING
+            float scatteringDiffusionProfile = 255.;
         #endif
+        gl_FragData[PREPASS_IRRADIANCE_INDEX] = vec4(tagLightingForSSS(irradiance), scatteringDiffusionProfile / 255.); // Irradiance + SS diffusion profile
+    #else
+        gl_FragData[0] = vec4(finalColor.rgb, finalColor.a);
     #endif
 
-    vec3 sqAlbedo = sqrt(surfaceAlbedo); // for pre and post scatter
+    #ifdef PREPASS_DEPTHNORMAL
+        gl_FragData[PREPASS_DEPTHNORMAL_INDEX] = vec4(vViewPos.z, (view * vec4(normalW, 0.0)).rgb); // Linear depth + normal
+    #endif
 
-    // Irradiance is diffuse * surfaceAlbedo
-    #ifdef SS_SCATTERING
-    gl_FragData[0] = vec4(finalColor.rgb - irradiance, finalColor.a); // Lit without irradiance
-    irradiance /= sqAlbedo;
-    gl_FragData[1] = vec4(tagLightingForSSS(irradiance), scatteringDiffusionProfile / 255.); // Irradiance + SS diffusion profile
-    #else
-    gl_FragData[0] = vec4(finalColor.rgb, finalColor.a); // Lit without irradiance
-    gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0); // Irradiance
+    #ifdef PREPASS_ALBEDO
+        gl_FragData[PREPASS_ALBEDO_INDEX] = vec4(sqAlbedo, 1.0); // albedo, for pre and post scatter
     #endif
-    gl_FragData[2] = vec4(vViewPos.z, (view * vec4(normalW, 0.0)).rgb); // Linear depth + normal
-    gl_FragData[3] = vec4(sqAlbedo, 1.0); // albedo, for pre and post scatter
 #endif
 
     gl_FragColor = finalColor;

+ 1 - 0
src/sceneComponent.ts

@@ -28,6 +28,7 @@ export class SceneComponentConstants {
     public static readonly NAME_DEPTHRENDERER = "DepthRenderer";
     public static readonly NAME_POSTPROCESSRENDERPIPELINEMANAGER = "PostProcessRenderPipelineManager";
     public static readonly NAME_SPRITE = "Sprite";
+    public static readonly NAME_SUBSURFACE = "SubSurface";
     public static readonly NAME_OUTLINERENDERER = "Outline";
     public static readonly NAME_PROCEDURALTEXTURE = "ProceduralTexture";
     public static readonly NAME_SHADOWGENERATOR = "ShadowGenerator";