Sfoglia il codice sorgente

Merge pull request #3020 from sebavan/BackgroundMaterial

BackgroundMaterial
sebavan 7 anni fa
parent
commit
021be49460
21 ha cambiato i file con 18619 aggiunte e 14313 eliminazioni
  1. 16 0
      Tools/Gulp/config.json
  2. 7111 7109
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  3. 50 49
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  4. 825 19
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  5. 7111 7109
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  6. 254 0
      dist/preview release/materialsLibrary/babylon.backgroundMaterial.d.ts
  7. 789 0
      dist/preview release/materialsLibrary/babylon.backgroundMaterial.js
  8. 1 0
      dist/preview release/materialsLibrary/babylon.backgroundMaterial.min.js
  9. 776 0
      dist/preview release/materialsLibrary/babylonjs.materials.js
  10. 9 9
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  11. 255 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  12. 12 1
      materialsLibrary/index.html
  13. 3 0
      materialsLibrary/src/background/babylon.backgroundMaterial.js.include.fx
  14. 862 0
      materialsLibrary/src/background/babylon.backgroundMaterial.ts
  15. 244 0
      materialsLibrary/src/background/background.fragment.fx
  16. 111 0
      materialsLibrary/src/background/background.vertex.fx
  17. 14 0
      materialsLibrary/src/background/backgroundFragmentDeclaration.fx
  18. 21 0
      materialsLibrary/src/background/backgroundUboDeclaration.fx
  19. 18 0
      materialsLibrary/src/background/backgroundVertexDeclaration.fx
  20. 118 0
      materialsLibrary/test/addbackground.js
  21. 19 17
      src/Shaders/ShadersInclude/lightFragment.fx

+ 16 - 0
Tools/Gulp/config.json

@@ -147,6 +147,7 @@
             "textureTools",
             "cameraBehaviors",
             "materialsLibrary/babylon.gridMaterial.js",
+            "materialsLibrary/babylon.backgroundMaterial.js",
             "loaders/babylon.glTFFileLoader.js"
         ],
         "distributed": [
@@ -1237,6 +1238,21 @@
                     "../../materialsLibrary/src/legacyPBR/legacyColorGradingDefinition.fx"
                 ],
                 "output": "babylon.legacyPbrMaterial.js"
+            },
+            {
+                "files": [
+                    "../../materialsLibrary/src/background/babylon.backgroundMaterial.ts"
+                ],
+                "shaderFiles": [
+                    "../../materialsLibrary/src/background/background.vertex.fx",
+                    "../../materialsLibrary/src/background/background.fragment.fx"
+                ],
+                "shadersIncludeFiles": [
+                    "../../materialsLibrary/src/background/backgroundFragmentDeclaration.fx",
+                    "../../materialsLibrary/src/background/backgroundUboDeclaration.fx",
+                    "../../materialsLibrary/src/background/backgroundVertexDeclaration.fx"
+                ],
+                "output": "babylon.backgroundMaterial.js"
             }
         ],
         "build": {

File diff suppressed because it is too large
+ 7111 - 7109
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


File diff suppressed because it is too large
+ 50 - 49
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


File diff suppressed because it is too large
+ 825 - 19
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


File diff suppressed because it is too large
+ 7111 - 7109
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 254 - 0
dist/preview release/materialsLibrary/babylon.backgroundMaterial.d.ts

@@ -0,0 +1,254 @@
+
+declare namespace BABYLON {
+    /**
+     * Background material
+     */
+    class BackgroundMaterial extends BABYLON.PushMaterial {
+        /**
+         * Key light Color (multiply against the R channel of the environement texture)
+         */
+        protected _primaryColor: Color3;
+        primaryColor: Color3;
+        /**
+         * Key light Level (allowing HDR output of the background)
+         */
+        protected _primaryLevel: float;
+        primaryLevel: float;
+        /**
+         * Secondary light Color (multiply against the G channel of the environement texture)
+         */
+        protected _secondaryColor: Color3;
+        secondaryColor: Color3;
+        /**
+         * Secondary light Level (allowing HDR output of the background)
+         */
+        protected _secondaryLevel: float;
+        secondaryLevel: float;
+        /**
+         * Third light Color (multiply against the B channel of the environement texture)
+         */
+        protected _thirdColor: Color3;
+        thirdColor: Color3;
+        /**
+         * Third light Level (allowing HDR output of the background)
+         */
+        protected _thirdLevel: float;
+        thirdLevel: float;
+        /**
+         * Environment Texture used in the material.
+         * Should be author in a specific way for the best result (refer to the documentation).
+         */
+        protected _environmentTexture: Nullable<BaseTexture>;
+        environmentTexture: Nullable<BaseTexture>;
+        /**
+         * Opacity Texture used in the material.
+         * If present, the environment will be seen as a reflection when the luminance is close to 1 and a skybox
+         * where close from 0.
+         * This helps achieving a nice grounding effect by simulating a reflection on the ground but not the skybox.
+         * If not present only the skybox mode is used.
+         */
+        protected _opacityTexture: Nullable<BaseTexture>;
+        opacityTexture: Nullable<BaseTexture>;
+        /**
+         * Environment Texture level of blur.
+         *
+         * Can be use to reuse an existing HDR Texture and target a specific LOD to prevent authoring the
+         * texture twice.
+         */
+        protected _environmentBlur: float;
+        environmentBlur: float;
+        /**
+         * Specify wether or not the different channels of the environment represents background lighting information.
+         * If no, the lumiance will be use equally on each channels.
+         */
+        protected _lightChannelsInTexture: boolean;
+        lightChannelsInTexture: boolean;
+        /**
+         * Specify the list of lights casting shadow on the material.
+         * All scene shadow lights will be included if null.
+         */
+        protected _shadowLights: Nullable<IShadowLight[]>;
+        shadowLights: Nullable<IShadowLight[]>;
+        /**
+         * For the lights having a blurred shadow generator, this can add a second blur pass in order to reach
+         * soft lighting on the background.
+         */
+        protected _shadowBlurScale: int;
+        shadowBlurScale: int;
+        /**
+         * Helps adjusting the shadow to a softer level if required.
+         * 0 means black shadows and 1 means no shadows.
+         */
+        protected _shadowLevel: float;
+        shadowLevel: float;
+        /**
+         * This helps specifying that the material is falling off to the sky box at grazing angle.
+         * This helps ensuring a nice transition when the camera goes under the ground.
+         */
+        protected _opacityFresnel: boolean;
+        opacityFresnel: boolean;
+        /**
+         * Default configuration related to image processing available in the Background Material.
+         */
+        protected _imageProcessingConfiguration: ImageProcessingConfiguration;
+        /**
+         * Keep track of the image processing observer to allow dispose and replace.
+         */
+        private _imageProcessingObserver;
+        /**
+         * Attaches a new image processing configuration to the PBR Material.
+         * @param configuration (if null the scene configuration will be use)
+         */
+        protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void;
+        /**
+         * Gets the image processing configuration used either in this material.
+         */
+        /**
+         * Sets the Default image processing configuration used either in the this material.
+         *
+         * If sets to null, the scene one is in use.
+         */
+        imageProcessingConfiguration: ImageProcessingConfiguration;
+        /**
+         * Gets wether the color curves effect is enabled.
+         */
+        /**
+         * Sets wether the color curves effect is enabled.
+         */
+        cameraColorCurvesEnabled: boolean;
+        /**
+         * Gets wether the color grading effect is enabled.
+         */
+        /**
+         * Gets wether the color grading effect is enabled.
+         */
+        cameraColorGradingEnabled: boolean;
+        /**
+         * Gets wether tonemapping is enabled or not.
+         */
+        /**
+         * Sets wether tonemapping is enabled or not
+         */
+        cameraToneMappingEnabled: boolean;
+        /**
+         * The camera exposure used on this material.
+         * This property is here and not in the camera to allow controlling exposure without full screen post process.
+         * This corresponds to a photographic exposure.
+         */
+        /**
+         * The camera exposure used on this material.
+         * This property is here and not in the camera to allow controlling exposure without full screen post process.
+         * This corresponds to a photographic exposure.
+         */
+        cameraExposure: float;
+        /**
+         * Gets The camera contrast used on this material.
+         */
+        /**
+         * Sets The camera contrast used on this material.
+         */
+        cameraContrast: float;
+        /**
+         * Gets the Color Grading 2D Lookup Texture.
+         */
+        /**
+         * Sets the Color Grading 2D Lookup Texture.
+         */
+        cameraColorGradingTexture: Nullable<BaseTexture>;
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        cameraColorCurves: Nullable<ColorCurves>;
+        /**
+         * Number of Simultaneous lights allowed on the material.
+         */
+        private _maxSimultaneousLights;
+        private _renderTargets;
+        /**
+         * constructor
+         * @param name The name of the material
+         * @param scene The scene to add the material to
+         */
+        constructor(name: string, scene: BABYLON.Scene);
+        /**
+         * The entire material has been created in order to prevent overdraw.
+         * @returns false
+         */
+        needAlphaTesting(): boolean;
+        /**
+         * The entire material has been created in order to prevent overdraw.
+         * @returns false
+         */
+        needAlphaBlending(): boolean;
+        /**
+         * Gets the environment texture to use in the material.
+         * @returns the texture
+         */
+        private _getEnvironmentTexture();
+        /**
+         * Checks wether the material is ready to be rendered for a given mesh.
+         * @param mesh The mesh to render
+         * @param subMesh The submesh to check against
+         * @param useInstances Specify wether or not the material is used with instances
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        /**
+         * Build the uniform buffer used in the material.
+         */
+        buildUniformLayout(): void;
+        /**
+         * Unbind the material.
+         */
+        unbind(): void;
+        /**
+         * Bind only the world matrix to the material.
+         * @param world The world matrix to bind.
+         */
+        bindOnlyWorldMatrix(world: Matrix): void;
+        /**
+         * Bind the material for a dedicated submeh (every used meshes will be considered opaque).
+         * @param world The world matrix to bind.
+         * @param subMesh The submesh to bind for.
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+        /**
+         * Dispose the material.
+         * @forceDisposeEffect Force disposal of the associated effect.
+         * @forceDisposeTextures Force disposal of the associated textures.
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
+        /**
+         * Clones the material.
+         * @name The cloned name.
+         * @returns The cloned material.
+         */
+        clone(name: string): BackgroundMaterial;
+        /**
+         * Serializes the current material to its JSON representation.
+         * @returns The JSON representation.
+         */
+        serialize(): any;
+        /**
+         * Gets the class name of the material
+         * @returns "BackgroundMaterial"
+         */
+        getClassName(): string;
+        /**
+         * Parse a JSON input to create back a background material.
+         * @param source
+         * @param scene
+         * @param rootUrl
+         * @returns the instantiated BackgroundMaterial.
+         */
+        static Parse(source: any, scene: Scene, rootUrl: string): BackgroundMaterial;
+    }
+}

File diff suppressed because it is too large
+ 789 - 0
dist/preview release/materialsLibrary/babylon.backgroundMaterial.js


File diff suppressed because it is too large
+ 1 - 0
dist/preview release/materialsLibrary/babylon.backgroundMaterial.min.js


File diff suppressed because it is too large
+ 776 - 0
dist/preview release/materialsLibrary/babylonjs.materials.js


File diff suppressed because it is too large
+ 9 - 9
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 255 - 0
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -1193,3 +1193,258 @@ declare module BABYLON {
         static Parse(source: any, scene: Scene, rootUrl: string): LegacyPBRMaterial;
     }
 }
