David Catuhe 9 vuotta sitten
vanhempi
commit
38ea39a10c

+ 72 - 63
src/Mesh/babylon.mesh.js

@@ -18,11 +18,11 @@ var BABYLON;
         __extends(Mesh, _super);
         /**
          * @constructor
-         * @param {string} name - The value used by scene.getMeshByName() to do a lookup.
-         * @param {Scene} scene - The scene to add this mesh to.
-         * @param {Node} parent - The parent of this mesh, if it has one
-         * @param {Mesh} source - An optional Mesh from which geometry is shared, cloned.
-         * @param {boolean} doNotCloneChildren - When cloning, skip cloning child meshes of source, default False.
+         * @param {string} name The value used by scene.getMeshByName() to do a lookup.
+         * @param {Scene} scene The scene to add this mesh to.
+         * @param {Node} parent The parent of this mesh, if it has one
+         * @param {Mesh} source An optional Mesh from which geometry is shared, cloned.
+         * @param {boolean} doNotCloneChildren When cloning, skip cloning child meshes of source, default False.
          *                  When false, achieved by calling a clone(), also passing False.
          *                  This will make creation of children, recursive.
          */
@@ -230,9 +230,9 @@ var BABYLON;
         /**
          * Add a mesh as LOD level triggered at the given distance.
          * tuto : http://doc.babylonjs.com/tutorials/How_to_use_LOD
-         * @param {number} distance - the distance from the center of the object to show this level
-         * @param {Mesh} mesh - the mesh to be added as LOD level
-         * @return {Mesh} this mesh (for chaining)
+         * @param {number} distance The distance from the center of the object to show this level
+         * @param {Mesh} mesh The mesh to be added as LOD level
+         * @return {Mesh} This mesh (for chaining)
          */
         Mesh.prototype.addLODLevel = function (distance, mesh) {
             if (mesh && mesh._masterMesh) {
@@ -264,8 +264,8 @@ var BABYLON;
         /**
          * Remove a mesh from the LOD array
          * tuto : http://doc.babylonjs.com/tutorials/How_to_use_LOD
-         * @param {Mesh} mesh - the mesh to be removed.
-         * @return {Mesh} this mesh (for chaining)
+         * @param {Mesh} mesh The mesh to be removed.
+         * @return {Mesh} This mesh (for chaining)
          */
         Mesh.prototype.removeLODLevel = function (mesh) {
             for (var index = 0; index < this._LODLevels.length; index++) {
@@ -314,7 +314,7 @@ var BABYLON;
         };
         Object.defineProperty(Mesh.prototype, "geometry", {
             /**
-             * Returns the mesh internal `Geometry` object.
+             * Returns the mesh internal Geometry object.
              */
             get: function () {
                 return this._geometry;
@@ -356,7 +356,7 @@ var BABYLON;
             return this._geometry.getVerticesData(kind, copyWhenShared);
         };
         /**
-         * Returns the mesh `VertexBuffer` object from the requested `kind` : positions, indices, normals, etc.
+         * Returns the mesh VertexBuffer object from the requested `kind` : positions, indices, normals, etc.
          * Returns `undefined` if the mesh has no geometry.
          * Possible `kind` values :
          * - BABYLON.VertexBuffer.PositionKind
@@ -541,7 +541,7 @@ var BABYLON;
             this._visibleInstances[renderId].push(instance);
         };
         /**
-         * This method recomputes and sets a new `BoundingInfo` to the mesh unless it is locked.
+         * This method recomputes and sets a new BoundingInfo to the mesh unless it is locked.
          * This means the mesh underlying bounding box and sphere are recomputed.
          */
         Mesh.prototype.refreshBoundingInfo = function () {
@@ -591,12 +591,12 @@ var BABYLON;
         };
         /**
          * Sets the vertex data of the mesh geometry for the requested `kind`.
-         * If the mesh has no geometry, a new `Geometry` object is set to the mesh and then passed this vertex data.
+         * If the mesh has no geometry, a new Geometry object is set to the mesh and then passed this vertex data.
          * The `data` are either a numeric array either a Float32Array.
-         * The parameter `updatable` is passed as is to the underlying `Geometry` object constructor (if initianilly none) or updater.
+         * The parameter `updatable` is passed as is to the underlying Geometry object constructor (if initianilly none) or updater.
          * The parameter `stride` is an optional positive integer, it is usually automatically deducted from the `kind` (3 for positions or normals, 2 for UV, etc).
-         * Note that a new underlying `VertexBuffer` object is created each call.
-         * If the `kind` is the `PositionKind`, the mesh `BoundingInfo` is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.
+         * Note that a new underlying VertexBuffer object is created each call.
+         * If the `kind` is the `PositionKind`, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.
          *
          * Possible `kind` values :
          * - BABYLON.VertexBuffer.PositionKind
@@ -627,8 +627,8 @@ var BABYLON;
          * Updates the existing vertex data of the mesh geometry for the requested `kind`.
          * If the mesh has no geometry, it is simply returned as it is.
          * The `data` are either a numeric array either a Float32Array.
-         * No new underlying `VertexBuffer` object is created.
-         * If the `kind` is the `PositionKind` and if `updateExtends` is true, the mesh `BoundingInfo` is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.
+         * No new underlying VertexBuffer object is created.
+         * If the `kind` is the `PositionKind` and if `updateExtends` is true, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.
          * If the parameter `makeItUnique` is true, a new global geometry is created from this positions and is set to the mesh.
          *
          * Possible `kind` values :
@@ -966,7 +966,7 @@ var BABYLON;
             this.onAfterRenderObservable.notifyObservers(this);
         };
         /**
-         * Returns an array populated with `ParticleSystem` objects whose the mesh is the emitter.
+         * Returns an array populated with ParticleSystem objects whose the mesh is the emitter.
          */
         Mesh.prototype.getEmittedParticleSystems = function () {
             var results = new Array();
@@ -979,7 +979,7 @@ var BABYLON;
             return results;
         };
         /**
-         * Returns an array populated with `ParticleSystem` objects whose the mesh or its children are the emitter.
+         * Returns an array populated with ParticleSystem objects whose the mesh or its children are the emitter.
          */
         Mesh.prototype.getHierarchyEmittedParticleSystems = function () {
             var results = new Array();
@@ -1017,7 +1017,7 @@ var BABYLON;
             }
         };
         /**
-         * Boolean, true is the mesh in the frustum defined by the `Plane` objects from the `frustumPlanes` array parameter.
+         * Boolean, true is the mesh in the frustum defined by the Plane objects from the `frustumPlanes` array parameter.
          */
         Mesh.prototype.isInFrustum = function (frustumPlanes) {
             if (this.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADING) {
@@ -1140,7 +1140,7 @@ var BABYLON;
             return true;
         };
         /**
-         * Returns a new `Mesh` object generated from the current mesh properties.
+         * Returns a new Mesh object generated from the current mesh properties.
          * This method must not get confused with createInstance().
          * The parameter `name` is a string, the name given to the new mesh.
          * The optional parameter `newParent` can be any `Node` object (default `null`).
@@ -1410,7 +1410,7 @@ var BABYLON;
         };
         // Instances
         /**
-         * Creates a new `InstancedMesh` object from the mesh model.
+         * Creates a new InstancedMesh object from the mesh model.
          * An instance shares the same properties and the same material than its model.
          * Only these properties of each instance can then be set individually :
          * - position
@@ -1419,7 +1419,7 @@ var BABYLON;
          * - setPivotMatrix
          * - scaling
          * tuto : http://doc.babylonjs.com/tutorials/How_to_use_Instances
-         * Warning : this method is not supported for `Line` mesh and `LineSystem`
+         * Warning : this method is not supported for Line mesh and LineSystem
          */
         Mesh.prototype.createInstance = function (name) {
             return new BABYLON.InstancedMesh(name, this);
@@ -1494,7 +1494,7 @@ var BABYLON;
         };
         // Statics
         /**
-         * Returns a new `Mesh` object what is a deep copy of the passed mesh.
+         * Returns a new Mesh object what is a deep copy of the passed mesh.
          * The parameter `parsedMesh` is the mesh to be copied.
          * The parameter `rootUrl` is a string, it's the root URL to prefix the `delayLoadingFile` property with
          */
@@ -1662,7 +1662,7 @@ var BABYLON;
         };
         /**
          * Creates a ribbon mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The ribbon is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
          *
          * Please read this full tutorial to understand how to design a ribbon : http://doc.babylonjs.com/tutorials/Ribbon_Tutorial
@@ -1689,7 +1689,7 @@ var BABYLON;
         };
         /**
          * Creates a plane polygonal mesh.  By default, this is a disc.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `radius` sets the radius size (float) of the polygon (default 0.5).
          * The parameter `tessellation` sets the number of polygon sides (positive integer, default 64). So a tessellation valued to 3 will build a triangle, to 4 a square, etc.
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
@@ -1707,7 +1707,7 @@ var BABYLON;
         };
         /**
          * Creates a box mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `size` sets the size (float) of each box side (default 1).
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
@@ -1723,7 +1723,7 @@ var BABYLON;
         };
         /**
          * Creates a sphere mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `diameter` sets the diameter size (float) of the sphere (default 1).
          * The parameter `segments` sets the sphere number of horizontal stripes (positive integer, default 32).
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
@@ -1743,7 +1743,7 @@ var BABYLON;
         };
         /**
          * Creates a cylinder or a cone mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `height` sets the height size (float) of the cylinder/cone (float, default 2).
          * The parameter `diameter` sets the diameter of the top and bottom cap at once (float, default 1).
          * The parameters `diameterTop` and `diameterBottom` overwrite the parameter `diameter` and set respectively the top cap and bottom cap diameter (floats, default 1). The parameter "diameterBottom" can't be zero.
@@ -1776,7 +1776,7 @@ var BABYLON;
         // Torus  (Code from SharpDX.org)
         /**
          * Creates a torus mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `diameter` sets the diameter size (float) of the torus (default 1).
          * The parameter `thickness` sets the diameter size of the tube of the torus (float, default 0.5).
          * The parameter `tessellation` sets the number of torus sides (postive integer, default 16).
@@ -1796,7 +1796,7 @@ var BABYLON;
         };
         /**
          * Creates a torus knot mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `radius` sets the global radius size (float) of the torus knot (default 2).
          * The parameter `radialSegments` sets the number of sides on each tube segments (positive integer, default 32).
          * The parameter `tubularSegments` sets the number of tubes to decompose the knot into (positive integer, default 32).
@@ -1820,7 +1820,7 @@ var BABYLON;
         };
         /**
          * Creates a line mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * A line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
          * The parameter `points` is an array successive Vector3.
@@ -1838,7 +1838,7 @@ var BABYLON;
         };
         /**
          * Creates a dashed line mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * A dashed line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
          * The parameter `points` is an array successive Vector3.
@@ -1862,7 +1862,7 @@ var BABYLON;
         /**
          * Creates an extruded shape mesh.
          * The extrusion is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          *
          * Please read this full tutorial to understand how to design an extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion
          * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
@@ -1893,7 +1893,7 @@ var BABYLON;
         /**
          * Creates an custom extruded shape mesh.
          * The custom extrusion is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          *
          * Please read this full tutorial to understand how to design a custom extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion
          * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
@@ -1901,15 +1901,19 @@ var BABYLON;
          * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.
          * The parameter `rotationFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
          * and the distance of this point from the begining of the path :
-         * ```rotationFunction = function(i, distance) {
-         *  // do things
-         *  return rotationValue; }```
+         * ```javascript
+         * var rotationFunction = function(i, distance) {
+         *     // do things
+         *     return rotationValue; }
+         * ```
          * It must returns a float value that will be the rotation in radians applied to the shape on each path point.
          * The parameter `scaleFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
          * and the distance of this point from the begining of the path :
-         * ````scaleFunction = function(i, distance) {
-         *   // do things
-         *  return scaleValue;}```
+         * ```javascript
+         * var scaleFunction = function(i, distance) {
+         *     // do things
+         *    return scaleValue;}
+         * ```
          * It must returns a float value that will be the scale value applied to the shape on each path point.
          * The parameter `ribbonClosePath` (boolean, default false) forces the extrusion underlying ribbon to close all the paths in its `pathArray`.
          * The parameter `ribbonCloseArray` (boolean, default false) forces the extrusion underlying ribbon to close its `pathArray`.
@@ -1938,7 +1942,7 @@ var BABYLON;
         /**
          * Creates lathe mesh.
          * The lathe is a shape with a symetry axis : a 2D model shape is rotated around this axis to design the lathe.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          *
          * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be rotated in its local space : the shape must be designed in the xOy plane and will be
          * rotated around the Y axis. It's usually a 2D shape, so the Vector3 z coordinates are often set to zero.
@@ -1960,7 +1964,7 @@ var BABYLON;
         };
         /**
          * Creates a plane mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `size` sets the size (float) of both sides of the plane at once (default 1).
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
@@ -1978,7 +1982,7 @@ var BABYLON;
         };
         /**
          * Creates a ground mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameters `width` and `height` (floats, default 1) set the width and height sizes of the ground.
          * The parameter `subdivisions` (positive integer) sets the number of subdivisions per side.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
@@ -1994,7 +1998,7 @@ var BABYLON;
         };
         /**
          * Creates a tiled ground mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameters `xmin` and `xmax` (floats, default -1 and 1) set the ground minimum and maximum X coordinates.
          * The parameters `zmin` and `zmax` (floats, default -1 and 1) set the ground minimum and maximum Z coordinates.
          * The parameter `subdivisions` is a javascript object `{w: positive integer, h: positive integer}` (default `{w: 6, h: 6}`). `w` and `h` are the
@@ -2018,15 +2022,18 @@ var BABYLON;
         /**
          * Creates a ground mesh from a height map.
          * tuto : http://doc.babylonjs.com/tutorials/14._Height_Map
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `url` sets the URL of the height map image resource.
          * The parameters `width` and `height` (positive floats, default 10) set the ground width and height sizes.
          * The parameter `subdivisions` (positive integer, default 1) sets the number of subdivision per side.
          * The parameter `minHeight` (float, default 0) is the minimum altitude on the ground.
          * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.
          * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).
-         * This function is passed the newly built mesh : ```function(mesh) { // do things
-         * return; }```
+         * This function is passed the newly built mesh :
+         * ```javascript
+         * function(mesh) { // do things
+         *     return; }
+         * ```
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         Mesh.CreateGroundFromHeightMap = function (name, url, width, height, subdivisions, minHeight, maxHeight, scene, updatable, onReady) {
@@ -2045,16 +2052,18 @@ var BABYLON;
          * Creates a tube mesh.
          * The tube is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
          *
-         * Please consider using the same method from the `MeshBuilder` class instead.
-         * The parameter `path` is a required array of successive `Vector3`. It is the curve used as the axis of the tube.
+         * Please consider using the same method from the MeshBuilder class instead.
+         * The parameter `path` is a required array of successive Vector3. It is the curve used as the axis of the tube.
          * The parameter `radius` (positive float, default 1) sets the tube radius size.
          * The parameter `tessellation` (positive float, default 64) is the number of sides on the tubular surface.
          * The parameter `radiusFunction` (javascript function, default null) is a vanilla javascript function. If it is not null, it overwrittes the parameter `radius`.
          * This function is called on each point of the tube path and is passed the index `i` of the i-th point and the distance of this point from the first point of the path.
          * It must return a radius value (positive float) :
-         * ```var radiusFunction = function(i, distance) {
-         *   // do things
-         *   return radius; }```
+         * ```javascript
+         * var radiusFunction = function(i, distance) {
+         *     // do things
+         *     return radius; }
+         * ```
          * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
          * The optional parameter `instance` is an instance of an existing Tube object to be updated with the passed `pathArray` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#tube
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
@@ -2078,14 +2087,14 @@ var BABYLON;
         /**
          * Creates a polyhedron mesh.
          *
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `type` (positive integer, max 14, default 0) sets the polyhedron type to build among the 15 embbeded types. Please refer to the type sheet in the tutorial
          *  to choose the wanted type.
          * The parameter `size` (positive float, default 1) sets the polygon size.
          * You can overwrite the `size` on each dimension bu using the parameters `sizeX`, `sizeY` or `sizeZ` (positive floats, default to `size` value).
          * You can build other polyhedron types than the 15 embbeded ones by setting the parameter `custom` (`polyhedronObject`, default null). If you set the parameter `custom`, this overwrittes the parameter `type`.
          * A `polyhedronObject` is a formatted javascript object. You'll find a full file with pre-set polyhedra here : https://github.com/BabylonJS/Extensions/tree/master/Polyhedron
-         * You can set the color and the UV of each side of the polyhedron with the parameters `faceColors` (`Color4`, default `(1, 1, 1, 1)`) and faceUV (`Vector4`, default `(0, 0, 1, 1)`).
+         * You can set the color and the UV of each side of the polyhedron with the parameters `faceColors` (Color4, default `(1, 1, 1, 1)`) and faceUV (Vector4, default `(0, 0, 1, 1)`).
          * To understand how to set `faceUV` or `faceColors`, please read this by considering the right number of faces of your polyhedron, instead of only 6 for the box : http://doc.babylonjs.com/tutorials/CreateBox_Per_Face_Textures_And_Colors
          * The parameter `flat` (boolean, default true). If set to false, it gives the polyhedron a single global face, so less vertices and shared normals. In this case, `faceColors` and `faceUV` are ignored.
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
@@ -2097,7 +2106,7 @@ var BABYLON;
         };
         /**
          * Creates a sphere based upon an icosahedron with 20 triangular faces which can be subdivided.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * The parameter `radius` sets the radius size (float) of the icosphere (default 1).
          * You can set some different icosphere dimensions, for instance to build an ellipsoid, by using the parameters `radiusX`, `radiusY` and `radiusZ` (all by default have the same value than `radius`).
          * The parameter `subdivisions` sets the number of subdivisions (postive integer, default 4). The more subdivisions, the more faces on the icosphere whatever its size.
@@ -2111,11 +2120,11 @@ var BABYLON;
         };
         /**
          * Creates a decal mesh.
-         * Please consider using the same method from the `MeshBuilder` class instead.
+         * Please consider using the same method from the MeshBuilder class instead.
          * A decal is a mesh usually applied as a model onto the surface of another mesh. So don't forget the parameter `sourceMesh` depicting the decal.
-         * The parameter `position` (`Vector3`, default `(0, 0, 0)`) sets the position of the decal in World coordinates.
-         * The parameter `normal` (`Vector3`, default `Vector3.Up`) sets the normal of the mesh where the decal is applied onto in World coordinates.
-         * The parameter `size` (`Vector3`, default `(1, 1, 1)`) sets the decal scaling.
+         * The parameter `position` (Vector3, default `(0, 0, 0)`) sets the position of the decal in World coordinates.
+         * The parameter `normal` (Vector3, default `Vector3.Up`) sets the normal of the mesh where the decal is applied onto in World coordinates.
+         * The parameter `size` (Vector3, default `(1, 1, 1)`) sets the decal scaling.
          * The parameter `angle` (float in radian, default 0) sets the angle to rotate the decal.
          */
         Mesh.CreateDecal = function (name, sourceMesh, position, normal, size, angle) {
@@ -2242,7 +2251,7 @@ var BABYLON;
         // Tools
         /**
          * Returns an object `{min: Vector3, max: Vector3}`
-         * This min and max `Vector3` are the minimum and maximum vectors of each mesh bounding box from the passed array, in the World system
+         * This min and max Vector3 are the minimum and maximum vectors of each mesh bounding box from the passed array, in the World system
          */
         Mesh.MinMax = function (meshes) {
             var minVector = null;

+ 28 - 19
src/Mesh/babylon.meshBuilder.js

@@ -8,7 +8,7 @@ var BABYLON;
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#box
          * The parameter `size` sets the size (float) of each box side (default 1).
          * You can set some different box dimensions by using the parameters `width`, `height` and `depth` (all by default have the same value than `size`).
-         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of 6 `Color3` elements) and `faceUV` (an array of 6 `Vector4` elements).
+         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of 6 Color3 elements) and `faceUV` (an array of 6 Vector4 elements).
          * Please read this tutorial : http://doc.babylonjs.com/tutorials/CreateBox_Per_Face_Textures_And_Colors
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
@@ -178,7 +178,7 @@ var BABYLON;
          * The parameter `hasRings` (boolean, default false) makes the subdivisions independent from each other, so they become different faces.
          * The parameter `enclose`  (boolean, default false) adds two extra faces per subdivision to a sliced cylinder to close it around its height axis.
          * The parameter `arc` (float, default 1) is the ratio (max 1) to apply to the circumference to slice the cylinder.
-         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of n `Color3` elements) and `faceUV` (an array of n `Vector4` elements).
+         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of n Color3 elements) and `faceUV` (an array of n Vector4 elements).
          * The value of n is the number of cylinder faces. If the cylinder has only 1 subdivisions, n equals : top face + cylinder surface + bottom face = 3
          * Now, if the cylinder has 5 independent subdivisions (hasRings = true), n equals : top face + 5 stripe surfaces + bottom face = 2 + 5 = 7
          * Finally, if the cylinder has 5 independent subdivisions and is enclose, n equals : top face + 5 x (stripe surface + 2 closing faces) + bottom face = 2 + 5 * 3 = 17
@@ -392,15 +392,19 @@ var BABYLON;
          * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.
          * The parameter `rotationFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
          * and the distance of this point from the begining of the path :
-         * ```rotationFunction = function(i, distance) {
-         *  // do things
-         *  return rotationValue; }```
+         * ```javascript
+         * var rotationFunction = function(i, distance) {
+         *     // do things
+         *     return rotationValue; }
+         * ```
          * It must returns a float value that will be the rotation in radians applied to the shape on each path point.
          * The parameter `scaleFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
          * and the distance of this point from the begining of the path :
-         * ````scaleFunction = function(i, distance) {
-         *   // do things
-         *  return scaleValue;}```
+         * ```javascript
+         * var scaleFunction = function(i, distance) {
+         *     // do things
+         *     return scaleValue;}
+         * ```
          * It must returns a float value that will be the scale value applied to the shape on each path point.
          * The parameter `ribbonClosePath` (boolean, default false) forces the extrusion underlying ribbon to close all the paths in its `pathArray`.
          * The parameter `ribbonCloseArray` (boolean, default false) forces the extrusion underlying ribbon to close its `pathArray`.
@@ -482,7 +486,7 @@ var BABYLON;
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#plane
          * The parameter `size` sets the size (float) of both sides of the plane at once (default 1).
          * You can set some different plane dimensions by using the parameters `width` and `height` (both by default have the same value than `size`).
-         * The parameter `sourcePlane` is a `Plane` instance. It builds a mesh plane from a Math plane.
+         * The parameter `sourcePlane` is a Plane instance. It builds a mesh plane from a Math plane.
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
@@ -548,8 +552,11 @@ var BABYLON;
          * The parameter `minHeight` (float, default 0) is the minimum altitude on the ground.
          * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.
          * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).
-         * This function is passed the newly built mesh : ```function(mesh) { // do things
-         * return; }```
+         * This function is passed the newly built mesh :
+         * ```javascript
+         * function(mesh) { // do things
+         *     return; }
+         * ```
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateGroundFromHeightMap = function (name, url, options, scene) {
@@ -602,15 +609,17 @@ var BABYLON;
          * The tube is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
          *
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#tube
-         * The parameter `path` is a required array of successive `Vector3`. It is the curve used as the axis of the tube.
+         * The parameter `path` is a required array of successive Vector3. It is the curve used as the axis of the tube.
          * The parameter `radius` (positive float, default 1) sets the tube radius size.
          * The parameter `tessellation` (positive float, default 64) is the number of sides on the tubular surface.
          * The parameter `radiusFunction` (javascript function, default null) is a vanilla javascript function. If it is not null, it overwrittes the parameter `radius`.
          * This function is called on each point of the tube path and is passed the index `i` of the i-th point and the distance of this point from the first point of the path.
          * It must return a radius value (positive float) :
-         * ```var radiusFunction = function(i, distance) {
-         *   // do things
-         *   return radius; }```
+         * ```javascript
+         * var radiusFunction = function(i, distance) {
+         *     // do things
+         *     return radius; }
+         * ```
          * The parameter `arc` (positive float, maximum 1, default 1) is the ratio to apply to the tube circumference : 2 x PI x arc.
          * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
          * The optional parameter `instance` is an instance of an existing Tube object to be updated with the passed `pathArray` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#tube
@@ -722,7 +731,7 @@ var BABYLON;
          * You can overwrite the `size` on each dimension bu using the parameters `sizeX`, `sizeY` or `sizeZ` (positive floats, default to `size` value).
          * You can build other polyhedron types than the 15 embbeded ones by setting the parameter `custom` (`polyhedronObject`, default null). If you set the parameter `custom`, this overwrittes the parameter `type`.
          * A `polyhedronObject` is a formatted javascript object. You'll find a full file with pre-set polyhedra here : https://github.com/BabylonJS/Extensions/tree/master/Polyhedron
-         * You can set the color and the UV of each side of the polyhedron with the parameters `faceColors` (`Color4`, default `(1, 1, 1, 1)`) and faceUV (`Vector4`, default `(0, 0, 1, 1)`).
+         * You can set the color and the UV of each side of the polyhedron with the parameters `faceColors` (Color4, default `(1, 1, 1, 1)`) and faceUV (Vector4, default `(0, 0, 1, 1)`).
          * To understand how to set `faceUV` or `faceColors`, please read this by considering the right number of faces of your polyhedron, instead of only 6 for the box : http://doc.babylonjs.com/tutorials/CreateBox_Per_Face_Textures_And_Colors
          * The parameter `flat` (boolean, default true). If set to false, it gives the polyhedron a single global face, so less vertices and shared normals. In this case, `faceColors` and `faceUV` are ignored.
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
@@ -739,9 +748,9 @@ var BABYLON;
          * Creates a decal mesh.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#decals
          * A decal is a mesh usually applied as a model onto the surface of another mesh. So don't forget the parameter `sourceMesh` depicting the decal.
-         * The parameter `position` (`Vector3`, default `(0, 0, 0)`) sets the position of the decal in World coordinates.
-         * The parameter `normal` (`Vector3`, default `Vector3.Up`) sets the normal of the mesh where the decal is applied onto in World coordinates.
-         * The parameter `size` (`Vector3`, default `(1, 1, 1)`) sets the decal scaling.
+         * The parameter `position` (Vector3, default `(0, 0, 0)`) sets the position of the decal in World coordinates.
+         * The parameter `normal` (Vector3, default `Vector3.Up`) sets the normal of the mesh where the decal is applied onto in World coordinates.
+         * The parameter `size` (Vector3, default `(1, 1, 1)`) sets the decal scaling.
          * The parameter `angle` (float in radian, default 0) sets the angle to rotate the decal.
          */
         MeshBuilder.CreateDecal = function (name, sourceMesh, options) {

+ 6 - 6
src/Particles/babylon.solidParticleSystem.js

@@ -8,7 +8,7 @@ var BABYLON;
         * Creates a SPS (Solid Particle System) object.
         * `name` (String) is the SPS name, this will be the underlying mesh name.
         * `scene` (Scene) is the scene in which the SPS is added.
-        * `updatableè (default true) : if the SPS must be updatable or immutable.
+        * `updatable` (default true) : if the SPS must be updatable or immutable.
         * `isPickable` (default false) : if the solid particles must be pickable.
         */
         function SolidParticleSystem(name, scene, options) {
@@ -140,7 +140,7 @@ var BABYLON;
         * Digests the mesh and generates as many solid particles in the system as wanted. Returns the SPS.
         * These particles will have the same geometry than the mesh parts and will be positioned at the same localisation than the mesh original places.
         * Thus the particles generated from `digest()` have their property `position` set yet.
-        * `mesh` (`Mesh`) is the mesh to be digested
+        * `mesh` ( Mesh ) is the mesh to be digested
         * `facetNb` (optional integer, default 1) is the number of mesh facets per particle, this parameter is overriden by the parameter `number` if any
         * `delta` (optional integer, default 0) is the random extra number of facets per particle , each particle will have between `facetNb` and `facetNb + delta` facets
         * `number` (optional positive integer) is the wanted number of particles : each particle is built with `mesh_total_facets / number` facets
@@ -328,7 +328,7 @@ var BABYLON;
         /**
         * Adds some particles to the SPS from the model shape. Returns the shape id.
         * Please read the doc : http://doc.babylonjs.com/overviews/Solid_Particle_System#create-an-immutable-sps
-        * `mesh` is any `Mesh` object that will be used as a model for the solid particles.
+        * `mesh` is any Mesh object that will be used as a model for the solid particles.
         * `nb` (positive integer) the number of particles to be created from this model
         * `positionFunction` is an optional javascript function to called for each particle on SPS creation.
         * `vertexFunction` is an optional javascript function to called for each vertex of each particle on SPS creation
@@ -413,9 +413,9 @@ var BABYLON;
         *  Sets all the particles : this method actually really updates the mesh according to the particle positions, rotations, colors, textures, etc.
         *  This method calls `updateParticle()` for each particle of the SPS.
         *  For an animated SPS, it is usually called within the render loop.
-        * @param start (default 0) the particle index in the particle array where to start to compute the particle property values
-        * @param end (default nbParticle - 1)  the particle index in the particle array where to stop to compute the particle property values
-        * @param update (default true) if the mesh must be finally updated on this call after all the particle computations.
+        * @param start The particle index in the particle array where to start to compute the particle property values _(default 0)_
+        * @param end The particle index in the particle array where to stop to compute the particle property values _(default nbParticle - 1)_
+        * @param update If the mesh must be finally updated on this call after all the particle computations _(default true)_
         */
         SolidParticleSystem.prototype.setParticles = function (start, end, update) {
             if (start === void 0) { start = 0; }

+ 88 - 14
src/PostProcess/babylon.ssaoRenderingPipeline.js

@@ -3,6 +3,12 @@ var __extends = (this && this.__extends) || function (d, b) {
     function __() { this.constructor = d; }
     d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
 };
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
 var BABYLON;
 (function (BABYLON) {
     var SSAORenderingPipeline = (function (_super) {
@@ -80,10 +86,13 @@ var BABYLON;
             this._depthTexture = scene.enableDepthRenderer().getDepthMap(); // Force depth renderer "on"
             var ssaoRatio = ratio.ssaoRatio || ratio;
             var combineRatio = ratio.combineRatio || ratio;
+            this._ratio = {
+                ssaoRatio: ssaoRatio,
+                combineRatio: combineRatio
+            };
             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), 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._createBlurPostProcess(ssaoRatio);
             this._createSSAOCombinePostProcess(combineRatio);
             // Set up pipeline
             this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), this.SSAOOriginalSceneColorEffect, function () { return _this._originalColorPostProcess; }, true));
@@ -102,31 +111,78 @@ var BABYLON;
          * @return {BABYLON.BlurPostProcess} The horizontal blur post-process
          */
         SSAORenderingPipeline.prototype.getBlurHPostProcess = function () {
-            return this._blurHPostProcess;
+            BABYLON.Tools.Error("SSAORenderinPipeline.getBlurHPostProcess() is deprecated, no more blur post-process exists");
+            return null;
         };
         /**
          * Returns the vertical blur PostProcess
          * @return {BABYLON.BlurPostProcess} The vertical blur post-process
          */
         SSAORenderingPipeline.prototype.getBlurVPostProcess = function () {
-            return this._blurVPostProcess;
+            BABYLON.Tools.Error("SSAORenderinPipeline.getBlurVPostProcess() is deprecated, no more blur post-process exists");
+            return null;
         };
         /**
          * Removes the internal pipeline assets and detatches the pipeline from the scene cameras
          */
         SSAORenderingPipeline.prototype.dispose = function (disableDepthRender) {
             if (disableDepthRender === void 0) { disableDepthRender = false; }
-            this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
-            this._originalColorPostProcess = undefined;
-            this._ssaoPostProcess = undefined;
-            this._blurHPostProcess = undefined;
-            this._blurVPostProcess = undefined;
-            this._ssaoCombinePostProcess = undefined;
+            for (var i = 0; i < this._scene.cameras.length; i++) {
+                var camera = this._scene.cameras[i];
+                this._originalColorPostProcess.dispose(camera);
+                this._ssaoPostProcess.dispose(camera);
+                this._blurHPostProcess.dispose(camera);
+                this._blurVPostProcess.dispose(camera);
+                this._ssaoCombinePostProcess.dispose(camera);
+            }
             this._randomTexture.dispose();
             if (disableDepthRender)
                 this._scene.disableDepthRenderer();
+            this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
+        };
+        // Serialize rendering pipeline
+        SSAORenderingPipeline.prototype.serialize = function () {
+            var serializationObject = BABYLON.SerializationHelper.Serialize(this, _super.prototype.serialize.call(this));
+            serializationObject.customType = "BABYLON.SSAORenderingPipeline";
+            return serializationObject;
+        };
+        // Parse serialized pipeline
+        SSAORenderingPipeline.Parse = function (source, scene, rootUrl) {
+            return BABYLON.SerializationHelper.Parse(function () { return new SSAORenderingPipeline(source._name, scene, source._ratio); }, source, scene, rootUrl);
         };
         // Private Methods
+        SSAORenderingPipeline.prototype._createBlurPostProcess = function (ratio) {
+            var _this = this;
+            /*
+            var samplerOffsets = [
+                -8.0, -6.0, -4.0, -2.0,
+                0.0,
+                2.0, 4.0, 6.0, 8.0
+            ];
+            */
+            var samples = 16;
+            var samplerOffsets = [];
+            for (var i = -8; i < 8; i++) {
+                samplerOffsets.push(i * 2);
+            }
+            this._blurHPostProcess = new BABYLON.PostProcess("BlurH", "ssao", ["outSize", "samplerOffsets"], ["depthSampler"], ratio, null, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define BILATERAL_BLUR_H\n#define SAMPLES 9");
+            this._blurHPostProcess.onApply = function (effect) {
+                effect.setFloat("outSize", _this._ssaoCombinePostProcess.width);
+                effect.setTexture("depthSampler", _this._depthTexture);
+                if (_this._firstUpdate) {
+                    effect.setArray("samplerOffsets", samplerOffsets);
+                }
+            };
+            this._blurVPostProcess = new BABYLON.PostProcess("BlurV", "ssao", ["outSize", "samplerOffsets"], ["depthSampler"], ratio, null, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define SAMPLES 9");
+            this._blurVPostProcess.onApply = function (effect) {
+                effect.setFloat("outSize", _this._ssaoCombinePostProcess.height);
+                effect.setTexture("depthSampler", _this._depthTexture);
+                if (_this._firstUpdate) {
+                    effect.setArray("samplerOffsets", samplerOffsets);
+                    _this._firstUpdate = false;
+                }
+            };
+        };
         SSAORenderingPipeline.prototype._createSSAOPostProcess = function (ratio) {
             var _this = this;
             var numSamples = 16;
@@ -151,14 +207,14 @@ var BABYLON;
             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);
+                "area", "fallOff", "base", "range", "viewport"
+            ], ["randomSampler"], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define SAMPLES " + numSamples + "\n#define SSAO");
+            var viewport = new BABYLON.Vector2(0, 0);
             this._ssaoPostProcess.onApply = function (effect) {
                 if (_this._firstUpdate) {
                     effect.setArray3("sampleSphere", sampleSphere);
                     effect.setFloat("samplesFactor", samplesFactor);
                     effect.setFloat("randTextureTiles", 4.0);
-                    _this._firstUpdate = false;
                 }
                 effect.setFloat("totalStrength", _this.totalStrength);
                 effect.setFloat("radius", _this.radius);
@@ -178,7 +234,7 @@ var BABYLON;
         };
         SSAORenderingPipeline.prototype._createRandomTexture = function () {
             var size = 512;
-            this._randomTexture = new BABYLON.DynamicTexture("SSAORandomTexture", size, this._scene, false, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
+            this._randomTexture = new BABYLON.DynamicTexture("SSAORandomTexture", size, this._scene, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
             this._randomTexture.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
             this._randomTexture.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
             var context = this._randomTexture.getContext();
@@ -197,6 +253,24 @@ var BABYLON;
             }
             this._randomTexture.update(false);
         };
+        __decorate([
+            BABYLON.serialize()
+        ], SSAORenderingPipeline.prototype, "totalStrength", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], SSAORenderingPipeline.prototype, "radius", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], SSAORenderingPipeline.prototype, "area", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], SSAORenderingPipeline.prototype, "fallOff", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], SSAORenderingPipeline.prototype, "base", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], SSAORenderingPipeline.prototype, "_ratio", void 0);
         return SSAORenderingPipeline;
     }(BABYLON.PostProcessRenderPipeline));
     BABYLON.SSAORenderingPipeline = SSAORenderingPipeline;

