فهرست منبع

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

gleborgne 9 سال پیش
والد
کامیت
f89d69ac98
41فایلهای تغییر یافته به همراه48743 افزوده شده و 47627 حذف شده
  1. 22 31
      dist/preview release/babylon.core.js
  2. 794 726
      dist/preview release/babylon.d.ts
  3. 29 42
      dist/preview release/babylon.js
  4. 41604 41833
      dist/preview release/babylon.max.js
  5. 28 39
      dist/preview release/babylon.noworker.js
  6. 1 0
      dist/preview release/what's new.md
  7. 3 0
      materialsLibrary/config.json
  8. 183 28
      materialsLibrary/dist/babylon.pbrMaterial.js
  9. 3 3
      materialsLibrary/dist/babylon.pbrMaterial.min.js
  10. 168 6
      materialsLibrary/dist/dts/babylon.pbrMaterial.d.ts
  11. 13 1
      materialsLibrary/gulpfile.js
  12. 181 19
      materialsLibrary/materials/pbr/babylon.pbrMaterial.ts
  13. 18 0
      materialsLibrary/materials/pbr/includes/helperFunctions.fx
  14. 260 181
      materialsLibrary/materials/pbr/legacypbr.fragment.fx
  15. 0 4
      materialsLibrary/materials/pbr/legacypbr.vertex.fx
  16. 40 104
      materialsLibrary/materials/pbr/pbr.fragment.fx
  17. 4908 4546
      materialsLibrary/test/refs/babylon.max.js
  18. 9 0
      src/Animations/babylon.animation.js
  19. 11 0
      src/Animations/babylon.animation.ts
  20. 8 0
      src/Bones/babylon.skeleton.js
  21. 11 0
      src/Bones/babylon.skeleton.ts
  22. 28 1
      src/Cameras/VR/babylon.vrDeviceOrientationCamera.js
  23. 43 2
      src/Cameras/VR/babylon.vrDeviceOrientationCamera.ts
  24. 1 0
      src/Cameras/VR/babylon.webVRCamera.js
  25. 2 0
      src/Cameras/VR/babylon.webVRCamera.ts
  26. 1 0
      src/Cameras/babylon.camera.js
  27. 2 0
      src/Cameras/babylon.camera.ts
  28. 1 0
      src/Cameras/babylon.freeCamera.js
  29. 1 0
      src/Cameras/babylon.freeCamera.ts
  30. 29 1
      src/Materials/Textures/babylon.hdrCubeTexture.js
  31. 45 10
      src/Materials/Textures/babylon.hdrcubetexture.ts
  32. 11 0
      src/Tools/HDR/babylon.tools.cubemapToSphericalPolynomial.js
  33. 13 2
      src/Tools/HDR/babylon.tools.cubemaptosphericalpolynomial.ts
  34. 33 1
      src/Tools/HDR/babylon.tools.hdr.js
  35. 71 26
      src/Tools/HDR/babylon.tools.hdr.ts
  36. 12 0
      src/Tools/HDR/babylon.tools.panoramaToCubemap.js
  37. 51 0
      src/Tools/HDR/babylon.tools.panoramaToCubemap.ts
  38. 31 0
      src/Tools/HDR/babylon.tools.pmremgenerator.js
  39. 33 0
      src/Tools/HDR/babylon.tools.pmremgenerator.ts
  40. 20 10
      src/babylon.node.js
  41. 21 11
      src/babylon.node.ts

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 22 - 31
dist/preview release/babylon.core.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 794 - 726
dist/preview release/babylon.d.ts


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 29 - 42
dist/preview release/babylon.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 41604 - 41833
dist/preview release/babylon.max.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 28 - 39
dist/preview release/babylon.noworker.js


+ 1 - 0
dist/preview release/what's new.md

