Browse Source

Merge remote-tracking branch 'upstream/master'

jbousquie 9 years ago
parent
commit
ba97580b18
37 changed files with 1365 additions and 976 deletions
  1. 10 10
      dist/preview release/babylon.core.js
  2. 741 723
      dist/preview release/babylon.d.ts
  3. 17 17
      dist/preview release/babylon.js
  4. 98 40
      dist/preview release/babylon.max.js
  5. 17 17
      dist/preview release/babylon.noworker.js
  6. 9 1
      dist/preview release/what's new.md
  7. 1 1
      materialsLibrary/dist/babylon.fireMaterial.js
  8. 1 0
      materialsLibrary/dist/babylon.fireMaterial.min.js
  9. 1 0
      materialsLibrary/dist/babylon.lavaMaterial.min.js
  10. 1 0
      materialsLibrary/dist/babylon.normalMaterial.min.js
  11. 1 0
      materialsLibrary/dist/babylon.simpleMaterial.min.js
  12. 24 4
      materialsLibrary/dist/babylon.waterMaterial.js
  13. 1 0
      materialsLibrary/dist/babylon.waterMaterial.min.js
  14. 4 0
      materialsLibrary/gulpfile.js
  15. 3 3
      materialsLibrary/materials/fire/fire.fragment.fx
  16. 26 2
      materialsLibrary/materials/water/babylon.waterMaterial.ts
  17. 121 26
      materialsLibrary/materials/water/water.fragment.fx
  18. 3 2
      materialsLibrary/materials/water/water.vertex.fx
  19. 48 24
      materialsLibrary/test/babylon.max.js
  20. 10 1
      src/Animations/babylon.animatable.js
  21. 13 1
      src/Animations/babylon.animatable.ts
  22. 38 16
      src/Animations/babylon.animation.js
  23. 52 21
      src/Animations/babylon.animation.ts
  24. 3 0
      src/Materials/babylon.material.js
  25. 4 0
      src/Materials/babylon.material.ts
  26. 3 0
      src/Materials/babylon.standardMaterial.js
  27. 4 0
      src/Materials/babylon.standardMaterial.ts
  28. 9 3
      src/PostProcess/babylon.hdrRenderingPipeline.js
  29. 9 3
      src/PostProcess/babylon.hdrRenderingPipeline.ts
  30. 24 13
      src/PostProcess/babylon.ssaoRenderingPipeline.js
  31. 29 15
      src/PostProcess/babylon.ssaoRenderingPipeline.ts
  32. 12 11
      src/Shaders/default.fragment.fx
  33. 3 2
      src/Shaders/hdr.fragment.fx
  34. 8 11
      src/Shaders/ssao.fragment.fx
  35. 4 1
      src/Shaders/ssaoCombine.fragment.fx
  36. 10 6
      src/babylon.scene.js
  37. 3 2
      src/babylon.scene.ts

File diff suppressed because it is too large
+ 10 - 10
dist/preview release/babylon.core.js


File diff suppressed because it is too large
+ 741 - 723
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 17 - 17
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 98 - 40
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 17 - 17
dist/preview release/babylon.noworker.js


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