+
+
+declare namespace BABYLON {
+    /**
+     * Background material
+     */
+    class BackgroundMaterial extends BABYLON.PushMaterial {
+        /**
+         * Key light Color (multiply against the R channel of the environement texture)
+         */
+        protected _primaryColor: Color3;
+        primaryColor: Color3;
+        /**
+         * Key light Level (allowing HDR output of the background)
+         */
+        protected _primaryLevel: float;
+        primaryLevel: float;
+        /**
+         * Secondary light Color (multiply against the G channel of the environement texture)
+         */
+        protected _secondaryColor: Color3;
+        secondaryColor: Color3;
+        /**
+         * Secondary light Level (allowing HDR output of the background)
+         */
+        protected _secondaryLevel: float;
+        secondaryLevel: float;
+        /**
+         * Third light Color (multiply against the B channel of the environement texture)
+         */
+        protected _thirdColor: Color3;
+        thirdColor: Color3;
+        /**
+         * Third light Level (allowing HDR output of the background)
+         */
+        protected _thirdLevel: float;
+        thirdLevel: float;
+        /**
+         * Environment Texture used in the material.
+         * Should be author in a specific way for the best result (refer to the documentation).
+         */
+        protected _environmentTexture: Nullable<BaseTexture>;
+        environmentTexture: Nullable<BaseTexture>;
+        /**
+         * Opacity Texture used in the material.
+         * If present, the environment will be seen as a reflection when the luminance is close to 1 and a skybox
+         * where close from 0.
+         * This helps achieving a nice grounding effect by simulating a reflection on the ground but not the skybox.
+         * If not present only the skybox mode is used.
+         */
+        protected _opacityTexture: Nullable<BaseTexture>;
+        opacityTexture: Nullable<BaseTexture>;
+        /**
+         * Environment Texture level of blur.
+         *
+         * Can be use to reuse an existing HDR Texture and target a specific LOD to prevent authoring the
+         * texture twice.
+         */
+        protected _environmentBlur: float;
+        environmentBlur: float;
+        /**
+         * Specify wether or not the different channels of the environment represents background lighting information.
+         * If no, the lumiance will be use equally on each channels.
+         */
+        protected _lightChannelsInTexture: boolean;
+        lightChannelsInTexture: boolean;
+        /**
+         * Specify the list of lights casting shadow on the material.
+         * All scene shadow lights will be included if null.
+         */
+        protected _shadowLights: Nullable<IShadowLight[]>;
+        shadowLights: Nullable<IShadowLight[]>;
+        /**
+         * For the lights having a blurred shadow generator, this can add a second blur pass in order to reach
+         * soft lighting on the background.
+         */
+        protected _shadowBlurScale: int;
+        shadowBlurScale: int;
+        /**
+         * Helps adjusting the shadow to a softer level if required.
+         * 0 means black shadows and 1 means no shadows.
+         */
+        protected _shadowLevel: float;
+        shadowLevel: float;
+        /**
+         * This helps specifying that the material is falling off to the sky box at grazing angle.
+         * This helps ensuring a nice transition when the camera goes under the ground.
+         */
+        protected _opacityFresnel: boolean;
+        opacityFresnel: boolean;
+        /**
+         * Default configuration related to image processing available in the Background Material.
+         */
+        protected _imageProcessingConfiguration: ImageProcessingConfiguration;
+        /**
+         * Keep track of the image processing observer to allow dispose and replace.
+         */
+        private _imageProcessingObserver;
+        /**
+         * Attaches a new image processing configuration to the PBR Material.
+         * @param configuration (if null the scene configuration will be use)
+         */
+        protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void;
+        /**
+         * Gets the image processing configuration used either in this material.
+         */
+        /**
+         * Sets the Default image processing configuration used either in the this material.
+         *
+         * If sets to null, the scene one is in use.
+         */
+        imageProcessingConfiguration: ImageProcessingConfiguration;
+        /**
+         * Gets wether the color curves effect is enabled.
+         */
+        /**
+         * Sets wether the color curves effect is enabled.
+         */
+        cameraColorCurvesEnabled: boolean;
+        /**
+         * Gets wether the color grading effect is enabled.
+         */
+        /**
+         * Gets wether the color grading effect is enabled.
+         */
+        cameraColorGradingEnabled: boolean;
+        /**
+         * Gets wether tonemapping is enabled or not.
+         */
+        /**
+         * Sets wether tonemapping is enabled or not
+         */
+        cameraToneMappingEnabled: boolean;
+        /**
+         * The camera exposure used on this material.
+         * This property is here and not in the camera to allow controlling exposure without full screen post process.
+         * This corresponds to a photographic exposure.
+         */
+        /**
+         * The camera exposure used on this material.
+         * This property is here and not in the camera to allow controlling exposure without full screen post process.
+         * This corresponds to a photographic exposure.
+         */
+        cameraExposure: float;
+        /**
+         * Gets The camera contrast used on this material.
+         */
+        /**
+         * Sets The camera contrast used on this material.
+         */
+        cameraContrast: float;
+        /**
+         * Gets the Color Grading 2D Lookup Texture.
+         */
+        /**
+         * Sets the Color Grading 2D Lookup Texture.
+         */
+        cameraColorGradingTexture: Nullable<BaseTexture>;
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        cameraColorCurves: Nullable<ColorCurves>;
+        /**
+         * Number of Simultaneous lights allowed on the material.
+         */
+        private _maxSimultaneousLights;
+        private _renderTargets;
+        /**
+         * constructor
+         * @param name The name of the material
+         * @param scene The scene to add the material to
+         */
+        constructor(name: string, scene: BABYLON.Scene);
+        /**
+         * The entire material has been created in order to prevent overdraw.
+         * @returns false
+         */
+        needAlphaTesting(): boolean;
+        /**
+         * The entire material has been created in order to prevent overdraw.
+         * @returns false
+         */
+        needAlphaBlending(): boolean;
+        /**
+         * Gets the environment texture to use in the material.
+         * @returns the texture
+         */
+        private _getEnvironmentTexture();
+        /**
+         * Checks wether the material is ready to be rendered for a given mesh.
+         * @param mesh The mesh to render
+         * @param subMesh The submesh to check against
+         * @param useInstances Specify wether or not the material is used with instances
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        /**
+         * Build the uniform buffer used in the material.
+         */
+        buildUniformLayout(): void;
+        /**
+         * Unbind the material.
+         */
+        unbind(): void;
+        /**
+         * Bind only the world matrix to the material.
+         * @param world The world matrix to bind.
+         */
+        bindOnlyWorldMatrix(world: Matrix): void;
+        /**
+         * Bind the material for a dedicated submeh (every used meshes will be considered opaque).
+         * @param world The world matrix to bind.
+         * @param subMesh The submesh to bind for.
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+        /**
+         * Dispose the material.
+         * @forceDisposeEffect Force disposal of the associated effect.
+         * @forceDisposeTextures Force disposal of the associated textures.
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
+        /**
+         * Clones the material.
+         * @name The cloned name.
+         * @returns The cloned material.
+         */
+        clone(name: string): BackgroundMaterial;
+        /**
+         * Serializes the current material to its JSON representation.
+         * @returns The JSON representation.
+         */
+        serialize(): any;
+        /**
+         * Gets the class name of the material
+         * @returns "BackgroundMaterial"
+         */
+        getClassName(): string;
+        /**
+         * Parse a JSON input to create back a background material.
+         * @param source
+         * @param scene
+         * @param rootUrl
+         * @returns the instantiated BackgroundMaterial.
+         */
+        static Parse(source: any, scene: Scene, rootUrl: string): BackgroundMaterial;
+    }
+}