@@ -9,6 +9,7 @@
     - Animations blending. See [demo here](http://www.babylonjs-playground.com/#2BLI9T#3). More [info here](NEED DOC!) ([deltakosh](https://github.com/deltakosh))
     - New debuger tool: SkeletonViewer. See [demo here](Demo available here: http://www.babylonjs-playground.com/#1BZJVJ#8) (Adam & [deltakosh](https://github.com/deltakosh))
   - **Updates**
+    - Added Camera.ForceAttachControlToAlwaysPreventDefault to help embedding Babylon.js in iFrames ([deltakosh](https://github.com/deltakosh))
     - Support for Layer.alphaTest ([deltakosh](https://github.com/deltakosh))
     - New scene.pointerDownPredicate, scene.pointerMovePredicate, scene.pointerUpPredicate to define your own predicates for meshes picking selection ([deltakosh](https://github.com/deltakosh))
     - New OnPickTrigger support for spritesManager ([deltakosh](https://github.com/deltakosh))

+ 3 - 0
materialsLibrary/config.json

@@ -11,6 +11,9 @@
     },
     {
       "file": "materials/pbr/babylon.pbrMaterial.ts",
+      "referenceFiles": [
+        "materials/pbr/includes/helperFunctions.fx"  
+      ],
       "shaderFiles": [
         "materials/pbr/pbr.vertex.fx",
         "materials/pbr/pbr.fragment.fx",

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 183 - 28
materialsLibrary/dist/babylon.pbrMaterial.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3 - 3
materialsLibrary/dist/babylon.pbrMaterial.min.js


+ 168 - 6
materialsLibrary/dist/dts/babylon.pbrMaterial.d.ts

@@ -1,65 +1,221 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
+    /**
+     * The Physically based material of BJS.
+     *
+     * This offers the main features of a standard PBR material.
+     * For more information, please refer to the documentation :
+     * http://doc.babylonjs.com/extensions/Physically_Based_Rendering
+     */
     class PBRMaterial extends BABYLON.Material {
+        /**
+         * Intensity of the direct lights e.g. the four lights available in your scene.
+         * This impacts both the direct diffuse and specular highlights.
+         */
         directIntensity: number;
+        /**
+         * Intensity of the emissive part of the material.
+         * This helps controlling the emissive effect without modifying the emissive color.
+         */
         emissiveIntensity: number;
+        /**
+         * Intensity of the environment e.g. how much the environment will light the object
+         * either through harmonics for rough material or through the refelction for shiny ones.
+         */
         environmentIntensity: number;
+        /**
+         * This is a special control allowing the reduction of the specular highlights coming from the
+         * four lights of the scene. Those highlights may not be needed in full environment lighting.
+         */
         specularIntensity: number;
         private _lightingInfos;
+        /**
+         * Debug Control allowing disabling the bump map on this material.
+         */
+        disableBumpMap: boolean;
+        /**
+         * Debug Control helping enforcing or dropping the darkness of shadows.
+         * 1.0 means the shadows have their normal darkness, 0.0 means the shadows are not visible.
+         */
         overloadedShadowIntensity: number;
+        /**
+         * Debug Control helping dropping the shading effect coming from the diffuse lighting.
+         * 1.0 means the shade have their normal impact, 0.0 means no shading at all.
+         */
         overloadedShadeIntensity: number;
         private _overloadedShadowInfos;
+        /**
+         * 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: number;
+        /**
+         * The camera contrast used on this material.
+         * This property is here and not in the camera to allow controlling contrast without full screen post process.
+         */
         cameraContrast: number;
         private _cameraInfos;
         private _microsurfaceTextureLods;
+        /**
+         * Debug Control allowing to overload the ambient color.
+         * This as to be use with the overloadedAmbientIntensity parameter.
+         */
+        overloadedAmbient: Color3;
+        /**
+         * Debug Control indicating how much the overloaded ambient color is used against the default one.
+         */
         overloadedAmbientIntensity: number;
+        /**
+         * Debug Control allowing to overload the albedo color.
+         * This as to be use with the overloadedAlbedoIntensity parameter.
+         */
+        overloadedAlbedo: Color3;
+        /**
+         * Debug Control indicating how much the overloaded albedo color is used against the default one.
+         */
         overloadedAlbedoIntensity: number;
+        /**
+         * Debug Control allowing to overload the reflectivity color.
+         * This as to be use with the overloadedReflectivityIntensity parameter.
+         */
+        overloadedReflectivity: Color3;
+        /**
+         * Debug Control indicating how much the overloaded reflectivity color is used against the default one.
+         */
         overloadedReflectivityIntensity: number;
+        /**
+         * Debug Control allowing to overload the emissive color.
+         * This as to be use with the overloadedEmissiveIntensity parameter.
+         */
+        overloadedEmissive: Color3;
+        /**
+         * Debug Control indicating how much the overloaded emissive color is used against the default one.
+         */
         overloadedEmissiveIntensity: number;
         private _overloadedIntensity;
-        overloadedAmbient: Color3;
-        overloadedAlbedo: Color3;
-        overloadedReflectivity: Color3;
-        overloadedEmissive: Color3;
+        /**
+         * Debug Control allowing to overload the reflection color.
+         * This as to be use with the overloadedReflectionIntensity parameter.
+         */
         overloadedReflection: Color3;
+        /**
+         * Debug Control indicating how much the overloaded reflection color is used against the default one.
+         */
+        overloadedReflectionIntensity: number;
+        /**
+         * Debug Control allowing to overload the microsurface.
+         * This as to be use with the overloadedMicroSurfaceIntensity parameter.
+         */
         overloadedMicroSurface: number;
+        /**
+         * Debug Control indicating how much the overloaded microsurface is used against the default one.
+         */
         overloadedMicroSurfaceIntensity: number;
-        overloadedReflectionIntensity: number;
         private _overloadedMicroSurface;
-        disableBumpMap: boolean;
+        /**
+         * AKA Diffuse Texture in standard nomenclature.
+         */
         albedoTexture: BaseTexture;
+        /**
+         * AKA Occlusion Texture in other nomenclature.
+         */
         ambientTexture: BaseTexture;
         opacityTexture: BaseTexture;
         reflectionTexture: BaseTexture;
         emissiveTexture: BaseTexture;
+        /**
+         * AKA Specular texture in other nomenclature.
+         */
         reflectivityTexture: BaseTexture;
         bumpTexture: BaseTexture;
         lightmapTexture: BaseTexture;
         refractionTexture: BaseTexture;
         ambientColor: Color3;
+        /**
+         * AKA Diffuse Color in other nomenclature.
+         */
         albedoColor: Color3;
+        /**
+         * AKA Specular Color in other nomenclature.
+         */
         reflectivityColor: Color3;
         reflectionColor: Color3;
         emissiveColor: Color3;
+        /**
+         * AKA Glossiness in other nomenclature.
+         */
         microSurface: number;
+        /**
+         * source material index of refraction (IOR)' / 'destination material IOR.
+         */
         indexOfRefraction: number;
+        /**
+         * Controls if refraction needs to be inverted on Y. This could be usefull for procedural texture.
+         */
         invertRefractionY: boolean;
         opacityFresnelParameters: FresnelParameters;
         emissiveFresnelParameters: FresnelParameters;
+        /**
+         * This parameters will make the material used its opacity to control how much it is refracting aginst not.
+         * Materials half opaque for instance using refraction could benefit from this control.
+         */
         linkRefractionWithTransparency: boolean;
+        /**
+         * The emissive and albedo are linked to never be more than one (Energy conservation).
+         */
         linkEmissiveWithAlbedo: boolean;
         useLightmapAsShadowmap: boolean;
+        /**
+         * In this mode, the emissive informtaion will always be added to the lighting once.
+         * A light for instance can be thought as emissive.
+         */
         useEmissiveAsIllumination: boolean;
+        /**
+         * Secifies that the alpha is coming form the albedo channel alpha channel.
+         */
         useAlphaFromAlbedoTexture: boolean;
+        /**
+         * Specifies that the material will keeps the specular highlights over a transparent surface (only the most limunous ones).
+         * A car glass is a good exemple of that. When sun reflects on it you can not see what is behind.
+         */
         useSpecularOverAlpha: boolean;
+        /**
+         * Specifies if the reflectivity texture contains the glossiness information in its alpha channel.
+         */
         useMicroSurfaceFromReflectivityMapAlpha: boolean;
+        /**
+         * In case the reflectivity map does not contain the microsurface information in its alpha channel,
+         * The material will try to infer what glossiness each pixel should be.
+         */
         useAutoMicroSurfaceFromReflectivityMap: boolean;
+        /**
+         * Allows to work with scalar in linear mode. This is definitely a matter of preferences and tools used during
+         * the creation of the material.
+         */
         useScalarInLinearSpace: boolean;
+        /**
+         * BJS is using an harcoded light falloff based on a manually sets up range.
+         * In PBR, one way to represents the fallof is to use the inverse squared root algorythm.
+         * This parameter can help you switch back to the BJS mode in order to create scenes using both materials.
+         */
         usePhysicalLightFalloff: boolean;
+        /**
+         * Specifies that the material will keeps the reflection highlights over a transparent surface (only the most limunous ones).
+         * A car glass is a good exemple of that. When the street lights reflects on it you can not see what is behind.
+         */
         useRadianceOverAlpha: boolean;
+        /**
+         * Allows using the bump map in parallax mode.
+         */
         useParallax: boolean;
+        /**
+         * Allows using the bump map in parallax occlusion mode.
+         */
         useParallaxOcclusion: boolean;
+        /**
+         * Controls the scale bias of the parallax mode.
+         */
         parallaxScaleBias: number;
         disableLighting: boolean;
         private _renderTargets;
@@ -70,6 +226,12 @@ declare module BABYLON {
         private _defines;
         private _cachedDefines;
         private _useLogarithmicDepth;
+        /**
+         * Instantiates a new PBRMaterial instance.
+         *
+         * @param name The material name
+         * @param scene The scene the material will be use in.
+         */
         constructor(name: string, scene: Scene);
         useLogarithmicDepth: boolean;
         needAlphaBlending(): boolean;

+ 13 - 1
materialsLibrary/gulpfile.js

@@ -20,6 +20,10 @@ function shadersName(filename) {
       .replace('.fx', 'Shader');
 }
 
+function includeShadersName(filename) {
+    return filename.replace('.fx', '');
+}
+
 gulp.task('copyReference', function () {
     return gulp.src("../dist/preview release/babylon.max.js").pipe(gulp.dest("test/refs"));
 });
@@ -57,7 +61,15 @@ gulp.task('default', ["copyReference"], function () {
                 .pipe(uncommentShader())
                 .pipe(srcToVariable("BABYLON.Effect.ShadersStore", true, shadersName));
 
-        return merge2(js, shader)
+        if (!material.referenceFiles) {
+            material.referenceFiles = [];
+        }
+        
+        var includeShader = gulp.src(material.referenceFiles)
+            .pipe(uncommentShader())
+            .pipe(srcToVariable("BABYLON.Effect.IncludesShadersStore", true, includeShadersName));
+        
+        return merge2(js, shader, includeShader)
             .pipe(cleants())
             .pipe(replace(extendsSearchRegex, ""))
             .pipe(concat(material.output))

+ 181 - 19
materialsLibrary/materials/pbr/babylon.pbrMaterial.ts

@@ -102,33 +102,79 @@ module BABYLON {
         }
     }
 
+    /**
+     * The Physically based material of BJS.
+     * 
+     * This offers the main features of a standard PBR material.
+     * For more information, please refer to the documentation : 
+     * http://doc.babylonjs.com/extensions/Physically_Based_Rendering
+     */
     export class PBRMaterial extends BABYLON.Material {
 
+        /**
+         * Intensity of the direct lights e.g. the four lights available in your scene.
+         * This impacts both the direct diffuse and specular highlights.
+         */
         @serialize()
         public directIntensity: number = 1.0;
         
+        /**
+         * Intensity of the emissive part of the material.
+         * This helps controlling the emissive effect without modifying the emissive color.
+         */
         @serialize()
         public emissiveIntensity: number = 1.0;
         
+        /**
+         * Intensity of the environment e.g. how much the environment will light the object
+         * either through harmonics for rough material or through the refelction for shiny ones.
+         */
         @serialize()
         public environmentIntensity: number = 1.0;
         
+        /**
+         * This is a special control allowing the reduction of the specular highlights coming from the 
+         * four lights of the scene. Those highlights may not be needed in full environment lighting.
+         */
         @serialize()
         public specularIntensity: number = 1.0;
 
         private _lightingInfos: Vector4 = new Vector4(this.directIntensity, this.emissiveIntensity, this.environmentIntensity, this.specularIntensity);
+        
+        /**
+         * Debug Control allowing disabling the bump map on this material.
+         */
+        @serialize()
+        public disableBumpMap: boolean = false;
 
+        /**
+         * Debug Control helping enforcing or dropping the darkness of shadows.
+         * 1.0 means the shadows have their normal darkness, 0.0 means the shadows are not visible.
+         */
         @serialize()
         public overloadedShadowIntensity: number = 1.0;
         
+        /**
+         * Debug Control helping dropping the shading effect coming from the diffuse lighting.
+         * 1.0 means the shade have their normal impact, 0.0 means no shading at all.
+         */
         @serialize()
         public overloadedShadeIntensity: number = 1.0;
         
         private _overloadedShadowInfos: Vector4 = new Vector4(this.overloadedShadowIntensity, this.overloadedShadeIntensity, 0.0, 0.0);
 
+        /**
+         * 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.
+         */
         @serialize()
         public cameraExposure: number = 1.0;
         
+        /**
+         * The camera contrast used on this material.
+         * This property is here and not in the camera to allow controlling contrast without full screen post process.
+         */
         @serialize()
         public cameraContrast: number = 1.0;
         
@@ -136,52 +182,97 @@ module BABYLON {
 
         private _microsurfaceTextureLods: Vector2 = new Vector2(0.0, 0.0);
 
+        /**
+         * Debug Control allowing to overload the ambient color.
+         * This as to be use with the overloadedAmbientIntensity parameter.
+         */
+        @serializeAsColor3()
+        public overloadedAmbient: Color3 = BABYLON.Color3.White();
+
+        /**
+         * Debug Control indicating how much the overloaded ambient color is used against the default one.
+         */
         @serialize()
         public overloadedAmbientIntensity: number = 0.0;
         
+        /**
+         * Debug Control allowing to overload the albedo color.
+         * This as to be use with the overloadedAlbedoIntensity parameter.
+         */
+        @serializeAsColor3()
+        public overloadedAlbedo: Color3 = BABYLON.Color3.White();
+        
+        /**
+         * Debug Control indicating how much the overloaded albedo color is used against the default one.
+         */
         @serialize()
         public overloadedAlbedoIntensity: number = 0.0;
         
+        /**
+         * Debug Control allowing to overload the reflectivity color.
+         * This as to be use with the overloadedReflectivityIntensity parameter.
+         */
+        @serializeAsColor3()
+        public overloadedReflectivity: Color3 = BABYLON.Color3.White();
+        
+        /**
+         * Debug Control indicating how much the overloaded reflectivity color is used against the default one.
+         */
         @serialize()
         public overloadedReflectivityIntensity: number = 0.0;
         
+        /**
+         * Debug Control allowing to overload the emissive color.
+         * This as to be use with the overloadedEmissiveIntensity parameter.
+         */
+        @serializeAsColor3()
+        public overloadedEmissive: Color3 = BABYLON.Color3.White();
+        
+        /**
+         * Debug Control indicating how much the overloaded emissive color is used against the default one.
+         */
         @serialize()
         public overloadedEmissiveIntensity: number = 0.0;
         
         private _overloadedIntensity: Vector4 = new Vector4(this.overloadedAmbientIntensity, this.overloadedAlbedoIntensity, this.overloadedReflectivityIntensity, this.overloadedEmissiveIntensity);
-
-        @serializeAsColor3()
-        public overloadedAmbient: Color3 = BABYLON.Color3.White();
-        
-        @serializeAsColor3()
-        public overloadedAlbedo: Color3 = BABYLON.Color3.White();
-        
-        @serializeAsColor3()
-        public overloadedReflectivity: Color3 = BABYLON.Color3.White();
-        
-        @serializeAsColor3()
-        public overloadedEmissive: Color3 = BABYLON.Color3.White();
         
+        /**
+         * Debug Control allowing to overload the reflection color.
+         * This as to be use with the overloadedReflectionIntensity parameter.
+         */
         @serializeAsColor3()
         public overloadedReflection: Color3 = BABYLON.Color3.White();
+        
+        /**
+         * Debug Control indicating how much the overloaded reflection color is used against the default one.
+         */
+        @serialize()
+        public overloadedReflectionIntensity: number = 0.0;
 
+        /**
+         * Debug Control allowing to overload the microsurface.
+         * This as to be use with the overloadedMicroSurfaceIntensity parameter.
+         */
         @serialize()
         public overloadedMicroSurface: number = 0.0;
         
+        /**
+         * Debug Control indicating how much the overloaded microsurface is used against the default one.
+         */
         @serialize()
         public overloadedMicroSurfaceIntensity: number = 0.0;
         
-        @serialize()
-        public overloadedReflectionIntensity: number = 0.0;
-        
         private _overloadedMicroSurface: Vector3 = new Vector3(this.overloadedMicroSurface, this.overloadedMicroSurfaceIntensity, this.overloadedReflectionIntensity);
 
-        @serialize()
-        public disableBumpMap: boolean = false;
-
+        /**
+         * AKA Diffuse Texture in standard nomenclature.
+         */
         @serializeAsTexture()
         public albedoTexture: BaseTexture;
         
+        /**
+         * AKA Occlusion Texture in other nomenclature.
+         */
         @serializeAsTexture()
         public ambientTexture: BaseTexture;
         
@@ -194,6 +285,9 @@ module BABYLON {
         @serializeAsTexture()
         public emissiveTexture: BaseTexture;
         
+        /**
+         * AKA Specular texture in other nomenclature.
+         */
         @serializeAsTexture()
         public reflectivityTexture: BaseTexture;
         
@@ -209,9 +303,15 @@ module BABYLON {
         @serializeAsColor3("ambient")
         public ambientColor = new Color3(0, 0, 0);
         
+        /**
+         * AKA Diffuse Color in other nomenclature.
+         */
         @serializeAsColor3("albedo")
         public albedoColor = new Color3(1, 1, 1);
         
+        /**
+         * AKA Specular Color in other nomenclature.
+         */
         @serializeAsColor3("reflectivity")
         public reflectivityColor = new Color3(1, 1, 1);
         
@@ -221,12 +321,21 @@ module BABYLON {
         @serializeAsColor3("emissivie")
         public emissiveColor = new Color3(0, 0, 0);
         
+        /**
+         * AKA Glossiness in other nomenclature.
+         */
         @serialize()
-        public microSurface = 0.5;
+        public microSurface = 0.9;
         
+        /**
+         * source material index of refraction (IOR)' / 'destination material IOR.
+         */
         @serialize()
         public indexOfRefraction = 0.66;
         
+        /**
+         * Controls if refraction needs to be inverted on Y. This could be usefull for procedural texture.
+         */
         @serialize()
         public invertRefractionY = false;
         
@@ -236,45 +345,92 @@ module BABYLON {
         @serializeAsFresnelParameters()
         public emissiveFresnelParameters: FresnelParameters;
 
+        /**
+         * This parameters will make the material used its opacity to control how much it is refracting aginst not.
+         * Materials half opaque for instance using refraction could benefit from this control.
+         */
         @serialize()
         public linkRefractionWithTransparency = false;
         
+        /**
+         * The emissive and albedo are linked to never be more than one (Energy conservation).
+         */
         @serialize()
         public linkEmissiveWithAlbedo = false;
         
         @serialize()
         public useLightmapAsShadowmap = false;
         
+        /**
+         * In this mode, the emissive informtaion will always be added to the lighting once.
+         * A light for instance can be thought as emissive.
+         */
         @serialize()
         public useEmissiveAsIllumination = false;
         
+        /**
+         * Secifies that the alpha is coming form the albedo channel alpha channel.
+         */
         @serialize()
         public useAlphaFromAlbedoTexture = false;
         
+        /**
+         * Specifies that the material will keeps the specular highlights over a transparent surface (only the most limunous ones).
+         * A car glass is a good exemple of that. When sun reflects on it you can not see what is behind.
+         */
         @serialize()
         public useSpecularOverAlpha = true;
         
+        /**
+         * Specifies if the reflectivity texture contains the glossiness information in its alpha channel.
+         */
         @serialize()
         public useMicroSurfaceFromReflectivityMapAlpha = false;
         
+        /**
+         * In case the reflectivity map does not contain the microsurface information in its alpha channel,
+         * The material will try to infer what glossiness each pixel should be.
+         */
         @serialize()
         public useAutoMicroSurfaceFromReflectivityMap = false;
         
+        /**
+         * Allows to work with scalar in linear mode. This is definitely a matter of preferences and tools used during
+         * the creation of the material.
+         */
         @serialize()
         public useScalarInLinearSpace = false;
         
+        /**
+         * BJS is using an harcoded light falloff based on a manually sets up range.
+         * In PBR, one way to represents the fallof is to use the inverse squared root algorythm.
+         * This parameter can help you switch back to the BJS mode in order to create scenes using both materials.
+         */
         @serialize()
         public usePhysicalLightFalloff = true;
         
+        /**
+         * Specifies that the material will keeps the reflection highlights over a transparent surface (only the most limunous ones).
+         * A car glass is a good exemple of that. When the street lights reflects on it you can not see what is behind.
+         */
         @serialize()
         public useRadianceOverAlpha = true;
         
+        /**
+         * Allows using the bump map in parallax mode.
+         */
         @serialize()
         public useParallax = false;
 
+        /**
+         * Allows using the bump map in parallax occlusion mode.
+         */
         @serialize()
         public useParallaxOcclusion = false;
 
+        /**
+         * Controls the scale bias of the parallax mode.
+         */
         @serialize()
         public parallaxScaleBias = 0.05;
         
@@ -292,6 +448,12 @@ module BABYLON {
 
         private _useLogarithmicDepth: boolean;
 
+        /**
+         * Instantiates a new PBRMaterial instance.
+         * 
+         * @param name The material name
+         * @param scene The scene the material will be use in.
+         */
         constructor(name: string, scene: Scene) {
             super(name, scene);
 

+ 18 - 0
materialsLibrary/materials/pbr/includes/helperFunctions.fx

@@ -0,0 +1,18 @@
+// PBR HELPER METHODS
+float Square(float value)
+{
+    return value * value;
+}
+
+float getLuminance(vec3 color)
+{
+    return clamp(dot(color, vec3(0.2126, 0.7152, 0.0722)), 0., 1.);
+}
+
+float convertRoughnessToAverageSlope(float roughness)
+{
+    // Calculate AlphaG as square of roughness; add epsilon to avoid numerical issues
+    const float kMinimumVariance = 0.0005;
+    float alphaG = Square(roughness) + kMinimumVariance;
+    return alphaG;
+}

+ 260 - 181
materialsLibrary/materials/pbr/legacypbr.fragment.fx

@@ -8,6 +8,7 @@ uniform vec3 vEyePosition;
 uniform vec3 vAmbientColor;
 uniform vec4 vAlbedoColor;
 uniform vec3 vReflectionColor;
+uniform vec4 vLightRadiuses;
 
 // CUSTOM CONTROLS
 uniform vec4 vLightingIntensity;
@@ -29,24 +30,33 @@ uniform vec4 vOverloadedShadowIntensity;
 
 // PBR CUSTOM CONSTANTS
 const float kPi = 3.1415926535897932384626433832795;
+const float kRougnhessToAlphaScale = 0.1;
+const float kRougnhessToAlphaOffset = 0.29248125;
 
-// PBR HELPER METHODS
-float Square(float value)
-{
-    return value * value;
-}
+#include<helperFunctions>
 
-float getLuminance(vec3 color)
+// Based on Beckamm roughness to Blinn exponent + http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html 
+float getMipMapIndexFromAverageSlope(float maxMipLevel, float alpha)
 {
-    return clamp(dot(color, vec3(0.2126, 0.7152, 0.0722)), 0., 1.);
+    // do not take in account lower mips hence -1... and wait from proper preprocess.
+    // formula comes from approximation of the mathematical solution.
+    //float mip = maxMipLevel + kRougnhessToAlphaOffset + 0.5 * log2(alpha);
+    
+    // In the mean time 
+    // Always [0..1] goes from max mip to min mip in a log2 way.  
+    // Change 5 to nummip below.
+    // http://www.wolframalpha.com/input/?i=x+in+0..1+plot+(+5+%2B+0.3+%2B+0.1+*+5+*+log2(+(1+-+x)+*+(1+-+x)+%2B+0.0005))
+    float mip = kRougnhessToAlphaOffset + maxMipLevel + (maxMipLevel * kRougnhessToAlphaScale * log2(alpha));
+    
+    return clamp(mip, 0., maxMipLevel);
 }
 
-float convertRoughnessToAverageSlope(float roughness)
+float getMipMapIndexFromAverageSlopeWithPMREM(float maxMipLevel, float alphaG)
 {
-    // Calculate AlphaG as square of roughness; add epsilon to avoid numerical issues
-    const float kMinimumVariance = 0.0005;
-    float alphaG = Square(roughness) + kMinimumVariance;
-    return alphaG;
+    float specularPower = clamp(2. / alphaG - 2., 0.000001, 2048.);
+    
+    // Based on CubeMapGen for cosine power with 2048 spec default and 0.25 dropoff 
+    return clamp(- 0.5 * log2(specularPower) + 5.5, 0., maxMipLevel);
 }
 
 // From Microfacet Models for Refraction through Rough Surfaces, Walter et al. 2007
@@ -96,7 +106,7 @@ vec3 computeSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, flo
     vec3 fresnel = fresnelSchlickGGX(VdotH, specularColor, vec3(1., 1., 1.));
 
     float specTerm = max(0., visibility * distribution) * NdotL;
-    return fresnel * specTerm;
+    return fresnel * specTerm * kPi; // TODO: audit pi constants
 }
 
 float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness)
@@ -110,19 +120,29 @@ float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness)
         (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) *
         (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNV);
 
+
     return diffuseFresnelTerm * NdotL;
+    // PI Test
+    // diffuseFresnelTerm /= kPi;
+}
+
+float adjustRoughnessFromLightProperties(float roughness, float lightRadius, float lightDistance)
+{
+    // At small angle this approximation works. 
+    float lightRoughness = lightRadius / lightDistance;
+    // Distribution can sum.
+    float totalRoughness = clamp(lightRoughness + roughness, 0., 1.);
+    return totalRoughness;
 }
 
 float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
 {
-    if (microSurface == 0.)
-    {
-        float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
+    float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
+
+    float reflectivityLuminance = getLuminance(reflectivityColor);
+    float reflectivityLuma = sqrt(reflectivityLuminance);
+    microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
 
-        float reflectivityLuminance = getLuminance(reflectivityColor);
-        float reflectivityLuma = sqrt(reflectivityLuminance);
-        microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
-    }
     return microSurface;
 }
 
@@ -136,6 +156,17 @@ vec3 toGammaSpace(vec3 color)
     return vec3(pow(color.r, 1.0 / 2.2), pow(color.g, 1.0 / 2.2), pow(color.b, 1.0 / 2.2));
 }
 
+float computeLightFalloff(vec3 lightOffset, float lightDistanceSquared, float range)
+{
+    #ifdef USEPHYSICALLIGHTFALLOFF
+        float lightDistanceFalloff = 1.0 / ((lightDistanceSquared + 0.0001));
+        return lightDistanceFalloff;
+    #else
+        float lightFalloff = max(0., 1.0 - length(lightOffset) / range);
+        return lightFalloff;
+    #endif
+}
+
 #ifdef CAMERATONEMAP
     vec3 toneMaps(vec3 color)
     {
@@ -145,6 +176,8 @@ vec3 toGammaSpace(vec3 color)
         color.rgb = color.rgb * vCameraInfos.x;
 
         float tuning = 1.5; // TODO: sync up so e.g. 18% greys are matched to exposure appropriately
+        // PI Test
+        // tuning *=  kPi;
         vec3 tonemapped = 1.0 - exp2(-color.rgb * tuning); // simple local photographic tonemapper
         color.rgb = mix(color.rgb, tonemapped, 1.0);
         return color;
@@ -242,26 +275,36 @@ struct lightingInfo
 #endif
 };
 
-lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV) {
+lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius, out float NdotL) {
     lightingInfo result;
 
-    vec3 lightVectorW;
+    vec3 lightDirection;
     float attenuation = 1.0;
+    float lightDistance;
+    
+    // Point
     if (lightData.w == 0.)
     {
-        vec3 direction = lightData.xyz - vPositionW;
-
-        attenuation = max(0., 1.0 - length(direction) / range);
-        lightVectorW = normalize(direction);
+        vec3 lightOffset = lightData.xyz - vPositionW;
+        float lightDistanceSquared = dot(lightOffset, lightOffset);
+        attenuation = computeLightFalloff(lightOffset, lightDistanceSquared, range);
+        
+        lightDistance = sqrt(lightDistanceSquared);
+        lightDirection = normalize(lightOffset);
     }
+    // Directional
     else
     {
-        lightVectorW = normalize(-lightData.xyz);
+        lightDistance = length(-lightData.xyz);
+        lightDirection = normalize(-lightData.xyz);
     }
-
+    
+    // Roughness
+    roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
+    
     // diffuse
-    vec3 H = normalize(viewDirectionW + lightVectorW);
-    float NdotL = max(0.00000000001, dot(vNormal, lightVectorW));
+    vec3 H = normalize(viewDirectionW + lightDirection);
+    NdotL = max(0.00000000001, dot(vNormal, lightDirection));
     float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
 
     float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
@@ -272,42 +315,50 @@ lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData,
     float NdotH = max(0.00000000001, dot(vNormal, H));
 
     vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
-    result.specular = specTerm * specularColor * attenuation;
+    result.specular = specTerm * attenuation;
 #endif
 
     return result;
 }
 
-lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV) {
+lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius, out float NdotL) {
     lightingInfo result;
 
-    vec3 direction = lightData.xyz - vPositionW;
-    vec3 lightVectorW = normalize(direction);
-    float attenuation = max(0., 1.0 - length(direction) / range);
+    vec3 lightOffset = lightData.xyz - vPositionW;
+    vec3 lightVectorW = normalize(lightOffset);
 
     // diffuse
-    float cosAngle = max(0.0000001, dot(-lightDirection.xyz, lightVectorW));
-    float spotAtten = 0.0;
-
+    float cosAngle = max(0.000000000000001, dot(-lightDirection.xyz, lightVectorW));
+    
     if (cosAngle >= lightDirection.w)
     {
         cosAngle = max(0., pow(cosAngle, lightData.w));
-        spotAtten = clamp((cosAngle - lightDirection.w) / (1. - cosAngle), 0.0, 1.0);
-
+        
+        // Inverse squared falloff.
+        float lightDistanceSquared = dot(lightOffset, lightOffset);
+        float attenuation = computeLightFalloff(lightOffset, lightDistanceSquared, range);
+        
+        // Directional falloff.
+        attenuation *= cosAngle;
+        
+        // Roughness.
+        float lightDistance = sqrt(lightDistanceSquared);
+        roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
+        
         // Diffuse
         vec3 H = normalize(viewDirectionW - lightDirection.xyz);
-        float NdotL = max(0.00000000001, dot(vNormal, -lightDirection.xyz));
+        NdotL = max(0.00000000001, dot(vNormal, -lightDirection.xyz));
         float VdotH = clamp(dot(viewDirectionW, H), 0.00000000001, 1.0);
 
         float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
-        result.diffuse = diffuseTerm * diffuseColor * attenuation * spotAtten;
+        result.diffuse = diffuseTerm * diffuseColor * attenuation;
 
 #ifdef SPECULARTERM
         // Specular
         float NdotH = max(0.00000000001, dot(vNormal, H));
 
         vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
-        result.specular = specTerm * specularColor * attenuation * spotAtten;
+        result.specular = specTerm  * attenuation;
 #endif
 
         return result;
@@ -321,24 +372,26 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
     return result;
 }
 
-lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float roughness, float NdotV) {
+lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float roughness, float NdotV, float lightRadius, out float NdotL) {
     lightingInfo result;
 
-    vec3 lightVectorW = normalize(lightData.xyz);
+    // Roughness
+    // Do not touch roughness on hemispheric.
 
     // Diffuse
-    float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
-    result.diffuse = mix(groundColor, diffuseColor, ndl);
+    NdotL = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+    result.diffuse = mix(groundColor, diffuseColor, NdotL);
 
 #ifdef SPECULARTERM
     // Specular
+    vec3 lightVectorW = normalize(lightData.xyz);
     vec3 H = normalize(viewDirectionW + lightVectorW);
     float NdotH = max(0.00000000001, dot(vNormal, H));
-    float NdotL = max(0.00000000001, ndl);
+    NdotL = max(0.00000000001, NdotL);
     float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
 
     vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
-    result.specular = specTerm * specularColor;
+    result.specular = specTerm;
 #endif
 
     return result;
@@ -350,74 +403,81 @@ void main(void) {
     vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
 
     // Base color
-    vec4 baseColor = vec4(1., 1., 1., 1.);
-    vec3 diffuseColor = vAlbedoColor.rgb;
+    vec4 surfaceAlbedo = vec4(1., 1., 1., 1.);
+    vec3 surfaceAlbedoContribution = vAlbedoColor.rgb;
     
     // Alpha
     float alpha = vAlbedoColor.a;
 
-#ifdef ALBEDO
-    baseColor = texture2D(diffuseSampler, vAlbedoUV);
-    baseColor = vec4(toLinearSpace(baseColor.rgb), baseColor.a);
+    #ifdef ALBEDO
+        surfaceAlbedo = texture2D(albedoSampler, vAlbedoUV);
+        surfaceAlbedo = vec4(toLinearSpace(surfaceAlbedo.rgb), surfaceAlbedo.a);
 
-#ifdef ALPHATEST
-    if (baseColor.a < 0.4)
-        discard;
-#endif
+        #ifdef ALPHATEST
+            if (baseColor.a < 0.4)
+                discard;
+        #endif
 
-#ifdef ALPHAFROMALBEDO
-    alpha *= baseColor.a;
-#endif
+        #ifdef ALPHAFROMALBEDO
+            alpha *= surfaceAlbedo.a;
+        #endif
 
-    baseColor.rgb *= vAlbedoInfos.y;
-#endif
+        surfaceAlbedo.rgb *= vAlbedoInfos.y;
+    #else
+        // No Albedo texture.
+        surfaceAlbedo.rgb = surfaceAlbedoContribution;
+        surfaceAlbedoContribution = vec3(1., 1., 1.);
+    #endif
 
-#ifdef VERTEXCOLOR
-    baseColor.rgb *= vColor.rgb;
-#endif
+    #ifdef VERTEXCOLOR
+        baseColor.rgb *= vColor.rgb;
+    #endif
 
-#ifdef OVERLOADEDVALUES
-    baseColor.rgb = mix(baseColor.rgb, vOverloadedAlbedo, vOverloadedIntensity.y);
-    albedoColor.rgb = mix(albedoColor.rgb, vOverloadedAlbedo, vOverloadedIntensity.y);
-#endif
+    #ifdef OVERLOADEDVALUES
+        surfaceAlbedo.rgb = mix(surfaceAlbedo.rgb, vOverloadedAlbedo, vOverloadedIntensity.y);
+    #endif
 
     // Bump
-#ifdef NORMAL
-    vec3 normalW = normalize(vNormalW);
-#else
-    vec3 normalW = vec3(1.0, 1.0, 1.0);
-#endif
+    #ifdef NORMAL
+        vec3 normalW = normalize(vNormalW);
+    #else
+        vec3 normalW = vec3(1.0, 1.0, 1.0);
+    #endif
 
     // Ambient color
-    vec3 baseAmbientColor = vec3(1., 1., 1.);
+    vec3 ambientColor = vec3(1., 1., 1.);
 
-#ifdef AMBIENT
-    baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;
-    #ifdef OVERLOADEDVALUES
-        baseAmbientColor.rgb = mix(baseAmbientColor.rgb, vOverloadedAmbient, vOverloadedIntensity.x);
+    #ifdef AMBIENT
+        ambientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;
+        
+        #ifdef OVERLOADEDVALUES
+            ambientColor.rgb = mix(ambientColor.rgb, vOverloadedAmbient, vOverloadedIntensity.x);
+        #endif
     #endif
-#endif
 
     // Reflectivity map
     float microSurface = vReflectivityColor.a;
-    vec3 reflectivityColor = vReflectivityColor.rgb;
-
+    vec3 surfaceReflectivityColor = vReflectivityColor.rgb;
+    
     #ifdef OVERLOADEDVALUES
-        reflectivityColor.rgb = mix(reflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
+        surfaceReflectivityColor.rgb = mix(surfaceReflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
     #endif
 
     #ifdef REFLECTIVITY
-            vec4 reflectivityMapColor = texture2D(reflectivitySampler, vReflectivityUV);
-            reflectivityColor = toLinearSpace(reflectivityMapColor.rgb);
+        vec4 surfaceReflectivityColorMap = texture2D(reflectivitySampler, vReflectivityUV);
+        surfaceReflectivityColor = surfaceReflectivityColorMap.rgb;
+        surfaceReflectivityColor = toLinearSpace(surfaceReflectivityColor);
 
         #ifdef OVERLOADEDVALUES
-                reflectivityColor.rgb = mix(reflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
+            surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
         #endif
 
         #ifdef MICROSURFACEFROMREFLECTIVITYMAP
-            microSurface = reflectivityMapColor.a;
+            microSurface = surfaceReflectivityColorMap.a;
         #else
-            microSurface = computeDefaultMicroSurface(microSurface, reflectivityColor);
+            #ifdef MICROSURFACEAUTOMATIC
+                microSurface = computeDefaultMicroSurface(microSurface, surfaceReflectivityColor);
+            #endif
         #endif
     #endif
 
@@ -425,53 +485,52 @@ void main(void) {
         microSurface = mix(microSurface, vOverloadedMicroSurface.x, vOverloadedMicroSurface.y);
     #endif
 
-    // Apply Energy Conservation taking in account the environment level only if the environment is present.
-    float reflectance = max(max(reflectivityColor.r, reflectivityColor.g), reflectivityColor.b);
-    baseColor.rgb = (1. - reflectance) * baseColor.rgb;
-
-    // Compute Specular Fresnel + Reflectance.
+    // Compute N dot V.
     float NdotV = max(0.00000000001, dot(normalW, viewDirectionW));
 
     // Adapt microSurface.
     microSurface = clamp(microSurface, 0., 1.) * 0.98;
 
-    // Call rough to not conflict with previous one.
-    float rough = clamp(1. - microSurface, 0.000001, 1.0);
-
+    // Compute roughness.
+    float roughness = clamp(1. - microSurface, 0.000001, 1.0);
+    
     // Lighting
-    vec3 diffuseBase = vec3(0., 0., 0.);
+    vec3 lightDiffuseContribution = vec3(0., 0., 0.);
 
 #ifdef OVERLOADEDSHADOWVALUES
-    vec3 shadowedOnlyDiffuseBase = vec3(1., 1., 1.);
+    vec3 shadowedOnlyLightDiffuseContribution = vec3(1., 1., 1.);
 #endif
 
 #ifdef SPECULARTERM
-    vec3 specularBase = vec3(0., 0., 0.);
+    vec3 lightSpecularContribution= vec3(0., 0., 0.);
 #endif
-    float shadow = 1.;
+    float notShadowLevel = 1.; // 1 - shadowLevel
+    float NdotL = -1.;
 
 #ifdef LIGHT0
 #ifndef SPECULARTERM
     vec3 vLightSpecular0 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT0
-    lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, rough, NdotV);
+    lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0], NdotL);
 #endif
 #ifdef HEMILIGHT0
-    lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, rough, NdotV);
+    lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, roughness, NdotV, vLightRadiuses[0], NdotL);
 #endif
 #if defined(POINTLIGHT0) || defined(DIRLIGHT0)
-    lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, rough, NdotV);
+    lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0], NdotL);
 #endif
-
-    shadow = 1.;
-    diffuseBase += info.diffuse * shadow;
+    notShadowLevel = 1.;
+    lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
-    shadowedOnlyDiffuseBase *= shadow;
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
+    shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
-
 #ifdef SPECULARTERM
-    specularBase += info.specular * shadow;
+    lightSpecularContribution += info.specular * notShadowLevel;
 #endif
 #endif
 
@@ -480,23 +539,26 @@ void main(void) {
     vec3 vLightSpecular1 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT1
-    info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, rough, NdotV);
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1], NdotL);
 #endif
 #ifdef HEMILIGHT1
-    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1, rough, NdotV);
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1, roughness, NdotV, vLightRadiuses[1], NdotL);
 #endif
 #if defined(POINTLIGHT1) || defined(DIRLIGHT1)
-    info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, rough, NdotV);
+    info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1], NdotL);
 #endif
-
-    shadow = 1.;
-    diffuseBase += info.diffuse * shadow;
+    notShadowLevel = 1.;
+    lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
-    shadowedOnlyDiffuseBase *= shadow;
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
+    shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
 
 #ifdef SPECULARTERM
-    specularBase += info.specular * shadow;
+    lightSpecularContribution += info.specular * notShadowLevel;
 #endif
 #endif
 
@@ -505,23 +567,26 @@ void main(void) {
     vec3 vLightSpecular2 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT2
-    info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, rough, NdotV);
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2], NdotL);
 #endif
 #ifdef HEMILIGHT2
-    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, rough, NdotV);
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, roughness, NdotV, vLightRadiuses[2], NdotL);
 #endif
 #if defined(POINTLIGHT2) || defined(DIRLIGHT2)
-    info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, rough, NdotV);
+    info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2], NdotL);
 #endif