@@ -2,6 +2,10 @@
   - **Major updates**
     - Point lights shadow mapping. [Demo here](http://www.babylonjs-playground.com/#LYCSQ#12) ([deltakosh](https://github.com/deltakosh))
     - Introducing [Materials Library](https://github.com/BabylonJS/Babylon.js/tree/master/materialsLibrary) ([deltakosh](https://github.com/deltakosh))
+      - Water material: http://doc.babylonjs.com/extensions/Water ([julien-moreau](https://github.com/julien-moreau))
+      - Fire material: http://doc.babylonjs.com/extensions/fire ([julien-moreau](https://github.com/julien-moreau))
+      - Normal material: http://doc.babylonjs.com/extensions/normal ([temechon](https://github.com/temechon))
+      - Lava Material: http://doc.babylonjs.com/extensions/lava ([temechon](https://github.com/temechon))
     - New cache mecanism for StandardMaterial ([deltakosh](https://github.com/deltakosh))
     - New Solid Particle System ([jerome](https://github.com/jbousquie))
     - New `StandardMaterial.lightmapTexture` which can be controlled with `StandardMaterial.useLightmapAsShadowMap` ([deltakosh](https://github.com/deltakosh))
@@ -9,10 +13,12 @@
     - New serializers [folder](https://github.com/BabylonJS/Babylon.js/serializers) to host .babylon serializers ([deltakosh](https://github.com/deltakosh))
       - New .obj serializer ([BitOfGold](https://github.com/BitOfGold))
     - Sprites now can be [picked](http://www.babylonjs-playground.com/#1XMVZW#4) and can use [actions](http://www.babylonjs-playground.com/#9RUHH#4) ([deltakosh](https://github.com/deltakosh))
-    - New `Mesh.CreatePolygon()` method ([jerome](https://github.com/jbousquie))
+    - New `Mesh.CreatePolyhedron()` method ([jerome](https://github.com/jbousquie))
     - New `Mesh.CreateIcoSphere()` method. [Demo here](http://www.babylonjs-playground.com/#24DUYD) (G'kar)
     - Introducing [babylon.core.js](http://doc.babylonjs.com/generals/Framework_versions) ([deltakosh](https://github.com/deltakosh))
   - **Updates**
+    - Added `Animatable.goToFrame()` ([deltakosh](https://github.com/deltakosh))   
+    - Fixed behavior or `Animation.CreateAndStartAnimation` and added `Animation.CreateMergeAndStartAnimation` to reproduce previous behavior ([deltakosh](https://github.com/deltakosh))
     - Adding `StandardMaterial.linkEmissiveWithDiffuse` to, well, link emissive with diffuse value. (With)[http://www.babylonjs-playground.com/#2FPUCS#2] and (without)[http://www.babylonjs-playground.com/#2FPUCS#1] ([deltakosh](https://github.com/deltakosh))
     - Adding support for equi-rectangular mapping. See [demo here](http://www.babylonjs-playground.com/#27FN5R#8) ([deltakosh](https://github.com/deltakosh))
     - Sprites and particles scheduler updated to be resolved before transparent objects ([deltakosh](https://github.com/deltakosh))
@@ -37,6 +43,8 @@
     - new Heightmap Impostor for Cannon.js physics engine. [PR](https://github.com/BabylonJS/Babylon.js/pull/78), [Demo] (http://www.babylonjs-playground.com/#D3LQD#3) ([RaananW](https://github.com/RaananW))
     - A plane mesh can be created with a source plane (math). [PR](https://github.com/BabylonJS/Babylon.js/pull/779) ([RaananW](https://github.com/RaananW))
     - AbstractMesh.onPhysicsCollide will be triggered when a physics-enabled mesh collides against another. [PR](https://github.com/BabylonJS/Babylon.js/pull/806) ([RaananW](https://github.com/RaananW))
+    - Added scene onPointerMove public callback. [PR](https://github.com/BabylonJS/Babylon.js/pull/810) ([RaananW](https://github.com/RaananW))
+    - Added streaming support for BABYLON.Sound ([davrous](https://github.com/davrous))
   - **Bug fixes**
     - Fixed a bug with spherical mapping ([deltakosh](https://github.com/deltakosh)) 
     - Fixed a bug with clone and createInstance which was forcing the recomputation of bounding boxes ([deltakosh](https://github.com/deltakosh)) 

File diff suppressed because it is too large
+ 1 - 1
materialsLibrary/dist/babylon.fireMaterial.js


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


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


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


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


File diff suppressed because it is too large
+ 24 - 4
materialsLibrary/dist/babylon.waterMaterial.js


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


+ 4 - 0
materialsLibrary/gulpfile.js

@@ -7,6 +7,7 @@ var rename = require("gulp-rename");
 var cleants = require('gulp-clean-ts-extends');
 var replace = require("gulp-replace");
 var webserver = require('gulp-webserver');
+var uglify = require("gulp-uglify");
 
 var config = require("./config.json");
 var extendsSearchRegex = /var\s__extends[\s\S]+?\};/g;
@@ -41,6 +42,9 @@ gulp.task('default', ["copyReference"], function () {
             .pipe(cleants())
             .pipe(replace(extendsSearchRegex, ""))
             .pipe(concat(material.output))
+            .pipe(gulp.dest(config.build.distOutputDirectory))
+            .pipe(rename({extname: ".min.js"}))
+            .pipe(uglify())
             .pipe(gulp.dest(config.build.distOutputDirectory));
     });
 

+ 3 - 3
materialsLibrary/materials/fire/fire.fragment.fx

@@ -108,13 +108,13 @@ void main(void) {
 	
 	vec4 opacityColor = texture2D(opacitySampler, perturbedBaseCoords.xy);
 	
-	baseColor = texture2D(diffuseSampler, perturbedBaseCoords.xy) * 2.0;
-	baseColor *= opacityColor;
-
 #ifdef ALPHATEST
 	if (opacityColor.r < 0.1)
 		discard;
 #endif
+	
+	baseColor = texture2D(diffuseSampler, perturbedBaseCoords.xy) * 2.0;
+	baseColor *= opacityColor;
 
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif

+ 26 - 2
materialsLibrary/materials/water/babylon.waterMaterial.ts

@@ -53,6 +53,7 @@ module BABYLON {
         public BONES4 = false;
         public BonesPerMesh = 0;
         public INSTANCES = false;
+        public SPECULARTERM = false;
 
         constructor() {
             super();
@@ -66,6 +67,8 @@ module BABYLON {
 		*/
         public bumpTexture: BaseTexture;
         public diffuseColor = new Color3(1, 1, 1);
+        public specularColor = new Color3(0, 0, 0);
+        public specularPower = 64;
         public disableLighting = false;
         
         /**
@@ -96,6 +99,11 @@ module BABYLON {
         * @param {number}: Represents the maximum length of a wave
         */
 		public waveLength: number = 0.1;
+        
+        /**
+        * @param {number}: Defines the waves speed
+        */
+        public waveSpeed: number = 1.0;
 		
 		/*
 		* Private members
@@ -111,6 +119,7 @@ module BABYLON {
 		private _lastTime: number = 0;
         
         private _scaledDiffuse = new Color3();
+        private _scaledSpecular = new Color3();
         private _renderId: number;
 
         private _defines = new WaterMaterialDefines();
@@ -287,6 +296,11 @@ module BABYLON {
                     }
 
                     this._defines[type] = true;
+                    
+                    // Specular
+                    if (!light.specular.equalsFloats(0, 0, 0)) {
+                        this._defines.SPECULARTERM = true;
+                    }
 
                     // Shadows
                     if (scene.shadowsEnabled) {
@@ -421,7 +435,7 @@ module BABYLON {
 				
                 this._effect = scene.getEngine().createEffect(shaderName,
                     attribs,
-                    ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                    ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                         "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
                         "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
                         "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
@@ -433,7 +447,7 @@ module BABYLON {
                         "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
 						// Water
 						"worldReflectionViewProjection", "windDirection", "waveLength", "time", "windForce",
-						"cameraPosition", "bumpHeight", "waveHeight", "waterColor", "colorBlendFactor"
+						"cameraPosition", "bumpHeight", "waveHeight", "waterColor", "colorBlendFactor", "waveSpeed"
                     ],
                     ["normalSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3",
@@ -499,6 +513,10 @@ module BABYLON {
             }
 
             this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+            
+            if (this._defines.SPECULARTERM) {
+                this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            }
 
             if (scene.lightsEnabled && !this.disableLighting) {
                 var lightIndex = 0;
@@ -529,6 +547,11 @@ module BABYLON {
 
                     light.diffuse.scaleToRef(light.intensity, this._scaledDiffuse);
                     this._effect.setColor4("vLightDiffuse" + lightIndex, this._scaledDiffuse, light.range);
+                    
+                    if (this._defines.SPECULARTERM) {
+                        light.specular.scaleToRef(light.intensity, this._scaledSpecular);
+                        this._effect.setColor3("vLightSpecular" + lightIndex, this._scaledSpecular);
+                    }
 
                     // Shadows
                     if (scene.shadowsEnabled) {
@@ -576,6 +599,7 @@ module BABYLON {
             this._effect.setFloat("bumpHeight", this.bumpHeight);
 			this._effect.setColor4("waterColor", this.waterColor, 1.0);
 			this._effect.setFloat("colorBlendFactor", this.colorBlendFactor);
+            this._effect.setFloat("waveSpeed", this.waveSpeed);
 
             super.bind(world, mesh);
 		}

+ 121 - 26
materialsLibrary/materials/water/water.fragment.fx

@@ -4,6 +4,10 @@ precision highp float;
 uniform vec3 vEyePosition;
 uniform vec4 vDiffuseColor;
 
+#ifdef SPECULARTERM
+uniform vec4 vSpecularColor;
+#endif
+
 // Input
 varying vec3 vPositionW;
 
@@ -19,6 +23,9 @@ varying vec4 vColor;
 #ifdef LIGHT0
 uniform vec4 vLightData0;
 uniform vec4 vLightDiffuse0;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular0;
+#endif
 #ifdef SHADOW0
 #if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
 varying vec4 vPositionFromLight0;
@@ -39,6 +46,9 @@ uniform vec3 vLightGround0;
 #ifdef LIGHT1
 uniform vec4 vLightData1;
 uniform vec4 vLightDiffuse1;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular1;
+#endif
 #ifdef SHADOW1
 #if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
 varying vec4 vPositionFromLight1;
@@ -59,6 +69,9 @@ uniform vec3 vLightGround1;
 #ifdef LIGHT2
 uniform vec4 vLightData2;
 uniform vec4 vLightDiffuse2;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular2;
+#endif
 #ifdef SHADOW2
 #if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
 varying vec4 vPositionFromLight2;
@@ -79,6 +92,9 @@ uniform vec3 vLightGround2;
 #ifdef LIGHT3
 uniform vec4 vLightData3;
 uniform vec4 vLightDiffuse3;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular3;
+#endif
 #ifdef SHADOW3
 #if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
 varying vec4 vPositionFromLight3;
@@ -313,9 +329,12 @@ float CalcFogFactor()
 struct lightingInfo
 {
 	vec3 diffuse;
+#ifdef SPECULARTERM
+	vec3 specular;
+#endif
 };
 
-lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, float range) {
+lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float glossiness, vec3 bumpColor) {
 	lightingInfo result;
 
 	vec3 lightVectorW;
@@ -336,10 +355,20 @@ lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData,
 	float ndl = max(0., dot(vNormal, lightVectorW));
 	result.diffuse = ndl * diffuseColor * attenuation;
 
+	// Specular
+#ifdef SPECULARTERM
+	vec3 angleW = normalize(viewDirectionW - lightVectorW);
+	vec2 perturbation = bumpHeight * (bumpColor.rg - 0.5);
+	
+	vec3 halfvec = normalize(angleW + lightVectorW + vec3(perturbation.x, perturbation.y, 0.0) * max(1., glossiness));
+	float temp = pow(dot(vNormal, halfvec), max(1., glossiness));
+	result.specular = specularColor * temp * attenuation;
+#endif
+
 	return result;
 }
 
-lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, float range) {
+lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 specularColor, vec3 diffuseColor, float range, float glossiness, vec3 bumpColor) {
 	lightingInfo result;
 
 	vec3 direction = lightData.xyz - vPositionW;
@@ -359,20 +388,42 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
 		float ndl = max(0., dot(vNormal, -lightDirection.xyz));
 		result.diffuse = ndl * spotAtten * diffuseColor * attenuation;
 
+		// Specular
+#ifdef SPECULARTERM		
+		vec3 angleW = normalize(viewDirectionW - lightVectorW);
+		vec2 perturbation = bumpHeight * (bumpColor.rg - 0.5);
+		
+		vec3 halfvec = normalize(angleW + vec3(perturbation.x, perturbation.y, 0.0) * max(1., glossiness));
+		float temp = pow(dot(halfvec, vNormal), max(1., glossiness));
+		result.specular = specularColor * temp * spotAtten * attenuation;
+#endif
 		return result;
 	}
 
 	result.diffuse = vec3(0.);
+#ifdef SPECULARTERM
+	result.specular = vec3(0.);
+#endif
 
 	return result;
 }
 
-lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 groundColor) {
+lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float glossiness, vec3 bumpColor) {
 	lightingInfo result;
 
 	// Diffuse
 	float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
 	result.diffuse = mix(groundColor, diffuseColor, ndl);
+	
+	// Specular
+#ifdef SPECULARTERM
+	vec3 angleW = normalize(viewDirectionW + lightData.xyz);
+	vec2 perturbation = bumpHeight * (bumpColor.rg - 0.5);
+	
+	vec3 halfvec = normalize(angleW + vec3(perturbation.x, perturbation.y, 0.0) * max(1., glossiness));
+	float temp = pow(dot(halfvec, vNormal), max(1., glossiness));
+	result.specular = specularColor * temp;
+#endif
 
 	return result;
 }
@@ -389,12 +440,20 @@ void main(void) {
 	// Base color
 	vec4 baseColor = vec4(1., 1., 1., 1.);
 	vec3 diffuseColor = vDiffuseColor.rgb;
+	
+#ifdef SPECULARTERM
+	float glossiness = vSpecularColor.a;
+	vec3 specularColor = vSpecularColor.rgb;
+#else
+	float glossiness = 0.;
+#endif
 
 	// Alpha
 	float alpha = vDiffuseColor.a;
 
 #ifdef BUMP
 	baseColor = texture2D(normalSampler, vNormalUV);
+	vec3 bumpColor = baseColor.rgb;
 
 #ifdef ALPHATEST
 	if (baseColor.a < 0.4)
@@ -402,15 +461,26 @@ void main(void) {
 #endif
 
 	baseColor.rgb *= vNormalInfos.y;
+#else
+	vec3 bumpColor = vec3(1.0);
 #endif
 
 #ifdef VERTEXCOLOR
 	baseColor.rgb *= vColor.rgb;
 #endif
 
+	// Bump
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+	vec2 perturbation = bumpHeight * (baseColor.rg - 0.5);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+	vec2 perturbation = bumpHeight * (vec2(1.0, 1.0) - 0.5);
+#endif
+
 #ifdef REFLECTION
 	// Water
-	vec2 perturbation = bumpHeight * (baseColor.rg - 0.5);
+	vec3 eyeVector = normalize(vEyePosition - vPosition);
 	
 	vec2 projectedRefractionTexCoords = clamp(vRefractionMapTexCoord.xy / vRefractionMapTexCoord.z + perturbation, 0.0, 1.0);
 	vec4 refractiveColor = texture2D(refractionSampler, projectedRefractionTexCoords);
@@ -418,7 +488,6 @@ void main(void) {
 	vec2 projectedReflectionTexCoords = clamp(vReflectionMapTexCoord.xy / vReflectionMapTexCoord.z + perturbation, 0.0, 1.0);
 	vec4 reflectiveColor = texture2D(reflectionSampler, projectedReflectionTexCoords);
 	
-	vec3 eyeVector = normalize(vEyePosition - vPosition);
 	vec3 upVector = vec3(0.0, 1.0, 0.0);
 	
 	float fresnelTerm = max(dot(eyeVector, upVector), 0.0);
@@ -428,26 +497,25 @@ void main(void) {
 	baseColor = colorBlendFactor * waterColor + (1.0 - colorBlendFactor) * combinedColor;
 #endif
 
-	// Bump
-#ifdef NORMAL
-	vec3 normalW = normalize(vNormalW);
-#else
-	vec3 normalW = vec3(1.0, 1.0, 1.0);
-#endif
-
-		// Lighting
+	// Lighting
 	vec3 diffuseBase = vec3(0., 0., 0.);
+#ifdef SPECULARTERM
+	vec3 specularBase = vec3(0., 0., 0.);
+#endif
 	float shadow = 1.;
 
 #ifdef LIGHT0
+#ifndef SPECULARTERM
+	vec3 vLightSpecular0 = vec3(0.0);
+#endif
 #ifdef SPOTLIGHT0
-	lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightDiffuse0.a);
+	lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, glossiness, bumpColor);
 #endif
 #ifdef HEMILIGHT0
-	lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightGround0);
+	lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, glossiness, bumpColor);
 #endif
 #if defined(POINTLIGHT0) || defined(DIRLIGHT0)
-	lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightDiffuse0.a);
+	lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, glossiness, bumpColor);
 #endif
 #ifdef SHADOW0
 #ifdef SHADOWVSM0
@@ -471,17 +539,23 @@ void main(void) {
 	shadow = 1.;
 #endif
 	diffuseBase += info.diffuse * shadow;
+#ifdef SPECULARTERM
+	specularBase += info.specular * shadow;
+#endif
 #endif
 
 #ifdef LIGHT1
+#ifndef SPECULARTERM
+	vec3 vLightSpecular1 = vec3(0.0);
+#endif
 #ifdef SPOTLIGHT1
-	info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightDiffuse1.a);
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, glossiness, bumpColor);
 #endif
 #ifdef HEMILIGHT1
-	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightGround1.a);
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1.a, glossiness, bumpColor);
 #endif
 #if defined(POINTLIGHT1) || defined(DIRLIGHT1)
-	info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightDiffuse1.a);
+	info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, glossiness, bumpColor);
 #endif
 #ifdef SHADOW1
 #ifdef SHADOWVSM1
@@ -505,17 +579,23 @@ void main(void) {
 	shadow = 1.;
 #endif
 	diffuseBase += info.diffuse * shadow;
+#ifdef SPECULARTERM
+	specularBase += info.specular * shadow;
+#endif
 #endif
 
 #ifdef LIGHT2
+#ifndef SPECULARTERM
+	vec3 vLightSpecular2 = vec3(0.0);
+#endif
 #ifdef SPOTLIGHT2
-	info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightDiffuse2.a);
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, glossiness, bumpColor);
 #endif
 #ifdef HEMILIGHT2
-	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightGround2);
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, glossiness, bumpColor);
 #endif
 #if defined(POINTLIGHT2) || defined(DIRLIGHT2)
-	info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightDiffuse2.a);
+	info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, glossiness, bumpColor);
 #endif
 #ifdef SHADOW2
 #ifdef SHADOWVSM2
@@ -539,17 +619,23 @@ void main(void) {
 	shadow = 1.;
 #endif
 	diffuseBase += info.diffuse * shadow;
+#ifdef SPECULARTERM
+	specularBase += info.specular * shadow;
+#endif
 #endif
 
 #ifdef LIGHT3
+#ifndef SPECULARTERM
+	vec3 vLightSpecular3 = vec3(0.0);
+#endif
 #ifdef SPOTLIGHT3
-	info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightDiffuse3.a);
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, glossiness, bumpColor);
 #endif
 #ifdef HEMILIGHT3
-	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightGround3);
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, glossiness, bumpColor);
 #endif
 #if defined(POINTLIGHT3) || defined(DIRLIGHT3)
-	info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightDiffuse3.a);
+	info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, glossiness, bumpColor);
 #endif
 #ifdef SHADOW3
 #ifdef SHADOWVSM3
@@ -573,16 +659,25 @@ void main(void) {
 	shadow = 1.;
 #endif
 	diffuseBase += info.diffuse * shadow;
+#ifdef SPECULARTERM
+	specularBase += info.specular * shadow;
+#endif
 #endif
 
 #ifdef VERTEXALPHA
 	alpha *= vColor.a;
 #endif
 
+#ifdef SPECULARTERM
+	vec3 finalSpecular = specularBase * specularColor;
+#else
+	vec3 finalSpecular = vec3(0.0);
+#endif
+
 	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;
 
 	// Composition
-	vec4 color = vec4(finalDiffuse, alpha);
+	vec4 color = vec4(finalDiffuse + finalSpecular, alpha);
 
 #ifdef FOG
 	float fog = CalcFogFactor();

+ 3 - 2
materialsLibrary/materials/water/water.vertex.fx

@@ -92,6 +92,7 @@ uniform float waveLength;
 uniform float time;
 uniform float windForce;
 uniform float waveHeight;
+uniform float waveSpeed;
 
 // Water varyings
 varying vec3 vPosition;
@@ -184,8 +185,8 @@ void main(void) {
 #endif
 
 	vec3 p = position;
-	float newY = (sin(((p.x / 0.05) + time * windForce) * windDirection.x) * waveHeight * 5.0)
-			   + (cos(((p.z / 0.05) + time * windForce) * windDirection.y) * waveHeight * 5.0);
+	float newY = (sin(((p.x / 0.05) + time * waveSpeed * windForce) * windDirection.x) * waveHeight * 5.0)
+			   + (cos(((p.z / 0.05) + time * waveSpeed * windForce) * windDirection.y) * waveHeight * 5.0);
 	p.y += abs(newY);
 	
 	gl_Position = viewProjection * finalWorld * vec4(p, 1.0);

File diff suppressed because it is too large
+ 48 - 24
materialsLibrary/test/babylon.max.js


+ 10 - 1
src/Animations/babylon.animatable.js

@@ -49,6 +49,12 @@ var BABYLON;
             this._localDelayOffset = null;
             this._pausedDelay = null;
         };
+        Animatable.prototype.goToFrame = function (frame) {
+            var animations = this._animations;
+            for (var index = 0; index < animations.length; index++) {
+                animations[index].goToFrame(frame);
+            }
+        };
         Animatable.prototype.pause = function () {
             if (this._paused) {
                 return;
@@ -69,6 +75,7 @@ var BABYLON;
         };
         Animatable.prototype._animate = function (delay) {
             if (this._paused) {
+                this.animationStarted = false;
                 if (!this._pausedDelay) {
                     this._pausedDelay = delay;
                 }
@@ -84,11 +91,13 @@ var BABYLON;
             // Animating
             var running = false;
             var animations = this._animations;
-            for (var index = 0; index < animations.length; index++) {
+            var index;
+            for (index = 0; index < animations.length; index++) {
                 var animation = animations[index];
                 var isRunning = animation.animate(delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio);
                 running = running || isRunning;
             }
+            this.animationStarted = running;
             if (!running) {
                 // Remove from active animatables
                 index = this._scene._activeAnimatables.indexOf(this);

+ 13 - 1
src/Animations/babylon.animatable.ts

@@ -55,6 +55,14 @@
 
         }
 
+        public goToFrame(frame: number): void {
+            var animations = this._animations;
+
+            for (var index = 0; index < animations.length; index++) {
+                animations[index].goToFrame(frame);
+            }
+        }
+
         public pause(): void {
             if (this._paused) {
                 return;
@@ -80,6 +88,7 @@
 
         public _animate(delay: number): boolean {
             if (this._paused) {
+                this.animationStarted = false;
                 if (!this._pausedDelay) {
                     this._pausedDelay = delay;
                 }
@@ -96,13 +105,16 @@
             // Animating
             var running = false;
             var animations = this._animations;
+            var index: number;
 
-            for (var index = 0; index < animations.length; index++) {
+            for (index = 0; index < animations.length; index++) {
                 var animation = animations[index];
                 var isRunning = animation.animate(delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio);
                 running = running || isRunning;
             }
 
+            this.animationStarted = running;
+
             if (!running) {
                 // Remove from active animatables
                 index = this._scene._activeAnimatables.indexOf(this);

+ 38 - 16
src/Animations/babylon.animation.js

@@ -25,7 +25,7 @@ var BABYLON;
             this.dataType = dataType;
             this.loopMode = loopMode === undefined ? Animation.ANIMATIONLOOPMODE_CYCLE : loopMode;
         }
-        Animation.CreateAndStartAnimation = function (name, mesh, targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction, onAnimationEnd) {
+        Animation._PrepareAnimation = function (targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction) {
             var dataType = undefined;
             if (!isNaN(parseFloat(from)) && isFinite(from)) {
                 dataType = Animation.ANIMATIONTYPE_FLOAT;
@@ -53,8 +53,16 @@ var BABYLON;
             if (easingFunction !== undefined) {
                 animation.setEasingFunction(easingFunction);
             }
-            mesh.animations.push(animation);
-            return mesh.getScene().beginAnimation(mesh, 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
+            return animation;
+        };
+        Animation.CreateAndStartAnimation = function (name, node, targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction, onAnimationEnd) {
+            var animation = Animation._PrepareAnimation(targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction);
+            return node.getScene().beginDirectAnimation(node, [animation], 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
+        };
+        Animation.CreateMergeAndStartAnimation = function (name, node, targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction, onAnimationEnd) {
+            var animation = Animation._PrepareAnimation(targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction);
+            node.animations.push(animation);
+            return node.getScene().beginAnimation(node, 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
         };
         // Methods   
         Animation.prototype.createRange = function (name, from, to) {
@@ -233,6 +241,32 @@ var BABYLON;
             }
             return this._getKeyValue(this._keys[this._keys.length - 1].value);
         };
+        Animation.prototype.setValue = function (currentValue) {
+            // Set value
+            if (this.targetPropertyPath.length > 1) {
+                var property = this._target[this.targetPropertyPath[0]];
+                for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
+                    property = property[this.targetPropertyPath[index]];
+                }
+                property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
+            }
+            else {
+                this._target[this.targetPropertyPath[0]] = currentValue;
+            }
+            if (this._target.markAsDirty) {
+                this._target.markAsDirty(this.targetProperty);
+            }
+        };
+        Animation.prototype.goToFrame = function (frame) {
+            if (frame < this._keys[0].frame) {
+                frame = this._keys[0].frame;
+            }
+            else if (frame > this._keys[this._keys.length - 1].frame) {
+                frame = this._keys[this._keys.length - 1].frame;
+            }
+            var currentValue = this._interpolate(frame, 0, this.loopMode);
+            this.setValue(currentValue);
+        };
         Animation.prototype.animate = function (delay, from, to, loop, speedRatio) {
             if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
                 this._stopped = true;
@@ -323,19 +357,7 @@ var BABYLON;
             var currentFrame = returnValue ? from + ratio % range : to;
             var currentValue = this._interpolate(currentFrame, repeatCount, this.loopMode, offsetValue, highLimitValue);
             // Set value
-            if (this.targetPropertyPath.length > 1) {
-                var property = this._target[this.targetPropertyPath[0]];
-                for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
-                    property = property[this.targetPropertyPath[index]];
-                }
-                property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
-            }
-            else {
-                this._target[this.targetPropertyPath[0]] = currentValue;
-            }
-            if (this._target.markAsDirty) {
-                this._target.markAsDirty(this.targetProperty);
-            }
+            this.setValue(currentValue);
             if (!returnValue) {
                 this._stopped = true;
             }

+ 52 - 21
src/Animations/babylon.animation.ts

@@ -19,10 +19,8 @@
 
         private _ranges = new Array<AnimationRange>();
 
-        public static CreateAndStartAnimation(name: string, mesh: AbstractMesh, targetProperty: string,
-            framePerSecond: number, totalFrame: number,
-            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void) {
-
+        static _PrepareAnimation(targetProperty: string, framePerSecond: number, totalFrame: number,
+            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction): Animation {
             var dataType = undefined;
 
             if (!isNaN(parseFloat(from)) && isFinite(from)) {
@@ -52,10 +50,27 @@
                 animation.setEasingFunction(easingFunction);
             }
 
-            mesh.animations.push(animation);
+            return animation;
+        }
+
+        public static CreateAndStartAnimation(name: string, node: Node, targetProperty: string,
+            framePerSecond: number, totalFrame: number,
+            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void) {
+
+            var animation = Animation._PrepareAnimation(targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction);
+
+            return node.getScene().beginDirectAnimation(node, [animation], 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
+        }
+
+        public static CreateMergeAndStartAnimation(name: string, node: Node, targetProperty: string,
+            framePerSecond: number, totalFrame: number,
+            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void) {
+
+            var animation = Animation._PrepareAnimation(targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction);
 
-            return mesh.getScene().beginAnimation(mesh, 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
+            node.animations.push(animation);
 
+            return node.getScene().beginAnimation(node, 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
         }
 
         constructor(public name: string, public targetProperty: string, public framePerSecond: number, public dataType: number, public loopMode?: number) {
@@ -276,6 +291,36 @@
             return this._getKeyValue(this._keys[this._keys.length - 1].value);
         }
 
+        public setValue(currentValue: any): void {
+            // Set value
+            if (this.targetPropertyPath.length > 1) {
+                var property = this._target[this.targetPropertyPath[0]];
+
+                for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
+                    property = property[this.targetPropertyPath[index]];
+                }
+
+                property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
+            } else {
+                this._target[this.targetPropertyPath[0]] = currentValue;
+            }
+
+            if (this._target.markAsDirty) {
+                this._target.markAsDirty(this.targetProperty);
+            }
+        }
+
+        public goToFrame(frame: number): void {
+            if (frame < this._keys[0].frame) {
+                frame = this._keys[0].frame
+            } else if (frame > this._keys[this._keys.length - 1].frame) {
+                frame = this._keys[this._keys.length - 1].frame;
+            }
+
+            var currentValue = this._interpolate(frame, 0, this.loopMode);
+
+            this.setValue(currentValue);
+        }
 
         public animate(delay: number, from: number, to: number, loop: boolean, speedRatio: number): boolean {
             if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
@@ -377,21 +422,7 @@
             var currentValue = this._interpolate(currentFrame, repeatCount, this.loopMode, offsetValue, highLimitValue);
 
             // Set value
-            if (this.targetPropertyPath.length > 1) {
-                var property = this._target[this.targetPropertyPath[0]];
-
-                for (var index = 1; index < this.targetPropertyPath.length - 1; index++) {
-                    property = property[this.targetPropertyPath[index]];
-                }
-
-                property[this.targetPropertyPath[this.targetPropertyPath.length - 1]] = currentValue;
-            } else {
-                this._target[this.targetPropertyPath[0]] = currentValue;
-            }
-
-            if (this._target.markAsDirty) {
-                this._target.markAsDirty(this.targetProperty);
-            }
+            this.setValue(currentValue);
 
             if (!returnValue) {
                 this._stopped = true;

+ 3 - 0
src/Materials/babylon.material.js

@@ -152,6 +152,9 @@ var BABYLON;
         };
         Material.prototype.trackCreation = function (onCompiled, onError) {
         };
+        Material.prototype.resetCheckReadyOnlyOnceFlag = function () {
+            this._wasPreviouslyReady = false;
+        };
         Material.prototype._preBind = function () {
             var engine = this._scene.getEngine();
             engine.enableEffect(this._effect);

+ 4 - 0
src/Materials/babylon.material.ts

@@ -167,6 +167,10 @@
         public trackCreation(onCompiled: (effect: Effect) => void, onError: (effect: Effect, errors: string) => void) {
         }
 
+        public resetCheckReadyOnlyOnceFlag(): void {
+            this._wasPreviouslyReady = false;
+        }
+
         public _preBind(): void {
             var engine = this._scene.getEngine();
 

+ 3 - 0
src/Materials/babylon.standardMaterial.js

@@ -517,6 +517,9 @@ var BABYLON;
                 if (this._defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
+                if (this._defines.POINTSIZE) {
+                    fallbacks.addFallback(0, "POINTSIZE");
+                }
                 for (var lightIndex = 0; lightIndex < maxSimultaneousLights; lightIndex++) {
                     if (!this._defines["LIGHT" + lightIndex]) {
                         continue;

+ 4 - 0
src/Materials/babylon.standardMaterial.ts

@@ -602,6 +602,10 @@
                     fallbacks.addFallback(1, "FOG");
                 }
 
+                if (this._defines.POINTSIZE) {
+                    fallbacks.addFallback(0, "POINTSIZE");
+                }
+
                 for (var lightIndex = 0; lightIndex < maxSimultaneousLights; lightIndex++) {
                     if (!this._defines["LIGHT" + lightIndex]) {
                         continue;

+ 9 - 3
src/PostProcess/babylon.hdrRenderingPipeline.js

@@ -38,6 +38,11 @@ var BABYLON;
             * @type {number}
             */
             this.gaussStandDev = 0.8;
+            /**
+            * Gaussian blur multiplier. Multiplies the blur effect
+            * @type {number}
+            */
+            this.gaussMultiplier = 4.0;
             // HDR
             /**
             * Exposure, controls the overall intensity of the pipeline
@@ -322,12 +327,12 @@ var BABYLON;
             var blurOffsetsW = new Array(9);
             var blurOffsetsH = new Array(9);
             var blurWeights = new Array(9);
-            var uniforms = ["blurOffsets", "blurWeights"];
+            var uniforms = ["blurOffsets", "blurWeights", "multiplier"];
             // Utils for gaussian blur
             var calculateBlurOffsets = function (height) {
                 var lastOutputDimensions = {
-                    width: scene.getEngine().getRenderWidth() * (ratio / 4),
-                    height: scene.getEngine().getRenderHeight() * (ratio / 4)
+                    width: scene.getEngine().getRenderWidth(),
+                    height: scene.getEngine().getRenderHeight()
                 };
                 for (var i = 0; i < 9; i++) {
                     var value = (i - 4.0) * (1.0 / (height === true ? lastOutputDimensions.height : lastOutputDimensions.width));
@@ -355,6 +360,7 @@ var BABYLON;
                     }
                     effect.setArray("blurOffsets", height ? blurOffsetsH : blurOffsetsW);
                     effect.setArray("blurWeights", blurWeights);
+                    effect.setFloat("multiplier", _this.gaussMultiplier);
                 };
             };
             // Create horizontal gaussian blur post-processes

+ 9 - 3
src/PostProcess/babylon.hdrRenderingPipeline.ts

@@ -21,6 +21,11 @@
         * @type {number}
         */
         public gaussStandDev: number = 0.8;
+        /**
+        * Gaussian blur multiplier. Multiplies the blur effect
+        * @type {number}
+        */
+        public gaussMultiplier: number = 4.0;
 
         // HDR
         /**
@@ -393,13 +398,13 @@
             var blurOffsetsW = new Array<number>(9);
             var blurOffsetsH = new Array<number>(9);
             var blurWeights = new Array<number>(9);
-            var uniforms: string[] = ["blurOffsets", "blurWeights"];
+            var uniforms: string[] = ["blurOffsets", "blurWeights", "multiplier"];
 
             // Utils for gaussian blur
             var calculateBlurOffsets = (height: boolean) => {
                 var lastOutputDimensions: any = {
-                    width: scene.getEngine().getRenderWidth() * (ratio / 4),
-                    height: scene.getEngine().getRenderHeight() * (ratio / 4)
+                    width: scene.getEngine().getRenderWidth(),
+                    height: scene.getEngine().getRenderHeight()
                 };
 
                 for (var i = 0; i < 9; i++) {
@@ -430,6 +435,7 @@
                     }
                     effect.setArray("blurOffsets", height ? blurOffsetsH : blurOffsetsW);
                     effect.setArray("blurWeights", blurWeights);
+                    effect.setFloat("multiplier", this.gaussMultiplier);
                 };
             };
 

+ 24 - 13
src/PostProcess/babylon.ssaoRenderingPipeline.js

@@ -49,24 +49,30 @@ var BABYLON;
             */
             this.totalStrength = 1.0;
             /**
-            * The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.0002
+            * The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.0006
             * @type {number}
             */
-            this.radius = 0.0002;
+            this.radius = 0.0001;
             /**
             * Related to fallOff, used to interpolate SSAO samples (first interpolate function input) based on the occlusion difference of each pixel
             * Must not be equal to fallOff and superior to fallOff.
-            * Default value is 0.0075
+            * Default value is 0.975
             * @type {number}
             */
             this.area = 0.0075;
             /**
             * Related to area, used to interpolate SSAO samples (second interpolate function input) based on the occlusion difference of each pixel
             * Must not be equal to area and inferior to area.
-            * Default value is 0.0002
+            * Default value is 0.0
             * @type {number}
             */
-            this.fallOff = 0.0002;
+            this.fallOff = 0.000001;
+            /**
+            * The base color of the SSAO post-process
+            * The final result is "base + ssao" between [0, 1]
+            * @type {number}
+            */
+            this.base = 0.5;
             this._firstUpdate = true;
             this._scene = scene;
             // Set up assets
@@ -76,8 +82,8 @@ var BABYLON;
             var combineRatio = ratio.combineRatio || ratio;
             this._originalColorPostProcess = new BABYLON.PassPostProcess("SSAOOriginalSceneColor", combineRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOPostProcess(ssaoRatio);
-            this._blurHPostProcess = new BABYLON.BlurPostProcess("SSAOBlurH", new BABYLON.Vector2(1.0, 0.0), 4.0, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
-            this._blurVPostProcess = new BABYLON.BlurPostProcess("SSAOBlurV", new BABYLON.Vector2(0.0, 1.0), 4.0, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurHPostProcess = new BABYLON.BlurPostProcess("SSAOBlurH", new BABYLON.Vector2(1.0, 0.0), 2.0, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurVPostProcess = new BABYLON.BlurPostProcess("SSAOBlurV", new BABYLON.Vector2(0.0, 1.0), 2.0, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOCombinePostProcess(combineRatio);
             // Set up pipeline
             this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), this.SSAOOriginalSceneColorEffect, function () { return _this._originalColorPostProcess; }, true));
@@ -123,6 +129,7 @@ var BABYLON;
         // Private Methods
         SSAORenderingPipeline.prototype._createSSAOPostProcess = function (ratio) {
             var _this = this;
+            var numSamples = 16;
             var sampleSphere = [
                 0.5381, 0.1856, -0.4319,
                 0.1379, 0.2486, 0.4430,
@@ -141,8 +148,11 @@ var BABYLON;
                 0.0352, -0.0631, 0.5460,
                 -0.4776, 0.2847, -0.0271
             ];
-            var samplesFactor = 1.0 / 16.0;
-            this._ssaoPostProcess = new BABYLON.PostProcess("ssao", "ssao", ["sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius", "area", "fallOff"], ["randomSampler"], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false);
+            var samplesFactor = 1.0 / numSamples;
+            this._ssaoPostProcess = new BABYLON.PostProcess("ssao", "ssao", [
+                "sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius",
+                "area", "fallOff", "base"
+            ], ["randomSampler"], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define SAMPLES " + numSamples);
             this._ssaoPostProcess.onApply = function (effect) {
                 if (_this._firstUpdate) {
                     effect.setArray3("sampleSphere", sampleSphere);
@@ -154,6 +164,7 @@ var BABYLON;
                 effect.setFloat("radius", _this.radius);
                 effect.setFloat("area", _this.area);
                 effect.setFloat("fallOff", _this.fallOff);
+                effect.setFloat("base", _this.base);
                 effect.setTexture("textureSampler", _this._depthTexture);
                 effect.setTexture("randomSampler", _this._randomTexture);
             };
@@ -174,12 +185,12 @@ var BABYLON;
             var rand = function (min, max) {
                 return Math.random() * (max - min) + min;
             };
+            var randVector = BABYLON.Vector3.Zero();
             for (var x = 0; x < size; x++) {
                 for (var y = 0; y < size; y++) {
-                    var randVector = BABYLON.Vector3.Zero();
-                    randVector.x = Math.floor(rand(0.0, 1.0) * 255);
-                    randVector.y = Math.floor(rand(0.0, 1.0) * 255);
-                    randVector.z = Math.floor(rand(0.0, 1.0) * 255);
+                    randVector.x = Math.floor(rand(-1.0, 1.0) * 255);
+                    randVector.y = Math.floor(rand(-1.0, 1.0) * 255);
+                    randVector.z = Math.floor(rand(-1.0, 1.0) * 255);
                     context.fillStyle = 'rgb(' + randVector.x + ', ' + randVector.y + ', ' + randVector.z + ')';
                     context.fillRect(x, y, 1, 1);
                 }

+ 29 - 15
src/PostProcess/babylon.ssaoRenderingPipeline.ts

@@ -35,15 +35,15 @@
         public totalStrength: number = 1.0;
 
         /**
-        * The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.0002
+        * The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.0006
         * @type {number}
         */
-        public radius: number = 0.0002;
+        public radius: number = 0.0001;
 
         /**
         * Related to fallOff, used to interpolate SSAO samples (first interpolate function input) based on the occlusion difference of each pixel
         * Must not be equal to fallOff and superior to fallOff.
-        * Default value is 0.0075
+        * Default value is 0.975
         * @type {number}
         */
         public area: number = 0.0075;
@@ -51,10 +51,17 @@
         /**
         * Related to area, used to interpolate SSAO samples (second interpolate function input) based on the occlusion difference of each pixel
         * Must not be equal to area and inferior to area.
-        * Default value is 0.0002
+        * Default value is 0.0
         * @type {number}
         */
-        public fallOff: number = 0.0002;
+        public fallOff: number = 0.000001;
+
+        /**
+        * The base color of the SSAO post-process
+        * The final result is "base + ssao" between [0, 1]
+        * @type {number}
+        */
+        public base: number = 0.5;
 
         private _scene: Scene;
         private _depthTexture: RenderTargetTexture;
@@ -89,8 +96,8 @@
 
             this._originalColorPostProcess = new PassPostProcess("SSAOOriginalSceneColor", combineRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOPostProcess(ssaoRatio);
-            this._blurHPostProcess = new BlurPostProcess("SSAOBlurH", new Vector2(1.0, 0.0), 4.0, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
-            this._blurVPostProcess = new BlurPostProcess("SSAOBlurV", new Vector2(0.0, 1.0), 4.0, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurHPostProcess = new BlurPostProcess("SSAOBlurH", new Vector2(1.0, 0.0), 2.0, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurVPostProcess = new BlurPostProcess("SSAOBlurV", new Vector2(0.0, 1.0), 2.0, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOCombinePostProcess(combineRatio);
 
             // Set up pipeline
@@ -143,6 +150,7 @@
 
         // Private Methods
         private _createSSAOPostProcess(ratio: number): void {
+            var numSamples = 16;
             var sampleSphere = [
                 0.5381, 0.1856, -0.4319,
                 0.1379, 0.2486, 0.4430,
@@ -161,12 +169,17 @@
                 0.0352, -0.0631, 0.5460,
                 -0.4776, 0.2847, -0.0271
             ];
-            var samplesFactor = 1.0 / 16.0;
+            var samplesFactor = 1.0 / numSamples;
 
-            this._ssaoPostProcess = new PostProcess("ssao", "ssao", ["sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius", "area", "fallOff"],
+            this._ssaoPostProcess = new PostProcess("ssao", "ssao",
+                                                    [
+                                                        "sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius",
+                                                        "area", "fallOff", "base"
+                                                    ],
                                                     ["randomSampler"],
                                                     ratio, null, Texture.BILINEAR_SAMPLINGMODE,
-                                                    this._scene.getEngine(), false);
+                                                    this._scene.getEngine(), false,
+                                                    "#define SAMPLES " + numSamples);
 
             this._ssaoPostProcess.onApply = (effect: Effect) => {
                 if (this._firstUpdate) {
@@ -180,6 +193,7 @@
                 effect.setFloat("radius", this.radius);
                 effect.setFloat("area", this.area);
                 effect.setFloat("fallOff", this.fallOff);
+                effect.setFloat("base", this.base);
 
                 effect.setTexture("textureSampler", this._depthTexture);
                 effect.setTexture("randomSampler", this._randomTexture);
@@ -209,13 +223,13 @@
                 return Math.random() * (max - min) + min;
             }
 
+            var randVector = Vector3.Zero();
+
             for (var x = 0; x < size; x++) {
                 for (var y = 0; y < size; y++) {
-                    var randVector = Vector3.Zero();
-
-                    randVector.x = Math.floor(rand(0.0, 1.0) * 255);
-                    randVector.y = Math.floor(rand(0.0, 1.0) * 255);
-                    randVector.z = Math.floor(rand(0.0, 1.0) * 255);
+                    randVector.x = Math.floor(rand(-1.0, 1.0) * 255);
+                    randVector.y = Math.floor(rand(-1.0, 1.0) * 255);
+                    randVector.z = Math.floor(rand(-1.0, 1.0) * 255);
 
                     context.fillStyle = 'rgb(' + randVector.x + ', ' + randVector.y + ', ' + randVector.z + ')';
                     context.fillRect(x, y, 1, 1);

+ 12 - 11
src/Shaders/default.fragment.fx

@@ -830,22 +830,23 @@ void main(void) {
 	vec3 vReflectionUVW = computeReflectionCoords(vec4(vPositionW, 1.0), normalW);
 
 #ifdef REFLECTIONMAP_3D
-	float bias = 0.;
-
 #ifdef ROUGHNESS
-	bias = vReflectionInfos.y;
-#endif
+	 float bias = vReflectionInfos.y;
 
-#ifdef SPECULARTERM
-#ifdef SPECULAR
-#ifdef GLOSSINESS
-	bias *= (1.0 - specularMapColor.a);
-#endif
-#endif
-#endif
+	#ifdef SPECULARTERM
+	#ifdef SPECULAR
+	#ifdef GLOSSINESS
+		bias *= (1.0 - specularMapColor.a);
+	#endif
+	#endif
+	#endif
 
 	reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW, bias).rgb * vReflectionInfos.x;
 #else
+	reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.x;
+#endif
+
+#else
 	vec2 coords = vReflectionUVW.xy;
 
 #ifdef REFLECTIONMAP_PROJECTION

+ 3 - 2
src/Shaders/hdr.fragment.fx

@@ -6,15 +6,16 @@ varying vec2 vUV;
 #if defined(GAUSSIAN_BLUR_H) || defined(GAUSSIAN_BLUR_V)
 uniform float blurOffsets[9];
 uniform float blurWeights[9];
+uniform float multiplier;
 
 void main(void) {
 	vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
 
 	for (int i = 0; i < 9; i++) {
 		#ifdef GAUSSIAN_BLUR_H
-		color += (texture2D(textureSampler, vUV + vec2(blurOffsets[i], 0.0)) * blurWeights[i]);
+		color += (texture2D(textureSampler, vUV + vec2(blurOffsets[i] * multiplier, 0.0)) * blurWeights[i]);
 		#else
-		color += (texture2D(textureSampler, vUV + vec2(0.0, blurOffsets[i])) * blurWeights[i]);
+		color += (texture2D(textureSampler, vUV + vec2(0.0, blurOffsets[i] * multiplier)) * blurWeights[i]);
 		#endif
 	}
 

+ 8 - 11
src/Shaders/ssao.fragment.fx

@@ -1,25 +1,24 @@
 precision highp float;
 
-#define SAMPLES 16
-
 uniform sampler2D textureSampler;
 uniform sampler2D randomSampler;
 
 uniform float randTextureTiles;
 uniform float samplesFactor;
-uniform vec3 sampleSphere[16];
+uniform vec3 sampleSphere[SAMPLES];
 
 uniform float totalStrength;
 uniform float radius;
 uniform float area;
 uniform float fallOff;
+uniform float base;
 
 varying vec2 vUV;
 
-const vec2 offset1 = vec2(0.0, 0.001);
-const vec2 offset2 = vec2(0.001, 0.0);
+vec3 normalFromDepth(float depth, vec2 coords) {
+	vec2 offset1 = vec2(0.0, radius);
+	vec2 offset2 = vec2(radius, 0.0);
 
-vec3 normalFromDepth(const float depth, const vec2 coords) {
 	float depth1 = texture2D(textureSampler, coords + offset1).r;
 	float depth2 = texture2D(textureSampler, coords + offset2).r;
 
@@ -27,15 +26,13 @@ vec3 normalFromDepth(const float depth, const vec2 coords) {
     vec3 p2 = vec3(offset2, depth2 - depth);
 
     vec3 normal = cross(p1, p2);
-    normal.z = -normal.z;
+	normal.z = -normal.z;
 
     return normalize(normal);
 }
 
-void main(void)
+void main()
 {
-	const float base = 0.2;
-
 	vec3 random = normalize(texture2D(randomSampler, vUV * randTextureTiles).rgb);
 	float depth = texture2D(textureSampler, vUV).r;
 	vec3 position = vec3(vUV, depth);
@@ -53,7 +50,7 @@ void main(void)
 		ray = radiusDepth * reflect(sampleSphere[i], random);
 		hemiRay = position + sign(dot(ray, normal)) * ray;
 
-		occlusionDepth = texture2D(textureSampler, clamp(hemiRay.xy, 0.0, 1.0)).r;
+		occlusionDepth = texture2D(textureSampler, clamp(hemiRay.xy, vec2(0.001, 0.001), vec2(0.999, 0.999))).r;
 		difference = depth - occlusionDepth;
 
 		occlusion += step(fallOff, difference) * (1.0 - smoothstep(fallOff, area, difference));

+ 4 - 1
src/Shaders/ssaoCombine.fragment.fx

@@ -6,5 +6,8 @@ uniform sampler2D originalColor;
 varying vec2 vUV;
 
 void main(void) {
-	gl_FragColor = texture2D(originalColor, vUV) * texture2D(textureSampler, vUV);
+	vec4 ssaoColor = texture2D(textureSampler, vUV);
+	vec4 sceneColor = texture2D(originalColor, vUV);
+
+	gl_FragColor = sceneColor * ssaoColor;
 }

+ 10 - 6
src/babylon.scene.js

@@ -185,7 +185,7 @@ var BABYLON;
             configurable: true
         });
         Object.defineProperty(Scene.prototype, "debugLayer", {
-            // Properties 
+            // Properties
             get: function () {
                 return this._debugLayer;
             },
@@ -338,12 +338,16 @@ var BABYLON;
                     pickResult = _this.pickSprite(_this._pointerX, _this._pointerY, spritePredicate, false, _this.cameraToUseForPointers);
                     if (pickResult.hit && pickResult.pickedSprite) {
                         canvas.style.cursor = "pointer";
-                        return;
                     }
-                    // Restore pointer
-                    _this.setPointerOverMesh(null);
-                    canvas.style.cursor = "";
-                    _this._meshUnderPointer = null;
+                    else {
+                        // Restore pointer
+                        _this.setPointerOverMesh(null);
+                        canvas.style.cursor = "";
+                        _this._meshUnderPointer = null;
+                    }
+                }
+                if (_this.onPointerMove) {
+                    _this.onPointerMove(evt, pickResult);
                 }
             };
             this._onPointerDown = function (evt) {

+ 3 - 2
src/babylon.scene.ts

@@ -315,7 +315,7 @@
             this.workerCollisions = false;//(!!Worker && (!!BABYLON.CollisionWorker || BABYLON.WorkerIncluded));
         }
 
-        // Properties o
+        // Properties
         public get debugLayer(): DebugLayer {
             return this._debugLayer;
         }
@@ -492,7 +492,7 @@
                         this._meshUnderPointer = null;
                     }
                 }
-                
+
                 if (this.onPointerMove) {
                     this.onPointerMove(evt, pickResult);
                 }
@@ -2426,3 +2426,4 @@
         }
     }
 } 
+