+ 12 - 1
materialsLibrary/index.html

@@ -53,8 +53,10 @@
 	<script src="test/addpbrspecularglossiness.js"></script>
 	<script src="test/addlegacypbr.js"></script>
 	<script src="test/addCell.js"></script>
+	<script src="test/addbackground.js"></script>
 	
 	<script>
+	var backgroundSkybox = null;
 	BABYLONDEVTOOLS.Loader.load(function() {
 		if (BABYLON.Engine.isSupported()) {
 			var canvas = document.getElementById("renderCanvas");
@@ -199,6 +201,8 @@
 
 				var pbr = preparePBR();
 
+				var back = prepareBackgroundMaterial();
+
 				var pbrmetallicroughness = preparePBRMetallicRoughness();
 
 				var pbrspecularglossiness = preparePBRSpecularGlossiness();
@@ -220,11 +224,14 @@
 				sphere.material = std;				
 				sphere.receiveShadows = true;
 
-				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr', 'pbrmetallicroughness', 'pbrspecularglossiness', 'legacyPbr', 'fur', 'triPlanar', 'gradient', 'sky', 'grid', 'shadowOnly', 'cell']).onFinishChange(function () {
+				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr', 'pbrmetallicroughness', 'pbrspecularglossiness', 'legacyPbr', 'fur', 'triPlanar', 'gradient', 'sky', 'grid', 'shadowOnly', 'cell', 'background']).onFinishChange(function () {
 					water.enableRenderTargets(false);
 					skybox.material = skyboxMaterial;
 					currentMesh.isVisible = true;
 					fur.resetFur();
+					if (backgroundSkybox) {
+						backgroundSkybox.setEnabled(false);
+					}
                     
 					switch (options.material) {
 						case "shadowOnly":
@@ -282,6 +289,10 @@
 						case "cell":
 							currentMaterial = cell;
 							break;
+						case "background":
+							currentMaterial = back;
+							backgroundSkybox.setEnabled(true);
+							break;
 						default:
 							currentMaterial = std;
 							break;

+ 3 - 0
materialsLibrary/src/background/babylon.backgroundMaterial.js.include.fx

@@ -0,0 +1,3 @@
+BABYLON.Effect.IncludesShadersStore['backgroundFragmentDeclaration'] = " uniform vec4 vPrimaryColor;\nuniform vec4 vSecondaryColor;\nuniform vec4 vThirdColor;\nuniform float shadowLevel;\n#ifdef OPACITY\nuniform vec2 vOpacityInfo;\n#endif\n#ifdef ENVIRONMENT\nuniform vec2 vEnvironmentInfo;\nuniform mat4 environmentMatrix;\nuniform vec3 vEnvironmentMicrosurfaceInfos;\n#endif";
+BABYLON.Effect.IncludesShadersStore['backgroundUboDeclaration'] = "layout(std140,column_major) uniform;\nuniform Material\n{\nuniform vec4 vPrimaryColor;\nuniform vec4 vSecondaryColor;\nuniform vec4 vThirdColor;\nuniform vec2 vOpacityInfo;\nuniform vec2 vEnvironmentInfo;\nuniform mat4 opacityMatrix;\nuniform mat4 environmentMatrix;\nuniform vec3 vEnvironmentMicrosurfaceInfos;\nuniform float pointSize;\nuniform float shadowLevel;\n};\nuniform Scene {\nmat4 viewProjection;\nmat4 view;\n};";
+BABYLON.Effect.IncludesShadersStore['backgroundVertexDeclaration'] = "uniform mat4 view;\nuniform mat4 viewProjection;\nuniform float shadowLevel;\n#ifdef OPACITY\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfo;\n#endif\n#ifdef ENVIRONMENT\nuniform vec2 vEnvironmentInfo;\nuniform mat4 environmentMatrix;\nuniform vec3 vEnvionmentMicrosurfaceInfos;\n#endif\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif";

+ 862 - 0
materialsLibrary/src/background/babylon.backgroundMaterial.ts

@@ -0,0 +1,862 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+namespace BABYLON {
+    /**
+     * Background material defines definition.
+     */
+    class BackgroundMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
+        /**
+         * True if the opacity texture is in use.
+         */
+        public OPACITY = false;
+
+        /**
+         * The direct UV channel to use.
+         */
+        public OPACITYDIRECTUV = 0;
+
+        /**
+         * True if the opacity texture is used in gray scale.
+         */
+        public OPACITYRGB = false;
+
+        /**
+         * True if the environment texture is in use.
+         */
+        public ENVIRONMENT = false;
+
+        /**
+         * True if the environment is defined in gamma space.
+         */
+        public GAMMAENVIRONMENT = false;
+
+        /**
+         * True if the environment texture does not contain background dedicated data.
+         * The material will fallback to use the luminance of the background.
+         */
+        public RGBENVIRONMENT = false;
+
+        /**
+         * True if an extra blur needs to be added in the environment.
+         */
+        public ENVIRONMENTBLUR = false;
+
+        /**
+         * False if the current Webgl implementation does not support the texture lod extension.
+         */
+        public TEXTURELODSUPPORT = false;
+
+        /**
+         * True if you want the material to fade to the environment color at grazing angle.
+         */
+        public OPACITYFRESNEL = false;
+
+        /**
+         * True if you want the shadow being generated from the diffuse color of the light.
+         * It is actually using 1 - diffuse to adpat the color to the color not reflected
+         * by the target.
+         */
+        public SHADOWFROMLIGHTCOLOR = false;
+
+        // Image Processing Configuration.
+        public IMAGEPROCESSING = false;
+        public VIGNETTE = false;
+        public VIGNETTEBLENDMODEMULTIPLY = false;
+        public VIGNETTEBLENDMODEOPAQUE = false;
+        public TONEMAPPING = false;
+        public CONTRAST = false;
+        public COLORCURVES = false;
+        public COLORGRADING = false;
+        public COLORGRADING3D = false;
+        public SAMPLER3DGREENDEPTH = false;
+        public SAMPLER3DBGRMAP = false;
+        public IMAGEPROCESSINGPOSTPROCESS = false;
+        public EXPOSURE = false;
+
+        // Default BJS.
+        public MAINUV1 = false;
+        public MAINUV2 = false;
+        public UV1 = false;
+        public UV2 = false;
+        public CLIPPLANE = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public NORMAL = false;
+        public NUM_BONE_INFLUENCERS = 0;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+        public SHADOWFLOAT = false;
+
+        /**
+         * Constructor of the defines.
+         */
+        constructor() {
+            super();
+            this.rebuild();
+        }
+    }
+
+    /**
+     * Background material 
+     */
+    export class BackgroundMaterial extends BABYLON.PushMaterial {
+
+        /**
+         * Key light Color (multiply against the R channel of the environement texture)
+         */
+        @serializeAsColor3()
+        protected _primaryColor: Color3;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public primaryColor = BABYLON.Color3.White();
+
+        /**
+         * Key light Level (allowing HDR output of the background)
+         */
+        @serialize()
+        protected _primaryLevel: float;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public primaryLevel: float = 1;
+        /**
+         * Secondary light Color (multiply against the G channel of the environement texture)
+         */
+        @serializeAsColor3()
+        protected _secondaryColor: Color3;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public secondaryColor = BABYLON.Color3.Gray();
+
+        /**
+         * Secondary light Level (allowing HDR output of the background)
+         */
+        @serialize()
+        protected _secondaryLevel: float;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public secondaryLevel: float = 1;
+
+        /**
+         * Third light Color (multiply against the B channel of the environement texture)
+         */
+        @serializeAsColor3()
+        protected _thirdColor: Color3;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public thirdColor = BABYLON.Color3.Black();
+
+        /**
+         * Third light Level (allowing HDR output of the background)
+         */
+        @serialize()
+        protected _thirdLevel: float;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public thirdLevel: float = 1;
+
+        /**
+         * Environment Texture used in the material.
+         * Should be author in a specific way for the best result (refer to the documentation).
+         */
+        @serializeAsTexture()
+        protected _environmentTexture: Nullable<BaseTexture>;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public environmentTexture: Nullable<BaseTexture> = null;
+
+        /**
+         * Opacity Texture used in the material.
+         * If present, the environment will be seen as a reflection when the luminance is close to 1 and a skybox
+         * where close from 0.
+         * This helps achieving a nice grounding effect by simulating a reflection on the ground but not the skybox.
+         * If not present only the skybox mode is used.
+         */
+        @serializeAsTexture()
+        protected _opacityTexture: Nullable<BaseTexture>;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public opacityTexture: Nullable<BaseTexture> = null;
+
+        /**
+         * Environment Texture level of blur.
+         * 
+         * Can be use to reuse an existing HDR Texture and target a specific LOD to prevent authoring the 
+         * texture twice.
+         */
+        @serialize()
+        protected _environmentBlur: float;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public environmentBlur: float = 0;
+
+        /**
+         * Specify wether or not the different channels of the environment represents background lighting information.
+         * If no, the lumiance will be use equally on each channels.
+         */
+        @serialize()
+        protected _lightChannelsInTexture: boolean;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public lightChannelsInTexture: boolean = false;
+
+        /**
+         * Specify the list of lights casting shadow on the material.
+         * All scene shadow lights will be included if null.
+         */
+        protected _shadowLights: Nullable<IShadowLight[]> = null;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public shadowLights: Nullable<IShadowLight[]> = null;
+
+        /**
+         * For the lights having a blurred shadow generator, this can add a second blur pass in order to reach
+         * soft lighting on the background.
+         */
+        @serialize()
+        protected _shadowBlurScale: int;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public shadowBlurScale: int = 1;
+
+        /**
+         * Helps adjusting the shadow to a softer level if required.
+         * 0 means black shadows and 1 means no shadows.
+         */
+        @serialize()
+        protected _shadowLevel: float;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public shadowLevel: float = 0;
+
+        /**
+         * This helps specifying that the material is falling off to the sky box at grazing angle.
+         * This helps ensuring a nice transition when the camera goes under the ground.
+         */
+        @serialize()
+        protected _opacityFresnel: boolean;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public opacityFresnel: boolean = true;
+
+        /**
+         * Default configuration related to image processing available in the Background Material.
+         */
+        @serializeAsImageProcessingConfiguration()
+        protected _imageProcessingConfiguration: ImageProcessingConfiguration;
+
+        /**
+         * Keep track of the image processing observer to allow dispose and replace.
+         */
+        private _imageProcessingObserver: Nullable<Observer<ImageProcessingConfiguration>> = null;
+
+        /**
+         * Attaches a new image processing configuration to the PBR Material.
+         * @param configuration (if null the scene configuration will be use)
+         */
+        protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void {
+            if (configuration === this._imageProcessingConfiguration) {
+                return;
+            }
+
+            // Detaches observer.
+            if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
+                this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
+            }
+
+            // Pick the scene configuration if needed.
+            if (!configuration) {
+                this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration;
+            }
+            else {
+                this._imageProcessingConfiguration = configuration;
+            }
+
+            // Attaches observer.
+            this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
+                this._markAllSubMeshesAsImageProcessingDirty();
+            });
+        }
+
+        /**
+         * Gets the image processing configuration used either in this material.
+         */
+        public get imageProcessingConfiguration(): ImageProcessingConfiguration {
+            return this._imageProcessingConfiguration;
+        }
+
+        /**
+         * Sets the Default image processing configuration used either in the this material.
+         * 
+         * If sets to null, the scene one is in use.
+         */
+        public set imageProcessingConfiguration(value: Nullable<ImageProcessingConfiguration>) {
+            this._attachImageProcessingConfiguration(value);
+
+            // Ensure the effect will be rebuilt.
+            this._markAllSubMeshesAsTexturesDirty();
+        }
+
+        /**
+         * Gets wether the color curves effect is enabled.
+         */
+        public get cameraColorCurvesEnabled(): boolean {
+            return this.imageProcessingConfiguration.colorCurvesEnabled;
+        }
+        /**
+         * Sets wether the color curves effect is enabled.
+         */
+        public set cameraColorCurvesEnabled(value: boolean) {
+            this.imageProcessingConfiguration.colorCurvesEnabled = value;
+        }
+
+        /**
+         * Gets wether the color grading effect is enabled.
+         */
+        public get cameraColorGradingEnabled(): boolean {
+            return this.imageProcessingConfiguration.colorGradingEnabled;
+        }
+        /**
+         * Gets wether the color grading effect is enabled.
+         */
+        public set cameraColorGradingEnabled(value: boolean) {
+            this.imageProcessingConfiguration.colorGradingEnabled = value;
+        }
+
+        /**
+         * Gets wether tonemapping is enabled or not.
+         */
+        public get cameraToneMappingEnabled(): boolean {
+            return this._imageProcessingConfiguration.toneMappingEnabled;
+        };
+        /**
+         * Sets wether tonemapping is enabled or not
+         */
+        public set cameraToneMappingEnabled(value: boolean) {
+            this._imageProcessingConfiguration.toneMappingEnabled = value;
+        };
+
+        /**
+         * The camera exposure used on this material.
+         * This property is here and not in the camera to allow controlling exposure without full screen post process.
+         * This corresponds to a photographic exposure.
+         */
+        public get cameraExposure(): float {
+            return this._imageProcessingConfiguration.exposure;
+        };
+        /**
+         * The camera exposure used on this material.
+         * This property is here and not in the camera to allow controlling exposure without full screen post process.
+         * This corresponds to a photographic exposure.
+         */
+        public set cameraExposure(value: float) {
+            this._imageProcessingConfiguration.exposure = value;
+        };
+        
+        /**
+         * Gets The camera contrast used on this material.
+         */
+        public get cameraContrast(): float {
+            return this._imageProcessingConfiguration.contrast;
+        }
+
+        /**
+         * Sets The camera contrast used on this material.
+         */
+        public set cameraContrast(value: float) {
+            this._imageProcessingConfiguration.contrast = value;
+        }
+        
+        /**
+         * Gets the Color Grading 2D Lookup Texture.
+         */
+        public get cameraColorGradingTexture(): Nullable<BaseTexture> {
+            return this._imageProcessingConfiguration.colorGradingTexture;
+        }
+        /**
+         * Sets the Color Grading 2D Lookup Texture.
+         */
+        public set cameraColorGradingTexture(value: Nullable<BaseTexture>) {
+            this._imageProcessingConfiguration.colorGradingTexture = value;
+        }
+
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT). 
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; 
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        public get cameraColorCurves(): Nullable<ColorCurves> {
+            return this._imageProcessingConfiguration.colorCurves;
+        }
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT). 
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; 
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        public set cameraColorCurves(value: Nullable<ColorCurves>) {
+            this._imageProcessingConfiguration.colorCurves = value;
+        }
+
+        /**
+         * Number of Simultaneous lights allowed on the material.
+         */
+        private _maxSimultaneousLights: int = 4;
+
+        // Temp values kept as cache in the material.
+        private _renderTargets = new SmartArray<RenderTargetTexture>(16);
+
+        /**
+         * constructor
+         * @param name The name of the material
+         * @param scene The scene to add the material to
+         */
+        constructor(name: string, scene: BABYLON.Scene) {
+            super(name, scene);
+
+            // Setup the default processing configuration to the scene.
+            this._attachImageProcessingConfiguration(null);
+
+            this.getRenderTargetTextures = (): SmartArray<RenderTargetTexture> => {
+                this._renderTargets.reset();
+
+                if (this._opacityTexture && this._opacityTexture.isRenderTarget) {
+                    this._renderTargets.push(this._opacityTexture as RenderTargetTexture);
+                }
+
+                if (this._environmentTexture && this._environmentTexture.isRenderTarget) {
+                    this._renderTargets.push(this._environmentTexture as RenderTargetTexture);
+                }
+
+                return this._renderTargets;
+            }
+        }
+
+        /**
+         * The entire material has been created in order to prevent overdraw.
+         * @returns false
+         */
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        /**
+         * The entire material has been created in order to prevent overdraw.
+         * @returns false
+         */
+        public needAlphaBlending(): boolean {
+            return false;
+        }
+
+        /**
+         * Gets the environment texture to use in the material.
+         * @returns the texture
+         */
+        private _getEnvironmentTexture(): Nullable<BaseTexture> {
+            if (this._environmentTexture) {
+                return this._environmentTexture;
+            }
+
+            return this.getScene().environmentTexture;
+        }
+
+        /**
+         * Checks wether the material is ready to be rendered for a given mesh.
+         * @param mesh The mesh to render
+         * @param subMesh The submesh to check against
+         * @param useInstances Specify wether or not the material is used with instances
+         */
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances: boolean = false): boolean { 
+            if (subMesh.effect && this.isFrozen) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new BackgroundMaterialDefines();
+            }
+
+            var scene = this.getScene();
+            var defines = <BackgroundMaterialDefines>subMesh._materialDefines;
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
+                if (defines._renderId === scene.getRenderId()) {
+                    return true;
+                }
+            }
+
+            var engine = scene.getEngine();
+            
+            // Lights
+            MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
+            defines._needNormals = true;
+            
+            // Textures
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (scene.getEngine().getCaps().textureLOD) {
+                        defines.TEXTURELODSUPPORT = true;
+                    }
+
+                    if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                        if (!this._opacityTexture.isReadyOrNotBlocking()) {
+                            return false;
+                        }
+
+                        MaterialHelper.PrepareDefinesForMergedUV(this._opacityTexture, defines, "OPACITY");
+                        defines.OPACITYRGB = this._opacityTexture.getAlphaFromRGB;
+                        defines.OPACITYFRESNEL = this._opacityFresnel;
+                    } else {
+                        defines.OPACITY = false;
+                        defines.OPACITYRGB = false;
+                        defines.OPACITYFRESNEL = false;
+                    }
+
+                    var environmentTexture = this._getEnvironmentTexture();
+                    if (environmentTexture && StandardMaterial.ReflectionTextureEnabled) {
+                        if (!environmentTexture.isReadyOrNotBlocking()) {
+                            return false;
+                        }
+
+                        MaterialHelper.PrepareDefinesForMergedUV(environmentTexture, defines, "ENVIRONMENT"); 
+                        defines.GAMMAENVIRONMENT = environmentTexture.gammaSpace;
+                        defines.ENVIRONMENTBLUR = this._environmentBlur > 0;
+                        defines.RGBENVIRONMENT = !this.lightChannelsInTexture;
+                    } else {
+                        defines.ENVIRONMENT = false;
+                        defines.GAMMAENVIRONMENT = false;
+                        defines.RGBENVIRONMENT = false;
+                    }
+                }
+            }
+
+            if (defines._areImageProcessingDirty) {
+                if (!this._imageProcessingConfiguration.isReady()) {
+                    return false;
+                }
+
+                this._imageProcessingConfiguration.prepareDefines(defines);
+            }
+
+            // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, false);
+
+             // Attribs
+            if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
+                if (mesh) {
+                    if (!scene.getEngine().getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                        mesh.createNormals(true);
+                        Tools.Warn("BackgroundMaterial: Normals have been created for the mesh: " + mesh.name);
+                    }
+                }
+            }
+
+            // Get correct effect
+            if (defines.isDirty) {
+                defines.markAsProcessed();
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();
+                if (defines.FOG) {
+                    fallbacks.addFallback(0, "FOG");
+                }
+
+                if (defines.POINTSIZE) {
+                    fallbacks.addFallback(1, "POINTSIZE");
+                }
+
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this._maxSimultaneousLights);
+
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
+                    fallbacks.addCPUSkinningFallback(0, mesh);
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
+
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", 
+                        "vFogInfos", "vFogColor", "pointSize",
+                        "vClipPlane", "mBones", 
+
+                        "vPrimaryColor", "vSecondaryColor", "vThirdColor",
+                        "vEnvironmentInfo", "environmentMatrix", "vEnvironmentMicrosurfaceInfos",
+
+                        "shadowLevel",
+
+                        "vOpacityInfo", "opacityMatrix",
+                ];
+
+                var samplers = ["opacitySampler", "environmentSampler", "environmentSamplerLow", "environmentSamplerHigh"];
+                var uniformBuffers = ["Material", "Scene"];
+
+                ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
+                ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this._maxSimultaneousLights
+                });
+
+                var onCompiled = (effect: Effect) => {
+                    if (this.onCompiled) {
+                        this.onCompiled(effect);
+                    }
+
+                    this.bindSceneUniformBuffer(effect, scene.getSceneUniformBuffer());
+                };
+
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect("background", <EffectCreationOptions>{
+                    attributes: attribs,
+                    uniformsNames: uniforms,
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers,
+                    defines: join,
+                    fallbacks: fallbacks,
+                    onCompiled: onCompiled,
+                    onError: this.onError,
+                    indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights }
+                }, engine), defines);
+                
+                this.buildUniformLayout();
+            }
+
+            if (!subMesh.effect.isReady()) {
+                return false;
+            }
+
+            defines._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            return true;
+        }
+
+        /**
+         * Build the uniform buffer used in the material.
+         */
+        public buildUniformLayout(): void {
+            // Order is important !
+            this._uniformBuffer.addUniform("vPrimaryColor", 4);
+            this._uniformBuffer.addUniform("vSecondaryColor", 4);
+            this._uniformBuffer.addUniform("vThirdColor", 4);
+            this._uniformBuffer.addUniform("vOpacityInfo", 2);
+            this._uniformBuffer.addUniform("vEnvironmentInfo", 2);
+            this._uniformBuffer.addUniform("opacityMatrix", 16);
+            this._uniformBuffer.addUniform("environmentMatrix", 16);
+            this._uniformBuffer.addUniform("vEnvironmentMicrosurfaceInfos", 3);
+            this._uniformBuffer.addUniform("pointSize", 1);
+            this._uniformBuffer.addUniform("shadowLevel", 1);
+            this._uniformBuffer.create();
+        }
+
+        /**
+         * Unbind the material.
+         */
+        public unbind(): void {
+            if (this._opacityTexture && this._opacityTexture.isRenderTarget) {
+                this._uniformBuffer.setTexture("opacitySampler", null);
+            }
+
+            if (this._environmentTexture && this._environmentTexture.isRenderTarget) {
+                this._uniformBuffer.setTexture("environmentSampler", null);
+            }
+
+            super.unbind();
+        }
+
+        /**
+         * Bind only the world matrix to the material.
+         * @param world The world matrix to bind.
+         */
+        public bindOnlyWorldMatrix(world: Matrix): void {
+            this._activeEffect.setMatrix("world", world);
+        }
+
+        /**
+         * Bind the material for a dedicated submeh (every used meshes will be considered opaque).
+         * @param world The world matrix to bind.
+         * @param subMesh The submesh to bind for.
+         */
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
+            var scene = this.getScene();
+
+            var defines = <BackgroundMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
+            // Matrices
+            this.bindOnlyWorldMatrix(world);
+
+            // Bones
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+
+            let mustRebind = this._mustRebind(scene, effect, mesh.visibility);
+            if (mustRebind) {
+                this._uniformBuffer.bindToEffect(effect, "Material");
+
+                this.bindViewProjection(effect);
+
+                var environmentTexture = this._getEnvironmentTexture();
+                if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {
+
+                    // Texture uniforms
+                    if (scene.texturesEnabled) {
+                        if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vOpacityInfo", this._opacityTexture.coordinatesIndex, this._opacityTexture.level);
+                            MaterialHelper.BindTextureMatrix(this._opacityTexture, this._uniformBuffer, "opacity");
+                        }
+
+                        if (environmentTexture && StandardMaterial.ReflectionTextureEnabled) {
+                            this._uniformBuffer.updateMatrix("environmentMatrix", environmentTexture.getReflectionTextureMatrix());
+                            this._uniformBuffer.updateFloat2("vEnvironmentInfo", environmentTexture.level, this._environmentBlur);
+                            this._uniformBuffer.updateFloat3("vEnvironmentMicrosurfaceInfos", 
+                                environmentTexture.getSize().width, 
+                                environmentTexture.lodGenerationScale,
+                                environmentTexture.lodGenerationOffset);
+                        }
+                    }
+
+                    if (this.shadowLevel > 0) {
+                        this._uniformBuffer.updateFloat("shadowLevel", this.shadowLevel);
+                    }
+
+                    // Point size
+                    if (this.pointsCloud) {
+                        this._uniformBuffer.updateFloat("pointSize", this.pointSize);
+                    }
+
+                    this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryColor, this._primaryLevel);
+                    this._uniformBuffer.updateColor4("vSecondaryColor", this._secondaryColor, this._secondaryLevel);
+                    this._uniformBuffer.updateColor4("vThirdColor", this._thirdColor, this._thirdLevel);
+                }
+
+                // Textures
+                if (scene.texturesEnabled) {
+                    if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                        this._uniformBuffer.setTexture("opacitySampler", this._opacityTexture);
+                    }
+
+                    if (environmentTexture && StandardMaterial.ReflectionTextureEnabled) {
+                        if (defines.ENVIRONMENTBLUR && defines.TEXTURELODSUPPORT) {
+                            this._uniformBuffer.setTexture("environmentSampler", environmentTexture);
+                        }
+                        else if (!defines.ENVIRONMENTBLUR) {
+                            this._uniformBuffer.setTexture("environmentSampler", environmentTexture);
+                        }
+                        else {
+                            this._uniformBuffer.setTexture("environmentSampler", environmentTexture._lodTextureMid || environmentTexture);
+                            this._uniformBuffer.setTexture("environmentSamplerLow", environmentTexture._lodTextureLow || environmentTexture);
+                            this._uniformBuffer.setTexture("environmentSamplerHigh", environmentTexture._lodTextureHigh || environmentTexture);
+                        }
+                    }
+                }
+
+                // Clip plane
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
+
+                var eyePosition = scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.globalPosition;
+                // var invertNormal = (scene.useRightHandedSystem === (scene._mirroredCameraPosition != null));
+                effect.setFloat3("vEyePosition",
+                    eyePosition.x,
+                    eyePosition.y,
+                    eyePosition.z);
+            }
+
+            if (mustRebind || !this.isFrozen) {
+                if (scene.lightsEnabled) {
+                    MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights, false);
+                }
+
+                // View
+                this.bindView(effect);
+
+                // Fog
+                MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+
+                // image processing
+                this._imageProcessingConfiguration.bind(this._activeEffect);
+            }
+
+            this._uniformBuffer.update();
+
+            this._afterBind(mesh);
+
+            scene = null;
+        }
+
+        /**
+         * Dispose the material.
+         * @forceDisposeEffect Force disposal of the associated effect.
+         * @forceDisposeTextures Force disposal of the associated textures.
+         */
+        public dispose(forceDisposeEffect: boolean = false, forceDisposeTextures: boolean = false): void {
+            if (forceDisposeTextures) {
+                if (this.opacityTexture) {
+                    this.opacityTexture.dispose();
+                }
+                if (this.environmentTexture) {
+                    this.environmentTexture.dispose();
+                }
+            }
+
+            this._renderTargets.dispose();
+
+            if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
+                this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        /**
+         * Clones the material.
+         * @name The cloned name.
+         * @returns The cloned material.
+         */
+        public clone(name: string): BackgroundMaterial {
+            return SerializationHelper.Clone(() => new BackgroundMaterial(name, this.getScene()), this);
+        }
+
+        /**
+         * Serializes the current material to its JSON representation.
+         * @returns The JSON representation.
+         */
+        public serialize(): any {
+            var serializationObject = SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.GridMaterial";
+            return serializationObject;
+        }
+
+        /**
+         * Gets the class name of the material
+         * @returns "BackgroundMaterial"
+         */
+        public getClassName(): string {
+            return "BackgroundMaterial";
+        }
+
+        /**
+         * Parse a JSON input to create back a background material.
+         * @param source 
+         * @param scene 
+         * @param rootUrl 
+         * @returns the instantiated BackgroundMaterial.
+         */
+        public static Parse(source: any, scene: Scene, rootUrl: string): BackgroundMaterial {
+            return SerializationHelper.Parse(() => new BackgroundMaterial(source.name, scene), source, scene, rootUrl);
+        }
+    }
+}