-
-    shadow = 1.;
-    diffuseBase += info.diffuse * shadow;
+    notShadowLevel = 1.;
+    lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
-    shadowedOnlyDiffuseBase *= shadow;
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
+    shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
 
 #ifdef SPECULARTERM
-    specularBase += info.specular * shadow;
+    lightSpecularContribution += info.specular * notShadowLevel;
 #endif
 #endif
 
@@ -530,53 +595,43 @@ void main(void) {
     vec3 vLightSpecular3 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT3
-    info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, rough, NdotV);
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3], NdotL);
 #endif
 #ifdef HEMILIGHT3
-    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, rough, NdotV);
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, roughness, NdotV, vLightRadiuses[3], NdotL);
 #endif
 #if defined(POINTLIGHT3) || defined(DIRLIGHT3)
-    info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, rough, NdotV);
+    info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3], NdotL);
 #endif
 
-    shadow = 1.;
-    diffuseBase += info.diffuse * shadow;
+    notShadowLevel = 1.;
+    lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
-    shadowedOnlyDiffuseBase *= shadow;
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
+    shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
 
 #ifdef SPECULARTERM
-    specularBase += info.specular * shadow;
+    lightSpecularContribution += info.specular * notShadowLevel;
 #endif
 #endif
 
-// Reflection
-vec3 reflectionColor = vReflectionColor.rgb;
-vec3 ambientReflectionColor = vReflectionColor.rgb;
-
-reflectionColor *= vLightingIntensity.z;
-ambientReflectionColor *= vLightingIntensity.z;
-
-// Compute reflection reflectivity fresnel
-vec3 reflectivityEnvironmentR0 = reflectivityColor.rgb;
-vec3 reflectivityEnvironmentR90 = vec3(1.0, 1.0, 1.0);
-vec3 reflectivityEnvironmentReflectanceViewer = FresnelSchlickEnvironmentGGX(clamp(NdotV, 0., 1.), reflectivityEnvironmentR0, reflectivityEnvironmentR90, sqrt(microSurface));
-reflectionColor *= reflectivityEnvironmentReflectanceViewer;
-
-#ifdef OVERLOADEDVALUES
-    ambientReflectionColor = mix(ambientReflectionColor, vOverloadedReflection, vOverloadedMicroSurface.z);
-    reflectionColor = mix(reflectionColor, vOverloadedReflection, vOverloadedMicroSurface.z);
+#ifdef SPECULARTERM
+    lightSpecularContribution *= vLightingIntensity.w;
 #endif
 
 #ifdef OPACITY
     vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);
 