+ 87 - 17
src/PostProcess/babylon.ssaoRenderingPipeline.ts

@@ -32,12 +32,14 @@
         * The output strength of the SSAO post-process. Default value is 1.0.
         * @type {number}
         */
+        @serialize()
         public totalStrength: number = 1.0;
 
         /**
         * The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.0006
         * @type {number}
         */
+        @serialize()
         public radius: number = 0.0001;
 
         /**
@@ -46,6 +48,7 @@
         * Default value is 0.975
         * @type {number}
         */
+        @serialize()
         public area: number = 0.0075;
 
         /**
@@ -54,6 +57,7 @@
         * Default value is 0.0
         * @type {number}
         */
+        @serialize()
         public fallOff: number = 0.000001;
 
         /**
@@ -61,6 +65,7 @@
         * The final result is "base + ssao" between [0, 1]
         * @type {number}
         */
+        @serialize()
         public base: number = 0.5;
 
         private _scene: Scene;
@@ -69,12 +74,15 @@
 
         private _originalColorPostProcess: PassPostProcess;
         private _ssaoPostProcess: PostProcess;
-        private _blurHPostProcess: BlurPostProcess;
-        private _blurVPostProcess: BlurPostProcess;
+        private _blurHPostProcess: PostProcess;
+        private _blurVPostProcess: PostProcess;
         private _ssaoCombinePostProcess: PostProcess;
 
         private _firstUpdate: boolean = true;
 