+ 244 - 0
materialsLibrary/src/background/background.fragment.fx

@@ -0,0 +1,244 @@
+#ifdef TEXTURELODSUPPORT
+#extension GL_EXT_shader_texture_lod : enable
+#endif
+
+precision highp float;
+
+#include<__decl__backgroundFragment>
+
+// Constants
+uniform vec3 vEyePosition;
+
+// Input
+varying vec3 vPositionW;
+
+#ifdef MAINUV1
+    varying vec2 vMainUV1;
+#endif 
+
+#ifdef MAINUV2 
+    varying vec2 vMainUV2; 
+#endif 
+
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef OPACITY
+    #if OPACITYDIRECTUV == 1
+        #define vOpacityUV vMainUV1
+    #elif OPACITYDIRECTUV == 2
+        #define vOpacityUV vMainUV2
+    #else
+        varying vec2 vOpacityUV;
+    #endif
+    uniform sampler2D opacitySampler;
+#endif
+
+// Environment
+#ifdef ENVIRONMENT
+    #define sampleEnvironment(s, c) textureCube(s, c)
+
+    uniform samplerCube environmentSampler;
+
+    #ifdef ENVIRONMENTBLUR
+        #ifdef TEXTURELODSUPPORT
+            #define sampleEnvironmentLod(s, c, l) textureCubeLodEXT(s, c, l)
+        #else
+            uniform samplerCube environmentSamplerLow;
+            uniform samplerCube environmentSamplerHigh;
+        #endif
+    #endif
+#endif
+
+// Forces linear space for image processing
+#ifndef FROMLINEARSPACE
+    #define FROMLINEARSPACE;
+#endif
+
+// Prevent expensive light computations
+#ifndef SHADOWONLY
+    #define SHADOWONLY;
+#endif
+
+
+#include<imageProcessingDeclaration>
+
+// Lights
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
+
+#include<helperFunctions>
+#include<lightsFragmentFunctions>
+#include<shadowsFragmentFunctions>
+#include<imageProcessingFunctions>
+
+#include<clipPlaneFragmentDeclaration>
+
+// Fog
+#include<fogFragmentDeclaration>
+
+void main(void) {
+#include<clipPlaneFragment>
+
+    vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
+
+// _____________________________ Normal Information ______________________________
+#ifdef NORMAL
+    vec3 normalW = normalize(vNormalW);
+#else
+    vec3 normalW = vec3(0.0, 1.0, 0.0);
+#endif
+
+// _____________________________ Light Information _______________________________
+    float shadow = 1.;
+
+#include<lightFragment>[0..maxSimultaneousLights]
+
+// _____________________________ Environment ______________________________________
+#ifdef ENVIRONMENT
+    vec3 environmentColor = vec3(0., 0., 0.);
+
+    // Skybox Fetch.
+    vec3 environmentCoords = (vPositionW.xyz - vEyePosition.xyz);
+    #ifdef INVERTCUBICMAP
+            environmentCoords.y = 1.0 - environmentCoords.y;
+    #endif
+    // Rotate Environment
+    environmentCoords = vec3(environmentMatrix * vec4(environmentCoords, 0));
+
+    #ifdef ENVIRONMENTBLUR
+        float environmentLOD = vEnvironmentInfo.y;
+
+        #ifdef TEXTURELODSUPPORT
+            // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection
+            environmentLOD = environmentLOD * log2(vEnvironmentMicrosurfaceInfos.x) * vEnvironmentMicrosurfaceInfos.y + vEnvironmentMicrosurfaceInfos.z;
+            environmentColor = sampleEnvironmentLod(environmentSampler, environmentCoords, environmentLOD).rgb;
+        #else
+            float lodEnvironmentNormalized = clamp(environmentLOD, 0., 1.);
+            float lodEnvironmentNormalizedDoubled = lodEnvironmentNormalized * 2.0;
+
+            vec3 environmentSpecularMid = sampleEnvironment(environmentSampler, environmentCoords).rgb;
+            if(lodEnvironmentNormalizedDoubled < 1.0){
+                environmentColor = mix(
+                    sampleEnvironment(environmentSamplerHigh, environmentCoords).rgb,
+                    environmentSpecularMid,
+                    lodEnvironmentNormalizedDoubled
+                );
+            } else {
+                environmentColor = mix(
+                    environmentSpecularMid,
+                    sampleEnvironment(environmentSamplerLow, environmentCoords).rgb,
+                    lodEnvironmentNormalizedDoubled - 1.0
+                );
+            }
+        #endif
+    #else
+        environmentColor = sampleEnvironment(environmentSampler, environmentCoords).rgb;
+    #endif
+
+    #ifdef GAMMAENVIRONMENT
+        environmentColor = toLinearSpace(environmentColor.rgb);
+    #endif
+
+    // _____________________________ Levels _____________________________________
+    environmentColor *= vEnvironmentInfo.x;
+
+    // _____________________________ Alpha Information _______________________________
+    #ifdef OPACITY
+        vec3 reflectEnvironmentColor = vec3(0., 0., 0.);
+        vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);
+
+        #ifdef OPACITYRGB
+            float environmentMix = getLuminance(opacityMap.rgb);
+        #else
+            float environmentMix = opacityMap.a;
+        #endif
+
+        environmentMix *= vOpacityInfo.y;
+
+        #ifdef OPACITYFRESNEL
+            // TODO. Change by camera forward Direction.
+            float viewAngleToFloor = dot(normalW, normalize(vEyePosition));
+
+            // Fade out the floor plane as the angle between the floor and the camera tends to 0 (starting from startAngle)
+            const float startAngle = 0.1;
+            float fadeFactor = clamp(viewAngleToFloor/startAngle, 0.0, 1.0);
+
+            environmentMix *= fadeFactor * fadeFactor;
+            shadow = mix(1., shadow, environmentMix);
+        #endif
+
+        // Cubic Fetch
+        vec3 viewDir = vPositionW.xyz - vEyePosition.xyz;
+        vec3 reflectEnvironmentCoords = reflect(viewDir, normalW);
+        #ifdef INVERTCUBICMAP
+            reflectEnvironmentCoords.y = 1.0 - reflectEnvironmentCoords.y;
+        #endif
+        // Rotate Environment
+        reflectEnvironmentCoords = vec3(environmentMatrix * vec4(reflectEnvironmentCoords, 0));
+
+        #ifdef ENVIRONMENTBLUR
+            #ifdef TEXTURELODSUPPORT
+                // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection
+                reflectEnvironmentColor = sampleEnvironmentLod(environmentSampler, reflectEnvironmentCoords, environmentLOD).rgb;
+            #else
+                vec3 reflectEnvironmentSpecularMid = sampleEnvironment(environmentSampler, reflectEnvironmentCoords).rgb;
+                if(lodEnvironmentNormalizedDoubled < 1.0){
+                    reflectEnvironmentColor = mix(
+                        sampleEnvironment(environmentSamplerHigh, reflectEnvironmentCoords).rgb,
+                        environmentSpecularMid,
+                        lodEnvironmentNormalizedDoubled
+                    );
+                } else {
+                    reflectEnvironmentColor = mix(
+                        environmentSpecularMid,
+                        sampleEnvironment(environmentSamplerLow, reflectEnvironmentCoords).rgb,
+                        lodEnvironmentNormalizedDoubled - 1.0
+                    );
+                }
+            #endif
+        #else
+            reflectEnvironmentColor = sampleEnvironment(environmentSampler, reflectEnvironmentCoords).rgb;
+        #endif
+
+        #ifdef GAMMAENVIRONMENT
+            reflectEnvironmentColor = toLinearSpace(reflectEnvironmentColor.rgb);
+        #endif
+
+        // _____________________________ Levels _____________________________________
+        reflectEnvironmentColor *= vEnvironmentInfo.x;
+
+        // _____________________________ MIX ________________________________________
+        environmentColor = mix(environmentColor, reflectEnvironmentColor, environmentMix);
+    #endif
+#else
+    vec3 environmentColor = vec3(1., 1., 1.);
+#endif
+
+// _____________________________ Composition ____________________________________
+#ifdef RGBENVIRONMENT
+    environmentColor = vec3(1., 1., 1.) * getLuminance(environmentColor);
+#endif
+
+    // Might think of conserving energy here.
+    vec3 colorBase = environmentColor.r * vPrimaryColor.rgb * vPrimaryColor.a;
+    colorBase += environmentColor.g * vSecondaryColor.rgb * vSecondaryColor.a;
+    colorBase += environmentColor.b * vThirdColor.rgb * vThirdColor.a;
+
+    colorBase = mix(colorBase * shadowLevel, colorBase, shadow);
+
+    vec4 color = vec4(colorBase, 1.0);
+
+#include<fogFragment>
+
+#ifdef IMAGEPROCESSINGPOSTPROCESS
+	// Sanitize output incase invalid normals or tangents have caused div by 0 or undefined behavior
+	// this also limits the brightness which helpfully reduces over-sparkling in bloom (native handles this in the bloom blur shader)
+	color.rgb = clamp(color.rgb, 0., 30.0);
+#else
+	// Alway run even to ensure going back to gamma space.
+	color = applyImageProcessing(color);
+#endif
+
+    gl_FragColor = color;
+}