-#ifdef OPACITYRGB
-    opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11);
-    alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;
-#else
-    alpha *= opacityMap.a * vOpacityInfos.y;
-#endif
+    #ifdef OPACITYRGB
+        opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11);
+        alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;
+    #else
+        alpha *= opacityMap.a * vOpacityInfos.y;
+    #endif
 
 #endif
 
@@ -584,75 +639,99 @@ reflectionColor *= reflectivityEnvironmentReflectanceViewer;
     alpha *= vColor.a;
 #endif
 
-    // Emissive
-    vec3 emissiveColor = vEmissiveColor;
+// Reflection
+vec3 environmentRadiance = vReflectionColor.rgb;
+vec3 environmentIrradiance = vReflectionColor.rgb;
+
+#ifdef OVERLOADEDVALUES
+    environmentIrradiance = mix(environmentIrradiance, vOverloadedReflection, vOverloadedMicroSurface.z);
+    environmentRadiance = mix(environmentRadiance, vOverloadedReflection, vOverloadedMicroSurface.z);
+#endif
+
+environmentRadiance *= vLightingIntensity.z;
+environmentIrradiance *= vLightingIntensity.z;
+
+// Compute reflection reflectivity fresnel
+vec3 specularEnvironmentR0 = surfaceReflectivityColor.rgb;
+vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0);
+vec3 specularEnvironmentReflectance = FresnelSchlickEnvironmentGGX(clamp(NdotV, 0., 1.), specularEnvironmentR0, specularEnvironmentR90, sqrt(microSurface));
+
+// Apply Energy Conservation taking in account the environment level only if the environment is present.
+float reflectance = max(max(surfaceReflectivityColor.r, surfaceReflectivityColor.g), surfaceReflectivityColor.b);
+surfaceAlbedo.rgb = (1. - reflectance) * surfaceAlbedo.rgb;
+environmentRadiance *= specularEnvironmentReflectance;
+
+// Emissive
+vec3 surfaceEmissiveColor = vEmissiveColor;
 #ifdef EMISSIVE
     vec3 emissiveColorTex = texture2D(emissiveSampler, vEmissiveUV).rgb;
-    emissiveColor = toLinearSpace(emissiveColorTex.rgb) * emissiveColor * vEmissiveInfos.y;
+    surfaceEmissiveColor = toLinearSpace(emissiveColorTex.rgb) * surfaceEmissiveColor * vEmissiveInfos.y;
 #endif
 
 #ifdef OVERLOADEDVALUES
-    emissiveColor = mix(emissiveColor, vOverloadedEmissive, vOverloadedIntensity.w);
+    surfaceEmissiveColor = mix(surfaceEmissiveColor, vOverloadedEmissive, vOverloadedIntensity.w);
 #endif
 
-    // Composition
+// Composition
 #ifdef EMISSIVEASILLUMINATION
