Parcourir la source

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

David `Deltakosh` Catuhe il y a 4 ans
Parent
commit
8e57a34d60
37 fichiers modifiés avec 411 ajouts et 37 suppressions
  1. 2 0
      materialsLibrary/src/cell/cell.fragment.fx
  2. 3 0
      materialsLibrary/src/cell/cellMaterial.ts
  3. 2 0
      materialsLibrary/src/fire/fire.fragment.fx
  4. 3 0
      materialsLibrary/src/fire/fireMaterial.ts
  5. 3 0
      materialsLibrary/src/fur/fur.fragment.fx
  6. 3 0
      materialsLibrary/src/fur/furMaterial.ts
  7. 3 0
      materialsLibrary/src/gradient/gradient.fragment.fx
  8. 3 0
      materialsLibrary/src/gradient/gradientMaterial.ts
  9. 2 0
      materialsLibrary/src/grid/grid.fragment.fx
  10. 3 0
      materialsLibrary/src/grid/gridMaterial.ts
  11. 2 0
      materialsLibrary/src/lava/lava.fragment.fx
  12. 3 0
      materialsLibrary/src/lava/lavaMaterial.ts
  13. 2 0
      materialsLibrary/src/mix/mix.fragment.fx
  14. 3 0
      materialsLibrary/src/mix/mixMaterial.ts
  15. 3 0
      materialsLibrary/src/normal/normal.fragment.fx
  16. 3 0
      materialsLibrary/src/normal/normalMaterial.ts
  17. 2 0
      materialsLibrary/src/shadowOnly/shadowOnly.fragment.fx
  18. 3 0
      materialsLibrary/src/shadowOnly/shadowOnlyMaterial.ts
  19. 2 0
      materialsLibrary/src/simple/simple.fragment.fx
  20. 3 0
      materialsLibrary/src/simple/simpleMaterial.ts
  21. 2 0
      materialsLibrary/src/sky/sky.fragment.fx
  22. 3 0
      materialsLibrary/src/sky/skyMaterial.ts
  23. 3 0
      materialsLibrary/src/terrain/terrain.fragment.fx
  24. 3 0
      materialsLibrary/src/terrain/terrainMaterial.ts
  25. 3 0
      materialsLibrary/src/triPlanar/triPlanarMaterial.ts
  26. 3 0
      materialsLibrary/src/triPlanar/triplanar.fragment.fx
  27. 34 0
      src/Engines/Extensions/engine.multiRender.ts
  28. 12 0
      src/Materials/Textures/multiRenderTarget.ts
  29. 1 1
      src/Meshes/mesh.ts
  30. 142 11
      src/Rendering/geometryBufferRenderer.ts
  31. 121 13
      src/Rendering/prePassRenderer.ts
  32. 3 0
      src/Shaders/ShadersInclude/imageProcessingCompatibility.fx
  33. 7 5
      src/Shaders/ShadersInclude/prePassDeclaration.fx
  34. 3 0
      src/Shaders/default.fragment.fx
  35. 12 5
      src/Shaders/geometry.fragment.fx
  36. 4 2
      src/Shaders/pbr.fragment.fx
  37. 2 0
      src/Shaders/sprites.fragment.fx

+ 2 - 0
materialsLibrary/src/cell/cell.fragment.fx

@@ -146,4 +146,6 @@ void main(void)
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/cell/cellMaterial.ts