+ 111 - 0
materialsLibrary/src/background/background.vertex.fx

@@ -0,0 +1,111 @@
+precision highp float;
+
+#include<__decl__backgroundVertex>
+
+// Attributes
+attribute vec3 position;
+#ifdef NORMAL
+attribute vec3 normal;
+#endif
+
+#include<bonesDeclaration>
+
+// Uniforms
+#include<instancesDeclaration>
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#ifdef MAINUV1
+varying vec2 vMainUV1;
+#endif
+#ifdef MAINUV2
+varying vec2 vMainUV2; 
+#endif
+
+#if defined(OPACITY) && OPACITYDIRECTUV == 0
+varying vec2 vOpacityUV;
+#endif
+
+#include<clipPlaneVertexDeclaration>
+
+#include<fogVertexDeclaration>
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
+
+void main(void) {
+
+#include<instancesVertex>
+#include<bonesVertex>
+
+	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef NORMAL
+	mat3 normalWorld = mat3(finalWorld);
+
+	#ifdef NONUNIFORMSCALING
+		normalWorld = transposeMat3(inverseMat3(normalWorld));
+	#endif
+
+	vNormalW = normalize(normalWorld * normal);
+#endif
+
+#ifndef UV1
+    vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+    vec2 uv2 = vec2(0., 0.);
+#endif
+
+#ifdef MAINUV1
+	vMainUV1 = uv;
+#endif 
+
+#ifdef MAINUV2
+	vMainUV2 = uv2;
+#endif
+
+#if defined(OPACITY) && OPACITYDIRECTUV == 0 
+    if (vOpacityInfo.x == 0.)
+    {
+        vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));
+    }
+#endif
+
+    // Clip plane
+#include<clipPlaneVertex>
+
+    // Fog
+#include<fogVertex>
+
+    // Shadows
+#include<shadowsVertex>[0..maxSimultaneousLights]
+
+    // Vertex color
+#ifdef VERTEXCOLOR
+    vColor = color;
+#endif
+
+    // Point size
+#ifdef POINTSIZE
+    gl_PointSize = pointSize;
+#endif
+}