-    vec3 finalDiffuse = max(diffuseBase * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
-
+    vec3 finalDiffuse = max(lightDiffuseContribution * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
+    
     #ifdef OVERLOADEDSHADOWVALUES
-        shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
+        shadowedOnlyLightDiffuseContribution = max(shadowedOnlyLightDiffuseContribution * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
     #endif
 #else
     #ifdef LINKEMISSIVEWITHALBEDO
-        vec3 finalDiffuse = max((diffuseBase + emissiveColor) * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
+        vec3 finalDiffuse = max((lightDiffuseContribution + surfaceEmissiveColor) * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
+
         #ifdef OVERLOADEDSHADOWVALUES
-                shadowedOnlyDiffuseBase = max((shadowedOnlyDiffuseBase + emissiveColor) * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
+            shadowedOnlyLightDiffuseContribution = max((shadowedOnlyLightDiffuseContribution + surfaceEmissiveColor) * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
         #endif
     #else
-        vec3 finalDiffuse = max(diffuseBase * albedoColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
+        vec3 finalDiffuse = max(lightDiffuseContribution * surfaceAlbedoContribution + surfaceEmissiveColor + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
+
         #ifdef OVERLOADEDSHADOWVALUES
-            shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * albedoColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
+            shadowedOnlyLightDiffuseContribution = max(shadowedOnlyLightDiffuseContribution * surfaceAlbedoContribution + surfaceEmissiveColor + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
         #endif
     #endif
 #endif
 
 #ifdef OVERLOADEDSHADOWVALUES
-      finalDiffuse = mix(finalDiffuse, shadowedOnlyDiffuseBase, (1.0 - vOverloadedShadowIntensity.y));
+    finalDiffuse = mix(finalDiffuse, shadowedOnlyLightDiffuseContribution, (1.0 - vOverloadedShadowIntensity.y));
 #endif
 
-// diffuse lighting from environment 0.2 replaces Harmonic...
-// Ambient Reflection already includes the environment intensity.
-finalDiffuse += baseColor.rgb * ambientReflectionColor * 0.2;
-
 #ifdef SPECULARTERM
-    vec3 finalSpecular = specularBase * reflectivityColor * vLightingIntensity.w;
+    vec3 finalSpecular = lightSpecularContribution * surfaceReflectivityColor;
 #else
     vec3 finalSpecular = vec3(0.0);
 #endif
 
 #ifdef SPECULAROVERALPHA
-    alpha = clamp(alpha + dot(finalSpecular, vec3(0.3, 0.59, 0.11)), 0., 1.);
+    alpha = clamp(alpha + getLuminance(finalSpecular), 0., 1.);
+#endif
+
+#ifdef RADIANCEOVERALPHA
+    alpha = clamp(alpha + getLuminance(environmentRadiance), 0., 1.);
 #endif
 
 // Composition
 // Reflection already includes the environment intensity.
 #ifdef EMISSIVEASILLUMINATION
-    vec4 color = vec4(finalDiffuse * baseAmbientColor * vLightingIntensity.x + finalSpecular * vLightingIntensity.x + reflectionColor + emissiveColor * vLightingIntensity.y, alpha);
+    vec4 finalColor = vec4(finalDiffuse * ambientColor * vLightingIntensity.x + surfaceAlbedo.rgb * environmentIrradiance + finalSpecular * vLightingIntensity.x + environmentRadiance + surfaceEmissiveColor * vLightingIntensity.y, alpha);
 #else
-    vec4 color = vec4(finalDiffuse * baseAmbientColor * vLightingIntensity.x + finalSpecular * vLightingIntensity.x + reflectionColor, alpha);
+    vec4 finalColor = vec4(finalDiffuse * ambientColor * vLightingIntensity.x + surfaceAlbedo.rgb * environmentIrradiance + finalSpecular * vLightingIntensity.x + environmentRadiance, alpha);
 #endif
 
-    color = max(color, 0.0);
+    finalColor = max(finalColor, 0.0);
 
 #ifdef CAMERATONEMAP
-    color.rgb = toneMaps(color.rgb);
+    finalColor.rgb = toneMaps(finalColor.rgb);
 #endif
 
-    color.rgb = toGammaSpace(color.rgb);
+    finalColor.rgb = toGammaSpace(finalColor.rgb);
 
 #ifdef CAMERACONTRAST
-    color = contrasts(color);
+    finalColor = contrasts(finalColor);
 #endif
 
-    gl_FragColor = color;
+    gl_FragColor = finalColor;
 }

+ 0 - 4
materialsLibrary/materials/pbr/legacypbr.vertex.fx

@@ -12,7 +12,6 @@ attribute vec2 uv2;
 #ifdef VERTEXCOLOR
 attribute vec4 color;
 #endif
-
 #include<bonesDeclaration>
 
 // Uniforms
@@ -65,9 +64,6 @@ void main(void) {
 
 #include<bonesVertex>
 
-    finalWorld = finalWorld * influence;
-#endif
-
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
 
 	vec4 worldPos = finalWorld * vec4(position, 1.0);

+ 40 - 104
materialsLibrary/materials/pbr/pbr.fragment.fx

@@ -81,80 +81,7 @@ const float kPi = 3.1415926535897932384626433832795;
 const float kRougnhessToAlphaScale = 0.1;
 const float kRougnhessToAlphaOffset = 0.29248125;
 
-#ifdef PoissonSamplingEnvironment
-    const int poissonSphereSamplersCount = 32;
-    vec3 poissonSphereSamplers[poissonSphereSamplersCount];
-
-    void initSamplers()
-    {
-        poissonSphereSamplers[0] = vec3( -0.552198926093, 0.801049753814, -0.0322487480415 );
-        poissonSphereSamplers[1] = vec3( 0.344874796559, -0.650989584719, 0.283038477033 ); 
-        poissonSphereSamplers[2] = vec3( -0.0710183703467, 0.163770497767, -0.95022416734 ); 
-        poissonSphereSamplers[3] = vec3( 0.422221832073, 0.576613638193, 0.519157625948 ); 
-        poissonSphereSamplers[4] = vec3( -0.561872200916, -0.665581249881, -0.131630473211 ); 
-        poissonSphereSamplers[5] = vec3( -0.409905973809, 0.0250731510778, 0.674676954809 ); 
-        poissonSphereSamplers[6] = vec3( 0.206829570551, -0.190199352704, 0.919073906156 ); 
-        poissonSphereSamplers[7] = vec3( -0.857514664463, 0.0274425010091, -0.475068738967 ); 
-        poissonSphereSamplers[8] = vec3( -0.816275009951, -0.0432916479141, 0.40394579291 ); 
-        poissonSphereSamplers[9] = vec3( 0.397976181928, -0.633227519667, -0.617794410447 ); 
-        poissonSphereSamplers[10] = vec3( -0.181484199014, 0.0155418272003, -0.34675720703 ); 
-        poissonSphereSamplers[11] = vec3( 0.591734926919, 0.489930882201, -0.51675303188 ); 
-        poissonSphereSamplers[12] = vec3( -0.264514973057, 0.834248662136, 0.464624235985 ); 
-        poissonSphereSamplers[13] = vec3( -0.125845223505, 0.812029586099, -0.46213797731 ); 
-        poissonSphereSamplers[14] = vec3( 0.0345715424639, 0.349983742938, 0.855109899027 ); 
-        poissonSphereSamplers[15] = vec3( 0.694340492749, -0.281052190209, -0.379600605543 ); 
-        poissonSphereSamplers[16] = vec3( -0.241055518078, -0.580199280578, 0.435381168431 );
-        poissonSphereSamplers[17] = vec3( 0.126313722289, 0.715113642744, 0.124385788055 ); 
-        poissonSphereSamplers[18] = vec3( 0.752862552387, 0.277075021888, 0.275059597549 );
-        poissonSphereSamplers[19] = vec3( -0.400896300918, -0.309374534321, -0.74285782627 ); 
-        poissonSphereSamplers[20] = vec3( 0.121843331941, -0.00381197918195, 0.322441835258 ); 
-        poissonSphereSamplers[21] = vec3( 0.741656771351, -0.472083016745, 0.14589173819 ); 
-        poissonSphereSamplers[22] = vec3( -0.120347565985, -0.397252703556, -0.00153836114051 ); 
-        poissonSphereSamplers[23] = vec3( -0.846258835203, -0.433763808754, 0.168732209784 ); 
-        poissonSphereSamplers[24] = vec3( 0.257765618362, -0.546470581239, -0.242234375624 ); 
-        poissonSphereSamplers[25] = vec3( -0.640343473361, 0.51920903395, 0.549310644325 ); 
-        poissonSphereSamplers[26] = vec3( -0.894309984621, 0.297394061018, 0.0884583225292 ); 
-        poissonSphereSamplers[27] = vec3( -0.126241933628, -0.535151016335, -0.440093659672 ); 
-        poissonSphereSamplers[28] = vec3( -0.158176440297, -0.393125021578, 0.890727226039 ); 
-        poissonSphereSamplers[29] = vec3( 0.896024272938, 0.203068725821, -0.11198597748 ); 
-        poissonSphereSamplers[30] = vec3( 0.568671758933, -0.314144243629, 0.509070768816 ); 
-        poissonSphereSamplers[31] = vec3( 0.289665332178, 0.104356977462, -0.348379247171 );
-    }
-
-    vec3 environmentSampler(samplerCube cubeMapSampler, vec3 centralDirection, float microsurfaceAverageSlope)
-    {
-        vec3 result = vec3(0., 0., 0.);
-        for(int i = 0; i < poissonSphereSamplersCount; i++)
-        {
-            vec3 offset = poissonSphereSamplers[i];
-            vec3 direction = centralDirection + microsurfaceAverageSlope * offset;
-            result += textureCube(cubeMapSampler, direction, 0.).rgb;
-        }
-
-        result /= 32.0;
-        return result;
-    }
-
-#endif
-
-// PBR HELPER METHODS
-float Square(float value)
-{
-    return value * value;
-}
-
-float getLuminance(vec3 color)
-{
-    return clamp(dot(color, vec3(0.2126, 0.7152, 0.0722)), 0., 1.);
-}
-
-float convertRoughnessToAverageSlope(float roughness)
-{
-    // Calculate AlphaG as square of roughness; add epsilon to avoid numerical issues
-    const float kMinimumVariance = 0.0005;
-    float alphaG = Square(roughness) + kMinimumVariance;
-    return alphaG;
-}
+#include<helperFunctions>
 
 // Based on Beckamm roughness to Blinn exponent + http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html 
 float getMipMapIndexFromAverageSlope(float maxMipLevel, float alpha)
@@ -628,7 +555,7 @@ struct lightingInfo
 #endif
 };
 
-lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius) {
+lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius, out float NdotL) {
     lightingInfo result;
 
     vec3 lightDirection;
@@ -657,7 +584,7 @@ lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData,
     
     // diffuse
     vec3 H = normalize(viewDirectionW + lightDirection);
-    float NdotL = max(0.00000000001, dot(vNormal, lightDirection));
+    NdotL = max(0.00000000001, dot(vNormal, lightDirection));
     float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
 
     float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
@@ -674,7 +601,7 @@ lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData,
     return result;
 }
 
-lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius) {
+lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius, out float NdotL) {
     lightingInfo result;
 
     vec3 lightOffset = lightData.xyz - vPositionW;
@@ -700,7 +627,7 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
         
         // Diffuse
         vec3 H = normalize(viewDirectionW - lightDirection.xyz);
-        float NdotL = max(0.00000000001, dot(vNormal, -lightDirection.xyz));
+        NdotL = max(0.00000000001, dot(vNormal, -lightDirection.xyz));
         float VdotH = clamp(dot(viewDirectionW, H), 0.00000000001, 1.0);
 
         float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
@@ -725,22 +652,22 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
     return result;
 }
 
-lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float roughness, float NdotV, float lightRadius) {
+lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float roughness, float NdotV, float lightRadius, out float NdotL) {
     lightingInfo result;
 
     // Roughness
     // Do not touch roughness on hemispheric.
 
     // Diffuse
-    float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
-    result.diffuse = mix(groundColor, diffuseColor, ndl);
+    NdotL = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+    result.diffuse = mix(groundColor, diffuseColor, NdotL);
 
 #ifdef SPECULARTERM
     // Specular
     vec3 lightVectorW = normalize(lightData.xyz);
     vec3 H = normalize(viewDirectionW + lightVectorW);
     float NdotH = max(0.00000000001, dot(vNormal, H));
-    float NdotL = max(0.00000000001, ndl);
+    NdotL = max(0.00000000001, NdotL);
     float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
 
     vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
@@ -753,10 +680,6 @@ lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4
 void main(void) {
 #include<clipPlaneFragment>
 
-    #ifdef PoissonSamplingEnvironment
-        initSamplers();
-    #endif
-
     vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
 
     // Albedo
@@ -816,7 +739,7 @@ void main(void) {
         #endif
     #endif
 
-    // Specular map
+    // Reflectivity map
     float microSurface = vReflectivityColor.a;
     vec3 surfaceReflectivityColor = vReflectivityColor.rgb;
     
@@ -830,7 +753,7 @@ void main(void) {
         surfaceReflectivityColor = toLinearSpace(surfaceReflectivityColor);
 
         #ifdef OVERLOADEDVALUES
-                surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
+            surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
         #endif
 
         #ifdef MICROSURFACEFROMREFLECTIVITYMAP
@@ -866,19 +789,20 @@ void main(void) {
     vec3 lightSpecularContribution= vec3(0., 0., 0.);
 #endif
     float notShadowLevel = 1.; // 1 - shadowLevel
+    float NdotL = -1.;
 
 #ifdef LIGHT0
 #ifndef SPECULARTERM
     vec3 vLightSpecular0 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT0
-    lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0]);
+    lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0], NdotL);
 #endif
 #ifdef HEMILIGHT0
-    lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, roughness, NdotV, vLightRadiuses[0]);
+    lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, roughness, NdotV, vLightRadiuses[0], NdotL);
 #endif
 #if defined(POINTLIGHT0) || defined(DIRLIGHT0)
-    lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0]);
+    lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0], NdotL);
 #endif
 #ifdef SHADOW0
 #ifdef SHADOWVSM0
@@ -903,6 +827,10 @@ void main(void) {
 #endif
     lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
     shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
 
@@ -916,13 +844,13 @@ void main(void) {
     vec3 vLightSpecular1 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT1
-    info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1]);
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1], NdotL);
 #endif
 #ifdef HEMILIGHT1
-    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1, roughness, NdotV, vLightRadiuses[1]);
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1, roughness, NdotV, vLightRadiuses[1], NdotL);
 #endif
 #if defined(POINTLIGHT1) || defined(DIRLIGHT1)
-    info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1]);
+    info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1], NdotL);
 #endif
 #ifdef SHADOW1
 #ifdef SHADOWVSM1
@@ -948,6 +876,10 @@ void main(void) {
 
     lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
     shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
 
@@ -961,13 +893,13 @@ void main(void) {
     vec3 vLightSpecular2 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT2
-    info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2]);
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2], NdotL);
 #endif
 #ifdef HEMILIGHT2
-    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, roughness, NdotV, vLightRadiuses[2]);
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, roughness, NdotV, vLightRadiuses[2], NdotL);
 #endif
 #if defined(POINTLIGHT2) || defined(DIRLIGHT2)
-    info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2]);
+    info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2], NdotL);
 #endif
 #ifdef SHADOW2
 #ifdef SHADOWVSM2
@@ -993,6 +925,10 @@ void main(void) {
 
     lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
     shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
 
@@ -1006,13 +942,13 @@ void main(void) {
     vec3 vLightSpecular3 = vec3(0.0);
 #endif
 #ifdef SPOTLIGHT3
-    info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3]);
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3], NdotL);
 #endif
 #ifdef HEMILIGHT3
-    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, roughness, NdotV, vLightRadiuses[3]);
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, roughness, NdotV, vLightRadiuses[3], NdotL);
 #endif
 #if defined(POINTLIGHT3) || defined(DIRLIGHT3)
-    info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3]);
+    info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3], NdotL);
 #endif
 #ifdef SHADOW3
 #ifdef SHADOWVSM3
@@ -1038,6 +974,10 @@ void main(void) {
 
     lightDiffuseContribution += info.diffuse * notShadowLevel;
 #ifdef OVERLOADEDSHADOWVALUES
+    if (NdotL < 0.000000000011)
+    {
+        notShadowLevel = 1.;
+    }
     shadowedOnlyLightDiffuseContribution *= notShadowLevel;
 #endif
 
@@ -1175,10 +1115,6 @@ vec3 environmentIrradiance = vReflectionColor.rgb;
         #else
             environmentRadiance = textureCube(reflectionCubeSampler, vReflectionUVW, biasReflection).rgb * vReflectionInfos.x;
         #endif
-        
-        #ifdef PoissonSamplingEnvironment
-            environmentRadiance = environmentSampler(reflectionCubeSampler, vReflectionUVW, alphaG) * vReflectionInfos.x;
-        #endif
 
         #ifdef USESPHERICALFROMREFLECTIONMAP
             #ifndef REFLECTIONMAP_SKYBOX

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4908 - 4546
materialsLibrary/test/refs/babylon.max.js


+ 9 - 0
src/Animations/babylon.animation.js

@@ -6,6 +6,9 @@ var BABYLON;
             this.from = from;
             this.to = to;
         }