@@ -43,6 +43,7 @@ class CellMaterialDefines extends MaterialDefines {
     public CUSTOMUSERLIGHTING = true;
     public CELLBASIC = true;
     public DEPTHPREPASS = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -158,6 +159,8 @@ export class CellMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 2 - 0
materialsLibrary/src/fire/fire.fragment.fx

@@ -97,4 +97,6 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/fire/fireMaterial.ts

@@ -39,6 +39,7 @@ class FireMaterialDefines extends MaterialDefines {
     public BonesPerMesh = 0;
     public NUM_BONE_INFLUENCERS = 0;
     public INSTANCES = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -151,6 +152,8 @@ export class FireMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 3 - 0
materialsLibrary/src/fur/fur.fragment.fx

@@ -130,4 +130,7 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
+
 }

+ 3 - 0
materialsLibrary/src/fur/furMaterial.ts

@@ -45,6 +45,7 @@ class FurMaterialDefines extends MaterialDefines {
     public BonesPerMesh = 0;
     public INSTANCES = false;
     public HIGHLEVEL = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -235,6 +236,8 @@ export class FurMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 3 - 0
materialsLibrary/src/gradient/gradient.fragment.fx

@@ -99,4 +99,7 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
+
 }

+ 3 - 0
materialsLibrary/src/gradient/gradientMaterial.ts

@@ -39,6 +39,7 @@ class GradientMaterialDefines extends MaterialDefines {
     public NUM_BONE_INFLUENCERS = 0;
     public BonesPerMesh = 0;
     public INSTANCES = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -148,6 +149,8 @@ export class GradientMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 2 - 0
materialsLibrary/src/grid/grid.fragment.fx

@@ -116,4 +116,6 @@ void main(void) {
     #endif
 #else    
 #endif
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/grid/gridMaterial.ts

@@ -25,6 +25,7 @@ class GridMaterialDefines extends MaterialDefines {
     public UV2 = false;
     public INSTANCES = false;
     public THIN_INSTANCES = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -177,6 +178,8 @@ export class GridMaterial extends PushMaterial {
                 attribs.push(VertexBuffer.UV2Kind);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             MaterialHelper.PrepareAttributesForInstances(attribs, defines);
 
             // Defines

+ 2 - 0
materialsLibrary/src/lava/lava.fragment.fx

@@ -153,4 +153,6 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/lava/lavaMaterial.ts

@@ -82,6 +82,7 @@ class LavaMaterialDefines extends MaterialDefines {
     public BonesPerMesh = 0;
     public INSTANCES = false;
     public UNLIT = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -218,6 +219,8 @@ export class LavaMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 2 - 0
materialsLibrary/src/mix/mix.fragment.fx

@@ -164,4 +164,6 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/mix/mixMaterial.ts

@@ -43,6 +43,7 @@ class MixMaterialDefines extends MaterialDefines {
     public BonesPerMesh = 0;
     public INSTANCES = false;
     public MIXMAP2 = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -246,6 +247,8 @@ export class MixMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 3 - 0
materialsLibrary/src/normal/normal.fragment.fx

@@ -97,4 +97,7 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
+
 }

+ 3 - 0
materialsLibrary/src/normal/normalMaterial.ts

@@ -80,6 +80,7 @@ class NormalMaterialDefines extends MaterialDefines {
     public BonesPerMesh = 0;
     public INSTANCES = false;
     public LIGHTING = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -195,6 +196,8 @@ export class NormalMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 2 - 0
materialsLibrary/src/shadowOnly/shadowOnly.fragment.fx

@@ -52,4 +52,6 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/shadowOnly/shadowOnlyMaterial.ts

@@ -33,6 +33,7 @@ class ShadowOnlyMaterialDefines extends MaterialDefines {
     public NUM_BONE_INFLUENCERS = 0;
     public BonesPerMesh = 0;
     public INSTANCES = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -156,6 +157,8 @@ export class ShadowOnlyMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 2 - 0
materialsLibrary/src/simple/simple.fragment.fx

@@ -96,4 +96,6 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/simple/simpleMaterial.ts

@@ -40,6 +40,7 @@ class SimpleMaterialDefines extends MaterialDefines {
     public NUM_BONE_INFLUENCERS = 0;
     public BonesPerMesh = 0;
     public INSTANCES = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -147,6 +148,8 @@ export class SimpleMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 2 - 0
materialsLibrary/src/sky/sky.fragment.fx

@@ -168,4 +168,6 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }

+ 3 - 0
materialsLibrary/src/sky/skyMaterial.ts

@@ -29,6 +29,7 @@ class SkyMaterialDefines extends MaterialDefines {
     public FOG = false;
     public VERTEXCOLOR = false;
     public VERTEXALPHA = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -194,6 +195,8 @@ export class SkyMaterial extends PushMaterial {
                 fallbacks.addFallback(1, "FOG");
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 3 - 0
materialsLibrary/src/terrain/terrain.fragment.fx

@@ -180,4 +180,7 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
+
 }

+ 3 - 0
materialsLibrary/src/terrain/terrainMaterial.ts

@@ -43,6 +43,7 @@ class TerrainMaterialDefines extends MaterialDefines {
     public NUM_BONE_INFLUENCERS = 0;
     public BonesPerMesh = 0;
     public INSTANCES = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -209,6 +210,8 @@ export class TerrainMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 3 - 0
materialsLibrary/src/triPlanar/triPlanarMaterial.ts

@@ -47,6 +47,7 @@ class TriPlanarMaterialDefines extends MaterialDefines {
     public NUM_BONE_INFLUENCERS = 0;
     public BonesPerMesh = 0;
     public INSTANCES = false;
+    public IMAGEPROCESSINGPOSTPROCESS = false;
 
     constructor() {
         super();
@@ -210,6 +211,8 @@ export class TriPlanarMaterial extends PushMaterial {
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
+
             //Attributes
             var attribs = [VertexBuffer.PositionKind];
 

+ 3 - 0
materialsLibrary/src/triPlanar/triplanar.fragment.fx

@@ -147,4 +147,7 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
+
 }

+ 34 - 0
src/Engines/Extensions/engine.multiRender.ts

@@ -39,9 +39,43 @@ declare module "../../Engines/thinEngine" {
          * @param attachments gl attachments
          */
         bindAttachments(attachments: number[]) : void;
+
+        /**
+         * Creates a layout object to draw/clear on specific textures in a MRT
+         * @param textureStatus textureStatus[i] indicates if the i-th is active
+         * @returns A layout to be fed to the engine, calling `bindAttachments`.
+         */
+        buildTextureLayout(textureStatus: boolean[]) : number[];
+
+        /**
+         * Restores the webgl state to only draw on the main color attachment
+         */
+        restoreSingleAttachment() : void;
     }
 }
 
+ThinEngine.prototype.restoreSingleAttachment = function(): void {
+    const gl = this._gl;
+
+    this.bindAttachments([gl.BACK]);
+};
+
+ThinEngine.prototype.buildTextureLayout = function(textureStatus: boolean[]): number[] {
+    const gl = this._gl;
+
+    const result = [];
+
+    for (let i = 0; i < textureStatus.length; i++) {
+        if (textureStatus[i]) {
+            result.push((<any>gl)["COLOR_ATTACHMENT" + i]);
+        } else {
+            result.push(gl.NONE);
+        }
+    }
+
+    return result;
+};
+
 ThinEngine.prototype.bindAttachments = function(attachments: number[]): void {
     const gl = this._gl;
 

+ 12 - 0
src/Materials/Textures/multiRenderTarget.ts

@@ -217,6 +217,18 @@ export class MultiRenderTarget extends RenderTargetTexture {
     }
 
     /**
+     * Replaces a texture within the MRT.
+     * @param texture The new texture to insert in the MRT
+     * @param index The index of the texture to replace
+     */
+    public replaceTexture(texture: Texture, index: number) {
+        if (texture._texture) {
+            this._textures[index] = texture;
+            this._internalTextures[index] = texture._texture;
+        }
+    }
+
+    /**
      * Define the number of samples used if MSAA is enabled.
      */
     public get samples(): number {

+ 1 - 1
src/Meshes/mesh.ts

@@ -1878,7 +1878,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
 
         // Render to MRT
         if (scene.prePassRenderer) {
-            scene.prePassRenderer.bindAttachmentsForEffect(effect);
+            scene.prePassRenderer.bindAttachmentsForEffect(effect, subMesh);
         }
 
         const effectiveMesh = effectiveMeshReplacement || this._effectiveMesh;

+ 142 - 11
src/Rendering/geometryBufferRenderer.ts

@@ -5,8 +5,10 @@ import { Mesh } from "../Meshes/mesh";
 import { Constants } from "../Engines/constants";
 import { SmartArray } from "../Misc/smartArray";
 import { Texture } from "../Materials/Textures/texture";
+import { InternalTexture } from "../Materials/Textures/internalTexture";
 import { MultiRenderTarget } from "../Materials/Textures/multiRenderTarget";
 import { Effect } from "../Materials/effect";
+import { PrePassRenderer } from "../Rendering/prePassRenderer";
 import { MaterialHelper } from "../Materials/materialHelper";
 import { Scene } from "../scene";
 import { AbstractMesh } from "../Meshes/abstractMesh";
@@ -32,6 +34,11 @@ interface ISavedTransformationMatrix {
  */
 export class GeometryBufferRenderer {
     /**
+     * Constant used to retrieve the depth + normal texture index in the G-Buffer textures array
+     * using getIndex(GeometryBufferRenderer.DEPTHNORMAL_TEXTURE_INDEX)
+     */
+    public static readonly DEPTHNORMAL_TEXTURE_TYPE = 0;
+    /**
      * Constant used to retrieve the position texture index in the G-Buffer textures array
      * using getIndex(GeometryBufferRenderer.POSITION_TEXTURE_INDEX)
      */
@@ -79,14 +86,103 @@ export class GeometryBufferRenderer {
     private _positionIndex: number = -1;
     private _velocityIndex: number = -1;
     private _reflectivityIndex: number = -1;
+    private _depthNormalIndex: number = -1;
+
+    private _linkedWithPrePass: boolean = false;
+    private _prePassRenderer: PrePassRenderer;
+    private _attachments: number[];
 
     protected _effect: Effect;
     protected _cachedDefines: string;
 
     /**
+     * @hidden
+     * Sets up internal structures to share outputs with PrePassRenderer
+     * This method should only be called by the PrePassRenderer itself
+     */
+    public _linkPrePassRenderer(prePassRenderer: PrePassRenderer) {
+        this._linkedWithPrePass = true;
+        this._prePassRenderer = prePassRenderer;
+
+        if (this._multiRenderTarget) {
+            // prevents clearing of the RT since it's done by prepass
+            this._multiRenderTarget.onClearObservable.clear();
+            this._multiRenderTarget.onClearObservable.add((engine) => {
+                // pass
+            });
+        }
+    }
+
+    /**
+     * @hidden
+     * Separates internal structures from PrePassRenderer so the geometry buffer can now operate by itself.
+     * This method should only be called by the PrePassRenderer itself
+     */
+    public _unlinkPrePassRenderer() {
+        this._linkedWithPrePass = false;
+        this._createRenderTargets();
+    }
+
+    /**
+     * @hidden
+     * Resets the geometry buffer layout
+     */
+    public _resetLayout() {
+        this._enablePosition = false;
+        this._enableReflectivity = false;
+        this._enableVelocity = false;
+        this._attachments = [];
+    }
+
+    /**
+     * @hidden
+     * Replaces a texture in the geometry buffer renderer
+     * Useful when linking textures of the prepass renderer
+     */
+    public _forceTextureType(geometryBufferType: number, index: number) {
+        if (geometryBufferType === GeometryBufferRenderer.POSITION_TEXTURE_TYPE) {
+            this._positionIndex = index;
+            this._enablePosition = true;
+        } else if (geometryBufferType === GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE) {
+            this._velocityIndex = index;
+            this._enableVelocity = true;
+        } else if (geometryBufferType === GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE) {
+            this._reflectivityIndex = index;
+            this._enableReflectivity = true;
+        } else if (geometryBufferType === GeometryBufferRenderer.DEPTHNORMAL_TEXTURE_TYPE) {
+            this._depthNormalIndex = index;
+        }
+    }
+
+    /**
+     * @hidden
+     * Sets texture attachments
+     * Useful when linking textures of the prepass renderer
+     */
+    public _setAttachments(attachments: number[]) {
+        this._attachments = attachments;
+    }
+
+    /**
+     * @hidden
+     * Replaces the first texture which is hard coded as a depth texture in the geometry buffer
+     * Useful when linking textures of the prepass renderer
+     */
+    public _linkInternalTexture(internalTexture: InternalTexture) {
+        this._multiRenderTarget._texture = internalTexture;
+    }
+
+    /**
+     * Gets the render list (meshes to be rendered) used in the G buffer.
+     */
+    public get renderList() {
+        return this._multiRenderTarget.renderList;
+    }
+
+    /**
      * Set the render list (meshes to be rendered) used in the G buffer.
      */
-    public set renderList(meshes: Mesh[]) {
+    public set renderList(meshes: Nullable<AbstractMesh[]>) {
         this._multiRenderTarget.renderList = meshes;
     }
 
@@ -124,8 +220,12 @@ export class GeometryBufferRenderer {
      */
     public set enablePosition(enable: boolean) {
         this._enablePosition = enable;
-        this.dispose();
-        this._createRenderTargets();
+
+        // PrePass handles index and texture links
+        if (!this._linkedWithPrePass) {
+            this.dispose();
+            this._createRenderTargets();
+        }
     }
 
     /**
@@ -145,8 +245,10 @@ export class GeometryBufferRenderer {
             this._previousTransformationMatrices = {};
         }
 
-        this.dispose();
-        this._createRenderTargets();
+        if (!this._linkedWithPrePass) {
+            this.dispose();
+            this._createRenderTargets();
+        }
     }
 
     /**
@@ -161,8 +263,11 @@ export class GeometryBufferRenderer {
      */
     public set enableReflectivity(enable: boolean) {
         this._enableReflectivity = enable;
-        this.dispose();
-        this._createRenderTargets();
+
+        if (!this._linkedWithPrePass) {
+            this.dispose();
+            this._createRenderTargets();
+        }
     }
 
     /**
@@ -254,6 +359,15 @@ export class GeometryBufferRenderer {
             }
         }
 
+        // PrePass
+        if (this._linkedWithPrePass) {
+            defines.push("#define PREPASS");
+            if (this._depthNormalIndex !== -1) {
+                defines.push("#define DEPTHNORMAL_INDEX " + this._depthNormalIndex);
+                defines.push("#define PREPASS_DEPTHNORMAL");
+            }
+        }
+
         // Buffers
         if (this._enablePosition) {
             defines.push("#define POSITION");
@@ -311,7 +425,11 @@ export class GeometryBufferRenderer {
         }
 
         // Setup textures count
-        defines.push("#define RENDER_TARGET_COUNT " + this._multiRenderTarget.textures.length);
+        if (this._linkedWithPrePass) {
+            defines.push("#define RENDER_TARGET_COUNT " + this._attachments.length);
+        } else {
+            defines.push("#define RENDER_TARGET_COUNT " + this._multiRenderTarget.textures.length);
+        }
 
         // Get correct effect
         var join = defines.join("\n");
@@ -365,9 +483,8 @@ export class GeometryBufferRenderer {
         this.getGBuffer().dispose();
     }
 
-    protected _createRenderTargets(): void {
-        var engine = this._scene.getEngine();
-        var count = 2;
+    private _assignRenderTargetIndices() : number {
+        let count = 2;
 
         if (this._enablePosition) {
             this._positionIndex = count;
@@ -384,6 +501,13 @@ export class GeometryBufferRenderer {
             count++;
         }
 
+        return count;
+    }
+
+    protected _createRenderTargets(): void {
+        var engine = this._scene.getEngine();
+        var count = this._assignRenderTargetIndices();
+
         this._multiRenderTarget = new MultiRenderTarget("gBuffer",
             { width: engine.getRenderWidth() * this._ratio, height: engine.getRenderHeight() * this._ratio }, count, this._scene,
             { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_FLOAT });
@@ -519,6 +643,13 @@ export class GeometryBufferRenderer {
         this._multiRenderTarget.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
             var index;
 
+            if (this._linkedWithPrePass) {
+                if (!this._prePassRenderer.enabled) {
+                    return;
+                }
+                this._scene.getEngine().bindAttachments(this._attachments);
+            }
+
             if (depthOnlySubMeshes.length) {
                 engine.setColorWrite(false);
                 for (index = 0; index < depthOnlySubMeshes.length; index++) {

+ 121 - 13
src/Rendering/prePassRenderer.ts

@@ -11,6 +11,8 @@ import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
 import { Nullable } from "../types";
 import { AbstractMesh } from '../Meshes/abstractMesh';
 import { Material } from '../Materials/material';
+import { SubMesh } from '../Meshes/subMesh';
+import { GeometryBufferRenderer } from '../Rendering/geometryBufferRenderer';
 
 /**
  * Renders a pre pass of the scene
@@ -60,6 +62,13 @@ export class PrePassRenderer {
      */
     public excludedSkinnedMesh: AbstractMesh[] = [];
 
+    /**
+     * Force material to be excluded from the prepass
+     * Can be useful when `useGeometryBufferFallback` is set to `true`
+     * and you don't want a material to show in the effect.
+     */
+    public excludedMaterials: Material[] = [];
+
     private _textureIndices: number[] = [];
 
     private _scene: Scene;
@@ -121,6 +130,39 @@ export class PrePassRenderer {
         this.prePassRT.samples = n;
     }
 
+    private _geometryBuffer: Nullable<GeometryBufferRenderer>;
+    private _useGeometryBufferFallback = true;
+    /**
+     * 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();
+        }
+    }
+
     /**
      * Instanciates a prepass renderer
      * @param scene The scene
@@ -130,25 +172,26 @@ export class PrePassRenderer {
         this._engine = scene.getEngine();
 
         PrePassRenderer._SceneComponentInitialization(this._scene);
-
         this._resetLayout();
     }
 
     private _initializeAttachments() {
-        let gl = this._engine._gl;
-
-        this._multiRenderAttachments = [];
-        this._clearAttachments = [gl.NONE];
-        this._defaultAttachments = [gl.COLOR_ATTACHMENT0];
+        const multiRenderLayout = [];
+        const clearLayout = [false];
+        const defaultLayout = [true];
 
         for (let i = 0; i < this.mrtCount; i++) {
-            this._multiRenderAttachments.push((<any>gl)["COLOR_ATTACHMENT" + i]);
+            multiRenderLayout.push(true);
 
             if (i > 0) {
-                this._clearAttachments.push((<any>gl)["COLOR_ATTACHMENT" + i]);
-                this._defaultAttachments.push(gl.NONE);
+                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 _createCompositionEffect() {
@@ -156,6 +199,12 @@ export class PrePassRenderer {
             { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: this._mrtFormats });
         this.prePassRT.samples = 1;
 
+        this._initializeAttachments();
+        if (this._useGeometryBufferFallback && !this._geometryBuffer) {
+            // Initializes the link with geometry buffer
+            this.useGeometryBufferFallback = true;
+        }
+
         this.imageProcessingPostProcess = new ImageProcessingPostProcess("sceneCompositionPass", 1, null, undefined, this._engine);
         this.imageProcessingPostProcess.autoClear = false;
     }
@@ -164,19 +213,27 @@ export class PrePassRenderer {
      * Indicates if rendering a prepass is supported
      */
     public get isSupported() {
-        return this._engine.webGLVersion > 1;
+        return this._engine.webGLVersion > 1 || this._scene.getEngine().getCaps().drawBuffersExtension;
     }
 
     /**
      * Sets the proper output textures to draw in the engine.
      * @param effect The effect that is drawn. It can be or not be compatible with drawing to several output textures.
+     * @param subMesh Submesh on which the effect is applied
      */
-    public bindAttachmentsForEffect(effect: Effect) {
+    public bindAttachmentsForEffect(effect: Effect, subMesh: SubMesh) {
         if (this.enabled) {
             if (effect._multiTarget) {
                 this._engine.bindAttachments(this._multiRenderAttachments);
             } else {
                 this._engine.bindAttachments(this._defaultAttachments);
+
+                if (this._geometryBuffer) {
+                    const material = subMesh.getMaterial();
+                    if (material && this.excludedMaterials.indexOf(material) === -1) {
+                        this._geometryBuffer.renderList!.push(subMesh.getRenderingMesh());
+                    }
+                }
             }
         }
     }
@@ -189,6 +246,10 @@ export class PrePassRenderer {
             this._update();
         }
 
+        if (this._geometryBuffer) {
+            this._geometryBuffer.renderList!.length = 0;
+        }
+
         this._bindFrameBuffer();
     }
 
@@ -214,6 +275,7 @@ export class PrePassRenderer {
         if (width !== requiredWidth || height !== requiredHeight) {
             this.prePassRT.resize({ width: requiredWidth, height: requiredHeight });
 
+            this._updateGeometryBufferLayout();
             this._bindPostProcessChain();
         }
     }
@@ -244,7 +306,7 @@ export class PrePassRenderer {
             // Clearing other attachment with 0 on all other attachments
             this._engine.bindAttachments(this._clearAttachments);
             this._engine.clear(this._clearColor, true, false, false);
-            this._engine.bindAttachments(this._multiRenderAttachments);
+            this._engine.bindAttachments(this._defaultAttachments);
         }
     }
 
@@ -257,6 +319,50 @@ export class PrePassRenderer {
         }
     }
 
+    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.prePassRT.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));
+        }
+    }
+
     /**
      * 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
@@ -298,6 +404,7 @@ export class PrePassRenderer {
             this.prePassRT.updateCount(this.mrtCount, { types: this._mrtFormats });
         }
 
+        this._updateGeometryBufferLayout();
         this._resetPostProcessChain();
 
         for (let i = 0; i < this._effectConfigurations.length; i++) {
@@ -418,7 +525,8 @@ export class PrePassRenderer {
 
         if (!this.enabled) {
             // Prepass disabled, we render only on 1 color attachment
-            this._engine.bindAttachments([this._engine._gl.COLOR_ATTACHMENT0]);
+            this._engine.restoreDefaultFramebuffer();
+            this._engine.restoreSingleAttachment();
         }
     }
 

+ 3 - 0
src/Shaders/ShadersInclude/imageProcessingCompatibility.fx

@@ -0,0 +1,3 @@
+#ifdef IMAGEPROCESSINGPOSTPROCESS
+	gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2));
+#endif

+ 7 - 5
src/Shaders/ShadersInclude/prePassDeclaration.fx

@@ -1,14 +1,16 @@
 #ifdef PREPASS
 #extension GL_EXT_draw_buffers : require
-layout(location = 0) out vec4 glFragData[{X}];
-vec4 gl_FragColor;
+#ifdef WEBGL2
+layout(location = 0) out highp vec4 glFragData[{X}];
+highp vec4 gl_FragColor;
+#endif
 
 #ifdef PREPASS_DEPTHNORMAL
-    varying vec3 vViewPos;
+    varying highp vec3 vViewPos;
 #endif
 #ifdef PREPASS_VELOCITY
-    varying vec4 vCurrentPosition;
-    varying vec4 vPreviousPosition;
+    varying highp vec4 vCurrentPosition;
+    varying highp vec4 vPreviousPosition;
 #endif
 
 #endif

+ 3 - 0
src/Shaders/default.fragment.fx

@@ -512,6 +512,9 @@ color.rgb = max(color.rgb, 0.);
         #endif
     #endif
 #endif
+
+#if !defined(PREPASS) || defined(WEBGL2) 
 	gl_FragColor = color;
+#endif
 
 }

+ 12 - 5
src/Shaders/geometry.fragment.fx

@@ -53,15 +53,22 @@ void main() {
 		discard;
     #endif
 
-    gl_FragData[0] = vec4(vViewPos.z / vViewPos.w, 0.0, 0.0, 1.0);
-    //color0 = vec4(vViewPos.z / vViewPos.w, 0.0, 0.0, 1.0);
-
+    vec3 normalOutput;
     #ifdef BUMP
     vec3 normalW = normalize(vNormalW);
     #include<bumpFragment>
-    gl_FragData[1] = vec4(normalize(vec3(vWorldView * vec4(normalW, 0.0))), 1.0);
+    normalOutput = normalize(vec3(vWorldView * vec4(normalW, 0.0)));
     #else
-    gl_FragData[1] = vec4(normalize(vNormalV), 1.0);
+    normalOutput = normalize(vNormalV);
+    #endif
+
+    #ifdef PREPASS
+        #ifdef PREPASS_DEPTHNORMAL
+        gl_FragData[DEPTHNORMAL_INDEX] = vec4(vViewPos.z / vViewPos.w, normalOutput);
+        #endif
+    #else
+    gl_FragData[0] = vec4(vViewPos.z / vViewPos.w, 0.0, 0.0, 1.0);
+    gl_FragData[1] = vec4(normalOutput, 1.0);
     #endif
 
     #ifdef POSITION

+ 4 - 2
src/Shaders/pbr.fragment.fx

@@ -12,10 +12,10 @@
 #extension GL_EXT_frag_depth : enable
 #endif
 
-precision highp float;
-
 #include<prePassDeclaration>[SCENE_MRT_COUNT]
 
+precision highp float;
+
 // Forces linear space for image processing
 #ifndef FROMLINEARSPACE
     #define FROMLINEARSPACE
@@ -554,6 +554,8 @@ void main(void) {
     #endif
 #endif
 
+#if !defined(PREPASS) || defined(WEBGL2) 
     gl_FragColor = finalColor;
+#endif
     #include<pbrDebug>
 }

+ 2 - 0
src/Shaders/sprites.fragment.fx

@@ -23,4 +23,6 @@ void main(void) {
 #include<fogFragment>
 
 	gl_FragColor = color;
+
+#include<imageProcessingCompatibility>
 }