+ 14 - 0
materialsLibrary/src/background/backgroundFragmentDeclaration.fx

@@ -0,0 +1,14 @@
+    uniform vec4 vPrimaryColor;
+    uniform vec4 vSecondaryColor;
+    uniform vec4 vThirdColor;
+    uniform float shadowLevel;
+
+#ifdef OPACITY
+    uniform vec2 vOpacityInfo;
+#endif
+
+#ifdef ENVIRONMENT
+    uniform vec2 vEnvironmentInfo;
+    uniform mat4 environmentMatrix;
+    uniform vec3 vEnvironmentMicrosurfaceInfos;
+#endif

+ 21 - 0
materialsLibrary/src/background/backgroundUboDeclaration.fx

@@ -0,0 +1,21 @@
+layout(std140, column_major) uniform;
+
+uniform Material
+{
+	uniform vec4 vPrimaryColor;
+	uniform vec4 vSecondaryColor;
+	uniform vec4 vThirdColor;
+	uniform vec2 vOpacityInfo;
+	uniform vec2 vEnvironmentInfo;
+	uniform mat4 opacityMatrix;
+	uniform mat4 environmentMatrix;
+	uniform vec3 vEnvironmentMicrosurfaceInfos;
+
+	uniform float pointSize;
+	uniform float shadowLevel;
+};
+
+uniform Scene {
+	mat4 viewProjection;
+	mat4 view;
+};