+        @serialize()
+        private _ratio: any;
+
         /**
          * @constructor
          * @param {string} name - The rendering pipeline name
@@ -93,11 +101,14 @@
 
             var ssaoRatio = ratio.ssaoRatio || ratio;
             var combineRatio = ratio.combineRatio || ratio;
+            this._ratio = {
+                ssaoRatio: ssaoRatio,
+                combineRatio: combineRatio
+            };
 
             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), 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._createBlurPostProcess(ssaoRatio);
             this._createSSAOCombinePostProcess(combineRatio);
 
             // Set up pipeline
@@ -105,6 +116,7 @@
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAORenderEffect, () => { return this._ssaoPostProcess; }, true));
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAOBlurHRenderEffect, () => { return this._blurHPostProcess; }, true));
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAOBlurVRenderEffect, () => { return this._blurVPostProcess; }, true));
+
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAOCombineRenderEffect, () => { return this._ssaoCombinePostProcess; }, true));
 
             // Finish
@@ -119,7 +131,8 @@
          * @return {BABYLON.BlurPostProcess} The horizontal blur post-process
          */
         public getBlurHPostProcess(): BlurPostProcess {
-            return this._blurHPostProcess;
+            Tools.Error("SSAORenderinPipeline.getBlurHPostProcess() is deprecated, no more blur post-process exists");
+            return null;
         }
 
         /**
@@ -127,28 +140,83 @@
          * @return {BABYLON.BlurPostProcess} The vertical blur post-process
          */
         public getBlurVPostProcess(): BlurPostProcess {
-            return this._blurVPostProcess;
+            Tools.Error("SSAORenderinPipeline.getBlurVPostProcess() is deprecated, no more blur post-process exists");
+            return null;
         }
 
         /**
          * Removes the internal pipeline assets and detatches the pipeline from the scene cameras
          */
         public dispose(disableDepthRender: boolean = false): void {
-            this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
-
-            this._originalColorPostProcess = undefined;
-            this._ssaoPostProcess = undefined;
-            this._blurHPostProcess = undefined;
-            this._blurVPostProcess = undefined;
-            this._ssaoCombinePostProcess = undefined;
+            for (var i = 0; i < this._scene.cameras.length; i++) {
+                var camera = this._scene.cameras[i];
+
+                this._originalColorPostProcess.dispose(camera);
+                this._ssaoPostProcess.dispose(camera);
+                this._blurHPostProcess.dispose(camera);
+                this._blurVPostProcess.dispose(camera);
+                this._ssaoCombinePostProcess.dispose(camera);
+            }
 
             this._randomTexture.dispose();
 
             if (disableDepthRender)
                 this._scene.disableDepthRenderer();
+
+            this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
+        }
+
+        // Serialize rendering pipeline
+        public serialize(): any {
+            var serializationObject = SerializationHelper.Serialize(this, super.serialize());
+            serializationObject.customType = "BABYLON.SSAORenderingPipeline";
+
+            return serializationObject;
+        }
+
+        // Parse serialized pipeline
+        public static Parse(source: any, scene: Scene, rootUrl: string): SSAORenderingPipeline {
+            return SerializationHelper.Parse(() => new SSAORenderingPipeline(source._name, scene, source._ratio), source, scene, rootUrl);
         }
 
         // Private Methods