+        AnimationRange.prototype.clone = function () {
+            return new AnimationRange(this.name, this.from, this.to);
+        };
         return AnimationRange;
     }());
     BABYLON.AnimationRange = AnimationRange;
@@ -234,6 +237,12 @@ var BABYLON;
             if (this._keys) {
                 clone.setKeys(this._keys);
             }
+            if (this._ranges) {
+                clone._ranges = {};
+                for (var name in this._ranges) {
+                    clone._ranges[name] = this._ranges[name].clone();
+                }
+            }
             return clone;
         };
         Animation.prototype.setKeys = function (values) {

+ 11 - 0
src/Animations/babylon.animation.ts

@@ -2,6 +2,10 @@
     export class AnimationRange {
         constructor(public name: string, public from: number, public to: number) {
         }
+
+        public clone(): AnimationRange {
+            return new AnimationRange(this.name, this.from, this.to);
+        }
     }
 
     /**
@@ -281,6 +285,13 @@
                 clone.setKeys(this._keys);
             }
 
+            if (this._ranges) {
+                clone._ranges = {};
+                for (var name in this._ranges) {
+                    clone._ranges[name] = this._ranges[name].clone();
+                }
+            }
+
             return clone;
         }
 

+ 8 - 0
src/Bones/babylon.skeleton.js

@@ -181,6 +181,7 @@ var BABYLON;
         };
         Skeleton.prototype.clone = function (name, id) {
             var result = new Skeleton(name, id || name, this._scene);
+            result.needInitialSkinMatrix = this.needInitialSkinMatrix;
             for (var index = 0; index < this.bones.length; index++) {
                 var source = this.bones[index];
                 var parentBone = null;
@@ -191,6 +192,13 @@ var BABYLON;
                 var bone = new BABYLON.Bone(source.name, result, parentBone, source.getBaseMatrix().clone(), source.getRestPose().clone());
                 BABYLON.Tools.DeepCopy(source.animations, bone.animations);
             }
+            if (this._ranges) {
+                result._ranges = {};
+                for (var rangeName in this._ranges) {
+                    result._ranges[rangeName] = this._ranges[rangeName].clone();
+                }
+            }
+            result.prepare();
             return result;
         };
         Skeleton.prototype.dispose = function () {

+ 11 - 0
src/Bones/babylon.skeleton.ts

@@ -218,6 +218,8 @@
         public clone(name: string, id: string): Skeleton {
             var result = new Skeleton(name, id || name, this._scene);
 
+            result.needInitialSkinMatrix = this.needInitialSkinMatrix;
+
             for (var index = 0; index < this.bones.length; index++) {
                 var source = this.bones[index];
                 var parentBone = null;
@@ -231,6 +233,15 @@
                 Tools.DeepCopy(source.animations, bone.animations);
             }
 
+            if (this._ranges) {
+                result._ranges = {};
+                for (var rangeName in this._ranges) {
+                    result._ranges[rangeName] = this._ranges[rangeName].clone();
+                }
+            }
+
+            result.prepare();
+
             return result;
         }
 

+ 28 - 1
src/Cameras/VR/babylon.vrDeviceOrientationCamera.js

@@ -10,11 +10,38 @@ var BABYLON;
         function VRDeviceOrientationFreeCamera(name, position, scene, compensateDistortion) {
             if (compensateDistortion === void 0) { compensateDistortion = true; }
             _super.call(this, name, position, scene);
-            this.inputs.addDeviceOrientation();
+            this._alpha = 0;
+            this._beta = 0;
+            this._gamma = 0;
             var metrics = BABYLON.VRCameraMetrics.GetDefault();
             metrics.compensateDistortion = compensateDistortion;
             this.setCameraRigMode(BABYLON.Camera.RIG_MODE_VR, { vrCameraMetrics: metrics });
+            this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
         }
+        VRDeviceOrientationFreeCamera.prototype._onOrientationEvent = function (evt) {
+            this._alpha = +evt.alpha | 0;
+            this._beta = +evt.beta | 0;
+            this._gamma = +evt.gamma | 0;
+            if (this._gamma < 0) {
+                this._gamma = 90 + this._gamma;
+            }
+            else {
+                // Incline it in the correct angle.
+                this._gamma = 270 - this._gamma;
+            }
+            this.rotation.x = this._gamma / 180.0 * Math.PI;
+            this.rotation.y = -this._alpha / 180.0 * Math.PI;
+            this.rotation.z = this._beta / 180.0 * Math.PI;
+        };
+        VRDeviceOrientationFreeCamera.prototype.attachControl = function (element, noPreventDefault) {
+            _super.prototype.attachControl.call(this, element, noPreventDefault);
+            noPreventDefault = BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
+            window.addEventListener("deviceorientation", this._deviceOrientationHandler);
+        };
+        VRDeviceOrientationFreeCamera.prototype.detachControl = function (element) {
+            _super.prototype.detachControl.call(this, element);
+            window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
+        };
         VRDeviceOrientationFreeCamera.prototype.getTypeName = function () {
             return "VRDeviceOrientationFreeCamera";
         };

+ 43 - 2
src/Cameras/VR/babylon.vrDeviceOrientationCamera.ts

@@ -1,11 +1,52 @@
 module BABYLON {
     export class VRDeviceOrientationFreeCamera extends FreeCamera {
+        public _alpha = 0;
+        public _beta = 0;
+        public _gamma = 0;
+    
+        private _offsetOrientation: { yaw: number; pitch: number; roll: number };
+        private _deviceOrientationHandler;
+
         constructor(name: string, position: Vector3, scene: Scene, compensateDistortion = true) {
             super(name, position, scene);
-            this.inputs.addDeviceOrientation();
+
             var metrics = VRCameraMetrics.GetDefault();
             metrics.compensateDistortion = compensateDistortion;
-            this.setCameraRigMode(Camera.RIG_MODE_VR, { vrCameraMetrics: metrics });            
+            this.setCameraRigMode(Camera.RIG_MODE_VR, { vrCameraMetrics: metrics });
+
+            this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
+        }
+
+        public _onOrientationEvent(evt: DeviceOrientationEvent): void {
+            this._alpha = +evt.alpha|0;
+            this._beta = +evt.beta|0;
+            this._gamma = +evt.gamma|0;
+
+            if (this._gamma < 0) {
+                this._gamma = 90 + this._gamma;
+            }
+            else {
+                // Incline it in the correct angle.
+                this._gamma = 270 - this._gamma;
+            }
+
+            this.rotation.x = this._gamma / 180.0 * Math.PI;   
+            this.rotation.y = -this._alpha / 180.0 * Math.PI;   
+            this.rotation.z = this._beta / 180.0 * Math.PI;     
+        }
+
+        public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
+            super.attachControl(element, noPreventDefault);
+
+            noPreventDefault = Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
+
+            window.addEventListener("deviceorientation", this._deviceOrientationHandler);
+        }
+
+        public detachControl(element: HTMLElement): void {
+            super.detachControl(element);
+
+            window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
         }
 
         public getTypeName(): string {

+ 1 - 0
src/Cameras/VR/babylon.webVRCamera.js

@@ -56,6 +56,7 @@ var BABYLON;
         };
         WebVRFreeCamera.prototype.attachControl = function (element, noPreventDefault) {
             _super.prototype.attachControl.call(this, element, noPreventDefault);
+            noPreventDefault = BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
             if (navigator.getVRDevices) {
                 navigator.getVRDevices().then(this._getWebVRDevices);
             }

+ 2 - 0
src/Cameras/VR/babylon.webVRCamera.ts

@@ -65,6 +65,8 @@ module BABYLON {
         public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
             super.attachControl(element, noPreventDefault);
 
+            noPreventDefault = Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
+
             if (navigator.getVRDevices) {
                 navigator.getVRDevices().then(this._getWebVRDevices);
             }

+ 1 - 0
src/Cameras/babylon.camera.js

@@ -565,6 +565,7 @@ var BABYLON;
         Camera._RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED = 12;
         Camera._RIG_MODE_STEREOSCOPIC_OVERUNDER = 13;
         Camera._RIG_MODE_VR = 20;
+        Camera.ForceAttachControlToAlwaysPreventDefault = false;
         __decorate([
             BABYLON.serializeAsVector3()
         ], Camera.prototype, "position", void 0);

+ 2 - 0
src/Cameras/babylon.camera.ts

@@ -55,6 +55,8 @@
         public static get RIG_MODE_VR(): number {
             return Camera._RIG_MODE_VR;
         }
+
+        public static ForceAttachControlToAlwaysPreventDefault = false;
         
         // Members
         @serializeAsVector3()

+ 1 - 0
src/Cameras/babylon.freeCamera.js

@@ -52,6 +52,7 @@ var BABYLON;
             }
             this._noPreventDefault = noPreventDefault;
             this._attachedElement = element;
+            noPreventDefault = BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
             this.inputs.attachElement(element, noPreventDefault);
         };
         FreeCamera.prototype.detachControl = function (element) {

+ 1 - 0
src/Cameras/babylon.freeCamera.ts

@@ -37,6 +37,7 @@
             }
             this._noPreventDefault = noPreventDefault;
             this._attachedElement = element;
+            noPreventDefault = Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
 
             this.inputs.attachElement(element, noPreventDefault);
         }        

+ 29 - 1
src/Materials/Textures/babylon.hdrCubeTexture.js

@@ -5,18 +5,45 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * This represents a texture coming from an HDR input.
+     *
+     * The only supported format is currently panorama picture stored in RGBE format.
+     * Example of such files can be found on HDRLib: http://hdrlib.com/
+     */
     var HDRCubeTexture = (function (_super) {
         __extends(HDRCubeTexture, _super);
+        /**
+         * Instantiates an HDRTexture from the following parameters.
+         *
+         * @param url The location of the HDR raw data (Panorama stored in RGBE format)
+         * @param scene The scene the texture will be used in
+         * @param size The cubemap desired size (the more it increases the longer the generation will be)
+         * @param noMipmap Forces to not generate the mipmap if true
+         * @param generateHarmonics Specifies wether you want to extract the polynomial harmonics during the generation process
+         * @param useInGammaSpace Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
+         * @param usePMREMGenerator Specifies wether or not to generate the CubeMap through CubeMapGen to avoid seams issue at run time.
+         */
         function HDRCubeTexture(url, scene, size, noMipmap, generateHarmonics, useInGammaSpace, usePMREMGenerator) {
             if (noMipmap === void 0) { noMipmap = false; }
             if (generateHarmonics === void 0) { generateHarmonics = true; }
             if (useInGammaSpace === void 0) { useInGammaSpace = false; }
             if (usePMREMGenerator === void 0) { usePMREMGenerator = false; }
             _super.call(this, scene);
-            this.coordinatesMode = BABYLON.Texture.CUBIC_MODE;
             this._useInGammaSpace = false;
             this._generateHarmonics = true;
+            /**
+             * The texture coordinates mode. As this texture is stored in a cube format, please modify carefully.
+             */
+            this.coordinatesMode = BABYLON.Texture.CUBIC_MODE;
+            /**
+             * The spherical polynomial data extracted from the texture.
+             */
             this.sphericalPolynomial = null;
+            /**
+             * Specifies wether the texture has been generated through the PMREMGenerator tool.
+             * This is usefull at run time to apply the good shader.
+             */
             this.isPMREM = false;
             this.name = url;
             this.url = url;
@@ -91,6 +118,7 @@ var BABYLON;
             var mipmapGenerator = null;
             if (!this._noMipmap && this._usePMREMGenerator) {
                 mipmapGenerator = function (data) {
+                    // Custom setup of the generator matching with the PBR shader values.
                     var generator = new BABYLON.Internals.PMREMGenerator(data, _this._size, _this._size, 0, 3, _this.getScene().getEngine().getCaps().textureFloat, 2048, 0.25, false, true);
                     return generator.filterCubeMap();
                 };

+ 45 - 10
src/Materials/Textures/babylon.hdrcubetexture.ts

@@ -1,15 +1,12 @@
 module BABYLON {
+    
+    /**
+     * This represents a texture coming from an HDR input.
+     * 
+     * The only supported format is currently panorama picture stored in RGBE format.
+     * Example of such files can be found on HDRLib: http://hdrlib.com/
+     */
     export class HDRCubeTexture extends BaseTexture {
-        public url: string;
-        public coordinatesMode = Texture.CUBIC_MODE;
-
-        private _useInGammaSpace = false;
-        private _generateHarmonics = true;
-        private _noMipmap: boolean;
-        private _extensions: string[];
-        private _textureMatrix: Matrix;
-        private _size: number;
-        private _usePMREMGenerator: boolean;
 
         private static _facesMapping = [
             "right",
@@ -20,10 +17,46 @@ module BABYLON {
             "back"
         ];
 
+        private _useInGammaSpace = false;
+        private _generateHarmonics = true;
+        private _noMipmap: boolean;
+        private _extensions: string[];
+        private _textureMatrix: Matrix;
+        private _size: number;
+        private _usePMREMGenerator: boolean;
+        
+        /**
+         * The texture URL.
+         */
+        public url: string;
+        
+        /**
+         * The texture coordinates mode. As this texture is stored in a cube format, please modify carefully.
+         */
+        public coordinatesMode = Texture.CUBIC_MODE;
+
+        /**
+         * The spherical polynomial data extracted from the texture.
+         */
         public sphericalPolynomial: SphericalPolynomial = null;
 
+        /**
+         * Specifies wether the texture has been generated through the PMREMGenerator tool.
+         * This is usefull at run time to apply the good shader.
+         */
         public isPMREM = false;
 
+        /**
+         * Instantiates an HDRTexture from the following parameters.
+         * 
+         * @param url The location of the HDR raw data (Panorama stored in RGBE format)
+         * @param scene The scene the texture will be used in
+         * @param size The cubemap desired size (the more it increases the longer the generation will be)
+         * @param noMipmap Forces to not generate the mipmap if true
+         * @param generateHarmonics Specifies wether you want to extract the polynomial harmonics during the generation process
+         * @param useInGammaSpace Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
+         * @param usePMREMGenerator Specifies wether or not to generate the CubeMap through CubeMapGen to avoid seams issue at run time.
+         */
         constructor(url: string, scene: Scene, size: number, noMipmap = false, generateHarmonics = true, useInGammaSpace = false, usePMREMGenerator = false) {
             super(scene);
 
@@ -113,6 +146,7 @@ module BABYLON {
             var mipmapGenerator = null;
             if (!this._noMipmap && this._usePMREMGenerator) {
                 mipmapGenerator = (data: ArrayBufferView[]) => {
+                    // Custom setup of the generator matching with the PBR shader values.
                     var generator = new BABYLON.Internals.PMREMGenerator(data,
                         this._size,
                         this._size,
@@ -196,3 +230,4 @@ module BABYLON {
         }
     }
 } 
+

+ 11 - 0
src/Tools/HDR/babylon.tools.cubemapToSphericalPolynomial.js

@@ -12,9 +12,20 @@ var BABYLON;
             return FileFaceOrientation;
         }());
         ;
+        /**
+         * Helper class dealing with the extraction of spherical polynomial dataArray
+         * from a cube map.
+         */
         var CubeMapToSphericalPolynomialTools = (function () {
             function CubeMapToSphericalPolynomialTools() {
             }
+            /**
+             * Converts a cubemap to the according Spherical Polynomial data.
+             * This extracts the first 3 orders only as they are the only one used in the lighting.
+             *
+             * @param cubeInfo The Cube map to extract the information from.
+             * @return The Spherical Polynomial data.
+             */
             CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial = function (cubeInfo) {
                 var sphericalHarmonics = new BABYLON.SphericalHarmonics();
                 var totalSolidAngle = 0.0;

+ 13 - 2
src/Tools/HDR/babylon.tools.cubemaptosphericalpolynomial.ts

@@ -13,7 +13,11 @@ module BABYLON.Internals {
             this.worldAxisForFileY = worldAxisForFileY;
         }
     };
-
+    
+    /**
+     * Helper class dealing with the extraction of spherical polynomial dataArray
+     * from a cube map.
+     */
     export class CubeMapToSphericalPolynomialTools {
 
         private static FileFaces: FileFaceOrientation[] = [
@@ -25,6 +29,13 @@ module BABYLON.Internals {
             new FileFaceOrientation("back", new Vector3(0, 0, -1), new Vector3(-1, 0, 0), new Vector3(0, -1, 0))// -Z bottom
         ];
 
+        /**
+         * Converts a cubemap to the according Spherical Polynomial data. 
+         * This extracts the first 3 orders only as they are the only one used in the lighting.
+         * 
+         * @param cubeInfo The Cube map to extract the information from.
+         * @return The Spherical Polynomial data.
+         */
         public static ConvertCubeMapToSphericalPolynomial(cubeInfo: CubeMapInfo): SphericalPolynomial {
             var sphericalHarmonics = new SphericalHarmonics();
             var totalSolidAngle = 0.0;
@@ -127,4 +138,4 @@ module BABYLON.Internals {
             return SphericalPolynomial.getSphericalPolynomialFromHarmonics(sphericalHarmonics);
         }
     }
-} 
+} 

+ 33 - 1
src/Tools/HDR/babylon.tools.hdr.js

@@ -3,6 +3,9 @@ var BABYLON;
     var Internals;
     (function (Internals) {
         ;
+        /**
+         * This groups tools to convert HDR texture to native colors array.
+         */
         var HDRTools = (function () {
             function HDRTools() {
             }
@@ -40,7 +43,14 @@ var BABYLON;
                 }
                 return line;
             };
-            /* minimal header reading.  modify if you want to parse more information */
+            /**
+             * Reads header information from an RGBE texture stored in a native array.
+             * More information on this format are available here:
+             * https://en.wikipedia.org/wiki/RGBE_image_format
+             *
+             * @param uint8array The binary file stored in  native array.
+             * @return The header information.
+             */
             HDRTools.RGBE_ReadHeader = function (uint8array) {
                 var height = 0;
                 var width = 0;
@@ -84,6 +94,17 @@ var BABYLON;
                     dataPosition: lineIndex
                 };
             };
+            /**
+             * Returns the cubemap information (each faces texture data) extracted from an RGBE texture.
+             * This RGBE texture needs to store the information as a panorama.
+             *
+             * More information on this format are available here:
+             * https://en.wikipedia.org/wiki/RGBE_image_format
+             *
+             * @param buffer The binary file stored in an array buffer.
+             * @param size The expected size of the extracted cubemap.
+             * @return The Cube Map information.
+             */
             HDRTools.GetCubeMapTextureData = function (buffer, size) {
                 var uint8array = new Uint8Array(buffer);
                 var hdrInfo = this.RGBE_ReadHeader(uint8array);
@@ -91,6 +112,17 @@ var BABYLON;
                 var cubeMapData = Internals.PanoramaToCubeMapTools.ConvertPanoramaToCubemap(data, hdrInfo.width, hdrInfo.height, size);
                 return cubeMapData;
             };
+            /**
+             * Returns the pixels data extracted from an RGBE texture.
+             * This pixels will be stored left to right up to down in the R G B order in one array.
+             *
+             * More information on this format are available here:
+             * https://en.wikipedia.org/wiki/RGBE_image_format
+             *
+             * @param uint8array The binary file stored in an array buffer.
+             * @param hdrInfo The header information of the file.
+             * @return The pixels data in RGB right to left up to down order.
+             */
             HDRTools.RGBE_ReadPixels = function (uint8array, hdrInfo) {
                 // Keep for multi format supports.
                 return this.RGBE_ReadPixels_RLE(uint8array, hdrInfo);

+ 71 - 26
src/Tools/HDR/babylon.tools.hdr.ts

@@ -1,10 +1,27 @@
 module BABYLON.Internals {
+    /**
+     * Header information of HDR texture files.
+     */
     export interface HDRInfo {
+        /**
+         * The height of the texture in pixels.
+         */
         height: number;
+        
+        /**
+         * The width of the texture in pixels.
+         */
         width: number;
+        
+        /**
+         * The index of the beginning of the data in the binary file.
+         */
         dataPosition: number;
     };
 
+    /**
+     * This groups tools to convert HDR texture to native colors array.
+     */
     export class HDRTools {
 
         private static Ldexp(mantissa: number, exponent: number): number {
@@ -19,10 +36,9 @@ module BABYLON.Internals {
             return mantissa * Math.pow(2, exponent);
         }
 
-        private static Rgbe2float(float32array: Float32Array, 
+        private static Rgbe2float(float32array: Float32Array,
             red: number, green: number, blue: number, exponent: number,
-            index: number)
-        {
+            index: number) {
             if (exponent > 0) {   /*nonzero pixel*/
                 exponent = this.Ldexp(1.0, exponent - (128 + 8));
 
@@ -41,7 +57,7 @@ module BABYLON.Internals {
             var line = "";
             var character = "";
 
-            for(var i = startIndex; i < uint8array.length - startIndex; i++) {
+            for (var i = startIndex; i < uint8array.length - startIndex; i++) {
                 character = String.fromCharCode(uint8array[i]);
 
                 if (character == "\n") {
@@ -54,11 +70,18 @@ module BABYLON.Internals {
             return line;
         }
 
-        /* minimal header reading.  modify if you want to parse more information */
-        public static RGBE_ReadHeader(uint8array: Uint8Array) : HDRInfo {
+        /**
+         * Reads header information from an RGBE texture stored in a native array. 
+         * More information on this format are available here:
+         * https://en.wikipedia.org/wiki/RGBE_image_format
+         * 
+         * @param uint8array The binary file stored in  native array.
+         * @return The header information.
+         */
+        public static RGBE_ReadHeader(uint8array: Uint8Array): HDRInfo {
             var height: number = 0;
             var width: number = 0;
-            
+
             var line = this.readStringLine(uint8array, 0);
             if (line[0] != '#' || line[1] != '?') {
                 throw "Bad HDR Format.";
@@ -66,7 +89,7 @@ module BABYLON.Internals {
 
             var endOfHeader = false;
             var findFormat = false;
-            var lineIndex:number = 0;
+            var lineIndex: number = 0;
 
             do {
                 lineIndex += (line.length + 1);
@@ -81,24 +104,24 @@ module BABYLON.Internals {
             } while (!endOfHeader);
 
             if (!findFormat) {
-                throw "HDR Bad header format, unsupported FORMAT"; 
+                throw "HDR Bad header format, unsupported FORMAT";
             }
 
             lineIndex += (line.length + 1);
             line = this.readStringLine(uint8array, lineIndex);
-            
+
             var sizeRegexp = /^\-Y (.*) \+X (.*)$/g;
             var match = sizeRegexp.exec(line);
 
             // TODO. Support +Y and -X if needed.
             if (match.length < 3) {
-                throw "HDR Bad header format, no size"; 
+                throw "HDR Bad header format, no size";
             }
             width = parseInt(match[2]);
             height = parseInt(match[1]);
 
             if (width < 8 || width > 0x7fff) {
-                throw "HDR Bad header format, unsupported size"; 
+                throw "HDR Bad header format, unsupported size";
             }
 
             lineIndex += (line.length + 1);
@@ -110,7 +133,18 @@ module BABYLON.Internals {
             };
         }
 
-        public static GetCubeMapTextureData(buffer: ArrayBuffer, size: number) : CubeMapInfo {
+        /**
+         * Returns the cubemap information (each faces texture data) extracted from an RGBE texture.
+         * This RGBE texture needs to store the information as a panorama.
+         *  
+         * More information on this format are available here:
+         * https://en.wikipedia.org/wiki/RGBE_image_format
+         * 
+         * @param buffer The binary file stored in an array buffer.
+         * @param size The expected size of the extracted cubemap.
+         * @return The Cube Map information.
+         */
+        public static GetCubeMapTextureData(buffer: ArrayBuffer, size: number): CubeMapInfo {
             var uint8array = new Uint8Array(buffer);
             var hdrInfo = this.RGBE_ReadHeader(uint8array);
             var data = this.RGBE_ReadPixels_RLE(uint8array, hdrInfo);
@@ -120,12 +154,23 @@ module BABYLON.Internals {
             return cubeMapData;
         }
 
-        public static RGBE_ReadPixels(uint8array:Uint8Array, hdrInfo:HDRInfo): Float32Array {
+        /**
+         * Returns the pixels data extracted from an RGBE texture. 
+         * This pixels will be stored left to right up to down in the R G B order in one array.
+         *  
+         * More information on this format are available here:
+         * https://en.wikipedia.org/wiki/RGBE_image_format
+         * 
+         * @param uint8array The binary file stored in an array buffer.
+         * @param hdrInfo The header information of the file.
+         * @return The pixels data in RGB right to left up to down order.
+         */
+        public static RGBE_ReadPixels(uint8array: Uint8Array, hdrInfo: HDRInfo): Float32Array {
             // Keep for multi format supports.
             return this.RGBE_ReadPixels_RLE(uint8array, hdrInfo);
         }
 
-        private static RGBE_ReadPixels_RLE(uint8array:Uint8Array, hdrInfo:HDRInfo): Float32Array {
+        private static RGBE_ReadPixels_RLE(uint8array: Uint8Array, hdrInfo: HDRInfo): Float32Array {
             var num_scanlines = hdrInfo.height;
             var scanline_width = hdrInfo.width;
 
@@ -137,32 +182,32 @@ module BABYLON.Internals {
             var scanLineArray = new Uint8Array(scanLineArrayBuffer);
 
             // 3 channels of 4 bytes per pixel in float.
-            var resultBuffer = new ArrayBuffer(hdrInfo.width * hdrInfo.height * 4 * 3); 
+            var resultBuffer = new ArrayBuffer(hdrInfo.width * hdrInfo.height * 4 * 3);
             var resultArray = new Float32Array(resultBuffer);
 
             // read in each successive scanline
-            while(num_scanlines > 0) {
+            while (num_scanlines > 0) {
                 a = uint8array[dataIndex++];
                 b = uint8array[dataIndex++];
                 c = uint8array[dataIndex++];
                 d = uint8array[dataIndex++];
 
                 if (a != 2 || b != 2 || (c & 0x80)) {
-                  // this file is not run length encoded
-                  throw "HDR Bad header format, not RLE"; 
+                    // this file is not run length encoded
+                    throw "HDR Bad header format, not RLE";
                 }
 
-                if (((c<<8) | d) != scanline_width) {
-                  throw "HDR Bad header format, wrong scan line width"; 
+                if (((c << 8) | d) != scanline_width) {
+                    throw "HDR Bad header format, wrong scan line width";
                 }
 
                 index = 0;
 
                 // read each of the four channels for the scanline into the buffer
-                for(i = 0; i < 4; i++) {
+                for (i = 0; i < 4; i++) {
                     endIndex = (i + 1) * scanline_width;
 
-                    while(index < endIndex) {
+                    while (index < endIndex) {
                         a = uint8array[dataIndex++];
                         b = uint8array[dataIndex++];
 
@@ -173,7 +218,7 @@ module BABYLON.Internals {
                                 throw "HDR Bad Format, bad scanline data (run)";
                             }
 
-                            while(count-- > 0) {
+                            while (count-- > 0) {
                                 scanLineArray[index++] = b;
                             }
                         }
@@ -195,7 +240,7 @@ module BABYLON.Internals {
                 }
 
                 // now convert data from buffer into floats
-                for(i = 0; i < scanline_width; i++) {
+                for (i = 0; i < scanline_width; i++) {
                     a = scanLineArray[i];
                     b = scanLineArray[i + scanline_width];
                     c = scanLineArray[i + 2 * scanline_width];
@@ -212,4 +257,4 @@ module BABYLON.Internals {
             return resultArray;
         }
     }
-} 
+} 

+ 12 - 0
src/Tools/HDR/babylon.tools.panoramaToCubemap.js

@@ -2,9 +2,21 @@ var BABYLON;
 (function (BABYLON) {
     var Internals;
     (function (Internals) {
+        /**
+         * Helper class usefull to convert panorama picture to their cubemap representation in 6 faces.
+         */
         var PanoramaToCubeMapTools = (function () {
             function PanoramaToCubeMapTools() {
             }
+            /**
+             * Converts a panorma stored in RGB right to left up to down format into a cubemap (6 faces).
+             *
+             * @param float32Array The source data.
+             * @param inputWidth The width of the input panorama.
+             * @param inputhHeight The height of the input panorama.
+             * @param size The willing size of the generated cubemap (each faces will be size * size pixels)
+             * @return The cubemap data
+             */
             PanoramaToCubeMapTools.ConvertPanoramaToCubemap = function (float32Array, inputWidth, inputHeight, size) {
                 if (!float32Array) {
                     throw "ConvertPanoramaToCubemap: input cannot be null";

+ 51 - 0
src/Tools/HDR/babylon.tools.panoramaToCubemap.ts

@@ -1,14 +1,55 @@
 module BABYLON.Internals {
+    /**
+     * CubeMap information grouping all the data for each faces as well as the cubemap size.
+     */
     export interface CubeMapInfo {
+        /**
+         * The pixel array for the front face.
+         * This is stored in RGB, left to right, up to down format.
+         */
         front: Float32Array;
+        
+        /**
+         * The pixel array for the back face.
+         * This is stored in RGB, left to right, up to down format.
+         */
         back: Float32Array;
+        
+        /**
+         * The pixel array for the left face.
+         * This is stored in RGB, left to right, up to down format.
+         */
         left: Float32Array;
+        
+        /**
+         * The pixel array for the right face.
+         * This is stored in RGB, left to right, up to down format.
+         */
         right: Float32Array;
+        
+        /**
+         * The pixel array for the up face.
+         * This is stored in RGB, left to right, up to down format.
+         */
         up: Float32Array;
+        
+        /**
+         * The pixel array for the down face.
+         * This is stored in RGB, left to right, up to down format.
+         */
         down: Float32Array;
+        
+        /**
+         * The size of the cubemap stored.
+         * 
+         * Each faces will be size * size pixels.
+         */
         size: number;
     }
 
+    /**
+     * Helper class usefull to convert panorama picture to their cubemap representation in 6 faces.
+     */
     export class PanoramaToCubeMapTools {
 
         private static FACE_FRONT = [
@@ -48,6 +89,15 @@ module BABYLON.Internals {
             new Vector3(1.0, -1.0, -1.0)
         ];
 
+        /**
+         * Converts a panorma stored in RGB right to left up to down format into a cubemap (6 faces).
+         * 
+         * @param float32Array The source data.
+         * @param inputWidth The width of the input panorama.
+         * @param inputhHeight The height of the input panorama.
+         * @param size The willing size of the generated cubemap (each faces will be size * size pixels)
+         * @return The cubemap data 
+         */
         public static ConvertPanoramaToCubemap(float32Array: Float32Array, inputWidth: number, inputHeight: number, size: number): CubeMapInfo {
             if (!float32Array) {
                 throw "ConvertPanoramaToCubemap: input cannot be null";
@@ -144,3 +194,4 @@ module BABYLON.Internals {
         }
     }
 } 
+

+ 31 - 0
src/Tools/HDR/babylon.tools.pmremgenerator.js

@@ -8,6 +8,9 @@ var BABYLON;
 (function (BABYLON) {
     var Internals;
     (function (Internals) {
+        /**
+         * The bounding box information used during the conversion process.
+         */
         var CMGBoundinBox = (function () {
             function CMGBoundinBox() {
                 this.min = new BABYLON.Vector3(0, 0, 0);
@@ -54,7 +57,30 @@ var BABYLON;
             CMGBoundinBox.MIN = Number.MIN_VALUE;
             return CMGBoundinBox;
         }());
+        /**
+         * Helper class to PreProcess a cubemap in order to generate mipmap according to the level of blur
+         * required by the glossinees of a material.
+         *
+         * This only supports the cosine drop power as well as Warp fixup generation method.
+         *
+         * This is using the process from CubeMapGen described here:
+         * https://seblagarde.wordpress.com/2012/06/10/amd-cubemapgen-for-physically-based-rendering/
+         */
         var PMREMGenerator = (function () {
+            /**
+             * Constructor of the generator.
+             *
+             * @param input The different faces data from the original cubemap in the order X+ X- Y+ Y- Z+ Z-
+             * @param inputSize The size of the cubemap faces
+             * @param outputSize The size of the output cubemap faces
+             * @param maxNumMipLevels The max number of mip map to generate (0 means all)
+             * @param numChannels The number of channels stored in the cubemap (3 for RBGE for instance)
+             * @param isFloat Specifies if the input texture is in float or int (hdr is usually in float)
+             * @param specularPower The max specular level of the desired cubemap
+             * @param cosinePowerDropPerMip The amount of drop the specular power will follow on each mip
+             * @param excludeBase Specifies wether to process the level 0 (original level) or not
+             * @param fixup Specifies wether to apply the edge fixup algorythm or not
+             */
             function PMREMGenerator(input, inputSize, outputSize, maxNumMipLevels, numChannels, isFloat, specularPower, cosinePowerDropPerMip, excludeBase, fixup) {
                 this.input = input;
                 this.inputSize = inputSize;
@@ -69,6 +95,11 @@ var BABYLON;
                 this._outputSurface = [];
                 this._numMipLevels = 0;
             }
+            /**
+             * Launches the filter process and return the result.
+             *
+             * @return the filter cubemap in the form mip0 [faces1..6] .. mipN [faces1..6]
+             */
             PMREMGenerator.prototype.filterCubeMap = function () {
                 // Init cubemap processor
                 this.init();

+ 33 - 0
src/Tools/HDR/babylon.tools.pmremgenerator.ts

@@ -6,6 +6,10 @@
 //_______________________________________________________________
 
 namespace BABYLON.Internals {
+    
+    /**
+     * The bounding box information used during the conversion process.
+     */
     class CMGBoundinBox {
         private static MAX = Number.MAX_VALUE;
         private static MIN = Number.MIN_VALUE;
@@ -63,6 +67,15 @@ namespace BABYLON.Internals {
         }
     }
 
+    /**
+     * Helper class to PreProcess a cubemap in order to generate mipmap according to the level of blur
+     * required by the glossinees of a material.
+     * 
+     * This only supports the cosine drop power as well as Warp fixup generation method.
+     * 
+     * This is using the process from CubeMapGen described here:
+     * https://seblagarde.wordpress.com/2012/06/10/amd-cubemapgen-for-physically-based-rendering/
+     */
     export class PMREMGenerator {
         private static CP_MAX_MIPLEVELS = 16;
 
@@ -232,6 +245,20 @@ namespace BABYLON.Internals {
         private _filterLUT: ArrayBufferView[];
         private _numMipLevels: number = 0;
 
+        /**
+         * Constructor of the generator.
+         * 
+         * @param input The different faces data from the original cubemap in the order X+ X- Y+ Y- Z+ Z-
+         * @param inputSize The size of the cubemap faces
+         * @param outputSize The size of the output cubemap faces
+         * @param maxNumMipLevels The max number of mip map to generate (0 means all)
+         * @param numChannels The number of channels stored in the cubemap (3 for RBGE for instance)
+         * @param isFloat Specifies if the input texture is in float or int (hdr is usually in float)
+         * @param specularPower The max specular level of the desired cubemap
+         * @param cosinePowerDropPerMip The amount of drop the specular power will follow on each mip
+         * @param excludeBase Specifies wether to process the level 0 (original level) or not
+         * @param fixup Specifies wether to apply the edge fixup algorythm or not
+         */
         constructor(public input: ArrayBufferView[],
             public inputSize: number,
             public outputSize: number,
@@ -245,6 +272,11 @@ namespace BABYLON.Internals {
 
         }
 
+        /**
+         * Launches the filter process and return the result.
+         * 
+         * @return the filter cubemap in the form mip0 [faces1..6] .. mipN [faces1..6]
+         */
         public filterCubeMap(): ArrayBufferView[][] {
             // Init cubemap processor
             this.init();
@@ -1193,3 +1225,4 @@ namespace BABYLON.Internals {
         }
     }
 }
+

+ 20 - 10
src/babylon.node.js

@@ -131,39 +131,49 @@ var BABYLON;
             }
             return false;
         };
-        Node.prototype._getDescendants = function (list, results, directDecendantsOnly) {
+        /**
+         * Evaluate a list of nodes and determine if they should be considered as descendants considering the given criterias
+         * @param {BABYLON.Node[]} list the input array of nodes to evaluate
+         * @param {BABYLON.Node[]} results the result array containing the nodes matching the given criterias
+         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
+         */
+        Node.prototype._getDescendants = function (list, results, directDecendantsOnly, predicate) {
             if (directDecendantsOnly === void 0) { directDecendantsOnly = false; }
             for (var index = 0; index < list.length; index++) {
                 var item = list[index];
-                if ((directDecendantsOnly && item.parent === this) || (!directDecendantsOnly && item.isDescendantOf(this))) {
+                if (((directDecendantsOnly && item.parent === this) || (!directDecendantsOnly && item.isDescendantOf(this))) && (predicate === null || predicate(item))) {
                     results.push(item);
                 }
             }
         };
         /**
          * Will return all nodes that have this node as parent.
+         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          * @return {BABYLON.Node[]} all children nodes of all types.
          */
-        Node.prototype.getDescendants = function (directDecendantsOnly) {
+        Node.prototype.getDescendants = function (directDecendantsOnly, predicate) {
             var results = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly);
-            this._getDescendants(this._scene.lights, results, directDecendantsOnly);
-            this._getDescendants(this._scene.cameras, results, directDecendantsOnly);
+            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
+            this._getDescendants(this._scene.lights, results, directDecendantsOnly, predicate);
+            this._getDescendants(this._scene.cameras, results, directDecendantsOnly, predicate);
             return results;
         };
         /**
+         * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          * @Deprecated, legacy support.
          * use getDecendants instead.
          */
-        Node.prototype.getChildren = function () {
-            return this.getDescendants(true);
+        Node.prototype.getChildren = function (predicate) {
+            return this.getDescendants(true, predicate);
         };
         /**
          * Get all child-meshes of this node.
          */
-        Node.prototype.getChildMeshes = function (directDecendantsOnly) {
+        Node.prototype.getChildMeshes = function (directDecendantsOnly, predicate) {
             var results = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly);
+            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
             return results;
         };
         Node.prototype._setReady = function (state) {

+ 21 - 11
src/babylon.node.ts

@@ -176,10 +176,17 @@
             return false;
         }
 
-        public _getDescendants(list: Node[], results: Node[], directDecendantsOnly: boolean = false): void {
+        /**
+         * Evaluate a list of nodes and determine if they should be considered as descendants considering the given criterias
+         * @param {BABYLON.Node[]} list the input array of nodes to evaluate
+         * @param {BABYLON.Node[]} results the result array containing the nodes matching the given criterias
+         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
+         */
+        public _getDescendants(list: Node[], results: Node[], directDecendantsOnly: boolean = false, predicate?: (node: Node) => boolean): void {
             for (var index = 0; index < list.length; index++) {
                 var item = list[index];
-                if ((directDecendantsOnly && item.parent === this) || (!directDecendantsOnly && item.isDescendantOf(this))) {
+                if (((directDecendantsOnly && item.parent === this) || (!directDecendantsOnly && item.isDescendantOf(this))) && (predicate === null || predicate(item))) {
                     results.push(item);
                 }
             }
@@ -187,31 +194,34 @@
 
         /**
          * Will return all nodes that have this node as parent.
+         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          * @return {BABYLON.Node[]} all children nodes of all types.
          */
-        public getDescendants(directDecendantsOnly?: boolean): Node[] {
+        public getDescendants(directDecendantsOnly?: boolean, predicate?: (node: Node) => boolean): Node[] {
             var results = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly);
-            this._getDescendants(this._scene.lights, results, directDecendantsOnly);
-            this._getDescendants(this._scene.cameras, results, directDecendantsOnly);
+            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
+            this._getDescendants(this._scene.lights, results, directDecendantsOnly, predicate);
+            this._getDescendants(this._scene.cameras, results, directDecendantsOnly, predicate);
 
             return results;
         }
         
         /**
+         * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          * @Deprecated, legacy support.
          * use getDecendants instead.
          */
-        public getChildren(): Node[] {
-            return this.getDescendants(true);
+        public getChildren(predicate?: (node: Node) => boolean): Node[] {
+            return this.getDescendants(true, predicate);
         }
         
         /**
          * Get all child-meshes of this node.
          */
-        public getChildMeshes(directDecendantsOnly?: boolean): AbstractMesh[] {
+        public getChildMeshes(directDecendantsOnly?: boolean, predicate?: (node: Node) => boolean): AbstractMesh[] {
             var results: Array<AbstractMesh> = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly);
+            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
             return results;
         }
 
@@ -299,4 +309,4 @@
             }
         }
     }
-} 
+}