+ 18 - 0
materialsLibrary/src/background/backgroundVertexDeclaration.fx

@@ -0,0 +1,18 @@
+uniform mat4 view;
+uniform mat4 viewProjection;
+uniform float shadowLevel;
+
+#ifdef OPACITY
+uniform mat4 opacityMatrix;
+uniform vec2 vOpacityInfo;
+#endif
+
+#ifdef ENVIRONMENT
+uniform vec2 vEnvironmentInfo;
+uniform mat4 environmentMatrix;
+uniform vec3 vEnvionmentMicrosurfaceInfos;
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif

+ 118 - 0
materialsLibrary/test/addbackground.js

@@ -0,0 +1,118 @@
+window.prepareBackgroundMaterial = function() {
+	var back = new BABYLON.BackgroundMaterial("back", scene);
+	var backSky = new BABYLON.BackgroundMaterial("backSky", scene);
+	backSky.backFaceCulling = false;
+
+    var hdrTexture = new BABYLON.HDRCubeTexture("../assets/textures/hdr/environment.hdr", scene, 512);
+	back.environmentTexture = hdrTexture;
+	back.opacityTexture = new BABYLON.Texture("../assets/textures/amiga.jpg", scene);
+	back.opacityTexture.getAlphaFromRGB = true;
+	back.opacityTexture.uScale = 5;
+	back.opacityTexture.vScale = 5;
+	backSky.environmentTexture = hdrTexture;
+
+    // Skybox
+    backgroundSkybox = BABYLON.Mesh.CreateBox("hdrSkyBox", 1000.0, scene);
+	backgroundSkybox.material = backSky;
+	backgroundSkybox.setEnabled(false);
+	
+	registerRangeUI("background", "primaryColorR", 0, 1, function(value) {
+		back.primaryColor.r = value;
+		backSky.primaryColor.r = value;
+	}, function() {
+		return back.primaryColor.r;
+	});
+
+	registerRangeUI("background", "primaryColorG", 0, 1, function(value) {
+		back.primaryColor.g = value;
+		backSky.primaryColor.g = value;
+	}, function() {
+		return back.primaryColor.g;
+	});
+
+	registerRangeUI("background", "primaryColorB", 0, 1, function(value) {
+		back.primaryColor.b = value;
+		backSky.primaryColor.b = value;
+	}, function() {
+		return back.primaryColor.b;
+	});
+
+	registerRangeUI("background", "primaryLevel", 0, 30, function(value) {
+		back.primaryLevel = value;
+		backSky.primaryLevel = value;
+	}, function() {
+		return back.primaryLevel;
+	});
+
+	registerRangeUI("background", "secondaryColorR", 0, 1, function(value) {
+		back.secondaryColor.r = value;
+		backSky.secondaryColor.r = value;
+	}, function() {
+		return back.secondaryColor.r;
+	});
+
+	registerRangeUI("background", "secondaryColorG", 0, 1, function(value) {
+		back.secondaryColor.g = value;
+		backSky.secondaryColor.g = value;
+	}, function() {
+		return back.secondaryColor.g;
+	});
+
+	registerRangeUI("background", "secondaryColorB", 0, 1, function(value) {
+		back.secondaryColor.b = value;
+		backSky.secondaryColor.b = value;
+	}, function() {
+		return back.secondaryColor.b;
+	});
+
+	registerRangeUI("background", "secondaryLevel", 0, 30, function(value) {
+		back.secondaryLevel = value;
+		backSky.secondaryLevel = value;
+	}, function() {
+		return back.secondaryLevel;
+	});
+
+	registerRangeUI("background", "thirdColorR", 0, 1, function(value) {
+		back.thirdColor.r = value;
+		backSky.thirdColor.r = value;
+	}, function() {
+		return back.thirdColor.r;
+	});
+
+	registerRangeUI("background", "thirdColorG", 0, 1, function(value) {
+		back.thirdColor.g = value;
+		backSky.thirdColor.g = value;
+	}, function() {
+		return back.thirdColor.g;
+	});
+
+	registerRangeUI("background", "thirdColorB", 0, 1, function(value) {
+		back.thirdColor.b = value;
+		backSky.thirdColor.b = value;
+	}, function() {
+		return back.thirdColor.b;
+	});
+
+	registerRangeUI("background", "thirdLevel", 0, 30, function(value) {
+		back.thirdLevel = value;		
+		backSky.thirdLevel = value;
+	}, function() {
+		return back.thirdLevel;
+	});
+
+	registerRangeUI("background", "environmentBlur", 0, 1, function(value) {
+		back.environmentBlur = value;
+		backSky.environmentBlur = value;
+	}, function() {
+		return back.environmentBlur;
+	});
+
+	registerRangeUI("background", "shadowLevel", 0, 1, function(value) {
+		back.shadowLevel = value;
+		backSky.shadowLevel = value;
+	}, function() {
+		return back.shadowLevel;
+	});
+
+	return back;
+}