+        private _createBlurPostProcess(ratio: number): void {
+            /*
+            var samplerOffsets = [
+                -8.0, -6.0, -4.0, -2.0,
+                0.0,
+                2.0, 4.0, 6.0, 8.0
+            ];
+            */
+            var samples = 16;
+            var samplerOffsets = [];
+
+            for (var i = -8; i < 8; i++) {
+                samplerOffsets.push(i * 2);
+            }
+
+            this._blurHPostProcess = new PostProcess("BlurH", "ssao", ["outSize", "samplerOffsets"], ["depthSampler"], ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define BILATERAL_BLUR_H\n#define SAMPLES 9");
+            this._blurHPostProcess.onApply = (effect: Effect) => {
+                effect.setFloat("outSize", this._ssaoCombinePostProcess.width);
+                effect.setTexture("depthSampler", this._depthTexture);
+
+                if (this._firstUpdate) {
+                    effect.setArray("samplerOffsets", samplerOffsets);
+                }
+            };
+
+            this._blurVPostProcess = new PostProcess("BlurV", "ssao", ["outSize", "samplerOffsets"], ["depthSampler"], ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define SAMPLES 9");
+            this._blurVPostProcess.onApply = (effect: Effect) => {
+                effect.setFloat("outSize", this._ssaoCombinePostProcess.height);
+                effect.setTexture("depthSampler", this._depthTexture);
+
+                if (this._firstUpdate) {
+                    effect.setArray("samplerOffsets", samplerOffsets);
+                    this._firstUpdate = false;
+                }
+            };
+        }
+
         private _createSSAOPostProcess(ratio: number): void {
             var numSamples = 16;
             var sampleSphere = [
@@ -174,19 +242,20 @@
             this._ssaoPostProcess = new PostProcess("ssao", "ssao",
                                                     [
                                                         "sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius",
-                                                        "area", "fallOff", "base"
+                                                        "area", "fallOff", "base", "range", "viewport"
                                                     ],
                                                     ["randomSampler"],
                                                     ratio, null, Texture.BILINEAR_SAMPLINGMODE,
                                                     this._scene.getEngine(), false,
-                                                    "#define SAMPLES " + numSamples);
+                                                    "#define SAMPLES " + numSamples + "\n#define SSAO");
+
+            var viewport = new Vector2(0, 0);
 
             this._ssaoPostProcess.onApply = (effect: Effect) => {
                 if (this._firstUpdate) {
                     effect.setArray3("sampleSphere", sampleSphere);
                     effect.setFloat("samplesFactor", samplesFactor);
                     effect.setFloat("randTextureTiles", 4.0);
-                    this._firstUpdate = false;
                 }
 
                 effect.setFloat("totalStrength", this.totalStrength);
@@ -213,7 +282,7 @@
         private _createRandomTexture(): void {
             var size = 512;
 
-            this._randomTexture = new DynamicTexture("SSAORandomTexture", size, this._scene, false, Texture.BILINEAR_SAMPLINGMODE);
+            this._randomTexture = new DynamicTexture("SSAORandomTexture", size, this._scene, false, Texture.TRILINEAR_SAMPLINGMODE);
             this._randomTexture.wrapU = Texture.WRAP_ADDRESSMODE;
             this._randomTexture.wrapV = Texture.WRAP_ADDRESSMODE;
 
@@ -235,6 +304,7 @@
                     context.fillRect(x, y, 1, 1);
                 }
             }
+
             this._randomTexture.update(false);
         }
     }

+ 50 - 9
src/Shaders/ssao.fragment.fx

@@ -1,4 +1,9 @@
-uniform sampler2D textureSampler;
+// SSAO Shader
+uniform sampler2D textureSampler;
+
+varying vec2 vUV;
+
+#ifdef SSAO
 uniform sampler2D randomSampler;
 
 uniform float randTextureTiles;
@@ -11,22 +16,21 @@ uniform float area;
 uniform float fallOff;
 uniform float base;
 
-varying vec2 vUV;
-
-vec3 normalFromDepth(float depth, vec2 coords) {
+vec3 normalFromDepth(float depth, vec2 coords)
+{
 	vec2 offset1 = vec2(0.0, radius);
 	vec2 offset2 = vec2(radius, 0.0);
 
 	float depth1 = texture2D(textureSampler, coords + offset1).r;
 	float depth2 = texture2D(textureSampler, coords + offset2).r;
 
-    vec3 p1 = vec3(offset1, depth1 - depth);
-    vec3 p2 = vec3(offset2, depth2 - depth);
+	vec3 p1 = vec3(offset1, depth1 - depth);
+	vec3 p2 = vec3(offset2, depth2 - depth);
 
-    vec3 normal = cross(p1, p2);
+	vec3 normal = cross(p1, p2);
 	normal.z = -normal.z;
 
-    return normalize(normal);
+	return normalize(normal);
 }
 
 void main()
@@ -55,10 +59,47 @@ void main()
 	}
 
 	float ao = 1.0 - totalStrength * occlusion * samplesFactor;
-
 	float result = clamp(ao + base, 0.0, 1.0);
+
 	gl_FragColor.r = result;
 	gl_FragColor.g = result;
 	gl_FragColor.b = result;
 	gl_FragColor.a = 1.0;
 }
+#endif
+
+#ifdef BILATERAL_BLUR
+uniform sampler2D depthSampler;
+uniform float outSize;
+uniform float samplerOffsets[SAMPLES];
+
+void main()
+{
+
+	float texelsize = 1.0 / outSize;
+	float compareDepth = texture2D(depthSampler, vUV).r;
+	float result = 0.0;
+	float weightSum = 0.0;
+
+	for (int i = 0; i < SAMPLES; ++i)
+	{
+		#ifdef BILATERAL_BLUR_H
+		vec2 sampleOffset = vec2(texelsize * samplerOffsets[i], 0.0);
+		#else
+		vec2 sampleOffset = vec2(0.0, texelsize * samplerOffsets[i]);
+		#endif
+		vec2 samplePos = vUV + sampleOffset;
+
+		float sampleDepth = texture2D(depthSampler, samplePos).r;
+		float weight = (1.0 / (0.0001 + abs(compareDepth - sampleDepth)));
+
+		result += texture2D(textureSampler, samplePos).r * weight;
+		weightSum += weight;
+	}
+
+	result /= weightSum;
+
+	gl_FragColor.rgb = vec3(result);
+	gl_FragColor.a = 1.0;
+}
+#endif