+ 19 - 17
src/Shaders/ShadersInclude/lightFragment.fx

@@ -1,5 +1,5 @@
 #ifdef LIGHT{X}
-    #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X})
+    #if defined(SHADOWONLY) || (defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X}))
         //No light calculation
     #else
 		#ifdef PBR
@@ -58,22 +58,24 @@
 		shadow = 1.;
 	#endif
 
-	#ifdef CUSTOMUSERLIGHTING
-		diffuseBase += computeCustomDiffuseLighting(info, diffuseBase, shadow);
-		#ifdef SPECULARTERM
-			specularBase += computeCustomSpecularLighting(info, specularBase, shadow);
+	#ifndef SHADOWONLY
+		#ifdef CUSTOMUSERLIGHTING
+			diffuseBase += computeCustomDiffuseLighting(info, diffuseBase, shadow);
+			#ifdef SPECULARTERM
+				specularBase += computeCustomSpecularLighting(info, specularBase, shadow);
+			#endif
+		#elif defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
+			diffuseBase += lightmapColor * shadow;
+			#ifdef SPECULARTERM
+				#ifndef LIGHTMAPNOSPECULAR{X}
+					specularBase += info.specular * shadow * lightmapColor;
+				#endif
+			#endif
+		#else
+			diffuseBase += info.diffuse * shadow;
+			#ifdef SPECULARTERM
+				specularBase += info.specular * shadow;
+			#endif
 		#endif
-    #elif defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
-	    diffuseBase += lightmapColor * shadow;
-	    #ifdef SPECULARTERM
-            #ifndef LIGHTMAPNOSPECULAR{X}
-                specularBase += info.specular * shadow * lightmapColor;
-            #endif
-        #endif
-    #else
-	    diffuseBase += info.diffuse * shadow;
-	    #ifdef SPECULARTERM
-		    specularBase += info.specular * shadow;
-	    #endif
 	#endif
 #endif