Browse Source

merge changes

Etienne Margraff 9 years ago
parent
commit
21e9e8ee02
100 changed files with 56989 additions and 12880 deletions
  1. 1 0
      .gitattributes
  2. 3 0
      .gitignore
  3. 247 105
      Exporters/Blender/io_export_babylon.py
  4. 4 0
      Exporters/Blender/readme.md
  5. 1 1
      Exporters/Unity 5/Unity3D2Babylon/ExporterWindow.cs
  6. 103 20
      Exporters/Unity 5/Unity3D2Babylon/SceneBuilder.Meshes.cs
  7. 69 9
      Exporters/Unity 5/Unity3D2Babylon/SceneBuilder.cs
  8. 1 2
      Tools/Gulp/config.json
  9. 20 19
      dist/preview release/babylon.core.js
  10. 347 255
      dist/preview release/babylon.d.ts
  11. 28 28
      dist/preview release/babylon.js
  12. 2170 1937
      dist/preview release/babylon.max.js
  13. 27 27
      dist/preview release/babylon.noworker.js
  14. 86 83
      dist/preview release/what's new.md
  15. 47 42
      loaders/glTF/README.md
  16. 1406 1166
      loaders/glTF/babylon.glTFFileLoader.js
  17. 1656 1388
      loaders/glTF/babylon.glTFFileLoader.ts
  18. 269 279
      loaders/glTF/babylon.glTFFileLoaderInterfaces.ts
  19. 81 64
      materialsLibrary/config.json
  20. 43 2
      materialsLibrary/dist/babylon.fireMaterial.js
  21. 1 1
      materialsLibrary/dist/babylon.fireMaterial.min.js
  22. 499 0
      materialsLibrary/dist/babylon.furMaterial.js
  23. 1 0
      materialsLibrary/dist/babylon.furMaterial.min.js
  24. 72 11
      materialsLibrary/dist/babylon.lavaMaterial.js
  25. 1 1
      materialsLibrary/dist/babylon.lavaMaterial.min.js
  26. 40 4
      materialsLibrary/dist/babylon.normalMaterial.js
  27. 1 1
      materialsLibrary/dist/babylon.normalMaterial.min.js
  28. 253 107
      materialsLibrary/dist/babylon.pbrMaterial.js
  29. 3 3
      materialsLibrary/dist/babylon.pbrMaterial.min.js
  30. 40 4
      materialsLibrary/dist/babylon.simpleMaterial.js
  31. 1 1
      materialsLibrary/dist/babylon.simpleMaterial.min.js
  32. 66 2
      materialsLibrary/dist/babylon.terrainMaterial.js
  33. 1 1
      materialsLibrary/dist/babylon.terrainMaterial.min.js
  34. 509 0
      materialsLibrary/dist/babylon.triPlanarMaterial.js
  35. 1 0
      materialsLibrary/dist/babylon.triPlanarMaterial.min.js
  36. 51 2
      materialsLibrary/dist/babylon.waterMaterial.js
  37. 1 1
      materialsLibrary/dist/babylon.waterMaterial.min.js
  38. 29 0
      materialsLibrary/dist/dts/babylon.fireMaterial.d.ts
  39. 30 0
      materialsLibrary/dist/dts/babylon.furMaterial.d.ts
  40. 33 0
      materialsLibrary/dist/dts/babylon.lavaMaterial.d.ts
  41. 26 0
      materialsLibrary/dist/dts/babylon.normalMaterial.d.ts
  42. 86 0
      materialsLibrary/dist/dts/babylon.pbrMaterial.d.ts
  43. 26 0
      materialsLibrary/dist/dts/babylon.simpleMaterial.d.ts
  44. 35 0
      materialsLibrary/dist/dts/babylon.terrainMaterial.d.ts
  45. 36 0
      materialsLibrary/dist/dts/babylon.triPlanarMaterial.d.ts
  46. 77 0
      materialsLibrary/dist/dts/babylon.waterMaterial.d.ts
  47. 70 66
      materialsLibrary/gulpfile.js
  48. 414 357
      materialsLibrary/materials/fire/babylon.fireMaterial.ts
  49. 601 0
      materialsLibrary/materials/fur/babylon.furMaterial.ts
  50. 565 0
      materialsLibrary/materials/fur/fur.fragment.fx
  51. 202 0
      materialsLibrary/materials/fur/fur.vertex.fx
  52. 236 0
      materialsLibrary/materials/fur/readme.md
  53. 90 16
      materialsLibrary/materials/lava/babylon.lavaMaterial.ts
  54. 19 14
      materialsLibrary/materials/lava/lava.fragment.fx
  55. 38 19
      materialsLibrary/materials/lava/lava.vertex.fx
  56. 563 516
      materialsLibrary/materials/normal/babylon.normalMaterial.ts
  57. 562 558
      materialsLibrary/materials/normal/normal.fragment.fx
  58. 279 106
      materialsLibrary/materials/pbr/babylon.pbrMaterial.ts
  59. 59 73
      materialsLibrary/materials/pbr/legacypbr.fragment.fx
  60. 16 16
      materialsLibrary/materials/pbr/legacypbr.vertex.fx
  61. 75 90
      materialsLibrary/materials/pbr/pbr.fragment.fx
  62. 16 16
      materialsLibrary/materials/pbr/pbr.vertex.fx
  63. 562 516
      materialsLibrary/materials/simple/babylon.simpleMaterial.ts
  64. 560 555
      materialsLibrary/materials/simple/simple.fragment.fx
  65. 664 577
      materialsLibrary/materials/terrain/babylon.terrainMaterial.ts
  66. 713 712
      materialsLibrary/materials/terrain/terrain.fragment.fx
  67. 622 0
      materialsLibrary/materials/triPlanar/babylon.triPlanarMaterial.ts
  68. 686 0
      materialsLibrary/materials/triPlanar/triplanar.fragment.fx
  69. 190 0
      materialsLibrary/materials/triPlanar/triplanar.vertex.fx
  70. 64 1
      materialsLibrary/materials/water/babylon.waterMaterial.ts
  71. 695 693
      materialsLibrary/materials/water/water.fragment.fx
  72. 209 209
      materialsLibrary/materials/water/water.vertex.fx
  73. 14 0
      materialsLibrary/test/add/addfire.js
  74. 54 0
      materialsLibrary/test/add/addfur.js
  75. 71 61
      materialsLibrary/test/add/addpbr.js
  76. 19 0
      materialsLibrary/test/add/addterrain.js
  77. 19 0
      materialsLibrary/test/add/addtriplanar.js
  78. 37072 0
      materialsLibrary/test/babylon.max.js
  79. 36 33
      materialsLibrary/test/index.html
  80. 20 0
      materialsLibrary/test/index.js
  81. BIN
      materialsLibrary/test/textures/heightMap.png
  82. BIN
      materialsLibrary/test/textures/leopard_fur.JPG
  83. BIN
      materialsLibrary/test/textures/mixMap.png
  84. BIN
      materialsLibrary/test/textures/speckles.jpg
  85. 1 1
      proceduralTexturesLibrary/dist/babylon.brickProceduralTexture.js
  86. 1 1
      proceduralTexturesLibrary/dist/babylon.cloudProceduralTexture.js
  87. 1 1
      proceduralTexturesLibrary/dist/babylon.fireProceduralTexture.js
  88. 1 1
      proceduralTexturesLibrary/dist/babylon.grassProceduralTexture.js
  89. 1 1
      proceduralTexturesLibrary/dist/babylon.marbleProceduralTexture.js
  90. 1 1
      proceduralTexturesLibrary/dist/babylon.roadProceduralTexture.js
  91. 84 4
      proceduralTexturesLibrary/dist/babylon.starfieldProceduralTexture.js
  92. 1 1
      proceduralTexturesLibrary/dist/babylon.starfieldProceduralTexture.min.js
  93. 1 1
      proceduralTexturesLibrary/dist/babylon.woodProceduralTexture.js
  94. 73 5
      proceduralTexturesLibrary/proceduralTextures/starfield/babylon.starfieldProceduralTexture.ts
  95. 9 11
      proceduralTexturesLibrary/proceduralTextures/starfield/starfieldProceduralTexture.fragment.fx
  96. 2170 1937
      proceduralTexturesLibrary/test/babylon.max.js
  97. 21 34
      proceduralTexturesLibrary/test/index.html
  98. 20 20
      proceduralTexturesLibrary/test/index.js
  99. 1 91
      readme.md
  100. 0 0
      src/Actions/babylon.action.ts

+ 1 - 0
.gitattributes

@@ -0,0 +1 @@
+* -crlf

+ 3 - 0
.gitignore

@@ -120,3 +120,6 @@ UpgradeLog*.XML
 # Do not ignore loaders/obj
 !loaders/*
 node_modules
+
+# for JetBrains IDE
+.idea

+ 247 - 105
Exporters/Blender/io_export_babylon.py

@@ -1,7 +1,7 @@
 bl_info = {
     'name': 'Babylon.js',
     'author': 'David Catuhe, Jeff Palmer',
-    'version': (3, 0, 6),
+    'version': (4, 0, 0),
     'blender': (2, 75, 0),
     'location': 'File > Export > Babylon.js (.babylon)',
     'description': 'Export Babylon.js scenes (.babylon)',
@@ -38,9 +38,9 @@ if __name__ == '__main__':
 # output related constants
 MAX_VERTEX_ELEMENTS = 65535
 MAX_VERTEX_ELEMENTS_32Bit = 16777216
-VERTEX_OUTPUT_PER_LINE = 1000
+VERTEX_OUTPUT_PER_LINE = 100
 MAX_FLOAT_PRECISION = '%.4f'
-MAX_INFLUENCERS_PER_VERTEX = 4
+COMPRESS_MATRIX_INDICES = True # this is True for .babylon exporter & False for TOB
 
 # used in World constructor, defined in BABYLON.Scene
 #FOGMODE_NONE = 0
@@ -110,6 +110,8 @@ CUBIC_MODE = 3
 #PROJECTION_MODE = 4
 #SKYBOX_MODE = 5
 
+DEFAULT_MATERIAL_NAMESPACE = 'Same as Filename'
+
 # passed to Animation constructor from animatable objects, defined in BABYLON.Animation
 #ANIMATIONTYPE_FLOAT = 0
 ANIMATIONTYPE_VECTOR3 = 1
@@ -134,9 +136,9 @@ class ExporterSettingsPanel(bpy.types.Panel):
         description="Export only selected layers",
         default = False,
         )
-    bpy.types.Scene.export_noVertexOpt = bpy.props.BoolProperty(
-        name="No vertex sharing",
-        description="Turns off an optimization which reduces vertices",
+    bpy.types.Scene.export_flatshadeScene = bpy.props.BoolProperty(
+        name="Flat shade entire scene",
+        description="Use face normals on all meshes.  Increases vertices.",
         default = False,
         )        
     bpy.types.Scene.attachedSound = bpy.props.StringProperty(
@@ -165,7 +167,7 @@ class ExporterSettingsPanel(bpy.types.Panel):
 
         scene = context.scene
         layout.prop(scene, "export_onlySelectedLayer")
-        layout.prop(scene, "export_noVertexOpt")
+        layout.prop(scene, "export_flatshadeScene")
         layout.prop(scene, "inlineTextures")
 
         box = layout.box()
@@ -238,6 +240,10 @@ class Main(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
                 bpy.ops.object.mode_set(mode = 'OBJECT')
 
             Main.log('========= Conversion from Blender to Babylon.js =========', 0)
+            Main.log('Scene settings used:', 1)
+            Main.log('selected layers only:  ' + format_bool(scene.export_onlySelectedLayer), 2)
+            Main.log('flat shading entire scene:  ' + format_bool(scene.export_flatshadeScene), 2)
+            Main.log('inline textures:  ' + format_bool(scene.inlineTextures), 2)
             self.world = World(scene)
 
             bpy.ops.screen.animation_cancel()
@@ -591,8 +597,8 @@ class Mesh(FCurveAnimatable):
         self.name = object.name + str(nameID)
         Main.log('processing begun of mesh:  ' + self.name)
         self.isVisible = not object.hide_render
-        self.isEnabled = True
-        self.useFlatShading = object.data.useFlatShading
+        self.isEnabled = not object.data.loadDisabled
+        useFlatShading = scene.export_flatshadeScene or object.data.useFlatShading
         self.checkCollisions = object.data.checkCollisions
         self.receiveShadows = object.data.receiveShadows
         self.castShadows = object.data.castShadows
@@ -701,7 +707,6 @@ class Mesh(FCurveAnimatable):
                 # None will be returned when either the first encounter or must be unique due to baked textures
                 material = exporter.getMaterial(slot.name)
                 if (material != None):
-                    material.numOfUsers = material.numOfUsers + 1
                     Main.log('registered as also a user of material:  ' + slot.name, 2)
                 else:
                     material = StdMaterial(slot, exporter, object)
@@ -749,8 +754,10 @@ class Mesh(FCurveAnimatable):
             Colormap = mesh.tessface_vertex_colors.active.data
 
         if hasSkeleton:
-            self.skeletonWeights = []
-            self.skeletonIndicesCompressed = []
+            weightsPerVertex = []
+            indicesPerVertex = []
+            influenceCounts = [0, 0, 0, 0, 0, 0, 0, 0, 0] # 9, so accessed orign 1
+            highestInfluenceObserved = 0
 
         # used tracking of vertices as they are received
         alreadySavedVertices = []
@@ -759,6 +766,8 @@ class Mesh(FCurveAnimatable):
         vertices_UV2s = []
         vertices_Colors = []
         vertices_indices = []
+        vertices_sk_weights = []
+        vertices_sk_indices = []
 
         self.offsetFace = 0
 
@@ -769,11 +778,12 @@ class Mesh(FCurveAnimatable):
             vertices_UV2s.append([])
             vertices_Colors.append([])
             vertices_indices.append([])
+            vertices_sk_weights.append([])
+            vertices_sk_indices.append([])
 
         materialsCount = 1 if recipe.needsBaking else max(1, len(object.material_slots))
         verticesCount = 0
         indicesCount = 0
-        maxInfluencersExceeded = 0
 
         for materialIndex in range(materialsCount):
             if self.offsetFace != 0:
@@ -797,38 +807,22 @@ class Mesh(FCurveAnimatable):
 
                     vertex = mesh.vertices[vertex_index]
                     position = vertex.co
+                    normal = face.normal if useFlatShading else vertex.normal
                     
-                    if (scene.export_noVertexOpt):
-                        normal = face.normal
-                    else:
-                        normal = vertex.normal
-
                     #skeletons
                     if hasSkeleton:
                         matricesWeights = []
-                        matricesWeights.append(0.0)
-                        matricesWeights.append(0.0)
-                        matricesWeights.append(0.0)
-                        matricesWeights.append(0.0)
-                        matricesIndicesCompressed = 0
+                        matricesIndices = []
 
                         # Getting influences
-                        i = 0
-                        offset = 0
                         for group in vertex.groups:
                             index = group.group
                             weight = group.weight
 
                             for boneIndex, bone in enumerate(objArmature.pose.bones):
                                 if object.vertex_groups[index].name == bone.name:
-                                    if (i == MAX_INFLUENCERS_PER_VERTEX):
-                                        maxInfluencersExceeded += 1
-                                        break
-                                    matricesWeights[i] = weight
-                                    matricesIndicesCompressed += boneIndex << offset
-                                    offset = offset + 8
-
-                                    i = i + 1
+                                    matricesWeights.append(weight)
+                                    matricesIndices.append(boneIndex)
 
                     # Texture coordinates
                     if hasUV:
@@ -847,7 +841,7 @@ class Mesh(FCurveAnimatable):
                             vertex_Color = Colormap[face.index].color3
 
                     # Check if the current vertex is already saved
-                    alreadySaved = alreadySavedVertices[vertex_index] and not (hasSkeleton or scene.export_noVertexOpt)
+                    alreadySaved = alreadySavedVertices[vertex_index] and not useFlatShading
                     if alreadySaved:
                         alreadySaved = False
 
@@ -873,6 +867,12 @@ class Mesh(FCurveAnimatable):
                                 if (vColor.r != vertex_Color.r or vColor.g != vertex_Color.g or vColor.b != vertex_Color.b):
                                     continue
 
+                            if hasSkeleton:
+                                vSkWeight = vertices_sk_weights[vertex_index]
+                                vSkIndices = vertices_sk_indices[vertex_index]
+                                if not same_array(vSkWeight[index_UV], matricesWeights) or not same_array(vSkIndices[index_UV], matricesIndices):
+                                    continue 
+
                             if vertices_indices[vertex_index][index_UV] >= subMeshVerticesStart:
                                 alreadySaved = True
                                 break
@@ -905,11 +905,13 @@ class Mesh(FCurveAnimatable):
                             self.colors.append(vertex_Color.b)
                             self.colors.append(1.0)
                         if hasSkeleton:
-                            self.skeletonWeights.append(matricesWeights[0])
-                            self.skeletonWeights.append(matricesWeights[1])
-                            self.skeletonWeights.append(matricesWeights[2])
-                            self.skeletonWeights.append(matricesWeights[3])
-                            self.skeletonIndicesCompressed.append(matricesIndicesCompressed)
+                            vertices_sk_weights[vertex_index].append(matricesWeights)
+                            vertices_sk_indices[vertex_index].append(matricesIndices)
+                            nInfluencers = len(matricesWeights)
+                            influenceCounts[nInfluencers] += 1
+                            highestInfluenceObserved = nInfluencers if nInfluencers > highestInfluenceObserved else highestInfluenceObserved
+                            weightsPerVertex.append(matricesWeights)
+                            indicesPerVertex.append(matricesIndices)
 
                         vertices_indices[vertex_index].append(index)
 
@@ -922,11 +924,8 @@ class Mesh(FCurveAnimatable):
             self.subMeshes.append(SubMesh(materialIndex, subMeshVerticesStart, subMeshIndexStart, verticesCount - subMeshVerticesStart, indicesCount - subMeshIndexStart))
 
         if verticesCount > MAX_VERTEX_ELEMENTS:
-            Main.warn('Due to multi-materials & this meshes size, 32bit indices must be used.  This may not run on all hardware.', 2)
+            Main.warn('Due to multi-materials / Shapekeys & this meshes size, 32bit indices must be used.  This may not run on all hardware.', 2)
 
-        if maxInfluencersExceeded > 0:
-            Main.warn('Maximum # of influencers exceeded for ' + format_int(maxInfluencersExceeded) + ' vertices, extras ignored', 2)
-            
         BakedMaterial.meshBakingClean(object)
 
         Main.log('num positions      :  ' + str(len(self.positions)), 2)
@@ -935,9 +934,29 @@ class Mesh(FCurveAnimatable):
         Main.log('num uvs2           :  ' + str(len(self.uvs2     )), 2)
         Main.log('num colors         :  ' + str(len(self.colors   )), 2)
         Main.log('num indices        :  ' + str(len(self.indices  )), 2)
-        if hasattr(self, 'skeletonWeights'):
-            Main.log('num skeletonWeights:  ' + str(len(self.skeletonWeights)), 2)
-            Main.log('num skeletonIndices:  ' + str(len(self.skeletonIndicesCompressed * 4)), 2)
+        if hasSkeleton:
+            Main.log('Skeleton stats:  ', 2)
+            self.toFixedInfluencers(weightsPerVertex, indicesPerVertex, object.data.maxInfluencers, highestInfluenceObserved)
+
+            if (COMPRESS_MATRIX_INDICES):
+                self.skeletonIndices = Mesh.packSkeletonIndices(self.skeletonIndices)
+                if (self.numBoneInfluencers > 4):
+                    self.skeletonIndicesExtra = Mesh.packSkeletonIndices(self.skeletonIndicesExtra)
+                
+            totalInfluencers  = influenceCounts[1]
+            totalInfluencers += influenceCounts[2] * 2
+            totalInfluencers += influenceCounts[3] * 3
+            totalInfluencers += influenceCounts[4] * 4
+            totalInfluencers += influenceCounts[5] * 5
+            totalInfluencers += influenceCounts[6] * 6
+            totalInfluencers += influenceCounts[7] * 7
+            totalInfluencers += influenceCounts[8] * 8
+            Main.log('Total Influencers:  ' + format_f(totalInfluencers), 3)
+            Main.log('Avg # of influencers per vertex:  ' + format_f(totalInfluencers / len(self.positions)), 3)
+            Main.log('Highest # of influencers observed:  ' + str(highestInfluenceObserved) + ', num vertices with this:  ' + format_int(influenceCounts[highestInfluenceObserved]), 3)
+            Main.log('exported as ' + str(self.numBoneInfluencers) + ' influencers', 3)
+            nWeights = len(self.skeletonWeights) + len(self.skeletonWeightsExtra) if hasattr(self, 'skeletonWeightsExtra') else 0
+            Main.log('num skeletonWeights and skeletonIndices:  ' + str(nWeights), 3)
 
         numZeroAreaFaces = self.find_zero_area_faces()
         if numZeroAreaFaces > 0:
@@ -969,6 +988,85 @@ class Mesh(FCurveAnimatable):
         except:
             pass
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    def toFixedInfluencers(self, weightsPerVertex, indicesPerVertex, maxInfluencers, highestObserved):
+        if (maxInfluencers > 8 or maxInfluencers < 1):
+            maxInfluencers = 8
+            Main.warn('Maximum # of influencers invalid, set to 8', 3)
+            
+        self.numBoneInfluencers = maxInfluencers if maxInfluencers < highestObserved else highestObserved
+        needExtras = self.numBoneInfluencers > 4
+        
+        maxInfluencersExceeded = 0
+        
+        fixedWeights = []
+        fixedIndices = []
+        
+        fixedWeightsExtra = []
+        fixedIndicesExtra = []
+        
+        for i in range(len(weightsPerVertex)):
+            weights = weightsPerVertex[i]
+            indices = indicesPerVertex[i]
+            nInfluencers = len(weights)
+            
+            if (nInfluencers > self.numBoneInfluencers):
+                maxInfluencersExceeded += 1
+                Mesh.sortByDescendingInfluence(weights, indices)
+                
+            for j in range(4):
+                fixedWeights.append(weights[j] if nInfluencers > j else 0.0)
+                fixedIndices.append(indices[j] if nInfluencers > j else 0  )
+                
+            if needExtras:
+                for j in range(4, 8):
+                    fixedWeightsExtra.append(weights[j] if nInfluencers > j else 0.0)
+                    fixedIndicesExtra.append(indices[j] if nInfluencers > j else 0  )
+                            
+        self.skeletonWeights = fixedWeights
+        self.skeletonIndices = fixedIndices
+        
+        if needExtras:
+            self.skeletonWeightsExtra = fixedWeightsExtra
+            self.skeletonIndicesExtra = fixedIndicesExtra
+            
+        if maxInfluencersExceeded > 0:
+            Main.warn('Maximum # of influencers exceeded for ' + format_int(maxInfluencersExceeded) + ' vertices, extras ignored', 3)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    # sorts one set of weights & indices by descending weight, by reference
+    # not shown to help with MakeHuman, but did not hurt.  In just so it is not lost for future.
+    @staticmethod
+    def sortByDescendingInfluence(weights, indices):
+        notSorted = True
+        while(notSorted):
+            notSorted = False
+            for idx in range(1, len(weights)):
+                if weights[idx - 1] < weights[idx]:
+                    tmp = weights[idx]
+                    weights[idx    ] = weights[idx - 1]
+                    weights[idx - 1] = tmp
+                    
+                    tmp = indices[idx]
+                    indices[idx    ] = indices[idx - 1]
+                    indices[idx - 1] = tmp
+                    
+                    notSorted = True    
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    # assume that toFixedInfluencers has already run, which ensures indices length is a multiple of 4
+    @staticmethod
+    def packSkeletonIndices(indices):
+        compressedIndices = []
+
+        for i in range(math.floor(len(indices) / 4)):
+            idx = i * 4
+            matricesIndicesCompressed  = indices[idx    ]
+            matricesIndicesCompressed += indices[idx + 1] <<  8
+            matricesIndicesCompressed += indices[idx + 2] << 16
+            matricesIndicesCompressed += indices[idx + 3] << 24
+            
+            compressedIndices.append(matricesIndicesCompressed)
+            
+        return compressedIndices
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     def to_scene_file(self, file_handler):
         file_handler.write('{')
         write_string(file_handler, 'name', self.name, True)
@@ -988,7 +1086,6 @@ class Mesh(FCurveAnimatable):
         write_bool(file_handler, 'isVisible', self.isVisible)
         write_bool(file_handler, 'freezeWorldMatrix', self.freezeWorldMatrix)
         write_bool(file_handler, 'isEnabled', self.isEnabled)
-        write_bool(file_handler, 'useFlatShading', self.useFlatShading)
         write_bool(file_handler, 'checkCollisions', self.checkCollisions)
         write_bool(file_handler, 'receiveShadows', self.receiveShadows)
 
@@ -999,7 +1096,10 @@ class Mesh(FCurveAnimatable):
             write_float(file_handler, 'physicsRestitution', self.physicsRestitution)
 
         # Geometry
-        if hasattr(self, 'skeletonId'): write_int(file_handler, 'skeletonId', self.skeletonId)
+        if hasattr(self, 'skeletonId'): 
+            write_int(file_handler, 'skeletonId', self.skeletonId)
+            write_int(file_handler, 'numBoneInfluencers', self.numBoneInfluencers)
+
         write_vector_array(file_handler, 'positions', self.positions)
         write_vector_array(file_handler, 'normals'  , self.normals  )
 
@@ -1014,7 +1114,11 @@ class Mesh(FCurveAnimatable):
 
         if hasattr(self, 'skeletonWeights'):
             write_array(file_handler, 'matricesWeights', self.skeletonWeights)
-            write_array(file_handler, 'matricesIndices', self.skeletonIndicesCompressed)
+            write_array(file_handler, 'matricesIndices', self.skeletonIndices)
+
+        if hasattr(self, 'skeletonWeightsExtra'):
+            write_array(file_handler, 'matricesWeightsExtra', self.skeletonWeightsExtra)
+            write_array(file_handler, 'matricesIndicesExtra', self.skeletonIndicesExtra)
 
         write_array(file_handler, 'indices', self.indices)
 
@@ -1135,7 +1239,7 @@ class SubMesh:
 #===============================================================================
 class Bone:
     def __init__(self, bone, skeleton, scene, index):
-        Main.log('processing begun of bone:  ' + bone.name + ', index:  '+ str(index))
+        Main.log('processing begun of bone:  ' + bone.name + ', index:  '+ str(index), 2)
         self.name = bone.name
         self.index = index
 
@@ -1153,7 +1257,7 @@ class Bone:
 
         #animation
         if (skeleton.animation_data):
-            Main.log('animation begun of bone:  ' + self.name)
+            Main.log('animation begun of bone:  ' + self.name, 3)
             self.animation = Animation(ANIMATIONTYPE_MATRIX, scene.render.fps, ANIMATIONLOOPMODE_CYCLE, 'anim', '_matrix')
 
             start_frame = scene.frame_start
@@ -1668,7 +1772,7 @@ class BakingRecipe:
                         continue
                     
                     # for images, just need to make sure there is only 1 per type
-                    if mtex.texture.type == 'IMAGE':
+                    if mtex.texture.type == 'IMAGE' and not forceBaking:
                         if mtex.use_map_diffuse or mtex.use_map_color_diffuse:
                             if mtex.texture_coords == 'REFLECTION':
                                 nReflectionImages += 1
@@ -1739,10 +1843,8 @@ class BakingRecipe:
 #===============================================================================
 # Not intended to be instanced directly
 class Material:
-    def __init__(self):
-        # the number of users == 1 will cause the checkReadyOnlyOnce attribute to be set to true
-        self.numOfUsers = 1
-
+    def __init__(self, checkReadyOnlyOnce):
+        self.checkReadyOnlyOnce = checkReadyOnlyOnce
         # first pass of textures, either appending image type or recording types of bakes to do
         self.textures = []
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1757,8 +1859,7 @@ class Material:
         write_float(file_handler, 'specularPower', self.specularPower)
         write_float(file_handler, 'alpha', self.alpha)
         write_bool(file_handler, 'backFaceCulling', self.backFaceCulling)
-        if self.numOfUsers == 1:
-             write_bool(file_handler, 'checkReadyOnlyOnce', True)
+        write_bool(file_handler, 'checkReadyOnlyOnce', self.checkReadyOnlyOnce)
         for texSlot in self.textures:
             texSlot.to_scene_file(file_handler)
 
@@ -1766,8 +1867,10 @@ class Material:
 #===============================================================================
 class StdMaterial(Material):
     def __init__(self, material_slot, exporter, mesh):
-        super().__init__()
-        self.name = Main.nameSpace + '.' + material_slot.name
+        super().__init__(mesh.data.checkReadyOnlyOnce)
+        nameSpace = Main.nameSpace if mesh.data.materialNameSpace == DEFAULT_MATERIAL_NAMESPACE else mesh.data.materialNameSpace 
+        self.name = nameSpace + '.' + material_slot.name
+                
         Main.log('processing begun of Standard material:  ' +  material_slot.name, 2)
 
         # a material slot is not a reference to an actual material; need to look up
@@ -1796,36 +1899,41 @@ class StdMaterial(Material):
 
             if mtex.use_map_diffuse or mtex.use_map_color_diffuse:
                 if mtex.texture_coords == 'REFLECTION':
-                    Main.log('Reflection texture found', 2)
+                    Main.log('Reflection texture found"' + mtex.name + '"', 2)
                     self.textures.append(Texture('reflectionTexture', mtex.diffuse_color_factor, mtex, mesh, exporter))
                 else:
-                    Main.log('Diffuse texture found', 2)
+                    Main.log('Diffuse texture found"' + mtex.name + '"', 2)
                     self.textures.append(Texture('diffuseTexture', mtex.diffuse_color_factor, mtex, mesh, exporter))
 
             if mtex.use_map_ambient:
-                Main.log('Ambient texture found', 2)
+                Main.log('Ambient texture found"' + mtex.name + '"', 2)
                 self.textures.append(Texture('ambientTexture', mtex.ambient_factor, mtex, mesh, exporter))
 
             if mtex.use_map_alpha:
-                Main.log('Opacity texture found', 2)
-                self.textures.append(Texture('opacityTexture', mtex.alpha_factor, mtex, mesh, exporter))
+                if self.alpha > 0:
+                    Main.log('Opacity texture found"' + mtex.name + '"', 2)
+                    self.textures.append(Texture('opacityTexture', mtex.alpha_factor, mtex, mesh, exporter))
+                else:
+                    Main.warn('Opacity non-std way to indicate opacity, use material alpha to also use Opacity texture', 2)
+                    self.alpha = 1
 
             if mtex.use_map_emit:
-                Main.log('Emissive texture found', 2)
+                Main.log('Emissive texture found"' + mtex.name + '"', 2)
                 self.textures.append(Texture('emissiveTexture', mtex.emit_factor, mtex, mesh, exporter))
 
             if mtex.use_map_normal:
-                Main.log('Bump texture found', 2)
+                Main.log('Bump texture found"' + mtex.name + '"', 2)
                 self.textures.append(Texture('bumpTexture', 1.0 / mtex.normal_factor, mtex, mesh, exporter))
 
             if mtex.use_map_color_spec:
-                Main.log('Specular texture found', 2)
+                Main.log('Specular texture found"' + mtex.name + '"', 2)
                 self.textures.append(Texture('specularTexture', mtex.specular_color_factor, mtex, mesh, exporter))
 #===============================================================================
 class BakedMaterial(Material):
     def __init__(self, exporter, mesh, recipe):
-        super().__init__()
-        self.name = Main.nameSpace + '.' + mesh.name
+        super().__init__(mesh.data.checkReadyOnlyOnce)
+        nameSpace = Main.nameSpace if mesh.data.materialNameSpace == DEFAULT_MATERIAL_NAMESPACE else mesh.data.materialNameSpace 
+        self.name = nameSpace + '.' + mesh.name
         Main.log('processing begun of baked material:  ' +  mesh.name, 2)
 
         # any baking already took in the values. Do not want to apply them again, but want shadows to show.
@@ -1851,11 +1959,7 @@ class BakedMaterial(Material):
 
         # you need UV on a mesh in order to bake image.  This is not reqd for procedural textures, so may not exist
         # need to look if it might already be created, as for a mesh with multi-materials
-        uv = None
-        for uvMap in mesh.data.uv_textures:
-            if uvMap.name == 'BakingUV':
-                uv = uvMap
-                break
+        uv = mesh.data.uv_textures[0] if len(mesh.data.uv_textures) > 0 else None
 
         if uv == None:
             mesh.data.uv_textures.new('BakingUV')
@@ -1883,25 +1987,25 @@ class BakedMaterial(Material):
 
         # now go thru all the textures that need to be baked
         if recipe.diffuseBaking:
-            self.bake('diffuseTexture', 'DIFFUSE_COLOR', 'TEXTURE', image, mesh, exporter, recipe)
+            self.bake('diffuseTexture', 'DIFFUSE_COLOR', 'TEXTURE', image, mesh, uv, exporter, recipe)
 
         if recipe.ambientBaking:
-            self.bake('ambientTexture', 'AO', 'AO', image, mesh, exporter, recipe)
+            self.bake('ambientTexture', 'AO', 'AO', image, mesh, uv, exporter, recipe)
 
         if recipe.opacityBaking:  # no eqivalent found for cycles
-            self.bake('opacityTexture', None, 'ALPHA', image, mesh, exporter, recipe)
+            self.bake('opacityTexture', None, 'ALPHA', image, mesh, uv, exporter, recipe)
 
         if recipe.reflectionBaking:
-            self.bake('reflectionTexture', 'REFLECTION', 'MIRROR_COLOR', image, mesh, exporter, recipe)
+            self.bake('reflectionTexture', 'REFLECTION', 'MIRROR_COLOR', image, mesh, uv, exporter, recipe)
 
         if recipe.emissiveBaking:
-            self.bake('emissiveTexture', 'EMIT', 'EMIT', image, mesh, exporter, recipe)
+            self.bake('emissiveTexture', 'EMIT', 'EMIT', image, mesh, uv, exporter, recipe)
 
         if recipe.bumpBaking:
-            self.bake('bumpTexture', 'NORMAL', 'NORMALS', image, mesh, exporter, recipe)
+            self.bake('bumpTexture', 'NORMAL', 'NORMALS', image, mesh, uv, exporter, recipe)
 
         if recipe.specularBaking:
-            self.bake('specularTexture', 'SPECULAR', 'SPEC_COLOR', image, mesh, exporter, recipe)
+            self.bake('specularTexture', 'SPECULAR', 'SPEC_COLOR', image, mesh, uv, exporter, recipe)
 
         # Toggle vertex selection & mode, if setting changed their value
         bpy.ops.mesh.select_all(action='TOGGLE')  # still in edit mode toggle select back to previous
@@ -1911,19 +2015,21 @@ class BakedMaterial(Material):
 
         exporter.scene.render.engine = engine
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-    def bake(self, bjs_type, cycles_type, internal_type, image, mesh, exporter, recipe):
+    def bake(self, bjs_type, cycles_type, internal_type, image, mesh, uv, exporter, recipe):
         if recipe.cyclesRender:
             if cycles_type is None:
                 return
-            self.bakeCycles(cycles_type, image, recipe.nodeTrees)
+            self.bakeCycles(cycles_type, image, uv, recipe.nodeTrees)
         else:
-            self.bakeInternal(internal_type, image)
+            self.bakeInternal(internal_type, image, uv)
 
         self.textures.append(Texture(bjs_type, 1.0, image, mesh, exporter))
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-    def bakeInternal(self, bake_type, image):
-        Main.log('Internal baking texture, type: ' + bake_type + ', mapped using: BakingUV', 3)
-        image.filepath = self.name + '_' + bake_type + '.jpg'
+    def bakeInternal(self, bake_type, image, uv):
+        Main.log('Internal baking texture, type: ' + bake_type + ', mapped using: ' + uv.name, 3)
+        # need to use the legal name, since this will become the file name, chars like ':' not legal
+        legalName = legal_js_identifier(self.name)
+        image.filepath = legalName + '_' + bake_type + '.jpg'
 
         scene = bpy.context.scene
         scene.render.engine = 'BLENDER_RENDER'
@@ -1946,9 +2052,10 @@ class BakedMaterial(Material):
 
         bpy.ops.object.bake_image()
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-    def bakeCycles(self, bake_type, image, nodeTrees):
-        Main.log('Cycles baking texture, type: ' + bake_type + ', mapped using: BakingUV', 3)
-        image.filepath = self.name + '_' + bake_type + '.jpg'
+    def bakeCycles(self, bake_type, image, uv, nodeTrees):
+        Main.log('Cycles baking texture, type: ' + bake_type + ', mapped using: ' + uv.name, 3)
+        legalName = legal_js_identifier(self.name)
+        image.filepath = legalName + '_' + bake_type + '.jpg'
 
         scene = bpy.context.scene
         scene.render.engine = 'CYCLES'
@@ -2199,6 +2306,13 @@ def scale_vector(vector, mult, xOffset = 0):
 
 def same_vertex(vertA, vertB):
     return vertA.x == vertB.x and vertA.y == vertB.y and vertA.z == vertB.z
+
+def same_array(arrayA, arrayB):
+    if len(arrayA) != len(arrayB): return False
+    for i in range(len(arrayA)):
+        if arrayA[i] != arrayB[i] : return False
+        
+    return True
 #===============================================================================
 # module level methods for writing JSON (.babylon) files
 #===============================================================================
@@ -2250,7 +2364,7 @@ bpy.types.Mesh.autoAnimate = bpy.props.BoolProperty(
 )
 bpy.types.Mesh.useFlatShading = bpy.props.BoolProperty(
     name='Use Flat Shading',
-    description='',
+    description='Use face normals.  Increases vertices.',
     default = False
 )
 bpy.types.Mesh.checkCollisions = bpy.props.BoolProperty(
@@ -2276,13 +2390,28 @@ bpy.types.Mesh.bakeSize = bpy.props.IntProperty(
 bpy.types.Mesh.bakeQuality = bpy.props.IntProperty(
     name='Quality 1-100',
     description='The trade-off between Quality - File size(100 highest quality)',
-    default = 50
+    default = 50, min = 1, max = 100
+)
+bpy.types.Mesh.materialNameSpace = bpy.props.StringProperty(
+    name='Name Space',
+    description='Prefix to use for materials for sharing across .blends.',
+    default = DEFAULT_MATERIAL_NAMESPACE
+)
+bpy.types.Mesh.checkReadyOnlyOnce = bpy.props.BoolProperty(
+    name='Check Ready Only Once',
+    description='When checked better CPU utilization.  Advanced user option.',
+    default = False
 )
 bpy.types.Mesh.freezeWorldMatrix = bpy.props.BoolProperty(
     name='Freeze World Matrix',
     description='Indicate the position, rotation, & scale do not change for performance reasons',
     default = False
 )
+bpy.types.Mesh.loadDisabled = bpy.props.BoolProperty(
+    name='Load Disabled',
+    description='Indicate this mesh & children should not be active until enabled by code.',
+    default = False
+)
 bpy.types.Mesh.attachedSound = bpy.props.StringProperty(
     name='Sound',
     description='',
@@ -2303,6 +2432,11 @@ bpy.types.Mesh.maxSoundDistance = bpy.props.FloatProperty(
     description='',
     default = 100
 )
+bpy.types.Mesh.maxInfluencers = bpy.props.IntProperty(
+    name='Max bone Influencers / Vertex',
+    description='When fewer than this are observed, the lower value is used.',
+    default = 8, min = 1, max = 8
+)
 #===============================================================================
 bpy.types.Camera.autoAnimate = bpy.props.BoolProperty(
     name='Auto launch animations',
@@ -2417,22 +2551,31 @@ class ObjectPanel(bpy.types.Panel):
         isLight = isinstance(ob.data, bpy.types.Lamp)
 
         if isMesh:
-            layout.prop(ob.data, 'useFlatShading')
-            layout.prop(ob.data, 'checkCollisions')
-            layout.prop(ob.data, 'castShadows')
-            layout.prop(ob.data, 'receiveShadows')
-
-            layout.separator()
-
-            layout.prop(ob.data, 'autoAnimate')
+            row = layout.row()
+            row.prop(ob.data, 'useFlatShading')
+            row.prop(ob.data, 'checkCollisions')
+            
+            row = layout.row()
+            row.prop(ob.data, 'castShadows')
+            row.prop(ob.data, 'receiveShadows')
+            
+            row = layout.row()
+            row.prop(ob.data, 'freezeWorldMatrix')
+            row.prop(ob.data, 'loadDisabled')
+            
+            layout.prop(ob.data, 'autoAnimate')            
+            layout.prop(ob.data, 'maxInfluencers')
 
             box = layout.box()
-            box.label(text="Procedural Texture / Cycles Baking")
+            box.label('Materials')
+            box.prop(ob.data, 'materialNameSpace')
+            box.prop(ob.data, 'checkReadyOnlyOnce')
+            
+            box = layout.box()
+            box.label(text='Procedural Texture / Cycles Baking')
             box.prop(ob.data, 'bakeSize')
             box.prop(ob.data, 'bakeQuality')
 
-            layout.prop(ob.data, 'freezeWorldMatrix')
-
             box = layout.box()
             box.prop(ob.data, 'attachedSound')
             box.prop(ob.data, 'autoPlaySound')
@@ -2463,4 +2606,3 @@ class ObjectPanel(bpy.types.Panel):
             box.prop(ob.data, 'shadowBlurBoxOffset')
 
             layout.prop(ob.data, 'autoAnimate')
-

+ 4 - 0
Exporters/Blender/readme.md

@@ -31,6 +31,7 @@ For a discussion of Tower of Babel exporter, along with the difference this expo
  * Animations
 * **Materials**
  * Name
+ * Name space
  * Ambient color
  * Diffuse color
  * Specular color
@@ -46,6 +47,7 @@ For a discussion of Tower of Babel exporter, along with the difference this expo
  * Bump texture
  * Procedural Texture Baking
  * Cycles Render Baking
+ * Check Ready Only Once
 * **Multi-materials**
  * Name
  * Child materials
@@ -71,10 +73,12 @@ For a discussion of Tower of Babel exporter, along with the difference this expo
  * Texture coordinates (2 channels)
  * Vertex colors
  * Visibility
+ * Load disabled
  * Check collisions
  * Billboard
  * Receive and cast shadows
  * Bones (armatures) and bones' animations
+ 	* Variable Max Bone Influencers / vertex
  * Animations
 
 

+ 1 - 1
Exporters/Unity 5/Unity3D2Babylon/ExporterWindow.cs

@@ -40,7 +40,7 @@ namespace Unity3D2Babylon
 
         void Initialize()
         {
-            title = "Babylon.js";
+            titleContent.text = "Babylon.js";
         }
 
         void OnGUI()

+ 103 - 20
Exporters/Unity 5/Unity3D2Babylon/SceneBuilder.Meshes.cs

@@ -6,22 +6,113 @@ namespace Unity3D2Babylon
 {
     partial class SceneBuilder
     {
-        private void ConvertUnityEmptyObjectToBabylon(GameObject gameObject)
+        private BabylonAbstractMesh ConvertUnityMeshToInstance(GameObject gameObject)
         {
-            BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) };
+            BabylonAbstractMesh babylonMesh = new BabylonAbstractMesh();
 
-            var transform = gameObject.transform;
+            Transform transform = gameObject.transform;
+            babylonMesh.name = gameObject.name;
+            babylonMesh.position = new float[3];
+            babylonMesh.position[0] = transform.position.x;
+            babylonMesh.position[1] = transform.position.y;
+            babylonMesh.position[2] = transform.position.z;
 
-            babylonMesh.parentId = GetParentID(transform);
+            babylonMesh.rotation = new float[3];
+            babylonMesh.rotation[0] = transform.rotation.eulerAngles.x * (float)Math.PI / 180;
+            babylonMesh.rotation[1] = transform.rotation.eulerAngles.y * (float)Math.PI / 180;
+            babylonMesh.rotation[2] = transform.rotation.eulerAngles.z * (float)Math.PI / 180;
+
+            babylonMesh.scaling = new float[3];
+            babylonMesh.scaling[0] = transform.localScale.x;
+            babylonMesh.scaling[1] = transform.localScale.y;
+            babylonMesh.scaling[2] = transform.localScale.z;
+            return babylonMesh;
+        }
 
-            babylonMesh.position = transform.localPosition.ToFloat();
+        private void ConvertTransform(BabylonMesh babylonMesh, Transform transform, GameObject gameObject, BabylonAbstractMesh[] instances = null)
+        {
+            Action SetTransformFromGameobject = () =>
+            {
+                babylonMesh.position = transform.localPosition.ToFloat();
 
-            babylonMesh.rotation = new float[3];
-            babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
-            babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
-            babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;
+                babylonMesh.rotation = new float[3];
+                babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
+                babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
+                babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;
+
+                babylonMesh.scaling = transform.localScale.ToFloat();
+            };
 
-            babylonMesh.scaling = transform.localScale.ToFloat();
+            Action SetTransformFromFirstInstance = () =>
+            {
+                BabylonAbstractMesh first = instances[0];
+
+                babylonMesh.position = new float[3];
+                babylonMesh.position[0] = first.position[0];
+                babylonMesh.position[1] = first.position[1];
+                babylonMesh.position[2] = first.position[2];
+
+                babylonMesh.rotation = new float[3];
+                babylonMesh.rotation[0] = first.rotation[0];
+                babylonMesh.rotation[1] = first.rotation[1];
+                babylonMesh.rotation[2] = first.rotation[2];
+
+                babylonMesh.scaling = new float[3];
+                babylonMesh.scaling[0] = first.scaling[0];
+                babylonMesh.scaling[1] = first.scaling[1];
+                babylonMesh.scaling[2] = first.scaling[2];
+            };
+
+            //Check if this is a prefab
+            if (instances != null)
+            {
+                /*
+                    Unity3D prefabs don't have transforms (position, rotation, scale) because they are just a template and are not drawn on screen          
+                    but Babylon.js meshes must have a transform because they are drawn on the screen
+                    so what we do is take the first instance
+                    copy its transform (position, rotation, scale) into the prefab mesh
+                    then remove that first instance
+                */
+
+                babylonMesh.instances = new BabylonAbstractMesh[instances.Length - 1];
+
+                //Effectively remove first instance from list of all instances
+                for (int i = 0; i < instances.Length - 1; i++)
+                {
+                    babylonMesh.instances[i] = instances[i + 1];
+                }
+
+                //If this is the root object then copy values directly from first instance
+                if (GetParentID(transform) == null)
+                {
+                    SetTransformFromFirstInstance();
+                }
+                else
+                {
+                    GameObject parent = gameObject.transform.parent.gameObject;
+                    if ((parent.GetComponent<Light>() == null) && (parent.GetComponent<Camera>() == null))
+                    {
+                        SetTransformFromGameobject();
+                    } else
+                    {
+                        SetTransformFromFirstInstance();
+                    }
+                }
+            }
+            else
+            {
+                SetTransformFromGameobject();
+            }
+        }
+
+        private void ConvertUnityEmptyObjectToBabylon(GameObject gameObject, BabylonAbstractMesh[] instances = null)
+        {
+            BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) };
+
+            var transform = gameObject.transform;
+
+            babylonMesh.parentId = GetParentID(transform);
+            ConvertTransform(babylonMesh, transform, gameObject, instances);
 
             babylonScene.MeshesList.Add(babylonMesh);
 
@@ -34,7 +125,7 @@ namespace Unity3D2Babylon
             }
         }
 
-        private void ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress)
+        private void ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress, BabylonAbstractMesh[] instances = null)
         {
             BabylonMesh babylonMesh = new BabylonMesh();
             var renderer = gameObject.GetComponent<Renderer>();
@@ -46,15 +137,7 @@ namespace Unity3D2Babylon
             babylonMesh.receiveShadows = renderer.receiveShadows;
 
             babylonMesh.parentId = GetParentID(transform);
-
-            babylonMesh.position = transform.localPosition.ToFloat();
-
-            babylonMesh.rotation = new float[3];
-            babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
-            babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
-            babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;
-
-            babylonMesh.scaling = transform.localScale.ToFloat();
+            ConvertTransform(babylonMesh, transform, gameObject, instances);
 
             babylonMesh.positions = new float[mesh.vertexCount * 3];
 

+ 69 - 9
Exporters/Unity 5/Unity3D2Babylon/SceneBuilder.cs

@@ -7,6 +7,7 @@ using UnityEngine;
 using Object = UnityEngine.Object;
 using JsonFx.Serialization;
 using JsonFx.Serialization.Resolvers;
+using UnityEditor;
 
 namespace Unity3D2Babylon
 {
@@ -108,10 +109,52 @@ namespace Unity3D2Babylon
             var itemsCount = gameObjects.Length;
 
             var index = 0;
+
+            //Dictionary to store prefabs and their instances
+            Dictionary<GameObject, List<BabylonAbstractMesh>> dicPrefabs = new Dictionary<GameObject, List<BabylonAbstractMesh>>();
+
             foreach (var gameObject in gameObjects)
             {
                 var progress = ((float)index / itemsCount);
                 index++;
+
+                /* 
+                    The order of processing is important here.
+                    We will only check if this is a mesh prefab if it is not a light or camera
+                */
+
+                // Light
+                var light = gameObject.GetComponent<Light>();
+                if (light != null)
+                {
+                    ConvertUnityLightToBabylon(light, progress);
+                    continue;
+                }
+
+                // Camera
+                var camera = gameObject.GetComponent<Camera>();
+                if (camera != null)
+                {
+                    ConvertUnityCameraToBabylon(camera, progress);
+                    continue;
+                }
+
+                // Check if this is a prefab instance
+                GameObject gobjPrefab = (GameObject)PrefabUtility.GetPrefabParent(gameObject);
+                if (gobjPrefab != null)
+                {
+                    //Add prefab to dictionary if it doesn't already exist
+                    if (!dicPrefabs.ContainsKey(gobjPrefab))
+                    {
+                        dicPrefabs[gobjPrefab] = new List<BabylonAbstractMesh>();
+                    }
+
+                    List<BabylonAbstractMesh> lstInstances = dicPrefabs[gobjPrefab];
+                    BabylonAbstractMesh instance = ConvertUnityMeshToInstance(gameObject);
+                    lstInstances.Add(instance);
+                    continue;
+                }
+
                 // Static meshes
                 var meshFilter = gameObject.GetComponent<MeshFilter>();
                 if (meshFilter != null)
@@ -128,24 +171,41 @@ namespace Unity3D2Babylon
                     continue;
                 }
 
-                // Light
-                var light = gameObject.GetComponent<Light>();
-                if (light != null)
+                // Empty
+                ConvertUnityEmptyObjectToBabylon(gameObject);
+            }
+
+            index = 0;
+            itemsCount = dicPrefabs.Count;
+
+            //Convert prefabs
+            foreach (KeyValuePair<GameObject, List<BabylonAbstractMesh>> pair in dicPrefabs)
+            {
+                var progress = ((float)index / itemsCount);
+                index++;
+
+                List<BabylonAbstractMesh> lstValue = pair.Value;
+                GameObject prefab = pair.Key;
+                BabylonAbstractMesh[] lstInstance = lstValue.ToArray();
+
+                // Static meshes
+                var meshFilter = prefab.GetComponent<MeshFilter>();
+                if (meshFilter != null)
                 {
-                    ConvertUnityLightToBabylon(light, progress);
+                    ConvertUnityMeshToBabylon(meshFilter.sharedMesh, meshFilter.transform, prefab, progress, lstInstance);
                     continue;
                 }
 
-                // Camera
-                var camera = gameObject.GetComponent<Camera>();
-                if (camera != null)
+                // Skinned meshes
+                var skinnedMesh = prefab.GetComponent<SkinnedMeshRenderer>();
+                if (skinnedMesh != null)
                 {
-                    ConvertUnityCameraToBabylon(camera, progress);
+                    ConvertUnityMeshToBabylon(skinnedMesh.sharedMesh, skinnedMesh.transform, prefab, progress, lstInstance);
                     continue;
                 }
 
                 // Empty
-                ConvertUnityEmptyObjectToBabylon(gameObject);
+                ConvertUnityEmptyObjectToBabylon(prefab, lstInstance);
             }
 
             // Materials

+ 1 - 2
Tools/Gulp/config.json

@@ -60,7 +60,6 @@
       "../../src/Materials/Textures/babylon.dynamicTexture.js",
       "../../src/Materials/Textures/babylon.videoTexture.js",
       "../../src/Materials/Textures/Procedurals/babylon.customProceduralTexture.js",
-      "../../src/Materials/Textures/babylon.proceduralTexture.js",
       "../../src/Materials/babylon.effect.js",
       "../../src/Materials/babylon.material.js",
       "../../src/Materials/babylon.standardMaterial.js",
@@ -174,4 +173,4 @@
       "../../src/Particles/babylon.solidParticleSystem.js"
     ]
   }
-}
+}

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


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


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


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


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


+ 86 - 83
dist/preview release/what's new.md

@@ -1,83 +1,86 @@
-- 2.3.0:
-  - **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))
-      - PBR Material: http://doc.babylonjs.com/extensions/pbr ([deltakosh](https://github.com/deltakosh))
-    - 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))
-    - Support for reflection probes. [See documentation here](http://doc.babylonjs.com/tutorials/How_to_use_Reflection_probes) ([deltakosh](https://github.com/deltakosh))
-    - 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.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**
-    - New button to log the camera position in the debug layer ([temechon](https://github.com/temechon))
-    - 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#12) ([deltakosh](https://github.com/deltakosh))
-    - Sprites and particles scheduler updated to be resolved before transparent objects ([deltakosh](https://github.com/deltakosh))
-    - Added ability to deactivate ArcRotateCamera panning mechanism (by setting panningSensibility to 0) ([vouskprod](http://www.github.com/vousk))    
-    - Added `DirectionalLight.autoUpdateExtends` to prevent directional lights to adapt to scene extends ([deltakosh](https://github.com/deltakosh))
-    - Added a new parameter to `debugLayer.show()` to define root element to use ([deltakosh](https://github.com/deltakosh))
-    - New `MeshBuilder` class used to create all kind of mesh shapes ([deltakosh](https://github.com/deltakosh))
-    - Added `Scene.constantlyUpdateMeshUnderPointer` to improve performance when moving mouse ([deltakosh](https://github.com/deltakosh))
-    - Added `StandardMaterial.disableLighting` ([deltakosh](https://github.com/deltakosh))
-    - Improved reflection shader performance ([deltakosh](https://github.com/deltakosh))
-    - New `Material.sideOrientation` property to define clockwise or counter-clockwise faces selection. [Demo here](http://www.babylonjs-playground.com/#1TZJQY) ([deltakosh](https://github.com/deltakosh))
-    - It is now possible to create a custom loading screen. [PR](https://github.com/BabylonJS/Babylon.js/pull/700) ([RaananW](https://github.com/RaananW))
-    - Per face color and texture feature in `MeshBuilder.CreateCylinder()` ([jerome](https://github.com/jbousquie))
-    - _Arc_ feature in `CreateCylinder`, `CreateSphere`, `CreateTube`, `CreateDisc` and `CreateLathe` ([jerome](https://github.com/jbousquie))
-    - _Slice_ feature in `MeshBuilder.CreateSphere()` ([jerome](https://github.com/jbousquie))
-    - `closed` parameter in `MeshBuilder.CreateLathe()` ([jerome](https://github.com/jbousquie))
-    - `diameter`, `hasRings`, `enclose` parameters in `MeshBuilder.CreateCreateCylinder()` ([jerome](https://github.com/jbousquie))
-    - `Material.dispose()` now removes disposed material from meshes ([deltakosh](https://github.com/deltakosh))
-    - New `Material.getBindedMeshes()` function ([deltakosh](https://github.com/deltakosh))
-    - OimoJS Plugin now uses Quaternions exclusively and calculates body rotations correctly. [PR](https://github.com/BabylonJS/Babylon.js/pull/761) ([RaananW](https://github.com/RaananW))
-    - It is now possible to get the physics engine's body and wolrd objects using the physics engine. [PR](https://github.com/BabylonJS/Babylon.js/pull/761) ([RaananW](https://github.com/RaananW))
-    - 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))
-    - Added collisionsEnabled and workerCollisions for serialization [PR](https://github.com/BabylonJS/Babylon.js/pull/830) ([Dad72](https://github.com/dad72))
-  - **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)) 
-    - Fixed a bug with CSG when submeshes are kept ([deltakosh](https://github.com/deltakosh)) 
-    - Fixed a bug with texture coordinates matrices ([deltakosh](https://github.com/deltakosh))
-    - Fixed Sphere texture coordinates generation ([deltakosh](https://github.com/deltakosh))
-    - Fixed a bug with `Mesh.attachToBone` when bone's matrix has a negative determinant ([deltakosh](https://github.com/deltakosh))
-    - Fixed a possible but with the active camera while taking a screenshot. [PR](https://github.com/BabylonJS/Babylon.js/pull/701) ([RaananW](https://github.com/RaananW))
-    - Fixed a bug with worker-collisions and instances. [PR](https://github.com/BabylonJS/Babylon.js/pull/705) ([RaananW](https://github.com/RaananW))
-    - Fixed a bug with removed meshes and geometries from the worker-cache. [PR](https://github.com/BabylonJS/Babylon.js/pull/711) ([RaananW](https://github.com/RaananW))
-    - Fixed `closePath` and `closeArray` ribbon parameter now working back together ([jerome](https://github.com/jbousquie))
-    - Fixed morphing on capped tubes  ([jerome](https://github.com/jbousquie))
-    - Fixed morphing on extruded shapes  ([jerome](https://github.com/jbousquie))
-    - Fixed tube and extruded shape cap light artifact  ([jerome](https://github.com/jbousquie))
-    - Fixed a bug calculating velocity during collision with gravity enabled. [PR](https://github.com/BabylonJS/Babylon.js/pull/738) ([RaananW](https://github.com/RaananW))
-    - Fixed a bug in instance serialization. [PR](https://github.com/BabylonJS/Babylon.js/pull/726) ([RaananW](https://github.com/RaananW))
-  - **Breaking changes**
-    - `VertexData.CreateCylinder()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateRibbon()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateBox()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateSphere)` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateTorus()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateTorusKnot()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreatePlane()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateDisc()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateLines()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateDashedLines()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateGround()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateTiledGround()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
-    - `VertexData.CreateGroundFromHeightMap()` now supports only the single _options_ parameter ([deltakosh](https://github.com/deltakosh))
-    - `Tools.IsExponantOfTwo()` renamed to `Tools.IsExponentOfTwo()` ([deltakosh](https://github.com/deltakosh))
-    - `Tools.GetExponantOfTwo()` renamed to `Tools.GetExponentOfTwo()` ([deltakosh](https://github.com/deltakosh))
-    - Updated Cannon.js plugin to the newest version (0.6.2). New cannon.js must be used. [PR](https://github.com/BabylonJS/Babylon.js/pull/755) ([RaananW](https://github.com/RaananW))
+- 2.3.0:
+  - **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))
+      - PBR Material: http://doc.babylonjs.com/extensions/pbr ([deltakosh](https://github.com/deltakosh))
+    - 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))
+    - Support for reflection probes. [See documentation here](http://doc.babylonjs.com/tutorials/How_to_use_Reflection_probes) ([deltakosh](https://github.com/deltakosh))
+    - 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.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**
+	- Unity3D exporter will recognise instances of prefabs ([ozRocker](https://github.com/punkoffice))
+    - New parse mechanism (for loading .babylon file) ([deltakosh](https://github.com/deltakosh))   
+    - New button to log the camera position in the debug layer ([temechon](https://github.com/temechon))
+    - 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#12) ([deltakosh](https://github.com/deltakosh))
+    - Sprites and particles scheduler updated to be resolved before transparent objects ([deltakosh](https://github.com/deltakosh))
+    - Added ability to deactivate ArcRotateCamera panning mechanism (by setting panningSensibility to 0) ([vouskprod](http://www.github.com/vousk))    
+    - Added `DirectionalLight.autoUpdateExtends` to prevent directional lights to adapt to scene extends ([deltakosh](https://github.com/deltakosh))
+    - Added a new parameter to `debugLayer.show()` to define root element to use ([deltakosh](https://github.com/deltakosh))
+    - New `MeshBuilder` class used to create all kind of mesh shapes ([deltakosh](https://github.com/deltakosh))
+    - Added `Scene.constantlyUpdateMeshUnderPointer` to improve performance when moving mouse ([deltakosh](https://github.com/deltakosh))
+    - Added `StandardMaterial.disableLighting` ([deltakosh](https://github.com/deltakosh))
+    - Improved reflection shader performance ([deltakosh](https://github.com/deltakosh))
+    - New `Material.sideOrientation` property to define clockwise or counter-clockwise faces selection. [Demo here](http://www.babylonjs-playground.com/#1TZJQY) ([deltakosh](https://github.com/deltakosh))
+    - It is now possible to create a custom loading screen. [PR](https://github.com/BabylonJS/Babylon.js/pull/700) ([RaananW](https://github.com/RaananW))
+    - Per face color and texture feature in `MeshBuilder.CreateCylinder()` ([jerome](https://github.com/jbousquie))
+    - _Arc_ feature in `CreateCylinder`, `CreateSphere`, `CreateTube`, `CreateDisc` and `CreateLathe` ([jerome](https://github.com/jbousquie))
+    - _Slice_ feature in `MeshBuilder.CreateSphere()` ([jerome](https://github.com/jbousquie))
+    - `closed` parameter in `MeshBuilder.CreateLathe()` ([jerome](https://github.com/jbousquie))
+    - `diameter`, `hasRings`, `enclose` parameters in `MeshBuilder.CreateCreateCylinder()` ([jerome](https://github.com/jbousquie))
+    - `Material.dispose()` now removes disposed material from meshes ([deltakosh](https://github.com/deltakosh))
+    - New `Material.getBindedMeshes()` function ([deltakosh](https://github.com/deltakosh))
+    - OimoJS Plugin now uses Quaternions exclusively and calculates body rotations correctly. [PR](https://github.com/BabylonJS/Babylon.js/pull/761) ([RaananW](https://github.com/RaananW))
+    - It is now possible to get the physics engine's body and wolrd objects using the physics engine. [PR](https://github.com/BabylonJS/Babylon.js/pull/761) ([RaananW](https://github.com/RaananW))
+    - 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))
+    - Added collisionsEnabled and workerCollisions for serialization [PR](https://github.com/BabylonJS/Babylon.js/pull/830) ([Dad72](https://github.com/dad72))
+  - **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)) 
+    - Fixed a bug with CSG when submeshes are kept ([deltakosh](https://github.com/deltakosh)) 
+    - Fixed a bug with texture coordinates matrices ([deltakosh](https://github.com/deltakosh))
+    - Fixed Sphere texture coordinates generation ([deltakosh](https://github.com/deltakosh))
+    - Fixed a bug with `Mesh.attachToBone` when bone's matrix has a negative determinant ([deltakosh](https://github.com/deltakosh))
+    - Fixed a possible but with the active camera while taking a screenshot. [PR](https://github.com/BabylonJS/Babylon.js/pull/701) ([RaananW](https://github.com/RaananW))
+    - Fixed a bug with worker-collisions and instances. [PR](https://github.com/BabylonJS/Babylon.js/pull/705) ([RaananW](https://github.com/RaananW))
+    - Fixed a bug with removed meshes and geometries from the worker-cache. [PR](https://github.com/BabylonJS/Babylon.js/pull/711) ([RaananW](https://github.com/RaananW))
+    - Fixed `closePath` and `closeArray` ribbon parameter now working back together ([jerome](https://github.com/jbousquie))
+    - Fixed morphing on capped tubes  ([jerome](https://github.com/jbousquie))
+    - Fixed morphing on extruded shapes  ([jerome](https://github.com/jbousquie))
+    - Fixed tube and extruded shape cap light artifact  ([jerome](https://github.com/jbousquie))
+    - Fixed a bug calculating velocity during collision with gravity enabled. [PR](https://github.com/BabylonJS/Babylon.js/pull/738) ([RaananW](https://github.com/RaananW))
+    - Fixed a bug in instance serialization. [PR](https://github.com/BabylonJS/Babylon.js/pull/726) ([RaananW](https://github.com/RaananW))
+    - Fixed a memory leak with textures ([deltakosh](https://github.com/deltakosh)) 
+  - **Breaking changes**
+    - `VertexData.CreateCylinder()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateRibbon()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateBox()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateSphere)` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateTorus()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateTorusKnot()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreatePlane()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateDisc()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateLines()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateDashedLines()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateGround()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateTiledGround()` now supports only the single _options_ parameter ([jerome](https://github.com/jbousquie))
+    - `VertexData.CreateGroundFromHeightMap()` now supports only the single _options_ parameter ([deltakosh](https://github.com/deltakosh))
+    - `Tools.IsExponantOfTwo()` renamed to `Tools.IsExponentOfTwo()` ([deltakosh](https://github.com/deltakosh))
+    - `Tools.GetExponantOfTwo()` renamed to `Tools.GetExponentOfTwo()` ([deltakosh](https://github.com/deltakosh))
+    - Updated Cannon.js plugin to the newest version (0.6.2). New cannon.js must be used. [PR](https://github.com/BabylonJS/Babylon.js/pull/755) ([RaananW](https://github.com/RaananW))

+ 47 - 42
loaders/glTF/README.md

@@ -1,42 +1,47 @@
-# Babylon.js glTF File Loader
-
-# Usage
-The glTF file loader is a SceneLoader plugin.
-Just reference the loader in your HTML file:
-
-```
-<script src="babylon.2.1.js"></script>
-<script src="babylon.glTFFileLoader.js"></script>
-```
-
-And then, call the scene loader:
-```
-BABYLON.SceneLoader.Load("./", "duck.gltf", engine, function (scene) { 
-   // do somethings with the scene
-});
-```
-
-## Supported features
-* Load scenes (SceneLoader.Load)
-* Import geometries
-    * From binary files
-    * From base64 buffers
-* Import lights
-* Import cameras
-* Import and set custom shaders (if no shaders, the Babylon.js default material is applied)
-    * Automatically bind attributes
-    * Automatically bind matrices
-    * Set uniforms
-* Import and set animations
-* Skinning
-    * Skeletons
-    * Hardware skinning (shaders support)
-* Handle dummy nodes (empty nodes)
-
-## Unsupported features
-* ImportMesh function
-* Skinning
-    * Bones animations
-
-## To improve
-* Bones import
+# Babylon.js glTF File Loader
+
+# Usage
+The glTF file loader is a SceneLoader plugin.
+Just reference the loader in your HTML file:
+
+```
+<script src="babylon.2.2.js"></script>
+<script src="babylon.glTFFileLoader.js"></script>
+```
+
+And then, call the scene loader:
+```
+BABYLON.SceneLoader.Load("./", "duck.gltf", engine, function (scene) { 
+   // do somethings with the scene
+});
+```
+
+You can also call the ImportMesh function and import specific meshes
+```
+// meshesNames can be set to "null" to load all meshes and skeletons
+BABYLON.SceneLoader.ImportMesh(["myMesh1", "myMesh2", "..."], "./", "duck.gltf", scene, function (meshes, particleSystems, skeletons) { 
+   // do somethings with the meshes, particleSystems (not handled in glTF files) and skeletons
+});
+```
+
+## Supported features
+* Load scenes (SceneLoader.Load and SceneLoader.Append)
+* Support of ImportMesh function
+* Import geometries
+    * From binary files
+    * From base64 buffers
+* Import lights
+* Import cameras
+* Import and set custom shaders (if no shaders, the Babylon.js default material is applied)
+    * Automatically bind attributes
+    * Automatically bind matrices
+    * Set uniforms
+* Import and set animations
+* Skinning
+    * Skeletons
+    * Hardware skinning (shaders support)
+    * Bones import
+* Handle dummy nodes (empty nodes)
+
+## To improve
+* Test on more models

File diff suppressed because it is too large
+ 1406 - 1166
loaders/glTF/babylon.glTFFileLoader.js


File diff suppressed because it is too large
+ 1656 - 1388
loaders/glTF/babylon.glTFFileLoader.ts


+ 269 - 279
loaders/glTF/babylon.glTFFileLoaderInterfaces.ts

@@ -1,280 +1,270 @@
-module BABYLON {
-    /**
-    * Interfaces
-    */
-    export interface IGLTFChildRootProperty {
-        name?: string;
-    }
-
-    export interface IGLTFAccessor extends IGLTFChildRootProperty {
-        bufferView: string;
-        byteOffset: number;
-        byteStride: number;
-        count: number;
-        type: string;
-        componentType: EComponentType;
-
-        max?: number[],
-        min?: number[],
-        name?: string;
-    }
-
-    export interface IGLTFBufferView extends IGLTFChildRootProperty {
-        buffer: string;
-        byteOffset: number;
-        byteLength: number;
-
-        target?: number;
-    }
-
-    export interface IGLTFBuffer extends IGLTFChildRootProperty {
-        uri: string;
-
-        byteLength?: number;
-        type?: string;
-    }
-
-    export interface IGLTFShader extends IGLTFChildRootProperty {
-        uri: string;
-        type: EShaderType;
-    }
-
-    export interface IGLTFProgram extends IGLTFChildRootProperty {
-        attributes: string[];
-        fragmentShader: string;
-        vertexShader: string;
-    }
-
-    export interface IGLTFTechniqueParameter {
-        type: number;
-
-        count?: number;
-        semantic?: string;
-        node?: string;
-        value?: number|boolean|string|Array<any>;
-        source?: string;
-
-        babylonValue?: any;
-    }
-
-    export interface IGLTFTechniquePassCommonProfile {
-        lightingModel: string;
-        texcoordBindings: Object;
-
-        parameters?: Array<any>;
-    }
-
-    export interface IGLTFTechniquePassInstanceProgram {
-        program: string;
-
-        attributes?: Object;
-        uniforms: Object;
-    }
-
-    export interface IGLTFTechniquePassStatesFunctions {
-        blendColor?: number[];
-        blendEquationSeparate?: number[];
-        blendFuncSeparate?: number[];
-    }
-
-    export interface IGLTFTechniquePassStates {
-        enable: number[];
-        functions: IGLTFTechniquePassStatesFunctions;
-    }
-
-    export interface IGLTFTechniquePassDetails {
-        commonProfile: IGLTFTechniquePassCommonProfile;
-        type: string;
-    }
-
-    export interface IGLTFTechniquePass {
-        details: IGLTFTechniquePassDetails;
-        instanceProgram: IGLTFTechniquePassInstanceProgram;
-        states: IGLTFTechniquePassStates;
-    }
-
-    export interface IGLTFTechnique extends IGLTFChildRootProperty {
-        parameters: Object;
-        pass: string;
-        passes: Object;
-    }
-
-    export interface IGLTFMaterialInstanceTechnique {
-        technique: string;
-
-        values?: Object;
-    }
-
-    export interface IGLTFMaterial extends IGLTFChildRootProperty {
-        instanceTechnique: IGLTFMaterialInstanceTechnique;
-    }
-
-    export interface IGLTFMeshPrimitive {
-        attributes: Object;
-        indices: string;
-        material: string;
-
-        primitive?: number;
-    }
-
-    export interface IGLTFMesh extends IGLTFChildRootProperty {
-        primitives: IGLTFMeshPrimitive[];
-    }
-
-    export interface IGLTFImage extends IGLTFChildRootProperty {
-        uri: string;
-    }
-
-    export interface IGLTFSampler extends IGLTFChildRootProperty {
-        magFilter?: number;
-        minFilter?: number;
-        wrapS?: number;
-        wrapT?: number;
-    }
-
-    export interface IGLTFTexture extends IGLTFChildRootProperty {
-        sampler: string;
-        source: string;
-
-        format?: ETextureFormat;
-        internalFormat?: ETextureFormat;
-        target?: number;
-        type?: number;
-        
-        // Babylon.js values (optimize)
-        babylonTexture?: Texture;
-    }
-
-    export interface IGLTFAmbienLight {
-        color?: number[];
-    }
-
-    export interface IGLTFDirectionalLight {
-        color?: number[];
-    }
-
-    export interface IGLTFPointLight {
-        color?: number[];
-        constantAttenuation?: number;
-        linearAttenuation?: number;
-        quadraticAttenuation?: number;
-    }
-
-    export interface IGLTFSpotLight {
-        color?: number[];
-        constantAttenuation?: number;
-        fallOfAngle?: number;
-        fallOffExponent?: number;
-        linearAttenuation?: number;
-        quadraticAttenuation?: number;
-    }
-
-    export interface IGLTFLight extends IGLTFChildRootProperty {
-        type: string;
-    }
-
-    export interface IGLTFCameraOrthographic {
-        xmag: number;
-        ymag: number;
-        zfar: number;
-        znear: number;
-    }
-
-    export interface IGLTFCameraPerspective {
-        aspectRatio: number;
-        yfov: number;
-        zfar: number;
-        znear: number;
-    }
-
-    export interface IGLTFCamera extends IGLTFChildRootProperty {
-        type: string;
-    }
-
-    export interface IGLTFAnimationChannelTarget {
-        id: string;
-        path: string;
-    }
-
-    export interface IGLTFAnimationChannel {
-        sampler: string;
-        target: IGLTFAnimationChannelTarget;
-    }
-
-    export interface IGLTFAnimationSampler {
-        input: string;
-        output: string;
-
-        interpolation?: string;
-    }
-
-    export interface IGLTFAnimation extends IGLTFChildRootProperty {
-        channels?: IGLTFAnimationChannel[];
-        parameters?: Object;
-        samplers?: Object;
-    }
-
-    export interface IGLTFNodeInstanceSkin {
-        skeletons: string[];
-        skin: string;
-        meshes: string[];
-    }
-
-    export interface IGLTFSkins extends IGLTFChildRootProperty {
-        bindShapeMatrix: number[];
-        inverseBindMatrices: string;
-        jointNames: string[];
-    }
-
-    export interface IGLTFNode extends IGLTFChildRootProperty {
-        camera?: string;
-        children: string[];
-        instanceSkin?: IGLTFNodeInstanceSkin;
-        jointName?: string;
-        light?: string;
-        matrix: number[];
-        mesh?: string;
-        meshes?: string[];
-        rotation?: number[];
-        scale?: number[];
-        translation?: number[];
-    }
-
-    export interface IGLTFScene extends IGLTFChildRootProperty {
-        nodes: string[];
-    }
-
-    /**
-    * Runtime
-    */
-    export interface IGLTFRuntime {
-        accessors: Object;
-        buffers: Object;
-        bufferViews: Object;
-        meshes: Object;
-        lights: Object;
-        cameras: Object;
-        nodes: Object;
-        images: Object;
-        textures: Object;
-        shaders: Object;
-        programs: Object;
-        samplers: Object;
-        techniques: Object;
-        materials: Object;
-        animations: Object;
-        skins: Object;
-        currentScene: Object;
-
-        buffersCount: number;
-        shaderscount: number;
-
-        scene: Scene;
-        rootUrl: string;
-        loadedBuffers: number;
-        loadedShaders: number;
-        arrayBuffers: Object;
-
-        dummyNodes: Node[];
-    }
+module BABYLON {
+    /**
+    * Interfaces
+    */
+    export interface IGLTFChildRootProperty {
+        name?: string;
+    }
+
+    export interface IGLTFAccessor extends IGLTFChildRootProperty {
+        bufferView: string;
+        byteOffset: number;
+        byteStride: number;
+        count: number;
+        type: string;
+        componentType: EComponentType;
+
+        max?: number[],
+        min?: number[],
+        name?: string;
+    }
+
+    export interface IGLTFBufferView extends IGLTFChildRootProperty {
+        buffer: string;
+        byteOffset: number;
+        byteLength: number;
+
+        target?: number;
+    }
+
+    export interface IGLTFBuffer extends IGLTFChildRootProperty {
+        uri: string;
+
+        byteLength?: number;
+        type?: string;
+    }
+
+    export interface IGLTFShader extends IGLTFChildRootProperty {
+        uri: string;
+        type: EShaderType;
+    }
+
+    export interface IGLTFProgram extends IGLTFChildRootProperty {
+        attributes: string[];
+        fragmentShader: string;
+        vertexShader: string;
+    }
+
+    export interface IGLTFTechniqueParameter {
+        type: number;
+
+        count?: number;
+        semantic?: string;
+        node?: string;
+        value?: number|boolean|string|Array<any>;
+        source?: string;
+
+        babylonValue?: any;
+    }
+
+    export interface IGLTFTechniqueCommonProfile {
+        lightingModel: string;
+        texcoordBindings: Object;
+
+        parameters?: Array<any>;
+    }
+
+    export interface IGLTFTechniqueStatesFunctions {
+        blendColor?: number[];
+        blendEquationSeparate?: number[];
+        blendFuncSeparate?: number[];
+        colorMask: boolean[];
+        cullFace: number[];
+    }
+
+    export interface IGLTFTechniqueStates {
+        enable: number[];
+        functions: IGLTFTechniqueStatesFunctions;
+    }
+
+    export interface IGLTFTechnique extends IGLTFChildRootProperty {
+        parameters: Object;
+        program: string;
+
+        attributes: Object;
+        uniforms: Object;
+        states: IGLTFTechniqueStates;
+    }
+
+    export interface IGLTFMaterial extends IGLTFChildRootProperty {
+        technique?: string;
+        values: string[];
+    }
+
+    export interface IGLTFMeshPrimitive {
+        attributes: Object;
+        indices: string;
+        material: string;
+
+        mode?: number;
+    }
+
+    export interface IGLTFMesh extends IGLTFChildRootProperty {
+        primitives: IGLTFMeshPrimitive[];
+    }
+
+    export interface IGLTFImage extends IGLTFChildRootProperty {
+        uri: string;
+    }
+
+    export interface IGLTFSampler extends IGLTFChildRootProperty {
+        magFilter?: number;
+        minFilter?: number;
+        wrapS?: number;
+        wrapT?: number;
+    }
+
+    export interface IGLTFTexture extends IGLTFChildRootProperty {
+        sampler: string;
+        source: string;
+
+        format?: ETextureFormat;
+        internalFormat?: ETextureFormat;
+        target?: number;
+        type?: number;
+        
+        // Babylon.js values (optimize)
+        babylonTexture?: Texture;
+    }
+
+    export interface IGLTFAmbienLight {
+        color?: number[];
+    }
+
+    export interface IGLTFDirectionalLight {
+        color?: number[];
+    }
+
+    export interface IGLTFPointLight {
+        color?: number[];
+        constantAttenuation?: number;
+        linearAttenuation?: number;
+        quadraticAttenuation?: number;
+    }
+
+    export interface IGLTFSpotLight {
+        color?: number[];
+        constantAttenuation?: number;
+        fallOfAngle?: number;
+        fallOffExponent?: number;
+        linearAttenuation?: number;
+        quadraticAttenuation?: number;
+    }
+
+    export interface IGLTFLight extends IGLTFChildRootProperty {
+        type: string;
+    }
+
+    export interface IGLTFCameraOrthographic {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+
+    export interface IGLTFCameraPerspective {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+
+    export interface IGLTFCamera extends IGLTFChildRootProperty {
+        type: string;
+    }
+
+    export interface IGLTFAnimationChannelTarget {
+        id: string;
+        path: string;
+    }
+
+    export interface IGLTFAnimationChannel {
+        sampler: string;
+        target: IGLTFAnimationChannelTarget;
+    }
+
+    export interface IGLTFAnimationSampler {
+        input: string;
+        output: string;
+
+        interpolation?: string;
+    }
+
+    export interface IGLTFAnimation extends IGLTFChildRootProperty {
+        channels?: IGLTFAnimationChannel[];
+        parameters?: Object;
+        samplers?: Object;
+    }
+
+    export interface IGLTFNodeInstanceSkin {
+        skeletons: string[];
+        skin: string;
+        meshes: string[];
+    }
+
+    export interface IGLTFSkins extends IGLTFChildRootProperty {
+        bindShapeMatrix: number[];
+        inverseBindMatrices: string;
+        jointNames: string[];
+
+        babylonSkeleton?: Skeleton;
+    }
+
+    export interface IGLTFNode extends IGLTFChildRootProperty {
+        camera?: string;
+        children: string[];
+        skin?: string;
+        jointName?: string;
+        light?: string;
+        matrix: number[];
+        mesh?: string;
+        meshes?: string[];
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+
+        // Babylon.js values (optimize)
+        babylonNode?: Node;
+    }
+
+    export interface IGLTFScene extends IGLTFChildRootProperty {
+        nodes: string[];
+    }
+
+    /**
+    * Runtime
+    */
+    export interface IGLTFRuntime {
+        accessors: Object;
+        buffers: Object;
+        bufferViews: Object;
+        meshes: Object;
+        lights: Object;
+        cameras: Object;
+        nodes: Object;
+        images: Object;
+        textures: Object;
+        shaders: Object;
+        programs: Object;
+        samplers: Object;
+        techniques: Object;
+        materials: Object;
+        animations: Object;
+        skins: Object;
+        currentScene: Object;
+
+        buffersCount: number;
+        shaderscount: number;
+
+        scene: Scene;
+        rootUrl: string;
+        loadedBuffers: number;
+        loadedShaders: number;
+        arrayBuffers: Object;
+
+        importOnlyMeshes: boolean;
+        importMeshesNames?: string[];
+
+        dummyNodes: Node[];
+    }
 }

+ 81 - 64
materialsLibrary/config.json

@@ -1,65 +1,82 @@
-{
-  "materials": [
-     {
-      "file": "materials/pbr/babylon.pbrMaterial.ts",
-      "shaderFiles": [
-        "materials/pbr/pbr.vertex.fx",
-        "materials/pbr/pbr.fragment.fx",
-        "materials/pbr/legacypbr.vertex.fx",
-        "materials/pbr/legacypbr.fragment.fx"
-      ],
-      "output": "babylon.pbrMaterial.js"
-    },
-    {
-      "file": "materials/normal/babylon.normalMaterial.ts",
-      "shaderFiles": [
-        "materials/normal/normal.vertex.fx",
-        "materials/normal/normal.fragment.fx"
-      ],
-      "output": "babylon.normalMaterial.js"
-    },
-    {
-      "file": "materials/lava/babylon.lavaMaterial.ts",
-      "shaderFiles": [
-        "materials/lava/lava.vertex.fx",
-        "materials/lava/lava.fragment.fx"
-      ],
-      "output": "babylon.lavaMaterial.js"
-    },
-    {
-      "file": "materials/simple/babylon.simpleMaterial.ts",
-      "shaderFiles": [
-        "materials/simple/simple.vertex.fx",
-        "materials/simple/simple.fragment.fx"
-      ],
-      "output": "babylon.simpleMaterial.js"
-    },
-    {
-      "file": "materials/water/babylon.waterMaterial.ts",
-      "shaderFiles": [
-        "materials/water/water.vertex.fx",
-        "materials/water/water.fragment.fx"
-      ],
-      "output": "babylon.waterMaterial.js"
-    },
-    {
-      "file": "materials/fire/babylon.fireMaterial.ts",
-      "shaderFiles": [
-        "materials/fire/fire.vertex.fx",
-        "materials/fire/fire.fragment.fx"
-      ],
-      "output": "babylon.fireMaterial.js"
-    },
-    {
-      "file": "materials/terrain/babylon.terrainMaterial.ts",
-      "shaderFiles": [
-        "materials/terrain/terrain.vertex.fx",
-        "materials/terrain/terrain.fragment.fx"
-      ],
-      "output": "babylon.terrainMaterial.js"
-    }
-  ],
-  "build": {
-    "distOutputDirectory": "dist/"
-  }
+{
+  "materials": [
+     {
+      "file": "materials/pbr/babylon.pbrMaterial.ts",
+      "shaderFiles": [
+        "materials/pbr/pbr.vertex.fx",
+        "materials/pbr/pbr.fragment.fx",
+        "materials/pbr/legacypbr.vertex.fx",
+        "materials/pbr/legacypbr.fragment.fx"
+      ],
+      "output": "babylon.pbrMaterial.js"
+    },
+    {
+      "file": "materials/normal/babylon.normalMaterial.ts",
+      "shaderFiles": [
+        "materials/normal/normal.vertex.fx",
+        "materials/normal/normal.fragment.fx"
+      ],
+      "output": "babylon.normalMaterial.js"
+    },
+    {
+      "file": "materials/lava/babylon.lavaMaterial.ts",
+      "shaderFiles": [
+        "materials/lava/lava.vertex.fx",
+        "materials/lava/lava.fragment.fx"
+      ],
+      "output": "babylon.lavaMaterial.js"
+    },
+    {
+      "file": "materials/simple/babylon.simpleMaterial.ts",
+      "shaderFiles": [
+        "materials/simple/simple.vertex.fx",
+        "materials/simple/simple.fragment.fx"
+      ],
+      "output": "babylon.simpleMaterial.js"
+    },
+    {
+      "file": "materials/water/babylon.waterMaterial.ts",
+      "shaderFiles": [
+        "materials/water/water.vertex.fx",
+        "materials/water/water.fragment.fx"
+      ],
+      "output": "babylon.waterMaterial.js"
+    },
+    {
+      "file": "materials/fire/babylon.fireMaterial.ts",
+      "shaderFiles": [
+        "materials/fire/fire.vertex.fx",
+        "materials/fire/fire.fragment.fx"
+      ],
+      "output": "babylon.fireMaterial.js"
+    },
+    {
+      "file": "materials/fur/babylon.furMaterial.ts",
+      "shaderFiles": [
+        "materials/fur/fur.vertex.fx",
+        "materials/fur/fur.fragment.fx"
+      ],
+      "output": "babylon.furMaterial.js"
+    },
+    {
+      "file": "materials/terrain/babylon.terrainMaterial.ts",
+      "shaderFiles": [
+        "materials/terrain/terrain.vertex.fx",
+        "materials/terrain/terrain.fragment.fx"
+      ],
+      "output": "babylon.terrainMaterial.js"
+    },
+    {
+      "file": "materials/triPlanar/babylon.triPlanarMaterial.ts",
+      "shaderFiles": [
+        "materials/triPlanar/triplanar.vertex.fx",
+        "materials/triPlanar/triplanar.fragment.fx"
+      ],
+      "output": "babylon.triPlanarMaterial.js"
+    }
+  ],
+  "build": {
+    "distOutputDirectory": "dist/",
+    "dtsOutputDirectory": "dist/dts/"
+  }
 }

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


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


File diff suppressed because it is too large
+ 499 - 0
materialsLibrary/dist/babylon.furMaterial.js


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


File diff suppressed because it is too large
+ 72 - 11
materialsLibrary/dist/babylon.lavaMaterial.js


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


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


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


File diff suppressed because it is too large
+ 253 - 107
materialsLibrary/dist/babylon.pbrMaterial.js


File diff suppressed because it is too large
+ 3 - 3
materialsLibrary/dist/babylon.pbrMaterial.min.js


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


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


File diff suppressed because it is too large
+ 66 - 2
materialsLibrary/dist/babylon.terrainMaterial.js


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


File diff suppressed because it is too large
+ 509 - 0
materialsLibrary/dist/babylon.triPlanarMaterial.js


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


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


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


+ 29 - 0
materialsLibrary/dist/dts/babylon.fireMaterial.d.ts

@@ -0,0 +1,29 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class FireMaterial extends Material {
+        diffuseTexture: BaseTexture;
+        distortionTexture: BaseTexture;
+        opacityTexture: BaseTexture;
+        diffuseColor: Color3;
+        disableLighting: boolean;
+        speed: number;
+        private _scaledDiffuse;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        private _lastTime;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): FireMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): FireMaterial;
+    }
+}

+ 30 - 0
materialsLibrary/dist/dts/babylon.furMaterial.d.ts

@@ -0,0 +1,30 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class FurMaterial extends Material {
+        diffuseTexture: BaseTexture;
+        heightTexture: BaseTexture;
+        diffuseColor: Color3;
+        furLength: number;
+        furAngle: number;
+        furColor: Color3;
+        disableLighting: boolean;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): FurMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): FurMaterial;
+    }
+}

+ 33 - 0
materialsLibrary/dist/dts/babylon.lavaMaterial.d.ts

@@ -0,0 +1,33 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class LavaMaterial extends Material {
+        diffuseTexture: BaseTexture;
+        noiseTexture: BaseTexture;
+        fogColor: Color3;
+        speed: number;
+        movingSpeed: number;
+        lowFrequencySpeed: number;
+        fogDensity: number;
+        private _lastTime;
+        diffuseColor: Color3;
+        disableLighting: boolean;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): LavaMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): LavaMaterial;
+    }
+}

+ 26 - 0
materialsLibrary/dist/dts/babylon.normalMaterial.d.ts

@@ -0,0 +1,26 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class NormalMaterial extends Material {
+        diffuseTexture: BaseTexture;
+        diffuseColor: Color3;
+        disableLighting: boolean;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): NormalMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): NormalMaterial;
+    }
+}

+ 86 - 0
materialsLibrary/dist/dts/babylon.pbrMaterial.d.ts

@@ -0,0 +1,86 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class PBRMaterial extends BABYLON.Material {
+        directIntensity: number;
+        emissiveIntensity: number;
+        environmentIntensity: number;
+        specularIntensity: number;
+        private _lightingInfos;
+        overloadedShadowIntensity: number;
+        overloadedShadeIntensity: number;
+        private _overloadedShadowInfos;
+        cameraExposure: number;
+        cameraContrast: number;
+        private _cameraInfos;
+        overloadedAmbientIntensity: number;
+        overloadedAlbedoIntensity: number;
+        overloadedReflectivityIntensity: number;
+        overloadedEmissiveIntensity: number;
+        private _overloadedIntensity;
+        overloadedAmbient: Color3;
+        overloadedAlbedo: Color3;
+        overloadedReflectivity: Color3;
+        overloadedEmissive: Color3;
+        overloadedReflection: Color3;
+        overloadedMicroSurface: number;
+        overloadedMicroSurfaceIntensity: number;
+        overloadedReflectionIntensity: number;
+        private _overloadedMicroSurface;
+        disableBumpMap: boolean;
+        albedoTexture: BaseTexture;
+        ambientTexture: BaseTexture;
+        opacityTexture: BaseTexture;
+        reflectionTexture: BaseTexture;
+        emissiveTexture: BaseTexture;
+        reflectivityTexture: BaseTexture;
+        bumpTexture: BaseTexture;
+        lightmapTexture: BaseTexture;
+        ambientColor: Color3;
+        albedoColor: Color3;
+        reflectivityColor: Color3;
+        reflectionColor: Color3;
+        microSurface: number;
+        emissiveColor: Color3;
+        useAlphaFromAlbedoTexture: boolean;
+        useEmissiveAsIllumination: boolean;
+        linkEmissiveWithAlbedo: boolean;
+        useSpecularOverAlpha: boolean;
+        disableLighting: boolean;
+        useLightmapAsShadowmap: boolean;
+        opacityFresnelParameters: FresnelParameters;
+        emissiveFresnelParameters: FresnelParameters;
+        useMicroSurfaceFromReflectivityMapAlpha: boolean;
+        private _renderTargets;
+        private _worldViewProjectionMatrix;
+        private _globalAmbientColor;
+        private _tempColor;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        private _useLogarithmicDepth;
+        constructor(name: string, scene: Scene);
+        useLogarithmicDepth: boolean;
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        private _shouldUseAlphaFromAlbedoTexture();
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: MaterialDefines): boolean;
+        private static _scaledAlbedo;
+        private static _scaledReflectivity;
+        private static _scaledEmissive;
+        private static _scaledReflection;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: MaterialDefines): void;
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        unbind(): void;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        private _myScene;
+        private _myShadowGenerator;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): PBRMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): PBRMaterial;
+    }
+}

+ 26 - 0
materialsLibrary/dist/dts/babylon.simpleMaterial.d.ts

@@ -0,0 +1,26 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class SimpleMaterial extends Material {
+        diffuseTexture: BaseTexture;
+        diffuseColor: Color3;
+        disableLighting: boolean;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): SimpleMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): SimpleMaterial;
+    }
+}

+ 35 - 0
materialsLibrary/dist/dts/babylon.terrainMaterial.d.ts

@@ -0,0 +1,35 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class TerrainMaterial extends Material {
+        mixTexture: BaseTexture;
+        diffuseTexture1: Texture;
+        diffuseTexture2: Texture;
+        diffuseTexture3: Texture;
+        bumpTexture1: Texture;
+        bumpTexture2: Texture;
+        bumpTexture3: Texture;
+        diffuseColor: Color3;
+        specularColor: Color3;
+        specularPower: number;
+        disableLighting: boolean;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _scaledSpecular;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): TerrainMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): TerrainMaterial;
+    }
+}

+ 36 - 0
materialsLibrary/dist/dts/babylon.triPlanarMaterial.d.ts

@@ -0,0 +1,36 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class TriPlanarMaterial extends Material {
+        mixTexture: BaseTexture;
+        diffuseTextureX: Texture;
+        diffuseTextureY: Texture;
+        diffuseTextureZ: Texture;
+        normalTextureX: Texture;
+        normalTextureY: Texture;
+        normalTextureZ: Texture;
+        tileSize: number;
+        diffuseColor: Color3;
+        specularColor: Color3;
+        specularPower: number;
+        disableLighting: boolean;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _scaledSpecular;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): TriPlanarMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): TriPlanarMaterial;
+    }
+}

+ 77 - 0
materialsLibrary/dist/dts/babylon.waterMaterial.d.ts

@@ -0,0 +1,77 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+/// <reference path="../simple/babylon.simpleMaterial.d.ts" />
+declare module BABYLON {
+    class WaterMaterial extends Material {
+        renderTargetSize: Vector2;
+        bumpTexture: BaseTexture;
+        diffuseColor: Color3;
+        specularColor: Color3;
+        specularPower: number;
+        disableLighting: boolean;
+        /**
+        * @param {number}: Represents the wind force
+        */
+        windForce: number;
+        /**
+        * @param {Vector2}: The direction of the wind in the plane (X, Z)
+        */
+        windDirection: Vector2;
+        /**
+        * @param {number}: Wave height, represents the height of the waves
+        */
+        waveHeight: number;
+        /**
+        * @param {number}: Bump height, represents the bump height related to the bump map
+        */
+        bumpHeight: number;
+        /**
+        * @param {number}: The water color blended with the reflection and refraction samplers
+        */
+        waterColor: Color3;
+        /**
+        * @param {number}: The blend factor related to the water color
+        */
+        colorBlendFactor: number;
+        /**
+        * @param {number}: Represents the maximum length of a wave
+        */
+        waveLength: number;
+        /**
+        * @param {number}: Defines the waves speed
+        */
+        waveSpeed: number;
+        private _mesh;
+        private _refractionRTT;
+        private _reflectionRTT;
+        private _material;
+        private _reflectionTransform;
+        private _lastTime;
+        private _scaledDiffuse;
+        private _scaledSpecular;
+        private _renderId;
+        private _defines;
+        private _cachedDefines;
+        /**
+        * Constructor
+        */
+        constructor(name: string, scene: Scene, renderTargetSize?: Vector2);
+        refractionTexture: RenderTargetTexture;
+        reflectionTexture: RenderTargetTexture;
+        addToRenderList(node: any): void;
+        enableRenderTargets(enable: boolean): void;
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        private _checkCache(scene, mesh?, useInstances?);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+        bindOnlyWorldMatrix(world: Matrix): void;
+        bind(world: Matrix, mesh?: Mesh): void;
+        private _createRenderTargets(scene, renderTargetSize);
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): WaterMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): WaterMaterial;
+        static CreateDefaultMesh(name: string, scene: Scene): Mesh;
+    }
+}

+ 70 - 66
materialsLibrary/gulpfile.js

@@ -1,66 +1,70 @@
-var gulp = require("gulp");
-var typescript = require("gulp-typescript");
-var srcToVariable = require("./gulp-srcToVariable");
-var merge2 = require("merge2");
-var concat = require("gulp-concat");
-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;
-
-//function to convert the shaders' filenames to variable names.
-function shadersName(filename) {
-    return filename.replace('.fragment', 'Pixel')
-      .replace('.vertex', 'Vertex')
-      .replace('.fx', 'Shader');
-}
-
-gulp.task('copyReference', function () {
-    return gulp.src("../dist/preview release/babylon.max.js").pipe(gulp.dest("test"));
-});
-
-/*
-Compiles all typescript files and creating a declaration file.
-*/
-gulp.task('default', ["copyReference"], function () {
-    var tasks = config.materials.map(function (material) {
-        var js = gulp.src(material.file)
-            .pipe(typescript({
-                noExternalResolve: false,
-                target: 'ES5',
-                declarationFiles: true,
-                typescript: require('typescript')
-            })).js;
-
-        var shader = gulp.src(material.shaderFiles).pipe(srcToVariable("BABYLON.Effect.ShadersStore", true, shadersName));
-
-        return merge2(js, shader)
-            .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));
-    });
-
-    return tasks;
-});
-
-/**
- * Web server task to serve a local test page
- */
-gulp.task('webserver', function() {
-  gulp.src('.')
-    .pipe(webserver({
-      livereload: false,
-      open: 'http://localhost:1338/test/index.html',
-      port: 1338,
-      fallback: 'index.html'
-    }));
-});
-
+var gulp = require("gulp");
+var typescript = require("gulp-typescript");
+var srcToVariable = require("./gulp-srcToVariable");
+var merge2 = require("merge2");
+var concat = require("gulp-concat");
+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;
+
+//function to convert the shaders' filenames to variable names.
+function shadersName(filename) {
+    return filename.replace('.fragment', 'Pixel')
+      .replace('.vertex', 'Vertex')
+      .replace('.fx', 'Shader');
+}
+
+gulp.task('copyReference', function () {
+    return gulp.src("../dist/preview release/babylon.max.js").pipe(gulp.dest("test"));
+});
+
+/*
+Compiles all typescript files and creating a declaration file.
+*/
+gulp.task('default', ["copyReference"], function () {
+    var tasks = config.materials.map(function (material) {
+        var compilOutput = gulp.src(material.file)
+            .pipe(typescript({
+                noExternalResolve: false,
+                target: 'ES5',
+                declarationFiles: true,
+                typescript: require('typescript')
+            }));
+
+        var js = compilOutput.js;
+        // Build definitions file
+        var dts = compilOutput.dts.pipe(gulp.dest(config.build.dtsOutputDirectory));
+
+        var shader = gulp.src(material.shaderFiles).pipe(srcToVariable("BABYLON.Effect.ShadersStore", true, shadersName));
+
+        return merge2(js, shader)
+            .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));
+    });
+
+    return tasks;
+});
+
+/**
+ * Web server task to serve a local test page
+ */
+gulp.task('webserver', function() {
+  gulp.src('.')
+    .pipe(webserver({
+      livereload: false,
+      open: 'http://localhost:1338/test/index.html',
+      port: 1338,
+      fallback: 'index.html'
+    }));
+});
+

+ 414 - 357
materialsLibrary/materials/fire/babylon.fireMaterial.ts

@@ -1,357 +1,414 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON {
-    var maxSimultaneousLights = 4;
-
-    class FireMaterialDefines extends MaterialDefines {
-        public DIFFUSE = false;
-        public CLIPPLANE = false;
-        public ALPHATEST = false;
-        public POINTSIZE = false;
-        public FOG = false;
-        public UV1 = false;
-        public NORMAL = false;
-        public VERTEXCOLOR = false;
-        public VERTEXALPHA = false;
-        public BONES = false;
-        public BONES4 = false;
-        public BonesPerMesh = 0;
-        public INSTANCES = false;
-
-        constructor() {
-            super();
-            this._keys = Object.keys(this);
-        }
-    }
-
-    export class FireMaterial extends Material {
-        public diffuseTexture: BaseTexture;
-        public distortionTexture: BaseTexture;
-        public opacityTexture: BaseTexture;
-
-        public diffuseColor = new Color3(1, 1, 1);
-        public disableLighting = false;
-        
-        public speed = 1.0;
-        
-        private _scaledDiffuse = new Color3();
-        private _renderId: number;
-
-        private _defines = new FireMaterialDefines();
-        private _cachedDefines = new FireMaterialDefines();
-        
-        private _lastTime: number = 0;
-
-        constructor(name: string, scene: Scene) {
-            super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
-        }
-
-        public needAlphaBlending(): boolean {
-            return (this.alpha < 1.0);
-        }
-
-        public needAlphaTesting(): boolean {
-            return false;
-        }
-
-        public getAlphaTestTexture(): BaseTexture {
-            return null;
-        }
-
-        // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-
-            if (mesh._materialDefines && mesh._materialDefines.isEqual(this._defines)) {
-                return true;
-            }
-
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
-                    return true;
-                }
-            }
-
-            var scene = this.getScene();
-
-            if (!this.checkReadyOnEveryCall) {
-                if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
-                }
-            }
-
-            var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-
-            this._defines.reset();
-
-            // Textures
-            if (scene.texturesEnabled) {
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    if (!this.diffuseTexture.isReady()) {
-                        return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
-                    }
-                }                
-            }
-
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            
-            this._defines.ALPHATEST = true;
-
-            // Point size
-            if (this.pointsCloud || scene.forcePointsCloud) {
-                this._defines.POINTSIZE = true;
-            }
-
-            // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
-            }
-            
-            // Attribs
-            if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-                    this._defines.NORMAL = true;
-                }
-                if (needUVs) {
-                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
-                        this._defines.UV1 = true;
-                    }
-                }
-                if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
-                    this._defines.VERTEXCOLOR = true;
-
-                    if (mesh.hasVertexAlpha) {
-                        this._defines.VERTEXALPHA = true;
-                    }
-                }
-                if (mesh.useBones && mesh.computeBonesUsingShaders) {
-                    this._defines.BONES = true;
-                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
-                    this._defines.BONES4 = true;
-                }
-
-                // Instances
-                if (useInstances) {
-                    this._defines.INSTANCES = true;
-                }
-            }
-
-            // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
-
-                scene.resetCachedMaterial();
-
-                // Fallbacks
-                var fallbacks = new EffectFallbacks();             
-                if (this._defines.FOG) {
-                    fallbacks.addFallback(1, "FOG");
-                }
-             
-                if (this._defines.BONES4) {
-                    fallbacks.addFallback(0, "BONES4");
-                }
-
-                //Attributes
-                var attribs = [VertexBuffer.PositionKind];
-
-                if (this._defines.NORMAL) {
-                    attribs.push(VertexBuffer.NormalKind);
-                }
-
-                if (this._defines.UV1) {
-                    attribs.push(VertexBuffer.UVKind);
-                }
-
-                if (this._defines.VERTEXCOLOR) {
-                    attribs.push(VertexBuffer.ColorKind);
-                }
-
-                if (this._defines.BONES) {
-                    attribs.push(VertexBuffer.MatricesIndicesKind);
-                    attribs.push(VertexBuffer.MatricesWeightsKind);
-                }
-
-                if (this._defines.INSTANCES) {
-                    attribs.push("world0");
-                    attribs.push("world1");
-                    attribs.push("world2");
-                    attribs.push("world3");
-                }
-
-                // Legacy browser patch
-                var shaderName = "fire";
-                
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName,
-                    attribs,
-                    ["world", "view", "viewProjection", "vEyePosition",
-                        "vFogInfos", "vFogColor", "pointSize",
-                        "vDiffuseInfos", 
-                        "mBones",
-                        "vClipPlane", "diffuseMatrix",
-                        // Fire
-                        "time", "speed"
-                    ],
-                    ["diffuseSampler",
-                        // Fire
-                        "distortionSampler", "opacitySampler"
-                    ],
-                    join, fallbacks, this.onCompiled, this.onError);
-            }
-            
-            if (!this._effect.isReady()) {
-                return false;
-            }
-
-            this._renderId = scene.getRenderId();
-            this._wasPreviouslyReady = true;
-
-            if (mesh) {
-                if (!mesh._materialDefines) {
-                    mesh._materialDefines = new FireMaterialDefines();
-                }
-
-                this._defines.cloneTo(mesh._materialDefines);
-            }
-
-            return true;
-        }
-
-        public bindOnlyWorldMatrix(world: Matrix): void {
-            this._effect.setMatrix("world", world);
-        }
-
-        public bind(world: Matrix, mesh?: Mesh): void {
-            var scene = this.getScene();
-
-            // Matrices        
-            this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
-
-            // Bones
-            if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
-                this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
-            }
-
-            if (scene.getCachedMaterial() !== this) {
-                // Textures        
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
-
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
-                    
-                    this._effect.setTexture("distortionSampler", this.distortionTexture);
-                    this._effect.setTexture("opacitySampler", this.opacityTexture);
-                }
-                
-                // Clip plane
-                if (scene.clipPlane) {
-                    var clipPlane = scene.clipPlane;
-                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
-                }
-
-                // Point size
-                if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
-                }
-
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
-            }
-
-            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
-
-            // View
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
-            }
-            
-            // Fog
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
-                this._effect.setColor3("vFogColor", scene.fogColor);
-            }
-            
-            // Time
-            this._lastTime += scene.getEngine().getDeltaTime();
-            this._effect.setFloat("time", this._lastTime);
-            
-            // Speed
-            this._effect.setFloat("speed", this.speed);
-
-            super.bind(world, mesh);
-        }
-
-        public getAnimatables(): IAnimatable[] {
-            var results = [];
-
-            if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
-                results.push(this.diffuseTexture);
-            }
-            if (this.distortionTexture && this.distortionTexture.animations && this.distortionTexture.animations.length > 0) {
-                results.push(this.distortionTexture);
-            }
-            if (this.opacityTexture && this.opacityTexture.animations && this.opacityTexture.animations.length > 0) {
-                results.push(this.opacityTexture);
-            }
-
-            return results;
-        }
-
-        public dispose(forceDisposeEffect?: boolean): void {
-            if (this.diffuseTexture) {
-                this.diffuseTexture.dispose();
-            }
-            if (this.distortionTexture) {
-                this.distortionTexture.dispose();
-            }
-
-            super.dispose(forceDisposeEffect);
-        }
-
-        public clone(name: string): FireMaterial {
-            var newMaterial = new FireMaterial(name, this.getScene());
-
-            // Base material
-            this.copyTo(newMaterial);
-
-            // Fire material
-            if (this.diffuseTexture && this.diffuseTexture.clone) {
-                newMaterial.diffuseTexture = this.diffuseTexture.clone();
-            }
-            if (this.distortionTexture && this.distortionTexture.clone) {
-                newMaterial.distortionTexture = this.distortionTexture.clone();
-            }
-            if (this.opacityTexture && this.opacityTexture.clone) {
-                newMaterial.opacityTexture = this.opacityTexture.clone();
-            }
-
-            newMaterial.diffuseColor = this.diffuseColor.clone();
-            return newMaterial;
-        }
-    }
-} 
-
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON {
+    var maxSimultaneousLights = 4;
+
+    class FireMaterialDefines extends MaterialDefines {
+        public DIFFUSE = false;
+        public CLIPPLANE = false;
+        public ALPHATEST = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public UV1 = false;
+        public NORMAL = false;
+        public VERTEXCOLOR = false;
+        public VERTEXALPHA = false;
+        public BONES = false;
+        public BONES4 = false;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+
+        constructor() {
+            super();
+            this._keys = Object.keys(this);
+        }
+    }
+
+    export class FireMaterial extends Material {
+        public diffuseTexture: BaseTexture;
+        public distortionTexture: BaseTexture;
+        public opacityTexture: BaseTexture;
+
+        public diffuseColor = new Color3(1, 1, 1);
+        public disableLighting = false;
+        
+        public speed = 1.0;
+        
+        private _scaledDiffuse = new Color3();
+        private _renderId: number;
+
+        private _defines = new FireMaterialDefines();
+        private _cachedDefines = new FireMaterialDefines();
+        
+        private _lastTime: number = 0;
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+
+            this._cachedDefines.BonesPerMesh = -1;
+        }
+
+        public needAlphaBlending(): boolean {
+            return (this.alpha < 1.0);
+        }
+
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
+        // Methods   
+        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (!mesh) {
+                return true;
+            }
+
+            if (this._defines.INSTANCES !== useInstances) {
+                return false;
+            }
+
+            if (mesh._materialDefines && mesh._materialDefines.isEqual(this._defines)) {
+                return true;
+            }
+
+            return false;
+        }
+
+        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (this.checkReadyOnlyOnce) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+
+            var scene = this.getScene();
+
+            if (!this.checkReadyOnEveryCall) {
+                if (this._renderId === scene.getRenderId()) {
+                    if (this._checkCache(scene, mesh, useInstances)) {
+                        return true;
+                    }
+                }
+            }
+
+            var engine = scene.getEngine();
+            var needNormals = false;
+            var needUVs = false;
+
+            this._defines.reset();
+
+            // Textures
+            if (scene.texturesEnabled) {
+                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this.diffuseTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.DIFFUSE = true;
+                    }
+                }                
+            }
+
+            // Effect
+            if (scene.clipPlane) {
+                this._defines.CLIPPLANE = true;
+            }
+            
+            this._defines.ALPHATEST = true;
+
+            // Point size
+            if (this.pointsCloud || scene.forcePointsCloud) {
+                this._defines.POINTSIZE = true;
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
+                this._defines.FOG = true;
+            }
+            
+            // Attribs
+            if (mesh) {
+                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                    this._defines.NORMAL = true;
+                }
+                if (needUVs) {
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
+                        this._defines.UV1 = true;
+                    }
+                }
+                if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
+                    this._defines.VERTEXCOLOR = true;
+
+                    if (mesh.hasVertexAlpha) {
+                        this._defines.VERTEXALPHA = true;
+                    }
+                }
+                if (mesh.useBones && mesh.computeBonesUsingShaders) {
+                    this._defines.BONES = true;
+                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                    this._defines.BONES4 = true;
+                }
+
+                // Instances
+                if (useInstances) {
+                    this._defines.INSTANCES = true;
+                }
+            }
+
+            // Get correct effect      
+            if (!this._defines.isEqual(this._cachedDefines)) {
+                this._defines.cloneTo(this._cachedDefines);
+
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();             
+                if (this._defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+             
+                if (this._defines.BONES4) {
+                    fallbacks.addFallback(0, "BONES4");
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (this._defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (this._defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (this._defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                if (this._defines.BONES) {
+                    attribs.push(VertexBuffer.MatricesIndicesKind);
+                    attribs.push(VertexBuffer.MatricesWeightsKind);
+                }
+
+                if (this._defines.INSTANCES) {
+                    attribs.push("world0");
+                    attribs.push("world1");
+                    attribs.push("world2");
+                    attribs.push("world3");
+                }
+
+                // Legacy browser patch
+                var shaderName = "fire";
+                
+                var join = this._defines.toString();
+                this._effect = scene.getEngine().createEffect(shaderName,
+                    attribs,
+                    ["world", "view", "viewProjection", "vEyePosition",
+                        "vFogInfos", "vFogColor", "pointSize",
+                        "vDiffuseInfos", 
+                        "mBones",
+                        "vClipPlane", "diffuseMatrix",
+                        // Fire
+                        "time", "speed"
+                    ],
+                    ["diffuseSampler",
+                        // Fire
+                        "distortionSampler", "opacitySampler"
+                    ],
+                    join, fallbacks, this.onCompiled, this.onError);
+            }
+            
+            if (!this._effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            if (mesh) {
+                if (!mesh._materialDefines) {
+                    mesh._materialDefines = new FireMaterialDefines();
+                }
+
+                this._defines.cloneTo(mesh._materialDefines);
+            }
+
+            return true;
+        }
+
+        public bindOnlyWorldMatrix(world: Matrix): void {
+            this._effect.setMatrix("world", world);
+        }
+
+        public bind(world: Matrix, mesh?: Mesh): void {
+            var scene = this.getScene();
+
+            // Matrices        
+            this.bindOnlyWorldMatrix(world);
+            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
+                this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
+            }
+
+            if (scene.getCachedMaterial() !== this) {
+                // Textures        
+                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
+
+                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                    
+                    this._effect.setTexture("distortionSampler", this.distortionTexture);
+                    this._effect.setTexture("opacitySampler", this.opacityTexture);
+                }
+                
+                // Clip plane
+                if (scene.clipPlane) {
+                    var clipPlane = scene.clipPlane;
+                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
+                }
+
+                // Point size
+                if (this.pointsCloud) {
+                    this._effect.setFloat("pointSize", this.pointSize);
+                }
+
+                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+            }
+
+            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+
+            // View
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setMatrix("view", scene.getViewMatrix());
+            }
+            
+            // Fog
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
+                this._effect.setColor3("vFogColor", scene.fogColor);
+            }
+            
+            // Time
+            this._lastTime += scene.getEngine().getDeltaTime();
+            this._effect.setFloat("time", this._lastTime);
+            
+            // Speed
+            this._effect.setFloat("speed", this.speed);
+
+            super.bind(world, mesh);
+        }
+
+        public getAnimatables(): IAnimatable[] {
+            var results = [];
+
+            if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
+                results.push(this.diffuseTexture);
+            }
+            if (this.distortionTexture && this.distortionTexture.animations && this.distortionTexture.animations.length > 0) {
+                results.push(this.distortionTexture);
+            }
+            if (this.opacityTexture && this.opacityTexture.animations && this.opacityTexture.animations.length > 0) {
+                results.push(this.opacityTexture);
+            }
+
+            return results;
+        }
+
+        public dispose(forceDisposeEffect?: boolean): void {
+            if (this.diffuseTexture) {
+                this.diffuseTexture.dispose();
+            }
+            if (this.distortionTexture) {
+                this.distortionTexture.dispose();
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        public clone(name: string): FireMaterial {
+            var newMaterial = new FireMaterial(name, this.getScene());
+
+            // Base material
+            this.copyTo(newMaterial);
+
+            // Fire material
+            if (this.diffuseTexture && this.diffuseTexture.clone) {
+                newMaterial.diffuseTexture = this.diffuseTexture.clone();
+            }
+            if (this.distortionTexture && this.distortionTexture.clone) {
+                newMaterial.distortionTexture = this.distortionTexture.clone();
+            }
+            if (this.opacityTexture && this.opacityTexture.clone) {
+                newMaterial.opacityTexture = this.opacityTexture.clone();
+            }
+
+            newMaterial.diffuseColor = this.diffuseColor.clone();
+            return newMaterial;
+        }
+		
+		public serialize(): any {
+		
+            var serializationObject = super.serialize();
+            serializationObject.customType      = "BABYLON.FireMaterial";
+            serializationObject.diffuseColor    = this.diffuseColor.asArray();
+            serializationObject.speed           = this.speed;
+            serializationObject.disableLighting = this.disableLighting;
+
+            if (this.diffuseTexture) {
+                serializationObject.diffuseTexture = this.diffuseTexture.serialize();
+            }
+            
+			if (this.distortionTexture) {
+                serializationObject.distortionTexture = this.distortionTexture.serialize();
+            }
+			
+			if (this.opacityTexture) {
+                serializationObject.opacityTexture = this.opacityTexture.serialize();
+            }
+
+            return serializationObject;
+        }
+
+        public static Parse(source: any, scene: Scene, rootUrl: string): FireMaterial {
+            var material = new FireMaterial(source.name, scene);
+
+            material.diffuseColor   = Color3.FromArray(source.diffuseColor);
+            material.speed          = source.speed;
+            material.disableLighting    = source.disableLighting;
+
+            material.alpha          = source.alpha;
+
+            material.id             = source.id;
+
+            Tags.AddTagsTo(material, source.tags);
+            material.backFaceCulling = source.backFaceCulling;
+            material.wireframe = source.wireframe;
+
+            if (source.diffuseTexture) {
+                material.diffuseTexture = Texture.Parse(source.diffuseTexture, scene, rootUrl);
+            }
+
+            if (source.distortionTexture) {
+                material.distortionTexture = Texture.Parse(source.distortionTexture, scene, rootUrl);
+            }
+			
+			if (source.opacityTexture) {
+                material.opacityTexture = Texture.Parse(source.opacityTexture, scene, rootUrl);
+            }
+
+            if (source.checkReadyOnlyOnce) {
+                material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;
+            }
+
+            return material;
+        }
+    }
+} 
+

+ 601 - 0
materialsLibrary/materials/fur/babylon.furMaterial.ts

@@ -0,0 +1,601 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON {
+    var maxSimultaneousLights = 4;
+
+    class FurMaterialDefines extends MaterialDefines {
+        public DIFFUSE = false;
+        public HEIGHTMAP = false;
+        public CLIPPLANE = false;
+        public ALPHATEST = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public LIGHT0 = false;
+        public LIGHT1 = false;
+        public LIGHT2 = false;
+        public LIGHT3 = false;
+        public SPOTLIGHT0 = false;
+        public SPOTLIGHT1 = false;
+        public SPOTLIGHT2 = false;
+        public SPOTLIGHT3 = false;
+        public HEMILIGHT0 = false;
+        public HEMILIGHT1 = false;
+        public HEMILIGHT2 = false;
+        public HEMILIGHT3 = false;
+        public DIRLIGHT0 = false;
+        public DIRLIGHT1 = false;
+        public DIRLIGHT2 = false;
+        public DIRLIGHT3 = false;
+        public POINTLIGHT0 = false;
+        public POINTLIGHT1 = false;
+        public POINTLIGHT2 = false;
+        public POINTLIGHT3 = false;        
+        public SHADOW0 = false;
+        public SHADOW1 = false;
+        public SHADOW2 = false;
+        public SHADOW3 = false;
+        public SHADOWS = false;
+        public SHADOWVSM0 = false;
+        public SHADOWVSM1 = false;
+        public SHADOWVSM2 = false;
+        public SHADOWVSM3 = false;
+        public SHADOWPCF0 = false;
+        public SHADOWPCF1 = false;
+        public SHADOWPCF2 = false;
+        public SHADOWPCF3 = false;
+        public NORMAL = false;
+        public UV1 = false;
+        public UV2 = false;
+        public VERTEXCOLOR = false;
+        public VERTEXALPHA = false;
+        public BONES = false;
+        public BONES4 = false;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+
+        constructor() {
+            super();
+            this._keys = Object.keys(this);
+        }
+    }
+
+    export class FurMaterial extends Material {
+        public diffuseTexture: BaseTexture;
+        public heightTexture: BaseTexture;
+        public diffuseColor = new Color3(1, 1, 1);
+        public furLength: number = 1;
+        public furAngle: number = 0;
+        public furColor = new Color3(0.44,0.21,0.02);
+        public disableLighting = false;
+
+        private _worldViewProjectionMatrix = Matrix.Zero();
+        private _scaledDiffuse = new Color3(1.,1.,1.);
+        private _renderId: number;
+
+        private _defines = new FurMaterialDefines();
+        private _cachedDefines = new FurMaterialDefines();
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+
+            this._cachedDefines.BonesPerMesh = -1;
+        }
+
+        public needAlphaBlending(): boolean {
+            return (this.alpha < 1.0);
+        }
+
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
+        // Methods   
+        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (!mesh) {
+                return true;
+            }
+
+            if (this._defines.INSTANCES !== useInstances) {
+                return false;
+            }
+
+            if (mesh._materialDefines && mesh._materialDefines.isEqual(this._defines)) {
+                return true;
+            }
+
+            return false;
+        }
+
+        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (this.checkReadyOnlyOnce) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+
+            var scene = this.getScene();
+
+            if (!this.checkReadyOnEveryCall) {
+                if (this._renderId === scene.getRenderId()) {
+                    if (this._checkCache(scene, mesh, useInstances)) {
+                        return true;
+                    }
+                }
+            }
+
+            var engine = scene.getEngine();
+            var needNormals = false;
+            var needUVs = false;
+
+            this._defines.reset();
+
+            // Textures
+            if (scene.texturesEnabled) {
+                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this.diffuseTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.DIFFUSE = true;
+                    }
+                } 
+                if (this.heightTexture) {
+                    if (!this.heightTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.HEIGHTMAP = true;
+                    }
+                }               
+            }
+
+            // Effect
+            if (scene.clipPlane) {
+                this._defines.CLIPPLANE = true;
+            }
+
+            if (engine.getAlphaTesting()) {
+                this._defines.ALPHATEST = true;
+            }
+
+            // Point size
+            if (this.pointsCloud || scene.forcePointsCloud) {
+                this._defines.POINTSIZE = true;
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
+                this._defines.FOG = true;
+            }
+
+            var lightIndex = 0;
+            if (scene.lightsEnabled && !this.disableLighting) {
+                for (var index = 0; index < scene.lights.length; index++) {
+                    var light = scene.lights[index];
+
+                    if (!light.isEnabled()) {
+                        continue;
+                    }
+
+                    // Excluded check
+                    if (light._excludedMeshesIds.length > 0) {
+                        for (var excludedIndex = 0; excludedIndex < light._excludedMeshesIds.length; excludedIndex++) {
+                            var excludedMesh = scene.getMeshByID(light._excludedMeshesIds[excludedIndex]);
+
+                            if (excludedMesh) {
+                                light.excludedMeshes.push(excludedMesh);
+                            }
+                        }
+
+                        light._excludedMeshesIds = [];
+                    }
+
+                    // Included check
+                    if (light._includedOnlyMeshesIds.length > 0) {
+                        for (var includedOnlyIndex = 0; includedOnlyIndex < light._includedOnlyMeshesIds.length; includedOnlyIndex++) {
+                            var includedOnlyMesh = scene.getMeshByID(light._includedOnlyMeshesIds[includedOnlyIndex]);
+
+                            if (includedOnlyMesh) {
+                                light.includedOnlyMeshes.push(includedOnlyMesh);
+                            }
+                        }
+
+                        light._includedOnlyMeshesIds = [];
+                    }
+
+                    if (!light.canAffectMesh(mesh)) {
+                        continue;
+                    }
+                    needNormals = true;
+                    this._defines["LIGHT" + lightIndex] = true;
+
+                    var type;
+                    if (light instanceof SpotLight) {
+                        type = "SPOTLIGHT" + lightIndex;
+                    } else if (light instanceof HemisphericLight) {
+                        type = "HEMILIGHT" + lightIndex;
+                    } else if (light instanceof PointLight) {
+                        type = "POINTLIGHT" + lightIndex;
+                    } else {
+                        type = "DIRLIGHT" + lightIndex;
+                    }
+
+                    this._defines[type] = true;
+
+                    // Shadows
+                    if (scene.shadowsEnabled) {
+                        var shadowGenerator = light.getShadowGenerator();
+                        if (mesh && mesh.receiveShadows && shadowGenerator) {
+                            this._defines["SHADOW" + lightIndex] = true;
+
+                            this._defines.SHADOWS = true;
+
+                            if (shadowGenerator.useVarianceShadowMap || shadowGenerator.useBlurVarianceShadowMap) {
+                                this._defines["SHADOWVSM" + lightIndex] = true;
+                            }
+
+                            if (shadowGenerator.usePoissonSampling) {
+                                this._defines["SHADOWPCF" + lightIndex] = true;
+                            }
+                        }
+                    }
+
+                    lightIndex++;
+                    if (lightIndex === maxSimultaneousLights)
+                        break;
+                }
+            }
+
+            // Attribs
+            if (mesh) {
+                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                    this._defines.NORMAL = true;
+                }
+                if (needUVs) {
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
+                        this._defines.UV1 = true;
+                    }
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
+                        this._defines.UV2 = true;
+                    }
+                }
+                if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
+                    this._defines.VERTEXCOLOR = true;
+
+                    if (mesh.hasVertexAlpha) {
+                        this._defines.VERTEXALPHA = true;
+                    }
+                }
+                if (mesh.useBones && mesh.computeBonesUsingShaders) {
+                    this._defines.BONES = true;
+                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                    this._defines.BONES4 = true;
+                }
+
+                // Instances
+                if (useInstances) {
+                    this._defines.INSTANCES = true;
+                }
+            }
+
+            // Get correct effect      
+            if (!this._defines.isEqual(this._cachedDefines)) {
+                this._defines.cloneTo(this._cachedDefines);
+
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();             
+                if (this._defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+
+                for (lightIndex = 0; lightIndex < maxSimultaneousLights; lightIndex++) {
+                    if (!this._defines["LIGHT" + lightIndex]) {
+                        continue;
+                    }
+
+                    if (lightIndex > 0) {
+                        fallbacks.addFallback(lightIndex, "LIGHT" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOW" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOW" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOWPCF" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOWPCF" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOWVSM" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOWVSM" + lightIndex);
+                    }
+                }
+             
+                if (this._defines.BONES4) {
+                    fallbacks.addFallback(0, "BONES4");
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (this._defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (this._defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (this._defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
+                if (this._defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                if (this._defines.BONES) {
+                    attribs.push(VertexBuffer.MatricesIndicesKind);
+                    attribs.push(VertexBuffer.MatricesWeightsKind);
+                }
+
+                if (this._defines.INSTANCES) {
+                    attribs.push("world0");
+                    attribs.push("world1");
+                    attribs.push("world2");
+                    attribs.push("world3");
+                }
+
+                // Legacy browser patch
+                var shaderName = "fur";
+                var join = this._defines.toString();
+                this._effect = scene.getEngine().createEffect(shaderName,
+                    attribs,
+                    ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                        "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
+                        "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
+                        "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
+                        "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                        "vFogInfos", "vFogColor", "pointSize",
+                        "vDiffuseInfos", 
+                        "mBones",
+                        "vClipPlane", "diffuseMatrix",
+                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
+                        "furLength", "furAngle", "furColor"
+                    ],
+                    ["diffuseSampler",
+                        "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3",
+                        "heightTexture"
+                    ],
+                    join, fallbacks, this.onCompiled, this.onError);
+            }
+            if (!this._effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            if (mesh) {
+                if (!mesh._materialDefines) {
+                    mesh._materialDefines = new FurMaterialDefines();
+                }
+
+                this._defines.cloneTo(mesh._materialDefines);
+            }
+
+            return true;
+        }
+
+        public bindOnlyWorldMatrix(world: Matrix): void {
+            this._effect.setMatrix("world", world);
+        }
+
+        public bind(world: Matrix, mesh?: Mesh): void {
+            var scene = this.getScene();
+
+            // Matrices        
+            this.bindOnlyWorldMatrix(world);
+            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
+                this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
+            }
+
+            if (scene.getCachedMaterial() !== this) {
+                // Textures        
+                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
+
+                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                }
+                
+                if (this.heightTexture) {
+                    this._effect.setTexture("heightTexture", this.heightTexture);
+                }
+                
+                // Clip plane
+                if (scene.clipPlane) {
+                    var clipPlane = scene.clipPlane;
+                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
+                }
+
+                // Point size
+                if (this.pointsCloud) {
+                    this._effect.setFloat("pointSize", this.pointSize);
+                }
+
+                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+            }
+
+            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+
+            if (scene.lightsEnabled && !this.disableLighting) {
+                var lightIndex = 0;
+                for (var index = 0; index < scene.lights.length; index++) {
+                    var light = scene.lights[index];
+
+                    if (!light.isEnabled()) {
+                        continue;
+                    }
+
+                    if (!light.canAffectMesh(mesh)) {
+                        continue;
+                    }
+
+                    if (light instanceof PointLight) {
+                        // Point Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex);
+                    } else if (light instanceof DirectionalLight) {
+                        // Directional Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex);
+                    } else if (light instanceof SpotLight) {
+                        // Spot Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightDirection" + lightIndex);
+                    } else if (light instanceof HemisphericLight) {
+                        // Hemispheric Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightGround" + lightIndex);
+                    }
+
+                    light.diffuse.scaleToRef(light.intensity, this._scaledDiffuse);
+                    this._effect.setColor4("vLightDiffuse" + lightIndex, this._scaledDiffuse, light.range);
+
+                    // Shadows
+                    if (scene.shadowsEnabled) {
+                        var shadowGenerator = light.getShadowGenerator();
+                        if (mesh.receiveShadows && shadowGenerator) {
+                            this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
+                            this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
+                            this._effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.getShadowMap().getSize().width, shadowGenerator.bias);
+                        }
+                    }
+
+                    lightIndex++;
+
+                    if (lightIndex === maxSimultaneousLights)
+                        break;
+                }
+            }
+
+            // View
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setMatrix("view", scene.getViewMatrix());
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
+                this._effect.setColor3("vFogColor", scene.fogColor);
+            }
+            
+            this._effect.setFloat("furLength", this.furLength);
+            this._effect.setFloat("furAngle", this.furAngle);
+            this._effect.setColor4("furColor", this.furColor, 1.0);
+
+ 
+            super.bind(world, mesh);
+        }
+
+        public getAnimatables(): IAnimatable[] {
+            var results = [];
+
+            if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
+                results.push(this.diffuseTexture);
+            }
+            
+            if (this.heightTexture && this.heightTexture.animations && this.heightTexture.animations.length > 0) {
+                results.push(this.heightTexture);
+            }
+
+            return results;
+        }
+
+        public dispose(forceDisposeEffect?: boolean): void {
+            if (this.diffuseTexture) {
+                this.diffuseTexture.dispose();
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        public clone(name: string): FurMaterial {
+            var newMaterial = new FurMaterial(name, this.getScene());
+
+            // Base material
+            this.copyTo(newMaterial);
+
+            // Fur material
+            if (this.diffuseTexture && this.diffuseTexture.clone) {
+                newMaterial.diffuseTexture = this.diffuseTexture.clone();
+            }
+            if (this.heightTexture && this.heightTexture.clone) {
+                newMaterial.heightTexture = this.heightTexture.clone();
+            }
+            if (this.diffuseColor && this.diffuseColor.clone) {
+                newMaterial.diffuseColor = this.diffuseColor.clone();
+            }
+            
+            return newMaterial;
+        }
+        
+        public serialize(): any {		
+            var serializationObject = super.serialize();
+            serializationObject.customType      = "BABYLON.FurMaterial";
+            serializationObject.diffuseColor    = this.diffuseColor.asArray();
+            serializationObject.disableLighting = this.disableLighting;
+            serializationObject.furLength = this.furLength;
+            serializationObject.furAngle = this.furAngle;
+            serializationObject.furColor = this.furColor.asArray();
+            
+            if (this.diffuseTexture) {
+                serializationObject.diffuseTexture = this.diffuseTexture.serialize();
+            }
+            
+            if (this.heightTexture) {
+                serializationObject.heightTexture = this.heightTexture.serialize();
+            }
+
+            return serializationObject;
+        }
+
+        public static Parse(source: any, scene: Scene, rootUrl: string): FurMaterial {
+            var material = new FurMaterial(source.name, scene);
+
+            material.diffuseColor       = Color3.FromArray(source.diffuseColor);
+            material.furLength          = source.furLength;
+            material.furAngle           = source.furAngle;
+            material.furColor           = Color3.FromArray(source.furColor);
+            material.disableLighting    = source.disableLighting;
+
+            material.alpha          = source.alpha;
+
+            material.id             = source.id;
+
+            Tags.AddTagsTo(material, source.tags);
+            material.backFaceCulling = source.backFaceCulling;
+            material.wireframe = source.wireframe;
+
+            if (source.diffuseTexture) {
+                material.diffuseTexture = Texture.Parse(source.diffuseTexture, scene, rootUrl);
+            }
+            
+            if (source.heightTexture) {
+                material.heightTexture = Texture.Parse(source.heightTexture, scene, rootUrl);
+            }
+
+            if (source.checkReadyOnlyOnce) {
+                material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;
+            }
+
+            return material;
+        }
+    }
+} 
+

+ 565 - 0
materialsLibrary/materials/fur/fur.fragment.fx

@@ -0,0 +1,565 @@
+precision highp float;
+
+// Constants
+uniform vec3 vEyePosition;
+uniform vec4 vDiffuseColor;
+
+// Input
+uniform vec4 furColor;
+varying vec3 vPositionW;
+varying float vfur_length;
+
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+// Lights
+#ifdef LIGHT0
+uniform vec4 vLightData0;
+uniform vec4 vLightDiffuse0;
+#ifdef SHADOW0
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+varying vec4 vPositionFromLight0;
+uniform sampler2D shadowSampler0;
+#else
+uniform samplerCube shadowSampler0;
+#endif
+uniform vec3 shadowsInfo0;
+#endif
+#ifdef SPOTLIGHT0
+uniform vec4 vLightDirection0;
+#endif
+#ifdef HEMILIGHT0
+uniform vec3 vLightGround0;
+#endif
+#endif
+
+#ifdef LIGHT1
+uniform vec4 vLightData1;
+uniform vec4 vLightDiffuse1;
+#ifdef SHADOW1
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+varying vec4 vPositionFromLight1;
+uniform sampler2D shadowSampler1;
+#else
+uniform samplerCube shadowSampler1;
+#endif
+uniform vec3 shadowsInfo1;
+#endif
+#ifdef SPOTLIGHT1
+uniform vec4 vLightDirection1;
+#endif
+#ifdef HEMILIGHT1
+uniform vec3 vLightGround1;
+#endif
+#endif
+
+#ifdef LIGHT2
+uniform vec4 vLightData2;
+uniform vec4 vLightDiffuse2;
+#ifdef SHADOW2
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+varying vec4 vPositionFromLight2;
+uniform sampler2D shadowSampler2;
+#else
+uniform samplerCube shadowSampler2;
+#endif
+uniform vec3 shadowsInfo2;
+#endif
+#ifdef SPOTLIGHT2
+uniform vec4 vLightDirection2;
+#endif
+#ifdef HEMILIGHT2
+uniform vec3 vLightGround2;
+#endif
+#endif
+
+#ifdef LIGHT3
+uniform vec4 vLightData3;
+uniform vec4 vLightDiffuse3;
+#ifdef SHADOW3
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+varying vec4 vPositionFromLight3;
+uniform sampler2D shadowSampler3;
+#else
+uniform samplerCube shadowSampler3;
+#endif
+uniform vec3 shadowsInfo3;
+#endif
+#ifdef SPOTLIGHT3
+uniform vec4 vLightDirection3;
+#endif
+#ifdef HEMILIGHT3
+uniform vec3 vLightGround3;
+#endif
+#endif
+
+// Samplers
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform sampler2D diffuseSampler;
+uniform vec2 vDiffuseInfos;
+#endif
+
+// Shadows
+#ifdef SHADOWS
+
+float unpack(vec4 color)
+{
+	const vec4 bit_shift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
+	return dot(color, bit_shift);
+}
+
+#if defined(POINTLIGHT0) || defined(POINTLIGHT1) || defined(POINTLIGHT2) || defined(POINTLIGHT3)
+float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float bias)
+{
+	vec3 directionToLight = vPositionW - lightPosition;
+	float depth = length(directionToLight);
+
+	depth = clamp(depth, 0., 1.);
+
+	directionToLight.y = 1.0 - directionToLight.y;
+
+	float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
+
+	if (depth > shadow)
+	{
+		return darkness;
+	}
+	return 1.0;
+}
+
+float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float bias, float darkness)
+{
+	vec3 directionToLight = vPositionW - lightPosition;
+	float depth = length(directionToLight);
+
+	depth = clamp(depth, 0., 1.);
+
+	directionToLight.y = 1.0 - directionToLight.y;
+
+	float visibility = 1.;
+
+	vec3 poissonDisk[4];
+	poissonDisk[0] = vec3(-0.094201624, 0.04, -0.039906216);
+	poissonDisk[1] = vec3(0.094558609, -0.04, -0.076890725);
+	poissonDisk[2] = vec3(-0.094184101, 0.01, -0.092938870);
+	poissonDisk[3] = vec3(0.034495938, -0.01, 0.029387760);
+
+	// Poisson Sampling
+	float biasedDepth = depth - bias;
+
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[0])) < biasedDepth) visibility -= 0.25;
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[1])) < biasedDepth) visibility -= 0.25;
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[2])) < biasedDepth) visibility -= 0.25;
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[3])) < biasedDepth) visibility -= 0.25;
+
+	return  min(1.0, visibility + darkness);
+}
+#endif
+
+#if defined(SPOTLIGHT0) || defined(SPOTLIGHT1) || defined(SPOTLIGHT2) || defined(SPOTLIGHT3) ||  defined(DIRLIGHT0) || defined(DIRLIGHT1) || defined(DIRLIGHT2) || defined(DIRLIGHT3)
+float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness, float bias)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	float shadow = unpack(texture2D(shadowSampler, uv)) + bias;
+
+	if (depth.z > shadow)
+	{
+		return darkness;
+	}
+	return 1.;
+}
+
+float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, float mapSize, float bias, float darkness)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	float visibility = 1.;
+
+	vec2 poissonDisk[4];
+	poissonDisk[0] = vec2(-0.94201624, -0.39906216);
+	poissonDisk[1] = vec2(0.94558609, -0.76890725);
+	poissonDisk[2] = vec2(-0.094184101, -0.92938870);
+	poissonDisk[3] = vec2(0.34495938, 0.29387760);
+
+	// Poisson Sampling
+	float biasedDepth = depth.z - bias;
+
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] / mapSize)) < biasedDepth) visibility -= 0.25;
+
+	return  min(1.0, visibility + darkness);
+}
+
+// Thanks to http://devmaster.net/
+float unpackHalf(vec2 color)
+{
+	return color.x + (color.y / 255.0);
+}
+
+float linstep(float low, float high, float v) {
+	return clamp((v - low) / (high - low), 0.0, 1.0);
+}
+
+float ChebychevInequality(vec2 moments, float compare, float bias)
+{
+	float p = smoothstep(compare - bias, compare, moments.x);
+	float variance = max(moments.y - moments.x * moments.x, 0.02);
+	float d = compare - moments.x;
+	float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
+
+	return clamp(max(p, p_max), 0.0, 1.0);
+}
+
+float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias, float darkness)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z >= 1.0)
+	{
+		return 1.0;
+	}
+
+	vec4 texel = texture2D(shadowSampler, uv);
+
+	vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
+	return min(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness);
+}
+#endif
+#endif
+
+
+#ifdef CLIPPLANE
+varying float fClipDistance;
+#endif
+
+// Fog
+#ifdef FOG
+
+#define FOGMODE_NONE    0.
+#define FOGMODE_EXP     1.
+#define FOGMODE_EXP2    2.
+#define FOGMODE_LINEAR  3.
+#define E 2.71828
+
+uniform vec4 vFogInfos;
+uniform vec3 vFogColor;
+varying float fFogDistance;
+
+float CalcFogFactor()
+{
+	float fogCoeff = 1.0;
+	float fogStart = vFogInfos.y;
+	float fogEnd = vFogInfos.z;
+	float fogDensity = vFogInfos.w;
+
+	if (FOGMODE_LINEAR == vFogInfos.x)
+	{
+		fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);
+	}
+	else if (FOGMODE_EXP == vFogInfos.x)
+	{
+		fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);
+	}
+	else if (FOGMODE_EXP2 == vFogInfos.x)
+	{
+		fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);
+	}
+
+	return clamp(fogCoeff, 0.0, 1.0);
+}
+#endif
+
+// Light Computing
+struct lightingInfo
+{
+	vec3 diffuse;
+};
+
+lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, float range) {
+	lightingInfo result;
+
+	vec3 lightVectorW;
+	float attenuation = 1.0;
+	if (lightData.w == 0.)
+	{
+		vec3 direction = lightData.xyz - vPositionW;
+
+		attenuation = max(0., 1.0 - length(direction) / range);
+		lightVectorW = normalize(direction);
+	}
+	else
+	{
+		lightVectorW = normalize(-lightData.xyz);
+	}
+
+	// diffuse
+	float ndl = max(0., dot(vNormal, lightVectorW));
+	result.diffuse = ndl * diffuseColor * attenuation;
+
+	return result;
+}
+
+lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, float range) {
+	lightingInfo result;
+
+	vec3 direction = lightData.xyz - vPositionW;
+	vec3 lightVectorW = normalize(direction);
+	float attenuation = max(0., 1.0 - length(direction) / range);
+
+	// diffuse
+	float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));
+	float spotAtten = 0.0;
+
+	if (cosAngle >= lightDirection.w)
+	{
+		cosAngle = max(0., pow(cosAngle, lightData.w));
+		spotAtten = clamp((cosAngle - lightDirection.w) / (1. - cosAngle), 0.0, 1.0);
+
+		// Diffuse
+		float ndl = max(0., dot(vNormal, -lightDirection.xyz));
+		result.diffuse = ndl * spotAtten * diffuseColor * attenuation;
+
+		return result;
+	}
+
+	result.diffuse = vec3(0.);
+
+	return result;
+}
+
+lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 groundColor) {
+	lightingInfo result;
+
+	// Diffuse
+	float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+	result.diffuse = mix(groundColor, diffuseColor, ndl);
+
+	return result;
+}
+
+float Rand(vec3 rv) {
+	float x = dot(rv, vec3(12.9898,78.233, 24.65487));
+	return fract(sin(x) * 43758.5453);
+}
+
+void main(void) {
+	// Clip plane
+#ifdef CLIPPLANE
+	if (fClipDistance > 0.0)
+		discard;
+#endif
+
+	vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
+
+	// Base color
+	vec4 baseColor = furColor;
+	vec3 diffuseColor = vDiffuseColor.rgb;
+
+	// Alpha
+	float alpha = vDiffuseColor.a;
+
+#ifdef DIFFUSE
+	baseColor = texture2D(diffuseSampler, vDiffuseUV);
+
+#ifdef ALPHATEST
+	if (baseColor.a < 0.4)
+		discard;
+#endif
+
+	baseColor.rgb *= vDiffuseInfos.y;
+#endif
+
+#ifdef VERTEXCOLOR
+	baseColor.rgb *= vColor.rgb;
+#endif
+
+	// Bump
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+	// Lighting
+	vec3 diffuseBase = vec3(0., 0., 0.);
+	float shadow = 1.;
+
+#ifdef LIGHT0
+#ifdef SPOTLIGHT0
+	lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightDiffuse0.a);
+#endif
+#ifdef HEMILIGHT0
+	lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightGround0);
+#endif
+#if defined(POINTLIGHT0) || defined(DIRLIGHT0)
+	lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightDiffuse0.a);
+#endif
+#ifdef SHADOW0
+#ifdef SHADOWVSM0
+	shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0, shadowsInfo0.z, shadowsInfo0.x);
+#else
+#ifdef SHADOWPCF0
+	#if defined(POINTLIGHT0)
+	shadow = computeShadowWithPCFCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.z, shadowsInfo0.x);
+	#else
+	shadow = computeShadowWithPCF(vPositionFromLight0, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z, shadowsInfo0.x);
+	#endif
+#else
+	#if defined(POINTLIGHT0)
+	shadow = computeShadowCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
+	#else
+	shadow = computeShadow(vPositionFromLight0, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
+	#endif
+#endif
+#endif
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+#endif
+
+#ifdef LIGHT1
+#ifdef SPOTLIGHT1
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightDiffuse1.a);
+#endif
+#ifdef HEMILIGHT1
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightGround1.a);
+#endif
+#if defined(POINTLIGHT1) || defined(DIRLIGHT1)
+	info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightDiffuse1.a);
+#endif
+#ifdef SHADOW1
+#ifdef SHADOWVSM1
+	shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1, shadowsInfo1.z, shadowsInfo1.x);
+#else
+#ifdef SHADOWPCF1
+#if defined(POINTLIGHT1)
+	shadow = computeShadowWithPCFCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.z, shadowsInfo1.x);
+#else
+	shadow = computeShadowWithPCF(vPositionFromLight1, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z, shadowsInfo1.x);
+#endif
+#else
+	#if defined(POINTLIGHT1)
+	shadow = computeShadowCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
+	#else
+	shadow = computeShadow(vPositionFromLight1, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
+	#endif
+#endif
+#endif
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+#endif
+
+#ifdef LIGHT2
+#ifdef SPOTLIGHT2
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightDiffuse2.a);
+#endif
+#ifdef HEMILIGHT2
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightGround2);
+#endif
+#if defined(POINTLIGHT2) || defined(DIRLIGHT2)
+	info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightDiffuse2.a);
+#endif
+#ifdef SHADOW2
+#ifdef SHADOWVSM2
+	shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2, shadowsInfo2.z, shadowsInfo2.x);
+#else
+#ifdef SHADOWPCF2
+#if defined(POINTLIGHT2)
+	shadow = computeShadowWithPCFCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.z, shadowsInfo2.x);
+#else
+	shadow = computeShadowWithPCF(vPositionFromLight2, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z, shadowsInfo2.x);
+#endif
+#else
+	#if defined(POINTLIGHT2)
+	shadow = computeShadowCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
+	#else
+	shadow = computeShadow(vPositionFromLight2, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
+	#endif
+#endif	
+#endif	
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+#endif
+
+#ifdef LIGHT3
+#ifdef SPOTLIGHT3
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightDiffuse3.a);
+#endif
+#ifdef HEMILIGHT3
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightGround3);
+#endif
+#if defined(POINTLIGHT3) || defined(DIRLIGHT3)
+	info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightDiffuse3.a);
+#endif
+#ifdef SHADOW3
+#ifdef SHADOWVSM3
+		shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3, shadowsInfo3.z, shadowsInfo3.x);
+#else
+#ifdef SHADOWPCF3
+#if defined(POINTLIGHT3)
+	shadow = computeShadowWithPCFCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.z, shadowsInfo3.x);
+#else
+	shadow = computeShadowWithPCF(vPositionFromLight3, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z, shadowsInfo3.x);
+#endif
+#else
+	#if defined(POINTLIGHT3)
+	shadow = computeShadowCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
+	#else
+	shadow = computeShadow(vPositionFromLight3, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
+	#endif
+#endif	
+#endif	
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+#endif
+
+#ifdef VERTEXALPHA
+	alpha *= vColor.a;
+#endif
+
+	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;
+
+	// Composition
+	//float r = Rand(vPositionW) * 0.5;
+	float r = vfur_length * 0.5;
+	vec4 color = vec4(finalDiffuse * (0.5 + r), alpha);
+
+#ifdef FOG
+	float fog = CalcFogFactor();
+	color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;
+#endif
+
+	gl_FragColor = color;
+}

+ 202 - 0
materialsLibrary/materials/fur/fur.vertex.fx

@@ -0,0 +1,202 @@
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+attribute vec3 normal;
+
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#ifdef VERTEXCOLOR
+attribute vec4 color;
+#endif
+#ifdef BONES
+attribute vec4 matricesIndices;
+attribute vec4 matricesWeights;
+#endif
+
+
+// Uniforms
+uniform float furLength;
+uniform float furAngle;
+#ifdef HEIGHTMAP
+uniform sampler2D heightTexture;
+#endif
+
+#ifdef INSTANCES
+attribute vec4 world0;
+attribute vec4 world1;
+attribute vec4 world2;
+attribute vec4 world3;
+#else
+uniform mat4 world;
+#endif
+
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform mat4 diffuseMatrix;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#ifdef BONES
+uniform mat4 mBones[BonesPerMesh];
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+varying float vfur_length;
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+#ifdef CLIPPLANE
+uniform vec4 vClipPlane;
+varying float fClipDistance;
+#endif
+
+#ifdef FOG
+varying float fFogDistance;
+#endif
+
+#ifdef SHADOWS
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+uniform mat4 lightMatrix0;
+varying vec4 vPositionFromLight0;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+uniform mat4 lightMatrix1;
+varying vec4 vPositionFromLight1;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+uniform mat4 lightMatrix2;
+varying vec4 vPositionFromLight2;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+uniform mat4 lightMatrix3;
+varying vec4 vPositionFromLight3;
+#endif
+#endif
+
+float Rand(vec3 rv) {
+	float x = dot(rv, vec3(12.9898,78.233, 24.65487));
+	return fract(sin(x) * 43758.5453);
+}
+
+void main(void) {
+	mat4 finalWorld;
+
+#ifdef INSTANCES
+	finalWorld = mat4(world0, world1, world2, world3);
+#else
+	finalWorld = world;
+#endif
+
+#ifdef BONES
+	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
+	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
+	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
+
+#ifdef BONES4
+	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
+	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
+#else
+	finalWorld = finalWorld * (m0 + m1 + m2);
+#endif 
+
+#endif
+//FUR
+float r = Rand(position);
+#ifdef HEIGHTMAP	
+	vfur_length = furLength * texture2D(heightTexture, uv).rgb.x;
+#else	
+	vfur_length = (furLength * r);
+#endif
+	vec3 tangent1 = vec3(normal.y, -normal.x, 0);
+	vec3 tangent2 = vec3(-normal.z, 0, normal.x);
+	r = Rand(tangent1*r);
+	float J = (2.0 + 4.0* r);
+	r = Rand(tangent2*r);
+	float K = (2.0 + 2.0* r);
+	tangent1 = tangent1*J + tangent2*K;
+	tangent1 = normalize(tangent1);
+    vec3 newPosition = position + normal * vfur_length*cos(furAngle) + tangent1*vfur_length*sin(furAngle);
+	
+//END FUR
+	gl_Position = viewProjection * finalWorld * vec4(newPosition, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(newPosition, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef NORMAL
+	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+#endif
+
+	// Texture coordinates
+#ifndef UV1
+	vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+	vec2 uv2 = vec2(0., 0.);
+#endif
+
+#ifdef DIFFUSE
+	if (vDiffuseInfos.x == 0.)
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+	// Clip plane
+#ifdef CLIPPLANE
+	fClipDistance = dot(worldPos, vClipPlane);
+#endif
+
+	// Fog
+#ifdef FOG
+	fFogDistance = (view * worldPos).z;
+#endif
+
+	// Shadows
+#ifdef SHADOWS
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+	vPositionFromLight0 = lightMatrix0 * worldPos;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+	vPositionFromLight1 = lightMatrix1 * worldPos;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+	vPositionFromLight2 = lightMatrix2 * worldPos;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+	vPositionFromLight3 = lightMatrix3 * worldPos;
+#endif
+#endif
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+
+	// Point size
+#ifdef POINTSIZE
+	gl_PointSize = pointSize;
+#endif
+}

+ 236 - 0
materialsLibrary/materials/fur/readme.md

@@ -0,0 +1,236 @@
+# Fur material
+
+## Using the fur material
+
+The fur material needs a high number of the triangular facets that make up a mesh to work well.
+The number of facets needed also depends on the size of the mesh.
+Example that seem to work for ground and sphere are:
+
+```
+var ground = BABYLON.Mesh.CreateGround("ground", 8, 8, 200, scene);
+var sphere = BABYLON.Mesh.CreateSphere("sphere", 500, 8, scene);
+```
+
+The fur material is created using 
+
+```
+var furMaterial = new BABYLON.furMaterial("fur_material", scene);
+waterMaterial.bumpTexture = new BABYLON.Texture("bump.png", scene); // Set the bump texture
+
+ground.material = waterMaterial;
+```
+
+## Customize the fur material
+
+You can customise three properties of the fur material:
+
+```
+furMaterial.furLength = 3; // Represents the maximum length of the fur, which is then adjusted randomly. Default value is 1.
+furMaterial.furAngle = Math.PI/6; // Represents the angle the fur lies on the mesh from 0 to Math.PI/2. The default angle of 0 gives fur sticking straight up and PI/2 lies along the mesh.
+furMaterial.furColor = new BABYLON.Color3(0.44, 0.21, 0.02); // is the default color if furColor is not set.
+```
+
+## Using textures
+
+#heightTexture
+
+A greyscale image can be used to set the fur length. 
+A speckled greyscale image can produce fur like results.
+Any greyscale image with affect the fur length producing a heightMap type effect.
+
+```
+furMaterial.heightTexture = new BABYLON.Texture("speckles.jpg", scene); // Set the fur length with a texture.
+```
+#diffuseTexture
+A texture can also be used to paint the mesh. 
+The leopard fur texture used in the test is by Martin Wegmann from [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Leopard_fur.JPG)
+under the [license](https://creativecommons.org/licenses/by-sa/3.0/deed.en)
+
+```
+furMaterial.diffuseTexture = new BABYLON.Texture("leopard_fur.jpg", scene); // Set the fur length with a texture.
+```
+
+## Meshes where the number of facets is not user controlled on creation.
+
+Unlike the ground mesh where you can supply the number of subdivisions or the sphere mesh where you can supply the number of segments the majority of meshes are created using a minimum number of facets.
+To apply the fur material to these the number of facets per face of the mesh needs to be increased.
+
+The function increasedFacets will do this:
+When n is the number of points per side added to each side of a facet the number of facets is increased by the square of (n + 1).
+
+```
+function increasedFacets(mesh, pps) { //pps points per side		
+	var gaps = pps+1;
+	var n = gaps + 1;
+	var fvs =[];
+	for(var i=0; i<n; i++) {
+		fvs[i] = [];
+	}	
+	var A,B;
+	var d ={x:0,y:0,z:0};
+	var u ={x:0,y:0};
+	var indices = [];
+	var vertexIndex = [];
+	var side = [];
+	var uvs = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
+	var meshIndices = mesh.getIndices();
+	var positions = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);	
+	var normals =[];	
+	
+	for(var i = 0; i<meshIndices.length; i+=3) {
+		vertexIndex[0] = meshIndices[i];
+		vertexIndex[1] = meshIndices[i + 1];
+		vertexIndex[2] = meshIndices[i + 2];		
+		for(var j = 0; j<3; j++) {
+			A = vertexIndex[j];
+			B = vertexIndex[(j+1)%3];		
+			if(side[A] === undefined  && side[B] ===  undefined) {			
+				side[A] = [];
+				side[B] = [];			
+			}
+			else {
+				if(side[A] === undefined) {					
+					side[A] = [];
+				}
+				if(side[B] === undefined) {					
+					side[B] = [];								
+				}
+			}
+			if(side[A][B]  === undefined  && side[B][A] === undefined) {			
+				side[A][B] = [];
+				d.x = (positions[3 * B] - positions[3 * A])/gaps;
+				d.y = (positions[3 * B + 1] - positions[3 * A + 1])/gaps;
+				d.z = (positions[3 * B + 2] - positions[3 * A + 2])/gaps;
+				u.x = (uvs[2*B] - uvs[2*A])/gaps;
+				u.y = (uvs[2*B + 1] - uvs[2*A + 1])/gaps;
+				side[A][B].push(A);				
+				for(var k=1; k<gaps; k++) {				
+					side[A][B].push(positions.length/3);				
+					positions.push(positions[3 * A] + k*d.x, positions[3 * A + 1] + k*d.y, positions[3 * A + 2] + k*d.z);
+					uvs.push(uvs[2*A] + k*u.x, uvs[2*A + 1] + k*u.y);
+				}				
+				side[A][B].push(B);
+				side[B][A]=[];
+				l = side[A][B].length;
+				for(var a=0; a<l; a++) {
+					side[B][A][a] = side[A][B][l-1-a];
+				}
+			}
+			else {
+				if(side[A][B] === undefined) {			
+					side[A][B]=[];
+					l = side[B][A].length;
+					for(var a=0; a<l; a++) {
+						side[A][B][a] = side[B][A][l-1-a];
+					}
+				}
+				if(side[B][A] === undefined) {			
+					side[B][A]=[];				
+					l = side[A][B].length;
+					for(var a=0; a<l; a++) {
+						side[B][A][a] = side[A][B][l-1-a];
+					}
+				}
+			}					
+		}	
+		fvs[0][0] = meshIndices[i];
+		fvs[1][0] = side[meshIndices[i]][meshIndices[i + 1]][1];
+		fvs[1][1] = side[meshIndices[i]][meshIndices[i + 2]][1];		
+		for(var k = 2; k<gaps; k++) {
+			fvs[k][0] = side[meshIndices[i]][meshIndices[i + 1]][k];
+			fvs[k][k] = side[meshIndices[i]][meshIndices[i + 2]][k];		
+			d.x = (positions[3 * fvs[k][k]] - positions[3 * fvs[k][0]])/k;
+			d.y = (positions[3 * fvs[k][k] + 1] - positions[3 * fvs[k][0] + 1])/k;
+			d.z = (positions[3 * fvs[k][k] + 2] - positions[3 * fvs[k][0] + 2])/k;
+			u.x = (uvs[2*fvs[k][k]] - uvs[2*fvs[k][0]])/k;
+			u.y = (uvs[2*fvs[k][k] + 1] - uvs[2*fvs[k][0] + 1])/k;
+			for(var j = 1; j<k; j++) {				
+				fvs[k][j] = positions.length/3;				
+				positions.push(positions[3 * fvs[k][0]] + j*d.x, positions[3 * fvs[k][0] + 1] + j*d.y, positions[3 * fvs[k][0] + 2] + j*d.z);
+				uvs.push(uvs[2*fvs[k][0]] + j*u.x, uvs[2*fvs[k][0] + 1] + j*u.y);
+			}		
+		}
+		fvs[gaps] = side[meshIndices[i + 1]][meshIndices[i + 2]];
+		
+		indices.push(fvs[0][0],fvs[1][0],fvs[1][1]);
+		for(var k = 1; k<gaps; k++) {
+			for(var j = 0; j<k; j++) {			
+				indices.push(fvs[k][j],fvs[k+1][j],fvs[k+1][j+1]);
+				indices.push(fvs[k][j],fvs[k+1][j+1],fvs[k][j+1]);
+			}		
+			indices.push(fvs[k][j],fvs[k+1][j],fvs[k+1][j+1]);
+		}
+
+	}							
+
+	var vertexData = new BABYLON.VertexData();
+	vertexData.positions = positions;
+	vertexData.indices = indices;
+	vertexData.uvs = uvs;
+	
+	BABYLON.VertexData.ComputeNormals(positions, indices, normals);
+	vertexData.normals = normals;
+	mesh.dispose();
+	var newmesh = new BABYLON.Mesh("newmesh", scene);	
+	vertexData.applyToMesh(newmesh);
+
+	return newmesh;
+}
+```
+
+For sharp edged meshes such as a box the shader can separate the faces since the faces meeting at the corners have there own vertices and normals at these vertices. 
+These meshes are flat shaded. If this separation of the edges is a problem then the function convertToSmoothShadedMesh() can be used.
+However this can then produce some artefacts at the edges.
+
+```
+function convertToSmoothShadedMesh(mesh) {
+	var meshIndices = mesh.getIndices();
+	var meshPositions = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+	var mesh_uvs = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
+	var setPositions = [];
+	var indices = [];
+	var positions = [];
+	var uvs = [];
+	var normals = [];
+	var p;
+	var indexMap = [];
+	for(var i=0; i<meshPositions.length; i+=3) {
+		var temp =[];
+		temp.push(i/3, meshPositions[i], meshPositions[i + 1], meshPositions[i + 2], mesh_uvs[2*i/3], mesh_uvs[2*i/3 + 1]);
+		setPositions.push(temp);
+	}	
+	var i=0;
+	while(setPositions.length>0) {
+		p = setPositions.shift();
+		positions.push(p[1],p[2],p[3]);
+		uvs.push(p[4],p[5]);
+		indexMap[p[0]] = i;		
+		var j = 0;
+		while(j<setPositions.length) {		
+			if (Math.abs(p[1] - setPositions[j][1])<Math.pow(0.1, 10) && Math.abs(p[2] - setPositions[j][2])<Math.pow(0.1, 10) && Math.abs(p[3] - setPositions[j][3])<Math.pow(0.1, 10) ) {
+				indexMap[setPositions[j][0]] = i;			
+				setPositions.splice(j,1);
+			}
+			else {
+				j++;
+			}
+		}
+		i++;
+	}	
+	for(var i=0; i<meshIndices.length; i++) {
+		indices.push(indexMap[meshIndices[i]]);
+	}
+	
+	var vertexData = new BABYLON.VertexData();
+	vertexData.positions = positions;
+	vertexData.indices = indices;
+	vertexData.uvs = uvs;
+	
+	BABYLON.VertexData.ComputeNormals(positions, indices, normals);
+	vertexData.normals = normals;
+	vertexData.applyToMesh(mesh);
+
+	return mesh;
+	
+}
+```

+ 90 - 16
materialsLibrary/materials/lava/babylon.lavaMaterial.ts

@@ -28,7 +28,7 @@ module BABYLON {
         public POINTLIGHT0 = false;
         public POINTLIGHT1 = false;
         public POINTLIGHT2 = false;
-        public POINTLIGHT3 = false;        
+        public POINTLIGHT3 = false;
         public SHADOW0 = false;
         public SHADOW1 = false;
         public SHADOW2 = false;
@@ -47,8 +47,7 @@ module BABYLON {
         public UV2 = false;
         public VERTEXCOLOR = false;
         public VERTEXALPHA = false;
-        public BONES = false;
-        public BONES4 = false;
+        public NUM_BONE_INFLUENCERS = 0;
         public BonesPerMesh = 0;
         public INSTANCES = false;
 
@@ -63,6 +62,9 @@ module BABYLON {
         public noiseTexture: BaseTexture;
         public fogColor: Color3;
         public speed : number = 1;
+        public movingSpeed : number = 1;
+        public lowFrequencySpeed : number = 1;
+        public fogDensity : number = 0.15;
 
         private _lastTime : number = 0;
 
@@ -143,7 +145,7 @@ module BABYLON {
                         needUVs = true;
                         this._defines.DIFFUSE = true;
                     }
-                }                
+                }
             }
 
             // Effect
@@ -263,10 +265,10 @@ module BABYLON {
                         this._defines.VERTEXALPHA = true;
                     }
                 }
+
                 if (mesh.useBones && mesh.computeBonesUsingShaders) {
-                    this._defines.BONES = true;
+                    this._defines.NUM_BONE_INFLUENCERS = mesh.numBoneInfluencers;
                     this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
-                    this._defines.BONES4 = true;
                 }
 
                 // Instances
@@ -282,7 +284,7 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (this._defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
@@ -308,9 +310,9 @@ module BABYLON {
                         fallbacks.addFallback(0, "SHADOWVSM" + lightIndex);
                     }
                 }
-             
-                if (this._defines.BONES4) {
-                    fallbacks.addFallback(0, "BONES4");
+
+                if (this._defines.NUM_BONE_INFLUENCERS > 0){
+                    fallbacks.addCPUSkinningFallback(0, mesh);
                 }
 
                 //Attributes
@@ -332,9 +334,13 @@ module BABYLON {
                     attribs.push(VertexBuffer.ColorKind);
                 }
 
-                if (this._defines.BONES) {
+                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
                     attribs.push(VertexBuffer.MatricesIndicesKind);
                     attribs.push(VertexBuffer.MatricesWeightsKind);
+                    if (this._defines.NUM_BONE_INFLUENCERS > 4) {
+                        attribs.push(VertexBuffer.MatricesIndicesExtraKind);
+                        attribs.push(VertexBuffer.MatricesWeightsExtraKind);
+                    }
                 }
 
                 if (this._defines.INSTANCES) {
@@ -355,10 +361,12 @@ module BABYLON {
                         "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                         "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
-                        "vDiffuseInfos", 
+                        "vDiffuseInfos",
                         "mBones",
                         "vClipPlane", "diffuseMatrix",
-                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3","time", "speed", "fogColor"
+                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues",
+                        "time", "speed","movingSpeed",
+                        "fogColor","fogDensity", "lowFrequencySpeed"
                     ],
                     ["diffuseSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3", "noiseTexture"
@@ -423,13 +431,14 @@ module BABYLON {
                     this._effect.setFloat("pointSize", this.pointSize);
                 }
 
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
 
             this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
 
             if (scene.lightsEnabled && !this.disableLighting) {
                 var lightIndex = 0;
+                var depthValuesAlreadySet = false;
                 for (var index = 0; index < scene.lights.length; index++) {
                     var light = scene.lights[index];
 
@@ -462,7 +471,14 @@ module BABYLON {
                     if (scene.shadowsEnabled) {
                         var shadowGenerator = light.getShadowGenerator();
                         if (mesh.receiveShadows && shadowGenerator) {
-                            this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
+                            if (!(<any>light).needCube()) {
+                                this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
+                            } else {
+                                if (!depthValuesAlreadySet) {
+                                    depthValuesAlreadySet = true;
+                                    this._effect.setFloat2("depthValues", scene.activeCamera.minZ, scene.activeCamera.maxZ);
+                                }
+                            }
                             this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
                             this._effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.getShadowMap().getSize().width, shadowGenerator.bias);
                         }
@@ -494,6 +510,10 @@ module BABYLON {
                 this.fogColor = Color3.Black();
             }
             this._effect.setColor3("fogColor", this.fogColor);
+            this._effect.setFloat("fogDensity", this.fogDensity);
+
+            this._effect.setFloat("lowFrequencySpeed", this.lowFrequencySpeed);
+            this._effect.setFloat("movingSpeed", this.movingSpeed);
 
 
             super.bind(world, mesh);
@@ -543,6 +563,60 @@ module BABYLON {
 
             return newMaterial;
         }
+
+
+        public serialize(): any {
+            var serializationObject = super.serialize();
+            serializationObject.customType      = "BABYLON.LavaMaterial";
+            serializationObject.diffuseColor    = this.diffuseColor.asArray();
+            serializationObject.fogColor        = this.fogColor.asArray();
+            serializationObject.speed           = this.speed;
+            serializationObject.movingSpeed     = this.movingSpeed;
+            serializationObject.lowFrequencySpeed = this.lowFrequencySpeed;
+            serializationObject.fogDensity      = this.fogDensity;
+            serializationObject.checkReadyOnlyOnce = this.checkReadyOnlyOnce;
+
+            if (this.diffuseTexture) {
+                serializationObject.diffuseTexture = this.diffuseTexture.serialize();
+            }
+            if (this.noiseTexture) {
+                serializationObject.noiseTexture = this.noiseTexture.serialize();
+            }
+
+            return serializationObject;
+        }
+
+        public static Parse(source: any, scene: Scene, rootUrl: string): LavaMaterial {
+            var material = new LavaMaterial(source.name, scene);
+
+            material.diffuseColor   = Color3.FromArray(source.diffuseColor);
+            material.speed          = source.speed;
+            material.fogColor       = Color3.FromArray(source.fogColor);
+            material.movingSpeed    = source.movingSpeed;
+            material.lowFrequencySpeed = source.lowFrequencySpeed;
+            material.fogDensity     =  source.lowFrequencySpeed;
+
+            material.alpha          = source.alpha;
+
+            material.id             = source.id;
+
+            Tags.AddTagsTo(material, source.tags);
+            material.backFaceCulling = source.backFaceCulling;
+            material.wireframe = source.wireframe;
+
+            if (source.diffuseTexture) {
+                material.diffuseTexture = Texture.Parse(source.diffuseTexture, scene, rootUrl);
+            }
+
+            if (source.noiseTexture) {
+                material.noiseTexture = Texture.Parse(source.noiseTexture, scene, rootUrl);
+            }
+
+            if (source.checkReadyOnlyOnce) {
+                material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;
+            }
+
+            return material;
+        }
     }
 } 
-

+ 19 - 14
materialsLibrary/materials/lava/lava.fragment.fx

@@ -10,8 +10,10 @@ varying vec3 vPositionW;
 // MAGMAAAA
 uniform float time;
 uniform float speed;
+uniform float movingSpeed;
 uniform vec3 fogColor;
 uniform sampler2D noiseTexture;
+uniform float fogDensity;
 
 // Varying
 varying float noise;
@@ -122,14 +124,16 @@ float unpack(vec4 color)
 }
 
 #if defined(POINTLIGHT0) || defined(POINTLIGHT1) || defined(POINTLIGHT2) || defined(POINTLIGHT3)
+uniform vec2 depthValues;
+
 float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float bias)
 {
 	vec3 directionToLight = vPositionW - lightPosition;
 	float depth = length(directionToLight);
+	depth = clamp(depth, 0., 1.0);
 
-	depth = clamp(depth, 0., 1.);
-
-	directionToLight.y = 1.0 - directionToLight.y;
+	directionToLight = normalize(directionToLight);
+	directionToLight.y = - directionToLight.y;
 
 	float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
 
@@ -140,14 +144,16 @@ float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float dar
 	return 1.0;
 }
 
-float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float bias, float darkness)
+float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float bias, float darkness, float mapSize)
 {
 	vec3 directionToLight = vPositionW - lightPosition;
 	float depth = length(directionToLight);
 
-	depth = clamp(depth, 0., 1.);
+	depth = clamp(depth, 0., 1.0);
+	float diskScale = 2.0 / mapSize;
 
-	directionToLight.y = 1.0 - directionToLight.y;
+	directionToLight = normalize(directionToLight);
+	directionToLight.y = -directionToLight.y;
 
 	float visibility = 1.;
 
@@ -402,17 +408,16 @@ void main(void) {
 
 	T1.x += noiseTex.x * 2.0;
 	T1.y += noiseTex.y * 2.0;
-	T2.x -= noiseTex.y * 0.2;
-	T2.y += noiseTex.z * 0.2;
+	T2.x -= noiseTex.y * 0.2 + time*0.001*movingSpeed;
+	T2.y += noiseTex.z * 0.2 + time*0.002*movingSpeed;
 
 	float p = texture2D( noiseTexture, T1 * 3.0 ).a;
 
 	vec4 lavaColor = texture2D( diffuseSampler, T2 * 4.0);
-	vec4 temp = lavaColor * ( vec4( p, p, p, p ) * 2.0 ) + ( lavaColor * lavaColor - 0.1 );
+	vec4 temp = lavaColor * ( vec4( p, p, p, p ) * 2. ) + ( lavaColor * lavaColor - 0.1 );
 
 	baseColor = temp;
 
-	float fogDensity = 0.15;
 	float depth = gl_FragCoord.z * 4.0;
 	const float LOG2 = 1.442695;
     float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );
@@ -465,7 +470,7 @@ void main(void) {
 #else
 #ifdef SHADOWPCF0
 	#if defined(POINTLIGHT0)
-	shadow = computeShadowWithPCFCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.z, shadowsInfo0.x);
+	shadow = computeShadowWithPCFCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.z, shadowsInfo0.x, shadowsInfo0.y);
 	#else
 	shadow = computeShadowWithPCF(vPositionFromLight0, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z, shadowsInfo0.x);
 	#endif
@@ -499,7 +504,7 @@ void main(void) {
 #else
 #ifdef SHADOWPCF1
 #if defined(POINTLIGHT1)
-	shadow = computeShadowWithPCFCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.z, shadowsInfo1.x);
+	shadow = computeShadowWithPCFCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.z, shadowsInfo1.x, shadowsInfo1.y);
 #else
 	shadow = computeShadowWithPCF(vPositionFromLight1, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z, shadowsInfo1.x);
 #endif
@@ -533,7 +538,7 @@ void main(void) {
 #else
 #ifdef SHADOWPCF2
 #if defined(POINTLIGHT2)
-	shadow = computeShadowWithPCFCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.z, shadowsInfo2.x);
+	shadow = computeShadowWithPCFCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.z, shadowsInfo2.x, shadowsInfo2.y);
 #else
 	shadow = computeShadowWithPCF(vPositionFromLight2, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z, shadowsInfo2.x);
 #endif
@@ -567,7 +572,7 @@ void main(void) {
 #else
 #ifdef SHADOWPCF3
 #if defined(POINTLIGHT3)
-	shadow = computeShadowWithPCFCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.z, shadowsInfo3.x);
+	shadow = computeShadowWithPCFCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.z, shadowsInfo3.x, shadowsInfo3.y);
 #else
 	shadow = computeShadowWithPCF(vPositionFromLight3, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z, shadowsInfo3.x);
 #endif

+ 38 - 19
materialsLibrary/materials/lava/lava.vertex.fx

@@ -1,7 +1,7 @@
 precision highp float;
 // Inputs
 uniform float time;
-uniform float speed;
+uniform float lowFrequencySpeed;
 // Varying
 varying float noise;
 
@@ -19,10 +19,6 @@ attribute vec2 uv2;
 #ifdef VERTEXCOLOR
 attribute vec4 color;
 #endif
-#ifdef BONES
-attribute vec4 matricesIndices;
-attribute vec4 matricesWeights;
-#endif
 
 // Uniforms
 
@@ -44,8 +40,15 @@ uniform mat4 diffuseMatrix;
 uniform vec2 vDiffuseInfos;
 #endif
 
-#ifdef BONES
-uniform mat4 mBones[BonesPerMesh];
+#if NUM_BONE_INFLUENCERS > 0
+	uniform mat4 mBones[BonesPerMesh];
+
+	attribute vec4 matricesIndices;
+	attribute vec4 matricesWeights;
+	#if NUM_BONE_INFLUENCERS > 4
+		attribute vec4 matricesIndicesExtra;
+		attribute vec4 matricesWeightsExtra;
+	#endif
 #endif
 
 #ifdef POINTSIZE
@@ -207,25 +210,41 @@ void main(void) {
 	finalWorld = world;
 #endif
 
-#ifdef BONES
-	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
-	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
-	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
+#if NUM_BONE_INFLUENCERS > 0
+	mat4 influence;
+	influence = mBones[int(matricesIndices[0])] * matricesWeights[0];
 
-#ifdef BONES4
-	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
-	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
-#else
-	finalWorld = finalWorld * (m0 + m1 + m2);
-#endif 
+	#if NUM_BONE_INFLUENCERS > 1
+		influence += mBones[int(matricesIndices[1])] * matricesWeights[1];
+	#endif 
+	#if NUM_BONE_INFLUENCERS > 2
+		influence += mBones[int(matricesIndices[2])] * matricesWeights[2];
+	#endif	
+	#if NUM_BONE_INFLUENCERS > 3
+		influence += mBones[int(matricesIndices[3])] * matricesWeights[3];
+	#endif	
 
+	#if NUM_BONE_INFLUENCERS > 4
+		influence += mBones[int(matricesIndicesExtra[0])] * matricesWeightsExtra[0];
+	#endif
+	#if NUM_BONE_INFLUENCERS > 5
+		influence += mBones[int(matricesIndicesExtra[1])] * matricesWeightsExtra[1];
+	#endif	
+	#if NUM_BONE_INFLUENCERS > 6
+		influence += mBones[int(matricesIndicesExtra[2])] * matricesWeightsExtra[2];
+	#endif	
+	#if NUM_BONE_INFLUENCERS > 7
+		influence += mBones[int(matricesIndicesExtra[3])] * matricesWeightsExtra[3];
+	#endif	
+
+	finalWorld = finalWorld * influence;
 #endif
 
 
     // get a turbulent 3d noise using the normal, normal to high freq
     noise = 10.0 *  -.10 * turbulence( .5 * normal + time*1.15 );
     // get a 3d noise using the position, low frequency
-    float b = 5.0 * pnoise( 0.05 * position +vec3(time*1.025), vec3( 100.0 ) );
+    float b = lowFrequencySpeed * 5.0 * pnoise( 0.05 * position +vec3(time*1.025), vec3( 100.0 ) );
     // compose both noises
     float displacement = - 1.5 * noise + b;
 
@@ -295,4 +314,4 @@ void main(void) {
 #ifdef POINTSIZE
 	gl_PointSize = pointSize;
 #endif
-}
+}

File diff suppressed because it is too large
+ 563 - 516
materialsLibrary/materials/normal/babylon.normalMaterial.ts


File diff suppressed because it is too large
+ 562 - 558
materialsLibrary/materials/normal/normal.fragment.fx


+ 279 - 106
materialsLibrary/materials/pbr/babylon.pbrMaterial.ts

@@ -4,18 +4,18 @@ module BABYLON {
     var maxSimultaneousLights = 4;
 
     class PBRMaterialDefines extends MaterialDefines {
-        public DIFFUSE = false;
+        public ALBEDO = false;
         public AMBIENT = false;
         public OPACITY = false;
         public OPACITYRGB = false;
         public REFLECTION = false;
         public EMISSIVE = false;
-        public SPECULAR = false;
+        public REFLECTIVITY = false;
         public BUMP = false;
         public SPECULAROVERALPHA = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
-        public ALPHAFROMDIFFUSE = false;
+        public ALPHAFROMALBEDO = false;
         public POINTSIZE = false;
         public FOG = false;
         public LIGHT0 = false;
@@ -63,9 +63,9 @@ module BABYLON {
         public NUM_BONE_INFLUENCERS = 0;
         public BonesPerMesh = 0;
         public INSTANCES = false;
-        public GLOSSINESSFROMSPECULARMAP = false;
+        public MICROSURFACEFROMREFLECTIVITYMAP = false;
         public EMISSIVEASILLUMINATION = false;
-        public LINKEMISSIVEWITHDIFFUSE = false;
+        public LINKEMISSIVEWITHALBEDO = false;
         public LIGHTMAP = false;
         public USELIGHTMAPASSHADOWMAP = false;
         public REFLECTIONMAP_3D = false;
@@ -94,7 +94,9 @@ module BABYLON {
         public directIntensity: number = 1.0;
         public emissiveIntensity: number = 1.0;
         public environmentIntensity: number = 1.0;
-        private _lightingInfos: Vector4 = new Vector4(this.directIntensity, this.emissiveIntensity, this.environmentIntensity, 0.0);
+        public specularIntensity: number = 1.0;
+
+        private _lightingInfos: Vector4 = new Vector4(this.directIntensity, this.emissiveIntensity, this.environmentIntensity, this.specularIntensity);
 
         public overloadedShadowIntensity: number = 1.0;
         public overloadedShadeIntensity: number = 1.0;
@@ -105,42 +107,42 @@ module BABYLON {
         private _cameraInfos: Vector4 = new Vector4(1.0, 1.0, 0.0, 0.0);
 
         public overloadedAmbientIntensity: number = 0.0;
-        public overloadedDiffuseIntensity: number = 0.0;
-        public overloadedSpecularIntensity: number = 0.0;
+        public overloadedAlbedoIntensity: number = 0.0;
+        public overloadedReflectivityIntensity: number = 0.0;
         public overloadedEmissiveIntensity: number = 0.0;
-        private _overloadedIntensity: Vector4 = new Vector4(this.overloadedAmbientIntensity, this.overloadedDiffuseIntensity, this.overloadedSpecularIntensity, this.overloadedEmissiveIntensity);
+        private _overloadedIntensity: Vector4 = new Vector4(this.overloadedAmbientIntensity, this.overloadedAlbedoIntensity, this.overloadedReflectivityIntensity, this.overloadedEmissiveIntensity);
 
         public overloadedAmbient: Color3 = BABYLON.Color3.White();
-        public overloadedDiffuse: Color3 = BABYLON.Color3.White();
-        public overloadedSpecular: Color3 = BABYLON.Color3.White();
+        public overloadedAlbedo: Color3 = BABYLON.Color3.White();
+        public overloadedReflectivity: Color3 = BABYLON.Color3.White();
         public overloadedEmissive: Color3 = BABYLON.Color3.White();
         public overloadedReflection: Color3 = BABYLON.Color3.White();
 
-        public overloadedGlossiness: number = 0.0;
-        public overloadedGlossinessIntensity: number = 0.0;
+        public overloadedMicroSurface: number = 0.0;
+        public overloadedMicroSurfaceIntensity: number = 0.0;
         public overloadedReflectionIntensity: number = 0.0;
-        private _overloadedGlossiness: Vector3 = new Vector3(this.overloadedGlossiness, this.overloadedGlossinessIntensity, this.overloadedReflectionIntensity);
+        private _overloadedMicroSurface: Vector3 = new Vector3(this.overloadedMicroSurface, this.overloadedMicroSurfaceIntensity, this.overloadedReflectionIntensity);
        
         public disableBumpMap: boolean = false;
 
-        public diffuseTexture: BaseTexture;
+        public albedoTexture: BaseTexture;
         public ambientTexture: BaseTexture;
         public opacityTexture: BaseTexture;
         public reflectionTexture: BaseTexture;
         public emissiveTexture: BaseTexture;
-        public specularTexture: BaseTexture;
+        public reflectivityTexture: BaseTexture;
         public bumpTexture: BaseTexture;
         public lightmapTexture: BaseTexture;
 
         public ambientColor = new Color3(0, 0, 0);
-        public diffuseColor = new Color3(1, 1, 1);
-        public specularColor = new Color3(1, 1, 1);
+        public albedoColor = new Color3(1, 1, 1);
+        public reflectivityColor = new Color3(1, 1, 1);
         public reflectionColor = new Color3(0.5, 0.5, 0.5);
-        public glossiness = 0.5;
+        public microSurface = 0.5;
         public emissiveColor = new Color3(0, 0, 0);
-        public useAlphaFromDiffuseTexture = false;
+        public useAlphaFromAlbedoTexture = false;
         public useEmissiveAsIllumination = false;
-        public linkEmissiveWithDiffuse = false;
+        public linkEmissiveWithAlbedo = false;
         public useSpecularOverAlpha = true;
         public disableLighting = false;
 
@@ -149,7 +151,7 @@ module BABYLON {
         public opacityFresnelParameters: FresnelParameters;
         public emissiveFresnelParameters: FresnelParameters;
 
-        public useGlossinessFromSpecularMapAlpha = false;
+        public useMicroSurfaceFromReflectivityMapAlpha = false;
 
         private _renderTargets = new SmartArray<RenderTargetTexture>(16);
         private _worldViewProjectionMatrix = Matrix.Zero();
@@ -188,19 +190,19 @@ module BABYLON {
         }
 
         public needAlphaBlending(): boolean {
-            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture() || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled;
+            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromAlbedoTexture() || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled;
         }
 
         public needAlphaTesting(): boolean {
-            return this.diffuseTexture != null && this.diffuseTexture.hasAlpha;
+            return this.albedoTexture != null && this.albedoTexture.hasAlpha;
         }
 
-        private _shouldUseAlphaFromDiffuseTexture(): boolean {
-            return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
+        private _shouldUseAlphaFromAlbedoTexture(): boolean {
+            return this.albedoTexture != null && this.albedoTexture.hasAlpha && this.useAlphaFromAlbedoTexture;
         }
 
         public getAlphaTestTexture(): BaseTexture {
-            return this.diffuseTexture;
+            return this.albedoTexture;
         }
 
         private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
@@ -305,13 +307,14 @@ module BABYLON {
             return needNormals;
         }
 
-        private static _scaledDiffuse = new Color3();
-        private static _scaledSpecular = new Color3();
+        private static _scaledAlbedo = new Color3();
+        private static _scaledReflectivity = new Color3();
         private static _scaledEmissive = new Color3();
         private static _scaledReflection = new Color3();
 
         public static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: MaterialDefines) {
             var lightIndex = 0;
+            var depthValuesAlreadySet = false;
             for (var index = 0; index < scene.lights.length; index++) {
                 var light = scene.lights[index];
 
@@ -338,15 +341,15 @@ module BABYLON {
                 }
 
                 // GAMMA CORRECTION.
-                light.diffuse.toLinearSpaceToRef(PBRMaterial._scaledDiffuse);
-                PBRMaterial._scaledDiffuse.scaleToRef(light.intensity, PBRMaterial._scaledDiffuse);
+                light.diffuse.toLinearSpaceToRef(PBRMaterial._scaledAlbedo);
+                PBRMaterial._scaledAlbedo.scaleToRef(light.intensity, PBRMaterial._scaledAlbedo);
 
-                light.diffuse.scaleToRef(light.intensity, PBRMaterial._scaledDiffuse);
-                effect.setColor4("vLightDiffuse" + lightIndex, PBRMaterial._scaledDiffuse, light.range);
+                light.diffuse.scaleToRef(light.intensity, PBRMaterial._scaledAlbedo);
+                effect.setColor4("vLightDiffuse" + lightIndex, PBRMaterial._scaledAlbedo, light.range);
                 if (defines["SPECULARTERM"]) {
-                    light.specular.toLinearSpaceToRef(PBRMaterial._scaledSpecular);
-                    PBRMaterial._scaledSpecular.scaleToRef(light.intensity, PBRMaterial._scaledSpecular);
-                    effect.setColor3("vLightSpecular" + lightIndex, PBRMaterial._scaledSpecular);
+                    light.specular.toLinearSpaceToRef(PBRMaterial._scaledReflectivity);
+                    PBRMaterial._scaledReflectivity.scaleToRef(light.intensity, PBRMaterial._scaledReflectivity);
+                    effect.setColor3("vLightSpecular" + lightIndex, PBRMaterial._scaledReflectivity);
                 }
 
                 // Shadows
@@ -355,6 +358,11 @@ module BABYLON {
                     if (mesh.receiveShadows && shadowGenerator) {
                         if (!(<any>light).needCube()) {
                             effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
+                        } else {
+                            if (!depthValuesAlreadySet) {
+                                depthValuesAlreadySet = true;
+                                effect.setFloat2("depthValues", scene.activeCamera.minZ, scene.activeCamera.maxZ);
+                            }
                         }
                         effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
                         effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.getShadowMap().getSize().width, shadowGenerator.bias);
@@ -394,12 +402,12 @@ module BABYLON {
 
             // Textures
             if (scene.texturesEnabled) {
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    if (!this.diffuseTexture.isReady()) {
+                if (this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this.albedoTexture.isReady()) {
                         return false;
                     } else {
                         needUVs = true;
-                        this._defines.DIFFUSE = true;
+                        this._defines.ALBEDO = true;
                     }
                 }
 
@@ -484,13 +492,13 @@ module BABYLON {
                     }
                 }
 
-                if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
-                    if (!this.specularTexture.isReady()) {
+                if (this.reflectivityTexture && StandardMaterial.SpecularTextureEnabled) {
+                    if (!this.reflectivityTexture.isReady()) {
                         return false;
                     } else {
                         needUVs = true;
-                        this._defines.SPECULAR = true;
-                        this._defines.GLOSSINESSFROMSPECULARMAP = this.useGlossinessFromSpecularMapAlpha;
+                        this._defines.REFLECTIVITY = true;
+                        this._defines.MICROSURFACEFROMREFLECTIVITYMAP = this.useMicroSurfaceFromReflectivityMapAlpha;
                     }
                 }
             }
@@ -513,16 +521,16 @@ module BABYLON {
                 this._defines.ALPHATEST = true;
             }
 
-            if (this._shouldUseAlphaFromDiffuseTexture()) {
-                this._defines.ALPHAFROMDIFFUSE = true;
+            if (this._shouldUseAlphaFromAlbedoTexture()) {
+                this._defines.ALPHAFROMALBEDO = true;
             }
 
             if (this.useEmissiveAsIllumination) {
                 this._defines.EMISSIVEASILLUMINATION = true;
             }
 
-            if (this.linkEmissiveWithDiffuse) {
-                this._defines.LINKEMISSIVEWITHDIFFUSE = true;
+            if (this.linkEmissiveWithAlbedo) {
+                this._defines.LINKEMISSIVEWITHALBEDO = true;
             }
 
             if (this.useLogarithmicDepth) {
@@ -542,10 +550,10 @@ module BABYLON {
                 this._defines.OVERLOADEDSHADOWVALUES = true;
             }
 
-            if (this.overloadedGlossinessIntensity > 0 ||
+            if (this.overloadedMicroSurfaceIntensity > 0 ||
                 this.overloadedEmissiveIntensity > 0 ||
-                this.overloadedSpecularIntensity > 0 ||
-                this.overloadedDiffuseIntensity > 0 ||
+                this.overloadedReflectivityIntensity > 0 ||
+                this.overloadedAlbedoIntensity > 0 ||
                 this.overloadedAmbientIntensity > 0 ||
                 this.overloadedReflectionIntensity > 0) {
                 this._defines.OVERLOADEDVALUES = true;
@@ -630,8 +638,8 @@ module BABYLON {
                     fallbacks.addFallback(0, "REFLECTION");
                 }
 
-                if (this._defines.SPECULAR) {
-                    fallbacks.addFallback(0, "SPECULAR");
+                if (this._defines.REFLECTIVITY) {
+                    fallbacks.addFallback(0, "REFLECTIVITY");
                 }
 
                 if (this._defines.BUMP) {
@@ -739,21 +747,21 @@ module BABYLON {
                 var join = this._defines.toString();
                 this._effect = scene.getEngine().createEffect(shaderName,
                     attribs,
-                    ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor", "vReflectionColor",
+                    ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vAlbedoColor", "vReflectivityColor", "vEmissiveColor", "vReflectionColor",
                         "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
                         "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
                         "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                         "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
-                        "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos",
+                        "vAlbedoInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vReflectivityInfos", "vBumpInfos", "vLightmapInfos",
                         "mBones",
-                        "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix",
-                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
+                        "vClipPlane", "albedoMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "reflectivityMatrix", "bumpMatrix", "lightmapMatrix",
+                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues",
                         "opacityParts", "emissiveLeftColor", "emissiveRightColor",
-                        "vLightingIntensity", "vOverloadedShadowIntensity", "vOverloadedIntensity", "vCameraInfos", "vOverloadedDiffuse", "vOverloadedReflection", "vOverloadedSpecular", "vOverloadedEmissive", "vOverloadedGlossiness",
+                        "vLightingIntensity", "vOverloadedShadowIntensity", "vOverloadedIntensity", "vCameraInfos", "vOverloadedAlbedo", "vOverloadedReflection", "vOverloadedReflectivity", "vOverloadedEmissive", "vOverloadedMicroSurface",
                         "logarithmicDepthConstant"
                     ],
-                    ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler",
+                    ["albedoSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "reflectivitySampler", "bumpSampler", "lightmapSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
                     ],
                     join, fallbacks, this.onCompiled, this.onError);
@@ -818,11 +826,11 @@ module BABYLON {
                 }
 
                 // Textures        
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
+                if (this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    this._effect.setTexture("albedoSampler", this.albedoTexture);
 
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                    this._effect.setFloat2("vAlbedoInfos", this.albedoTexture.coordinatesIndex, this.albedoTexture.level);
+                    this._effect.setMatrix("albedoMatrix", this.albedoTexture.getTextureMatrix());
                 }
 
                 if (this.ambientTexture && StandardMaterial.AmbientTextureEnabled) {
@@ -864,11 +872,11 @@ module BABYLON {
                     this._effect.setMatrix("lightmapMatrix", this.lightmapTexture.getTextureMatrix());
                 }
 
-                if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
-                    this._effect.setTexture("specularSampler", this.specularTexture);
+                if (this.reflectivityTexture && StandardMaterial.SpecularTextureEnabled) {
+                    this._effect.setTexture("reflectivitySampler", this.reflectivityTexture);
 
-                    this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
-                    this._effect.setMatrix("specularMatrix", this.specularTexture.getTextureMatrix());
+                    this._effect.setFloat2("vReflectivityInfos", this.reflectivityTexture.coordinatesIndex, this.reflectivityTexture.level);
+                    this._effect.setMatrix("reflectivityMatrix", this.reflectivityTexture.getTextureMatrix());
                 }
 
                 if (this.bumpTexture && this._myScene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled && !this.disableBumpMap) {
@@ -895,14 +903,11 @@ module BABYLON {
                 this._myScene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
                 
                 // GAMMA CORRECTION.
-                this.specularColor.toLinearSpaceToRef(PBRMaterial._scaledSpecular);
+                this.reflectivityColor.toLinearSpaceToRef(PBRMaterial._scaledReflectivity);
 
                 this._effect.setVector3("vEyePosition", this._myScene._mirroredCameraPosition ? this._myScene._mirroredCameraPosition : this._myScene.activeCamera.position);
                 this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
-
-                if (this._defines.SPECULARTERM) {
-                    this._effect.setColor4("vSpecularColor", PBRMaterial._scaledSpecular, this.glossiness);
-                }
+                this._effect.setColor4("vReflectivityColor", PBRMaterial._scaledReflectivity, this.microSurface);
 
                 // GAMMA CORRECTION.
                 this.emissiveColor.toLinearSpaceToRef(PBRMaterial._scaledEmissive); 
@@ -914,8 +919,8 @@ module BABYLON {
             }
 
             // GAMMA CORRECTION.
-            this.diffuseColor.toLinearSpaceToRef(PBRMaterial._scaledDiffuse);
-            this._effect.setColor4("vDiffuseColor", PBRMaterial._scaledDiffuse, this.alpha * mesh.visibility);
+            this.albedoColor.toLinearSpaceToRef(PBRMaterial._scaledAlbedo);
+            this._effect.setColor4("vAlbedoColor", PBRMaterial._scaledAlbedo, this.alpha * mesh.visibility);
 
             // Lights
             if (this._myScene.lightsEnabled && !this.disableLighting) {
@@ -936,6 +941,8 @@ module BABYLON {
             this._lightingInfos.x = this.directIntensity;
             this._lightingInfos.y = this.emissiveIntensity;
             this._lightingInfos.z = this.environmentIntensity;
+            this._lightingInfos.w = this.specularIntensity;
+
             this._effect.setVector4("vLightingIntensity", this._lightingInfos);
 
             this._overloadedShadowInfos.x = this.overloadedShadowIntensity;
@@ -947,26 +954,26 @@ module BABYLON {
             this._effect.setVector4("vCameraInfos", this._cameraInfos);
 
             this._overloadedIntensity.x = this.overloadedAmbientIntensity;
-            this._overloadedIntensity.y = this.overloadedDiffuseIntensity;
-            this._overloadedIntensity.z = this.overloadedSpecularIntensity;
+            this._overloadedIntensity.y = this.overloadedAlbedoIntensity;
+            this._overloadedIntensity.z = this.overloadedReflectivityIntensity;
             this._overloadedIntensity.w = this.overloadedEmissiveIntensity;
             this._effect.setVector4("vOverloadedIntensity", this._overloadedIntensity);
 
             this.overloadedAmbient.toLinearSpaceToRef(this._tempColor);
             this._effect.setColor3("vOverloadedAmbient", this._tempColor);
-            this.overloadedDiffuse.toLinearSpaceToRef(this._tempColor);
-            this._effect.setColor3("vOverloadedDiffuse", this._tempColor);
-            this.overloadedSpecular.toLinearSpaceToRef(this._tempColor);
-            this._effect.setColor3("vOverloadedSpecular", this._tempColor);
+            this.overloadedAlbedo.toLinearSpaceToRef(this._tempColor);
+            this._effect.setColor3("vOverloadedAlbedo", this._tempColor);
+            this.overloadedReflectivity.toLinearSpaceToRef(this._tempColor);
+            this._effect.setColor3("vOverloadedReflectivity", this._tempColor);
             this.overloadedEmissive.toLinearSpaceToRef(this._tempColor);
             this._effect.setColor3("vOverloadedEmissive", this._tempColor);
             this.overloadedReflection.toLinearSpaceToRef(this._tempColor);
             this._effect.setColor3("vOverloadedReflection", this._tempColor);
 
-            this._overloadedGlossiness.x = this.overloadedGlossiness;
-            this._overloadedGlossiness.y = this.overloadedGlossinessIntensity;
-            this._overloadedGlossiness.z = this.overloadedReflectionIntensity;
-            this._effect.setVector3("vOverloadedGlossiness", this._overloadedGlossiness);
+            this._overloadedMicroSurface.x = this.overloadedMicroSurface;
+            this._overloadedMicroSurface.y = this.overloadedMicroSurfaceIntensity;
+            this._overloadedMicroSurface.z = this.overloadedReflectionIntensity;
+            this._effect.setVector3("vOverloadedMicroSurface", this._overloadedMicroSurface);
 
             // Log. depth
             if (this._defines.LOGARITHMICDEPTH) {
@@ -981,8 +988,8 @@ module BABYLON {
         public getAnimatables(): IAnimatable[] {
             var results = [];
 
-            if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
-                results.push(this.diffuseTexture);
+            if (this.albedoTexture && this.albedoTexture.animations && this.albedoTexture.animations.length > 0) {
+                results.push(this.albedoTexture);
             }
 
             if (this.ambientTexture && this.ambientTexture.animations && this.ambientTexture.animations.length > 0) {
@@ -1001,8 +1008,8 @@ module BABYLON {
                 results.push(this.emissiveTexture);
             }
 
-            if (this.specularTexture && this.specularTexture.animations && this.specularTexture.animations.length > 0) {
-                results.push(this.specularTexture);
+            if (this.reflectivityTexture && this.reflectivityTexture.animations && this.reflectivityTexture.animations.length > 0) {
+                results.push(this.reflectivityTexture);
             }
 
             if (this.bumpTexture && this.bumpTexture.animations && this.bumpTexture.animations.length > 0) {
@@ -1013,8 +1020,8 @@ module BABYLON {
         }
 
         public dispose(forceDisposeEffect?: boolean): void {
-            if (this.diffuseTexture) {
-                this.diffuseTexture.dispose();
+            if (this.albedoTexture) {
+                this.albedoTexture.dispose();
             }
 
             if (this.ambientTexture) {
@@ -1033,8 +1040,8 @@ module BABYLON {
                 this.emissiveTexture.dispose();
             }
 
-            if (this.specularTexture) {
-                this.specularTexture.dispose();
+            if (this.reflectivityTexture) {
+                this.reflectivityTexture.dispose();
             }
 
             if (this.bumpTexture) {
@@ -1053,6 +1060,7 @@ module BABYLON {
             newPBRMaterial.directIntensity = this.directIntensity;
             newPBRMaterial.emissiveIntensity = this.emissiveIntensity;
             newPBRMaterial.environmentIntensity = this.environmentIntensity;
+            newPBRMaterial.specularIntensity = this.specularIntensity;
         
             newPBRMaterial.cameraExposure = this.cameraExposure;
             newPBRMaterial.cameraContrast = this.cameraContrast;
@@ -1061,24 +1069,24 @@ module BABYLON {
             newPBRMaterial.overloadedShadeIntensity = this.overloadedShadeIntensity;
         
             newPBRMaterial.overloadedAmbientIntensity = this.overloadedAmbientIntensity;
-            newPBRMaterial.overloadedDiffuseIntensity = this.overloadedDiffuseIntensity;
-            newPBRMaterial.overloadedSpecularIntensity = this.overloadedSpecularIntensity;
+            newPBRMaterial.overloadedAlbedoIntensity = this.overloadedAlbedoIntensity;
+            newPBRMaterial.overloadedReflectivityIntensity = this.overloadedReflectivityIntensity;
             newPBRMaterial.overloadedEmissiveIntensity = this.overloadedEmissiveIntensity;
             newPBRMaterial.overloadedAmbient = this.overloadedAmbient;
-            newPBRMaterial.overloadedDiffuse = this.overloadedDiffuse;
-            newPBRMaterial.overloadedSpecular = this.overloadedSpecular;
+            newPBRMaterial.overloadedAlbedo = this.overloadedAlbedo;
+            newPBRMaterial.overloadedReflectivity = this.overloadedReflectivity;
             newPBRMaterial.overloadedEmissive = this.overloadedEmissive;
             newPBRMaterial.overloadedReflection = this.overloadedReflection;
 
-            newPBRMaterial.overloadedGlossiness = this.overloadedGlossiness;
-            newPBRMaterial.overloadedGlossinessIntensity = this.overloadedGlossinessIntensity;
+            newPBRMaterial.overloadedMicroSurface = this.overloadedMicroSurface;
+            newPBRMaterial.overloadedMicroSurfaceIntensity = this.overloadedMicroSurfaceIntensity;
             newPBRMaterial.overloadedReflectionIntensity = this.overloadedReflectionIntensity;
         
             newPBRMaterial.disableBumpMap = this.disableBumpMap;
 
             // Standard material
-            if (this.diffuseTexture && this.diffuseTexture.clone) {
-                newPBRMaterial.diffuseTexture = this.diffuseTexture.clone();
+            if (this.albedoTexture && this.albedoTexture.clone) {
+                newPBRMaterial.albedoTexture = this.albedoTexture.clone();
             }
             if (this.ambientTexture && this.ambientTexture.clone) {
                 newPBRMaterial.ambientTexture = this.ambientTexture.clone();
@@ -1092,8 +1100,8 @@ module BABYLON {
             if (this.emissiveTexture && this.emissiveTexture.clone) {
                 newPBRMaterial.emissiveTexture = this.emissiveTexture.clone();
             }
-            if (this.specularTexture && this.specularTexture.clone) {
-                newPBRMaterial.specularTexture = this.specularTexture.clone();
+            if (this.reflectivityTexture && this.reflectivityTexture.clone) {
+                newPBRMaterial.reflectivityTexture = this.reflectivityTexture.clone();
             }
             if (this.bumpTexture && this.bumpTexture.clone) {
                 newPBRMaterial.bumpTexture = this.bumpTexture.clone();
@@ -1104,14 +1112,14 @@ module BABYLON {
             }
 
             newPBRMaterial.ambientColor = this.ambientColor.clone();
-            newPBRMaterial.diffuseColor = this.diffuseColor.clone();
-            newPBRMaterial.specularColor = this.specularColor.clone();
+            newPBRMaterial.albedoColor = this.albedoColor.clone();
+            newPBRMaterial.reflectivityColor = this.reflectivityColor.clone();
             newPBRMaterial.reflectionColor = this.reflectionColor.clone();
-            newPBRMaterial.glossiness = this.glossiness;
+            newPBRMaterial.microSurface = this.microSurface;
             newPBRMaterial.emissiveColor = this.emissiveColor.clone();
-            newPBRMaterial.useAlphaFromDiffuseTexture = this.useAlphaFromDiffuseTexture;
+            newPBRMaterial.useAlphaFromAlbedoTexture = this.useAlphaFromAlbedoTexture;
             newPBRMaterial.useEmissiveAsIllumination = this.useEmissiveAsIllumination;
-            newPBRMaterial.useGlossinessFromSpecularMapAlpha = this.useGlossinessFromSpecularMapAlpha;
+            newPBRMaterial.useMicroSurfaceFromReflectivityMapAlpha = this.useMicroSurfaceFromReflectivityMapAlpha;
             newPBRMaterial.useSpecularOverAlpha = this.useSpecularOverAlpha;
             
             newPBRMaterial.emissiveFresnelParameters = this.emissiveFresnelParameters.clone();
@@ -1119,5 +1127,170 @@ module BABYLON {
 
             return newPBRMaterial;
         }
+        
+        public serialize(): any {
+            var serializationObject = super.serialize();
+                        
+            serializationObject.customType = "BABYLON.PBRMaterial";
+
+            serializationObject.directIntensity = this.directIntensity;
+            serializationObject.emissiveIntensity = this.emissiveIntensity;
+            serializationObject.environmentIntensity = this.environmentIntensity;
+            serializationObject.specularIntensity = this.specularIntensity;
+        
+            serializationObject.cameraExposure = this.cameraExposure;
+            serializationObject.cameraContrast = this.cameraContrast;
+
+            serializationObject.overloadedShadowIntensity = this.overloadedShadowIntensity;
+            serializationObject.overloadedShadeIntensity = this.overloadedShadeIntensity;
+        
+            serializationObject.overloadedAmbientIntensity = this.overloadedAmbientIntensity;
+            serializationObject.overloadedAlbedoIntensity = this.overloadedAlbedoIntensity;
+            serializationObject.overloadedReflectivityIntensity = this.overloadedReflectivityIntensity;
+            serializationObject.overloadedEmissiveIntensity = this.overloadedEmissiveIntensity;
+            serializationObject.overloadedAmbient = this.overloadedAmbient.asArray();
+            serializationObject.overloadedAlbedo = this.overloadedAlbedo.asArray();
+            serializationObject.overloadedReflectivity = this.overloadedReflectivity.asArray();
+            serializationObject.overloadedEmissive = this.overloadedEmissive.asArray();
+            serializationObject.overloadedReflection = this.overloadedReflection.asArray();
+
+            serializationObject.overloadedMicroSurface = this.overloadedMicroSurface;
+            serializationObject.overloadedMicroSurfaceIntensity = this.overloadedMicroSurfaceIntensity;
+            serializationObject.overloadedReflectionIntensity = this.overloadedReflectionIntensity;
+        
+            serializationObject.disableBumpMap = this.disableBumpMap;
+
+            // Standard material
+            if (this.albedoTexture) {
+                serializationObject.albedoTexture = this.albedoTexture.serialize();
+            }
+            if (this.ambientTexture) {
+                serializationObject.ambientTexture = this.ambientTexture.serialize();
+            }
+            if (this.opacityTexture) {
+                serializationObject.opacityTexture = this.opacityTexture.serialize();
+            }
+            if (this.reflectionTexture) {
+                serializationObject.reflectionTexture = this.reflectionTexture.serialize();
+            }
+            if (this.emissiveTexture) {
+                serializationObject.emissiveTexture = this.emissiveTexture.serialize();
+            }
+            if (this.reflectivityTexture) {
+                serializationObject.reflectivityTexture = this.reflectivityTexture.serialize();
+            }
+            if (this.bumpTexture) {
+                serializationObject.bumpTexture = this.bumpTexture.serialize();
+            }
+            if (this.lightmapTexture) {
+                serializationObject.lightmapTexture = this.lightmapTexture.serialize();
+                serializationObject.useLightmapAsShadowmap = this.useLightmapAsShadowmap;
+            }
+
+            serializationObject.ambientColor = this.ambientColor.asArray();
+            serializationObject.albedoColor = this.albedoColor.asArray();
+            serializationObject.reflectivityColor = this.reflectivityColor.asArray();
+            serializationObject.reflectionColor = this.reflectionColor.asArray();
+            serializationObject.microSurface = this.microSurface;
+            serializationObject.emissiveColor = this.emissiveColor.asArray();
+            serializationObject.useAlphaFromAlbedoTexture = this.useAlphaFromAlbedoTexture;
+            serializationObject.useEmissiveAsIllumination = this.useEmissiveAsIllumination;
+            serializationObject.useMicroSurfaceFromReflectivityMapAlpha = this.useMicroSurfaceFromReflectivityMapAlpha;
+            serializationObject.useSpecularOverAlpha = this.useSpecularOverAlpha;
+            
+            serializationObject.emissiveFresnelParameters = this.emissiveFresnelParameters.serialize();
+            serializationObject.opacityFresnelParameters = this.opacityFresnelParameters.serialize();
+
+            return serializationObject;
+        }
+                
+        public static Parse(source: any, scene: Scene, rootUrl: string): PBRMaterial {
+            var material = new PBRMaterial(source.name, scene);
+            
+            material.alpha = source.alpha;
+            material.id = source.id;
+            
+            if (source.disableDepthWrite) {
+                material.disableDepthWrite = source.disableDepthWrite;
+            }
+            
+           if (source.checkReadyOnlyOnce) {
+                material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;
+            }
+
+            Tags.AddTagsTo(material, source.tags);
+            material.backFaceCulling = source.backFaceCulling;
+            material.wireframe = source.wireframe;
+            
+            material.directIntensity = source.directIntensity;
+            material.emissiveIntensity = source.emissiveIntensity;
+            material.environmentIntensity = source.environmentIntensity;
+            material.specularIntensity = source.specularIntensity;
+        
+            material.cameraExposure = source.cameraExposure;
+            material.cameraContrast = source.cameraContrast;
+
+            material.overloadedShadowIntensity = source.overloadedShadowIntensity;
+            material.overloadedShadeIntensity = source.overloadedShadeIntensity;
+        
+            material.overloadedAmbientIntensity = source.overloadedAmbientIntensity;
+            material.overloadedAlbedoIntensity = source.overloadedAlbedoIntensity;
+            material.overloadedReflectivityIntensity = source.overloadedReflectivityIntensity;
+            material.overloadedEmissiveIntensity = source.overloadedEmissiveIntensity;
+            material.overloadedAmbient = Color3.FromArray(source.overloadedAmbient);
+            material.overloadedAlbedo = Color3.FromArray(source.overloadedAlbedo);
+            material.overloadedReflectivity = Color3.FromArray(source.overloadedReflectivity);
+            material.overloadedEmissive = Color3.FromArray(source.overloadedEmissive);
+            material.overloadedReflection = Color3.FromArray(source.overloadedReflection);
+
+            material.overloadedMicroSurface = source.overloadedMicroSurface;
+            material.overloadedMicroSurfaceIntensity = source.overloadedMicroSurfaceIntensity;
+            material.overloadedReflectionIntensity = source.overloadedReflectionIntensity;
+        
+            material.disableBumpMap = source.disableBumpMap;
+
+            // Standard material
+            if (source.albedoTexture) {
+                material.albedoTexture = Texture.Parse(source.albedoTexture, scene, rootUrl);
+            }
+            if (source.ambientTexture) {
+                material.ambientTexture = Texture.Parse(source.ambientTexture, scene, rootUrl);
+            }
+            if (source.opacityTexture) {
+                material.opacityTexture = Texture.Parse(source.opacityTexture, scene, rootUrl);
+            }
+            if (source.reflectionTexture) {
+                material.reflectionTexture = Texture.Parse(source.reflectionTexture, scene, rootUrl);
+            }
+            if (source.emissiveTexture) {
+                material.emissiveTexture = Texture.Parse(source.emissiveTexture, scene, rootUrl);
+            }
+            if (source.reflectivityTexture) {
+                material.reflectivityTexture = Texture.Parse(source.reflectivityTexture, scene, rootUrl);
+            }
+            if (source.bumpTexture) {
+                material.bumpTexture = Texture.Parse(source.bumpTexture, scene, rootUrl);
+            }
+            if (source.lightmapTexture) {
+                material.lightmapTexture = Texture.Parse(source.lightmapTexture, scene, rootUrl);
+                material.useLightmapAsShadowmap = source.useLightmapAsShadowmap;
+            }
+
+            material.ambientColor = Color3.FromArray(source.ambient);
+            material.albedoColor = Color3.FromArray(source.albedo);
+            material.reflectivityColor = Color3.FromArray(source.reflectivity);
+            material.reflectionColor = Color3.FromArray(source.reflectionColor);
+            material.microSurface = source.microSurface;
+            material.emissiveColor = Color3.FromArray(source.emissive);
+            material.useAlphaFromAlbedoTexture = source.useAlphaFromAlbedoTexture;
+            material.useEmissiveAsIllumination = source.useEmissiveAsIllumination;
+            material.useMicroSurfaceFromReflectivityMapAlpha = source.useMicroSurfaceFromReflectivityMapAlpha;
+            material.useSpecularOverAlpha = source.useSpecularOverAlpha;
+            
+            material.emissiveFresnelParameters = FresnelParameters.Parse(source.emissiveFresnelParameters);
+            material.opacityFresnelParameters = FresnelParameters.Parse(source.opacityFresnelParameters);
+       
+            return material;
+        }
     }
 }

+ 59 - 73
materialsLibrary/materials/pbr/legacypbr.fragment.fx

@@ -6,7 +6,7 @@
 
 uniform vec3 vEyePosition;
 uniform vec3 vAmbientColor;
-uniform vec4 vDiffuseColor;
+uniform vec4 vAlbedoColor;
 uniform vec3 vReflectionColor;
 
 // CUSTOM CONTROLS
@@ -16,11 +16,11 @@ uniform vec4 vCameraInfos;
 #ifdef OVERLOADEDVALUES
 uniform vec4 vOverloadedIntensity;
 uniform vec3 vOverloadedAmbient;
-uniform vec3 vOverloadedDiffuse;
-uniform vec3 vOverloadedSpecular;
+uniform vec3 vOverloadedAlbedo;
+uniform vec3 vOverloadedReflectivity;
 uniform vec3 vOverloadedEmissive;
 uniform vec3 vOverloadedReflection;
-uniform vec3 vOverloadedGlossiness;
+uniform vec3 vOverloadedMicroSurface;
 #endif
 
 #ifdef OVERLOADEDSHADOWVALUES
@@ -113,17 +113,17 @@ float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness)
     return diffuseFresnelTerm * NdotL;
 }
 
-float computeDefaultGlossiness(float glossiness, vec3 specularColor)
+float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
 {
-    if (glossiness == 0.)
+    if (microSurface == 0.)
     {
-        float kSpecularNoAlphaWorkflow_SmoothnessMax = 0.95;
+        float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
 
-        float specularLuminance = getLuminance(specularColor);
-        float specularLuma = sqrt(specularLuminance);
-        glossiness = specularLuma * kSpecularNoAlphaWorkflow_SmoothnessMax;
+        float reflectivityLuminance = getLuminance(reflectivityColor);
+        float reflectivityLuma = sqrt(reflectivityLuminance);
+        microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
     }
-    return glossiness;
+    return microSurface;
 }
 
 vec3 toLinearSpace(vec3 color)
@@ -174,9 +174,7 @@ vec3 toGammaSpace(vec3 color)
 #endif
 // END PBR HELPER METHODS
 
-#ifdef SPECULARTERM
-uniform vec4 vSpecularColor;
-#endif
+uniform vec4 vReflectivityColor;
 uniform vec3 vEmissiveColor;
 
 // Input
@@ -284,10 +282,10 @@ uniform vec3 vLightGround3;
 #endif
 
 // Samplers
-#ifdef DIFFUSE
-varying vec2 vDiffuseUV;
-uniform sampler2D diffuseSampler;
-uniform vec2 vDiffuseInfos;
+#ifdef ALBEDO
+varying vec2 vAlbedoUV;
+uniform sampler2D albedoSampler;
+uniform vec2 vAlbedoInfos;
 #endif
 
 #ifdef AMBIENT
@@ -314,10 +312,10 @@ uniform vec2 vLightmapInfos;
 uniform sampler2D lightmapSampler;
 #endif
 
-#if defined(SPECULAR) && defined(SPECULARTERM)
-varying vec2 vSpecularUV;
-uniform vec2 vSpecularInfos;
-uniform sampler2D specularSampler;
+#if defined(REFLECTIVITY)
+varying vec2 vReflectivityUV;
+uniform vec2 vReflectivityInfos;
+uniform sampler2D reflectivitySampler;
 #endif
 
 #ifdef CLIPPLANE
@@ -446,13 +444,13 @@ void main(void) {
 
     // Base color
     vec4 baseColor = vec4(1., 1., 1., 1.);
-    vec3 diffuseColor = vDiffuseColor.rgb;
+    vec3 diffuseColor = vAlbedoColor.rgb;
     
     // Alpha
-    float alpha = vDiffuseColor.a;
+    float alpha = vAlbedoColor.a;
 
-#ifdef DIFFUSE
-    baseColor = texture2D(diffuseSampler, vDiffuseUV);
+#ifdef ALBEDO
+    baseColor = texture2D(diffuseSampler, vAlbedoUV);
     baseColor = vec4(toLinearSpace(baseColor.rgb), baseColor.a);
 
 #ifdef ALPHATEST
@@ -460,11 +458,11 @@ void main(void) {
         discard;
 #endif
 
-#ifdef ALPHAFROMDIFFUSE
+#ifdef ALPHAFROMALBEDO
     alpha *= baseColor.a;
 #endif
 
-    baseColor.rgb *= vDiffuseInfos.y;
+    baseColor.rgb *= vAlbedoInfos.y;
 #endif
 
 #ifdef VERTEXCOLOR
@@ -472,8 +470,8 @@ void main(void) {
 #endif
 
 #ifdef OVERLOADEDVALUES
-    baseColor.rgb = mix(baseColor.rgb, vOverloadedDiffuse, vOverloadedIntensity.y);
-    diffuseColor.rgb = mix(diffuseColor.rgb, vOverloadedDiffuse, vOverloadedIntensity.y);
+    baseColor.rgb = mix(baseColor.rgb, vOverloadedAlbedo, vOverloadedIntensity.y);
+    albedoColor.rgb = mix(albedoColor.rgb, vOverloadedAlbedo, vOverloadedIntensity.y);
 #endif
 
     // Bump
@@ -493,57 +491,45 @@ void main(void) {
     #endif
 #endif
 
-    // Specular map
-#ifdef SPECULARTERM
-    float glossiness = vSpecularColor.a;
-    vec3 specularColor = vSpecularColor.rgb;
+    // Reflectivity map
+    float microSurface = vReflectivityColor.a;
+    vec3 reflectivityColor = vReflectivityColor.rgb;
 
     #ifdef OVERLOADEDVALUES
-        specularColor.rgb = mix(specularColor.rgb, vOverloadedSpecular, vOverloadedIntensity.z);
+        reflectivityColor.rgb = mix(reflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
     #endif
 
-    #ifdef SPECULAR
-            vec4 specularMapColor = texture2D(specularSampler, vSpecularUV);
-            specularColor = toLinearSpace(specularMapColor.rgb);
+    #ifdef REFLECTIVITY
+            vec4 reflectivityMapColor = texture2D(reflectivitySampler, vReflectivityUV);
+            reflectivityColor = toLinearSpace(reflectivityMapColor.rgb);
 
         #ifdef OVERLOADEDVALUES
-                specularColor.rgb = mix(specularColor.rgb, vOverloadedSpecular, vOverloadedIntensity.z);
+                reflectivityColor.rgb = mix(reflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
         #endif
 
-        #ifdef GLOSSINESSFROMSPECULARMAP
-            glossiness = specularMapColor.a;
+        #ifdef MICROSURFACEFROMREFLECTIVITYMAP
+            microSurface = reflectivityMapColor.a;
         #else
-            glossiness = computeDefaultGlossiness(glossiness, specularColor);
+            microSurface = computeDefaultMicroSurface(microSurface, reflectivityColor);
         #endif
     #endif
 
     #ifdef OVERLOADEDVALUES
-        glossiness = mix(glossiness, vOverloadedGlossiness.x, vOverloadedGlossiness.y);
-    #endif
-#else
-    float glossiness = 0.;
-    #ifdef OVERLOADEDVALUES
-        glossiness = mix(glossiness, vOverloadedGlossiness.x, vOverloadedGlossiness.y);
-    #endif
-
-    vec3 specularColor = vec3(0., 0., 0);
-    #ifdef OVERLOADEDVALUES
-            specularColor.rgb = mix(specularColor.rgb, vOverloadedSpecular, vOverloadedIntensity.z);
+        microSurface = mix(microSurface, vOverloadedMicroSurface.x, vOverloadedMicroSurface.y);
     #endif
-#endif
 
     // Apply Energy Conservation taking in account the environment level only if the environment is present.
-    float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
+    float reflectance = max(max(reflectivityColor.r, reflectivityColor.g), reflectivityColor.b);
     baseColor.rgb = (1. - reflectance) * baseColor.rgb;
 
     // Compute Specular Fresnel + Reflectance.
     float NdotV = max(0.00000000001, dot(normalW, viewDirectionW));
 
-    // Adapt glossiness.
-    glossiness = clamp(glossiness, 0., 1.) * 0.98;
+    // Adapt microSurface.
+    microSurface = clamp(microSurface, 0., 1.) * 0.98;
 
     // Call rough to not conflict with previous one.
-    float rough = clamp(1. - glossiness, 0.000001, 1.0);
+    float rough = clamp(1. - microSurface, 0.000001, 1.0);
 
     // Lighting
     vec3 diffuseBase = vec3(0., 0., 0.);
@@ -664,15 +650,15 @@ vec3 ambientReflectionColor = vReflectionColor.rgb;
 reflectionColor *= vLightingIntensity.z;
 ambientReflectionColor *= vLightingIntensity.z;
 
-// Compute reflection specular fresnel
-vec3 specularEnvironmentR0 = specularColor.rgb;
-vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0);
-vec3 specularEnvironmentReflectanceViewer = FresnelSchlickEnvironmentGGX(clamp(NdotV, 0., 1.), specularEnvironmentR0, specularEnvironmentR90, sqrt(glossiness));
-reflectionColor *= specularEnvironmentReflectanceViewer;
+// Compute reflection reflectivity fresnel
+vec3 reflectivityEnvironmentR0 = reflectivityColor.rgb;
+vec3 reflectivityEnvironmentR90 = vec3(1.0, 1.0, 1.0);
+vec3 reflectivityEnvironmentReflectanceViewer = FresnelSchlickEnvironmentGGX(clamp(NdotV, 0., 1.), reflectivityEnvironmentR0, reflectivityEnvironmentR90, sqrt(microSurface));
+reflectionColor *= reflectivityEnvironmentReflectanceViewer;
 
 #ifdef OVERLOADEDVALUES
-    ambientReflectionColor = mix(ambientReflectionColor, vOverloadedReflection, vOverloadedGlossiness.z);
-    reflectionColor = mix(reflectionColor, vOverloadedReflection, vOverloadedGlossiness.z);
+    ambientReflectionColor = mix(ambientReflectionColor, vOverloadedReflection, vOverloadedMicroSurface.z);
+    reflectionColor = mix(reflectionColor, vOverloadedReflection, vOverloadedMicroSurface.z);
 #endif
 
 #ifdef OPACITY
@@ -704,21 +690,21 @@ reflectionColor *= specularEnvironmentReflectanceViewer;
 
     // Composition
 #ifdef EMISSIVEASILLUMINATION
-    vec3 finalDiffuse = max(diffuseBase * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+    vec3 finalDiffuse = max(diffuseBase * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
 
     #ifdef OVERLOADEDSHADOWVALUES
-        shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+        shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
     #endif
 #else
-    #ifdef LINKEMISSIVEWITHDIFFUSE
-        vec3 finalDiffuse = max((diffuseBase + emissiveColor) * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+    #ifdef LINKEMISSIVEWITHALBEDO
+        vec3 finalDiffuse = max((diffuseBase + emissiveColor) * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
         #ifdef OVERLOADEDSHADOWVALUES
-                shadowedOnlyDiffuseBase = max((shadowedOnlyDiffuseBase + emissiveColor) * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+                shadowedOnlyDiffuseBase = max((shadowedOnlyDiffuseBase + emissiveColor) * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
         #endif
     #else
-        vec3 finalDiffuse = max(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
+        vec3 finalDiffuse = max(diffuseBase * albedoColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
         #ifdef OVERLOADEDSHADOWVALUES
-            shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
+            shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * albedoColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
         #endif
     #endif
 #endif
@@ -732,7 +718,7 @@ reflectionColor *= specularEnvironmentReflectanceViewer;
 finalDiffuse += baseColor.rgb * ambientReflectionColor * 0.2;
 
 #ifdef SPECULARTERM
-    vec3 finalSpecular = specularBase * specularColor;
+    vec3 finalSpecular = specularBase * reflectivityColor * vLightingIntensity.w;
 #else
     vec3 finalSpecular = vec3(0.0);
 #endif

+ 16 - 16
materialsLibrary/materials/pbr/legacypbr.vertex.fx

@@ -29,10 +29,10 @@ uniform mat4 world;
 uniform mat4 view;
 uniform mat4 viewProjection;
 
-#ifdef DIFFUSE
-varying vec2 vDiffuseUV;
-uniform mat4 diffuseMatrix;
-uniform vec2 vDiffuseInfos;
+#ifdef ALBEDO
+varying vec2 vAlbedoUV;
+uniform mat4 albedoMatrix;
+uniform vec2 vAlbedoInfos;
 #endif
 
 #ifdef AMBIENT
@@ -53,10 +53,10 @@ uniform vec2 vEmissiveInfos;
 uniform mat4 emissiveMatrix;
 #endif
 
-#if defined(SPECULAR) && defined(SPECULARTERM)
-varying vec2 vSpecularUV;
-uniform vec2 vSpecularInfos;
-uniform mat4 specularMatrix;
+#if defined(REFLECTIVITY)
+varying vec2 vReflectivityUV;
+uniform vec2 vReflectivityInfos;
+uniform mat4 reflectivityMatrix;
 #endif
 
 // Output
@@ -119,14 +119,14 @@ void main(void) {
 	vec2 uv2 = vec2(0., 0.);
 #endif
 
-#ifdef DIFFUSE
-	if (vDiffuseInfos.x == 0.)
+#ifdef ALBEDO
+	if (vAlbedoInfos.x == 0.)
 	{
-		vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+		vAlbedoUV = vec2(albedoMatrix * vec4(uv, 1.0, 0.0));
 	}
 	else
 	{
-		vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+		vAlbedoUV = vec2(albedoMatrix * vec4(uv2, 1.0, 0.0));
 	}
 #endif
 
@@ -163,14 +163,14 @@ void main(void) {
 	}
 #endif
 
-#if defined(SPECULAR) && defined(SPECULARTERM)
-	if (vSpecularInfos.x == 0.)
+#if defined(REFLECTIVITY)
+	if (vReflectivityInfos.x == 0.)
 	{
-		vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));
+		vReflectivityUV = vec2(reflectivityMatrix * vec4(uv, 1.0, 0.0));
 	}
 	else
 	{
-		vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));
+		vReflectivityUV = vec2(reflectivityMatrix * vec4(uv2, 1.0, 0.0));
 	}
 #endif
 

+ 75 - 90
materialsLibrary/materials/pbr/pbr.fragment.fx

@@ -15,7 +15,7 @@ precision highp float;
 uniform vec3 vEyePosition;
 uniform vec3 vAmbientColor;
 uniform vec3 vReflectionColor;
-uniform vec4 vDiffuseColor;
+uniform vec4 vAlbedoColor;
 
 // CUSTOM CONTROLS
 uniform vec4 vLightingIntensity;
@@ -24,11 +24,11 @@ uniform vec4 vCameraInfos;
 #ifdef OVERLOADEDVALUES
     uniform vec4 vOverloadedIntensity;
     uniform vec3 vOverloadedAmbient;
-    uniform vec3 vOverloadedDiffuse;
-    uniform vec3 vOverloadedSpecular;
+    uniform vec3 vOverloadedAlbedo;
+    uniform vec3 vOverloadedReflectivity;
     uniform vec3 vOverloadedEmissive;
     uniform vec3 vOverloadedReflection;
-    uniform vec3 vOverloadedGlossiness;
+    uniform vec3 vOverloadedMicroSurface;
 #endif
 
 #ifdef OVERLOADEDSHADOWVALUES
@@ -124,15 +124,15 @@ float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness)
     // diffuseFresnelTerm /= kPi;
 }
 
-float computeDefaultGlossiness(float glossiness, vec3 specularColor)
+float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
 {
-    float kSpecularNoAlphaWorkflow_SmoothnessMax = 0.95;
+    float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
 
-    float specularLuminance = getLuminance(specularColor);
-    float specularLuma = sqrt(specularLuminance);
-    glossiness = specularLuma * kSpecularNoAlphaWorkflow_SmoothnessMax;
+    float reflectivityLuminance = getLuminance(reflectivityColor);
+    float reflectivityLuma = sqrt(reflectivityLuminance);
+    microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
 
-    return glossiness;
+    return microSurface;
 }
 
 vec3 toLinearSpace(vec3 color)
@@ -185,10 +185,8 @@ vec3 toGammaSpace(vec3 color)
 #endif
 // END PBR HELPER METHODS
 
-#ifdef SPECULARTERM
-uniform vec4 vSpecularColor;
-#endif
-uniform vec3 vEmissiveColor;
+    uniform vec4 vReflectivityColor;
+    uniform vec3 vEmissiveColor;
 
 // Input
 varying vec3 vPositionW;
@@ -295,10 +293,10 @@ uniform vec3 vLightGround3;
 #endif
 
 // Samplers
-#ifdef DIFFUSE
-varying vec2 vDiffuseUV;
-uniform sampler2D diffuseSampler;
-uniform vec2 vDiffuseInfos;
+#ifdef ALBEDO
+varying vec2 vAlbedoUV;
+uniform sampler2D albedoSampler;
+uniform vec2 vAlbedoInfos;
 #endif
 
 #ifdef AMBIENT
@@ -325,10 +323,10 @@ uniform vec2 vLightmapInfos;
 uniform sampler2D lightmapSampler;
 #endif
 
-#if defined(SPECULAR) && defined(SPECULARTERM)
-varying vec2 vSpecularUV;
-uniform vec2 vSpecularInfos;
-uniform sampler2D specularSampler;
+#if defined(REFLECTIVITY)
+varying vec2 vReflectivityUV;
+uniform vec2 vReflectivityInfos;
+uniform sampler2D reflectivitySampler;
 #endif
 
 // Fresnel
@@ -438,16 +436,18 @@ float unpack(vec4 color)
 }
 
 #if defined(POINTLIGHT0) || defined(POINTLIGHT1) || defined(POINTLIGHT2) || defined(POINTLIGHT3)
+uniform vec2 depthValues;
+
 float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float bias)
 {
-    vec3 directionToLight = vPositionW - lightPosition;
-    float depth = length(directionToLight);
-
-    depth = clamp(depth, 0., 1.);
+	vec3 directionToLight = vPositionW - lightPosition;
+	float depth = length(directionToLight);
+	depth = clamp(depth, 0., 1.0);
 
-    directionToLight.y = 1.0 - directionToLight.y;
+	directionToLight = normalize(directionToLight);
+	directionToLight.y = - directionToLight.y;
 
-    float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
+	float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
 
     if (depth > shadow)
     {
@@ -462,13 +462,14 @@ float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float dar
 
 float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float bias, float darkness)
 {
-    vec3 directionToLight = vPositionW - lightPosition;
-    float depth = length(directionToLight);
-    float diskScale = (1.0 - (1.0 + depth * 3.0)) / mapSize;
+	vec3 directionToLight = vPositionW - lightPosition;
+	float depth = length(directionToLight);
 
-    depth = clamp(depth, 0., 1.);
+	depth = clamp(depth, 0., 1.0);
+	float diskScale = 2.0 / mapSize;
 
-    directionToLight.y = 1.0 - directionToLight.y;
+	directionToLight = normalize(directionToLight);
+	directionToLight.y = -directionToLight.y;
 
     float visibility = 1.;
 
@@ -800,13 +801,13 @@ void main(void) {
 
     // Base color
     vec4 baseColor = vec4(1., 1., 1., 1.);
-    vec3 diffuseColor = vDiffuseColor.rgb;
+    vec3 albedoColor = vAlbedoColor.rgb;
     
     // Alpha
-    float alpha = vDiffuseColor.a;
+    float alpha = vAlbedoColor.a;
 
-#ifdef DIFFUSE
-    baseColor = texture2D(diffuseSampler, vDiffuseUV);
+#ifdef ALBEDO
+    baseColor = texture2D(albedoSampler, vAlbedoUV);
     baseColor = vec4(toLinearSpace(baseColor.rgb), baseColor.a);
 
 #ifdef ALPHATEST
@@ -814,11 +815,11 @@ void main(void) {
         discard;
 #endif
 
-#ifdef ALPHAFROMDIFFUSE
+#ifdef ALPHAFROMALBEDO
     alpha *= baseColor.a;
 #endif
 
-    baseColor.rgb *= vDiffuseInfos.y;
+    baseColor.rgb *= vAlbedoInfos.y;
 #endif
 
 #ifdef VERTEXCOLOR
@@ -826,8 +827,8 @@ void main(void) {
 #endif
 
 #ifdef OVERLOADEDVALUES
-    baseColor.rgb = mix(baseColor.rgb, vOverloadedDiffuse, vOverloadedIntensity.y);
-    diffuseColor.rgb = mix(diffuseColor.rgb, vOverloadedDiffuse, vOverloadedIntensity.y);
+    baseColor.rgb = mix(baseColor.rgb, vOverloadedAlbedo, vOverloadedIntensity.y);
+    albedoColor.rgb = mix(albedoColor.rgb, vOverloadedAlbedo, vOverloadedIntensity.y);
 #endif
 
     // Bump
@@ -854,56 +855,44 @@ void main(void) {
 #endif
 
     // Specular map
-#ifdef SPECULARTERM
-    float glossiness = vSpecularColor.a;
-    vec3 specularColor = vSpecularColor.rgb;
+    float microSurface = vReflectivityColor.a;
+    vec3 reflectivityColor = vReflectivityColor.rgb;
     
     #ifdef OVERLOADEDVALUES
-        specularColor.rgb = mix(specularColor.rgb, vOverloadedSpecular, vOverloadedIntensity.z);
+        reflectivityColor.rgb = mix(reflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
     #endif
 
-    #ifdef SPECULAR
-        vec4 specularMapColor = texture2D(specularSampler, vSpecularUV);
-        specularColor = toLinearSpace(specularMapColor.rgb);
+    #ifdef REFLECTIVITY
+        vec4 reflectivityMapColor = texture2D(reflectivitySampler, vReflectivityUV);
+        reflectivityColor = toLinearSpace(reflectivityMapColor.rgb);
 
         #ifdef OVERLOADEDVALUES
-                specularColor.rgb = mix(specularColor.rgb, vOverloadedSpecular, vOverloadedIntensity.z);
+                reflectivityColor.rgb = mix(reflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
         #endif
 
-        #ifdef GLOSSINESSFROMSPECULARMAP
-            glossiness = specularMapColor.a;
+        #ifdef MICROSURFACEFROMREFLECTIVITYMAP
+            microSurface = reflectivityMapColor.a;
         #else
-            glossiness = computeDefaultGlossiness(glossiness, specularColor);
+            microSurface = computeDefaultMicroSurface(microSurface, reflectivityColor);
         #endif
     #endif
 
     #ifdef OVERLOADEDVALUES
-        glossiness = mix(glossiness, vOverloadedGlossiness.x, vOverloadedGlossiness.y);
-    #endif
-#else
-    float glossiness = 0.;
-    #ifdef OVERLOADEDVALUES
-        glossiness = mix(glossiness, vOverloadedGlossiness.x, vOverloadedGlossiness.y);
-    #endif
-    
-    vec3 specularColor = vec3(0., 0., 0);
-    #ifdef OVERLOADEDVALUES
-        specularColor.rgb = mix(specularColor.rgb, vOverloadedSpecular, vOverloadedIntensity.z);
+        microSurface = mix(microSurface, vOverloadedMicroSurface.x, vOverloadedMicroSurface.y);
     #endif
-#endif
 
     // Apply Energy Conservation taking in account the environment level only if the environment is present.
-    float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
+    float reflectance = max(max(reflectivityColor.r, reflectivityColor.g), reflectivityColor.b);
     baseColor.rgb = (1. - reflectance) * baseColor.rgb;
 
     // Compute Specular Fresnel + Reflectance.
     float NdotV = max(0.00000000001, dot(normalW, viewDirectionW));
 
-    // Adapt glossiness.
-    glossiness = clamp(glossiness, 0., 1.) * 0.98;
+    // Adapt microSurface.
+    microSurface = clamp(microSurface, 0., 1.) * 0.98;
 
     // Call rough to not conflict with previous one.
-    float rough = clamp(1. - glossiness, 0.000001, 1.0);
+    float rough = clamp(1. - microSurface, 0.000001, 1.0);
 
     // Lighting
     vec3 diffuseBase = vec3(0., 0., 0.);
@@ -1104,12 +1093,8 @@ vec3 ambientReflectionColor = vReflectionColor.rgb;
     vec3 vReflectionUVW = computeReflectionCoords(vec4(vPositionW, 1.0), normalW);
 
     #ifdef REFLECTIONMAP_3D
-        float bias = 0.;
-
-        #ifdef SPECULARTERM
-            // Go mat -> blurry reflexion according to glossiness
-            bias = 20. * (1.0 - glossiness);
-        #endif
+        // Go mat -> blurry reflexion according to microSurface
+        float bias = 20. * (1.0 - microSurface);
 
         reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW, bias).rgb * vReflectionInfos.x;
         reflectionColor = toLinearSpace(reflectionColor.rgb);
@@ -1134,17 +1119,17 @@ vec3 ambientReflectionColor = vReflectionColor.rgb;
 #endif
 
 #ifdef OVERLOADEDVALUES
-    ambientReflectionColor = mix(ambientReflectionColor, vOverloadedReflection, vOverloadedGlossiness.z);
-    reflectionColor = mix(reflectionColor, vOverloadedReflection, vOverloadedGlossiness.z);
+    ambientReflectionColor = mix(ambientReflectionColor, vOverloadedReflection, vOverloadedMicroSurface.z);
+    reflectionColor = mix(reflectionColor, vOverloadedReflection, vOverloadedMicroSurface.z);
 #endif
 
 reflectionColor *= vLightingIntensity.z;
 ambientReflectionColor *= vLightingIntensity.z;
 
 // Compute reflection specular fresnel
-vec3 specularEnvironmentR0 = specularColor.rgb;
+vec3 specularEnvironmentR0 = reflectivityColor.rgb;
 vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0);
-vec3 specularEnvironmentReflectanceViewer = FresnelSchlickEnvironmentGGX(clamp(NdotV, 0., 1.), specularEnvironmentR0, specularEnvironmentR90, sqrt(glossiness));
+vec3 specularEnvironmentReflectanceViewer = FresnelSchlickEnvironmentGGX(clamp(NdotV, 0., 1.), specularEnvironmentR0, specularEnvironmentR90, sqrt(microSurface));
 reflectionColor *= specularEnvironmentReflectanceViewer;
 
 #ifdef OPACITY
@@ -1188,23 +1173,23 @@ reflectionColor *= specularEnvironmentReflectanceViewer;
 
     // Composition
 #ifdef EMISSIVEASILLUMINATION
-    vec3 finalDiffuse = max(diffuseBase * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+    vec3 finalDiffuse = max(diffuseBase * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
     
     #ifdef OVERLOADEDSHADOWVALUES
-        shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+        shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
     #endif
 #else
-    #ifdef LINKEMISSIVEWITHDIFFUSE
-        vec3 finalDiffuse = max((diffuseBase + emissiveColor) * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+    #ifdef LINKEMISSIVEWITHALBEDO
+        vec3 finalDiffuse = max((diffuseBase + emissiveColor) * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
 
         #ifdef OVERLOADEDSHADOWVALUES
-            shadowedOnlyDiffuseBase = max((shadowedOnlyDiffuseBase + emissiveColor) * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+            shadowedOnlyDiffuseBase = max((shadowedOnlyDiffuseBase + emissiveColor) * albedoColor + vAmbientColor, 0.0) * baseColor.rgb;
         #endif
     #else
-        vec3 finalDiffuse = max(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
+        vec3 finalDiffuse = max(diffuseBase * albedoColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
 
         #ifdef OVERLOADEDSHADOWVALUES
-            shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
+            shadowedOnlyDiffuseBase = max(shadowedOnlyDiffuseBase * albedoColor + emissiveColor + vAmbientColor, 0.0) * baseColor.rgb;
         #endif
     #endif
 #endif
@@ -1218,7 +1203,7 @@ reflectionColor *= specularEnvironmentReflectanceViewer;
 finalDiffuse += baseColor.rgb * ambientReflectionColor * 0.2;
 
 #ifdef SPECULARTERM
-    vec3 finalSpecular = specularBase * specularColor;
+    vec3 finalSpecular = specularBase * reflectivityColor * vLightingIntensity.w;
 #else
     vec3 finalSpecular = vec3(0.0);
 #endif
@@ -1279,13 +1264,13 @@ finalDiffuse += baseColor.rgb * ambientReflectionColor * 0.2;
     // gl_FragColor = vec4(baseColor.rgb, 1.0);
 
     // Specular color.
-    // gl_FragColor = vec4(specularColor.rgb, 1.0);
+    // gl_FragColor = vec4(reflectivityColor.rgb, 1.0);
 
-    // Glossiness color.
-    // gl_FragColor = vec4(glossiness, glossiness, glossiness, 1.0);
+    // MicroSurface color.
+    // gl_FragColor = vec4(microSurface, microSurface, microSurface, 1.0);
 
     // Specular Map
-    // gl_FragColor = vec4(specularMapColor.rgb, 1.0);
+    // gl_FragColor = vec4(reflectivityMapColor.rgb, 1.0);
 
     //// Emissive Color
     //vec2 test = vEmissiveUV * 0.5 + 0.5;

+ 16 - 16
materialsLibrary/materials/pbr/pbr.vertex.fx

@@ -39,10 +39,10 @@ uniform mat4 world;
 uniform mat4 view;
 uniform mat4 viewProjection;
 
-#ifdef DIFFUSE
-varying vec2 vDiffuseUV;
-uniform mat4 diffuseMatrix;
-uniform vec2 vDiffuseInfos;
+#ifdef ALBEDO
+varying vec2 vAlbedoUV;
+uniform mat4 albedoMatrix;
+uniform vec2 vAlbedoInfos;
 #endif
 
 #ifdef AMBIENT
@@ -69,10 +69,10 @@ uniform vec2 vLightmapInfos;
 uniform mat4 lightmapMatrix;
 #endif
 
-#if defined(SPECULAR) && defined(SPECULARTERM)
-varying vec2 vSpecularUV;
-uniform vec2 vSpecularInfos;
-uniform mat4 specularMatrix;
+#if defined(REFLECTIVITY)
+varying vec2 vReflectivityUV;
+uniform vec2 vReflectivityInfos;
+uniform mat4 reflectivityMatrix;
 #endif
 
 #ifdef BUMP
@@ -199,14 +199,14 @@ void main(void) {
     vec2 uv2 = vec2(0., 0.);
 #endif
 
-#ifdef DIFFUSE
-    if (vDiffuseInfos.x == 0.)
+#ifdef ALBEDO
+    if (vAlbedoInfos.x == 0.)
     {
-        vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+        vAlbedoUV = vec2(albedoMatrix * vec4(uv, 1.0, 0.0));
     }
     else
     {
-        vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+        vAlbedoUV = vec2(albedoMatrix * vec4(uv2, 1.0, 0.0));
     }
 #endif
 
@@ -254,14 +254,14 @@ void main(void) {
     }
 #endif
 
-#if defined(SPECULAR) && defined(SPECULARTERM)
-    if (vSpecularInfos.x == 0.)
+#if defined(REFLECTIVITY)
+    if (vReflectivityInfos.x == 0.)
     {
-        vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));
+        vReflectivityUV = vec2(reflectivityMatrix * vec4(uv, 1.0, 0.0));
     }
     else
     {
-        vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));
+        vReflectivityUV = vec2(reflectivityMatrix * vec4(uv2, 1.0, 0.0));
     }
 #endif
 

File diff suppressed because it is too large
+ 562 - 516
materialsLibrary/materials/simple/babylon.simpleMaterial.ts


File diff suppressed because it is too large
+ 560 - 555
materialsLibrary/materials/simple/simple.fragment.fx


File diff suppressed because it is too large
+ 664 - 577
materialsLibrary/materials/terrain/babylon.terrainMaterial.ts


File diff suppressed because it is too large
+ 713 - 712
materialsLibrary/materials/terrain/terrain.fragment.fx


+ 622 - 0
materialsLibrary/materials/triPlanar/babylon.triPlanarMaterial.ts

@@ -0,0 +1,622 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON {
+    var maxSimultaneousLights = 4;
+
+    class TriPlanarMaterialDefines extends MaterialDefines {
+        public DIFFUSEX = false;
+        public DIFFUSEY = false;
+        public DIFFUSEZ = false;
+        
+        public BUMPX = false;
+        public BUMPY = false;
+        public BUMPZ = false;
+        
+        public CLIPPLANE = false;
+        public ALPHATEST = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public LIGHT0 = false;
+        public LIGHT1 = false;
+        public LIGHT2 = false;
+        public LIGHT3 = false;
+        public SPOTLIGHT0 = false;
+        public SPOTLIGHT1 = false;
+        public SPOTLIGHT2 = false;
+        public SPOTLIGHT3 = false;
+        public HEMILIGHT0 = false;
+        public HEMILIGHT1 = false;
+        public HEMILIGHT2 = false;
+        public HEMILIGHT3 = false;
+        public DIRLIGHT0 = false;
+        public DIRLIGHT1 = false;
+        public DIRLIGHT2 = false;
+        public DIRLIGHT3 = false;
+        public POINTLIGHT0 = false;
+        public POINTLIGHT1 = false;
+        public POINTLIGHT2 = false;
+        public POINTLIGHT3 = false;        
+        public SHADOW0 = false;
+        public SHADOW1 = false;
+        public SHADOW2 = false;
+        public SHADOW3 = false;
+        public SHADOWS = false;
+        public SHADOWVSM0 = false;
+        public SHADOWVSM1 = false;
+        public SHADOWVSM2 = false;
+        public SHADOWVSM3 = false;
+        public SHADOWPCF0 = false;
+        public SHADOWPCF1 = false;
+        public SHADOWPCF2 = false;
+        public SHADOWPCF3 = false;
+        public SPECULARTERM = false;
+        public NORMAL = false;
+        public VERTEXCOLOR = false;
+        public VERTEXALPHA = false;
+        public BONES = false;
+        public BONES4 = false;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+
+        constructor() {
+            super();
+            this._keys = Object.keys(this);
+        }
+    }
+
+    export class TriPlanarMaterial extends Material {
+        public mixTexture: BaseTexture;
+        
+        public diffuseTextureX: Texture;
+        public diffuseTextureY: Texture;
+        public diffuseTextureZ: Texture;
+        
+        public normalTextureX: Texture;
+        public normalTextureY: Texture;
+        public normalTextureZ: Texture;
+        
+        public tileSize: number = 1;
+        
+        public diffuseColor = new Color3(1, 1, 1);
+        public specularColor = new Color3(0.2, 0.2, 0.2);
+        public specularPower = 64;
+        public disableLighting = false;
+
+        private _worldViewProjectionMatrix = Matrix.Zero();
+        private _scaledDiffuse = new Color3();
+        private _scaledSpecular = new Color3();
+        private _renderId: number;
+
+        private _defines = new TriPlanarMaterialDefines();
+        private _cachedDefines = new TriPlanarMaterialDefines();
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+
+            this._cachedDefines.BonesPerMesh = -1;
+        }
+
+        public needAlphaBlending(): boolean {
+            return (this.alpha < 1.0);
+        }
+
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
+        // Methods   
+        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (!mesh) {
+                return true;
+            }
+
+            if (this._defines.INSTANCES !== useInstances) {
+                return false;
+            }
+
+            if (mesh._materialDefines && mesh._materialDefines.isEqual(this._defines)) {
+                return true;
+            }
+
+            return false;
+        }
+
+        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (this.checkReadyOnlyOnce) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+
+            var scene = this.getScene();
+
+            if (!this.checkReadyOnEveryCall) {
+                if (this._renderId === scene.getRenderId()) {
+                    if (this._checkCache(scene, mesh, useInstances)) {
+                        return true;
+                    }
+                }
+            }
+
+            var engine = scene.getEngine();
+            var needNormals = false;
+
+            this._defines.reset();
+
+            // Textures
+            if (scene.texturesEnabled) {
+                if (StandardMaterial.DiffuseTextureEnabled) {
+                    var textures = [this.diffuseTextureX, this.diffuseTextureY, this.diffuseTextureZ];
+                    var textureDefines = ["DIFFUSEX", "DIFFUSEY", "DIFFUSEZ"];
+                    
+                    for (var i=0; i < textures.length; i++) {
+                        if (textures[i]) {
+                            if (!textures[i].isReady()) {
+                                return false;
+                            } else {
+                                this._defines[textureDefines[i]] = true;
+                            }
+                        }
+                    }
+                }
+                if (StandardMaterial.BumpTextureEnabled) {
+                    var textures = [this.normalTextureX, this.normalTextureY, this.normalTextureZ];
+                    var textureDefines = ["BUMPX", "BUMPY", "BUMPZ"];
+                    
+                    for (var i=0; i < textures.length; i++) {
+                        if (textures[i]) {
+                            if (!textures[i].isReady()) {
+                                return false;
+                            } else {
+                                this._defines[textureDefines[i]] = true;
+                            }
+                        }
+                    }
+                }
+            }
+
+            // Effect
+            if (scene.clipPlane) {
+                this._defines.CLIPPLANE = true;
+            }
+
+            if (engine.getAlphaTesting()) {
+                this._defines.ALPHATEST = true;
+            }
+
+            // Point size
+            if (this.pointsCloud || scene.forcePointsCloud) {
+                this._defines.POINTSIZE = true;
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
+                this._defines.FOG = true;
+            }
+
+            var lightIndex = 0;
+            if (scene.lightsEnabled && !this.disableLighting) {
+                for (var index = 0; index < scene.lights.length; index++) {
+                    var light = scene.lights[index];
+
+                    if (!light.isEnabled()) {
+                        continue;
+                    }
+
+                    // Excluded check
+                    if (light._excludedMeshesIds.length > 0) {
+                        for (var excludedIndex = 0; excludedIndex < light._excludedMeshesIds.length; excludedIndex++) {
+                            var excludedMesh = scene.getMeshByID(light._excludedMeshesIds[excludedIndex]);
+
+                            if (excludedMesh) {
+                                light.excludedMeshes.push(excludedMesh);
+                            }
+                        }
+
+                        light._excludedMeshesIds = [];
+                    }
+
+                    // Included check
+                    if (light._includedOnlyMeshesIds.length > 0) {
+                        for (var includedOnlyIndex = 0; includedOnlyIndex < light._includedOnlyMeshesIds.length; includedOnlyIndex++) {
+                            var includedOnlyMesh = scene.getMeshByID(light._includedOnlyMeshesIds[includedOnlyIndex]);
+
+                            if (includedOnlyMesh) {
+                                light.includedOnlyMeshes.push(includedOnlyMesh);
+                            }
+                        }
+
+                        light._includedOnlyMeshesIds = [];
+                    }
+
+                    if (!light.canAffectMesh(mesh)) {
+                        continue;
+                    }
+                    needNormals = true;
+                    this._defines["LIGHT" + lightIndex] = true;
+
+                    var type;
+                    if (light instanceof SpotLight) {
+                        type = "SPOTLIGHT" + lightIndex;
+                    } else if (light instanceof HemisphericLight) {
+                        type = "HEMILIGHT" + lightIndex;
+                    } else if (light instanceof PointLight) {
+                        type = "POINTLIGHT" + lightIndex;
+                    } else {
+                        type = "DIRLIGHT" + lightIndex;
+                    }
+
+                    this._defines[type] = true;
+                    
+                    // Specular
+                    if (!light.specular.equalsFloats(0, 0, 0)) {
+                        this._defines.SPECULARTERM = true;
+                    }
+
+                    // Shadows
+                    if (scene.shadowsEnabled) {
+                        var shadowGenerator = light.getShadowGenerator();
+                        if (mesh && mesh.receiveShadows && shadowGenerator) {
+                            this._defines["SHADOW" + lightIndex] = true;
+
+                            this._defines.SHADOWS = true;
+
+                            if (shadowGenerator.useVarianceShadowMap || shadowGenerator.useBlurVarianceShadowMap) {
+                                this._defines["SHADOWVSM" + lightIndex] = true;
+                            }
+
+                            if (shadowGenerator.usePoissonSampling) {
+                                this._defines["SHADOWPCF" + lightIndex] = true;
+                            }
+                        }
+                    }
+
+                    lightIndex++;
+                    if (lightIndex === maxSimultaneousLights)
+                        break;
+                }
+            }
+
+            // Attribs
+            if (mesh) {
+                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                    this._defines.NORMAL = true;
+                }
+                if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
+                    this._defines.VERTEXCOLOR = true;
+
+                    if (mesh.hasVertexAlpha) {
+                        this._defines.VERTEXALPHA = true;
+                    }
+                }
+                if (mesh.useBones && mesh.computeBonesUsingShaders) {
+                    this._defines.BONES = true;
+                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                    this._defines.BONES4 = true;
+                }
+
+                // Instances
+                if (useInstances) {
+                    this._defines.INSTANCES = true;
+                }
+            }
+
+            // Get correct effect      
+            if (!this._defines.isEqual(this._cachedDefines)) {
+                this._defines.cloneTo(this._cachedDefines);
+
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();             
+                if (this._defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+
+                for (lightIndex = 0; lightIndex < maxSimultaneousLights; lightIndex++) {
+                    if (!this._defines["LIGHT" + lightIndex]) {
+                        continue;
+                    }
+
+                    if (lightIndex > 0) {
+                        fallbacks.addFallback(lightIndex, "LIGHT" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOW" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOW" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOWPCF" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOWPCF" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOWVSM" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOWVSM" + lightIndex);
+                    }
+                }
+             
+                if (this._defines.BONES4) {
+                    fallbacks.addFallback(0, "BONES4");
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (this._defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (this._defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                if (this._defines.BONES) {
+                    attribs.push(VertexBuffer.MatricesIndicesKind);
+                    attribs.push(VertexBuffer.MatricesWeightsKind);
+                }
+
+                if (this._defines.INSTANCES) {
+                    attribs.push("world0");
+                    attribs.push("world1");
+                    attribs.push("world2");
+                    attribs.push("world3");
+                }
+
+                // Legacy browser patch
+                var shaderName = "triplanar";
+                var join = this._defines.toString();
+                this._effect = scene.getEngine().createEffect(shaderName,
+                    attribs,
+                    ["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",
+                        "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                        "vFogInfos", "vFogColor", "pointSize",
+                        "mBones",
+                        "vClipPlane",
+                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
+                        "tileSize"
+                    ],
+                    ["diffuseSamplerX", "diffuseSamplerY", "diffuseSamplerZ",
+                        "normalSamplerX", "normalSamplerY", "normalSamplerZ",
+                        "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
+                    ],
+                    join, fallbacks, this.onCompiled, this.onError);
+            }
+            if (!this._effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            if (mesh) {
+                if (!mesh._materialDefines) {
+                    mesh._materialDefines = new TriPlanarMaterialDefines();
+                }
+
+                this._defines.cloneTo(mesh._materialDefines);
+            }
+
+            return true;
+        }
+
+        public bindOnlyWorldMatrix(world: Matrix): void {
+            this._effect.setMatrix("world", world);
+        }
+
+        public bind(world: Matrix, mesh?: Mesh): void {
+            var scene = this.getScene();
+
+            // Matrices        
+            this.bindOnlyWorldMatrix(world);
+            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
+                this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
+            }
+            
+            this._effect.setFloat("tileSize", this.tileSize);
+
+            if (scene.getCachedMaterial() !== this) {
+                // Textures        
+                if (this.diffuseTextureX) {
+                    this._effect.setTexture("diffuseSamplerX", this.diffuseTextureX);
+                }
+                if (this.diffuseTextureY) {
+                    this._effect.setTexture("diffuseSamplerY", this.diffuseTextureY);
+                }
+                if (this.diffuseTextureZ) {
+                    this._effect.setTexture("diffuseSamplerZ", this.diffuseTextureZ);
+                }
+                if (this.normalTextureX) {
+                    this._effect.setTexture("normalSamplerX", this.normalTextureX);
+                }
+                if (this.normalTextureY) {
+                    this._effect.setTexture("normalSamplerY", this.normalTextureY);
+                }
+                if (this.normalTextureZ) {
+                    this._effect.setTexture("normalSamplerZ", this.normalTextureZ);
+                }
+                // Clip plane
+                if (scene.clipPlane) {
+                    var clipPlane = scene.clipPlane;
+                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
+                }
+
+                // Point size
+                if (this.pointsCloud) {
+                    this._effect.setFloat("pointSize", this.pointSize);
+                }
+
+                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+            }
+
+            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;
+                for (var index = 0; index < scene.lights.length; index++) {
+                    var light = scene.lights[index];
+
+                    if (!light.isEnabled()) {
+                        continue;
+                    }
+
+                    if (!light.canAffectMesh(mesh)) {
+                        continue;
+                    }
+
+                    if (light instanceof PointLight) {
+                        // Point Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex);
+                    } else if (light instanceof DirectionalLight) {
+                        // Directional Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex);
+                    } else if (light instanceof SpotLight) {
+                        // Spot Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightDirection" + lightIndex);
+                    } else if (light instanceof HemisphericLight) {
+                        // Hemispheric Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightGround" + lightIndex);
+                    }
+
+                    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) {
+                        var shadowGenerator = light.getShadowGenerator();
+                        if (mesh.receiveShadows && shadowGenerator) {
+                            this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
+                            this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
+                            this._effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.getShadowMap().getSize().width, shadowGenerator.bias);
+                        }
+                    }
+
+                    lightIndex++;
+
+                    if (lightIndex === maxSimultaneousLights)
+                        break;
+                }
+            }
+
+            // View
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setMatrix("view", scene.getViewMatrix());
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
+                this._effect.setColor3("vFogColor", scene.fogColor);
+            }
+
+            super.bind(world, mesh);
+        }
+
+        public getAnimatables(): IAnimatable[] {
+            var results = [];
+
+            if (this.mixTexture && this.mixTexture.animations && this.mixTexture.animations.length > 0) {
+                results.push(this.mixTexture);
+            }
+
+            return results;
+        }
+
+        public dispose(forceDisposeEffect?: boolean): void {
+            if (this.mixTexture) {
+                this.mixTexture.dispose();
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        public clone(name: string): TriPlanarMaterial {
+            var newMaterial = new TriPlanarMaterial(name, this.getScene());
+
+            // Base material
+            this.copyTo(newMaterial);
+
+            // Simple material
+            if (this.mixTexture && this.mixTexture.clone) {
+                newMaterial.mixTexture = this.mixTexture.clone();
+            }
+
+            newMaterial.diffuseColor = this.diffuseColor.clone();
+            return newMaterial;
+        }
+		
+		public serialize(): any {
+		
+            var serializationObject = super.serialize();
+            serializationObject.customType      = "BABYLON.TerrainMaterial";
+            serializationObject.diffuseColor    = this.diffuseColor.asArray();
+			serializationObject.specularColor   = this.specularColor.asArray();
+            serializationObject.specularPower   = this.specularPower;
+            serializationObject.disableLighting = this.disableLighting;
+
+            if (this.diffuseTextureX) {
+                serializationObject.diffuseTextureX = this.diffuseTextureX.serialize();
+            }
+			
+			if (this.diffuseTextureY) {
+                serializationObject.diffuseTextureY = this.diffuseTextureY.serialize();
+            }
+			
+			if (this.diffuseTextureZ) {
+                serializationObject.diffuseTextureZ = this.diffuseTextureZ.serialize();
+            }
+
+            return serializationObject;
+        }
+
+        public static Parse(source: any, scene: Scene, rootUrl: string): TriPlanarMaterial {
+            var material = new TriPlanarMaterial(source.name, scene);
+
+            material.diffuseColor   = Color3.FromArray(source.diffuseColor);
+			material.specularColor   = Color3.FromArray(source.specularColor);
+            material.specularPower          = source.specularPower;
+            material.disableLighting    = source.disableLighting;
+
+            material.alpha          = source.alpha;
+
+            material.id             = source.id;
+
+            Tags.AddTagsTo(material, source.tags);
+            material.backFaceCulling = source.backFaceCulling;
+            material.wireframe = source.wireframe;
+
+            if (source.diffuseTextureX) {
+                material.diffuseTextureX = <Texture>Texture.Parse(source.diffuseTextureX, scene, rootUrl);
+            }
+			
+			if (source.diffuseTextureY) {
+                material.diffuseTextureY = <Texture>Texture.Parse(source.diffuseTextureY, scene, rootUrl);
+            }
+
+			if (source.diffuseTextureZ) {
+                material.diffuseTextureZ = <Texture>Texture.Parse(source.diffuseTextureZ, scene, rootUrl);
+            }
+
+            return material;
+        }
+    }
+} 
+

+ 686 - 0
materialsLibrary/materials/triPlanar/triplanar.fragment.fx

@@ -0,0 +1,686 @@
+precision highp float;
+
+// Constants
+uniform vec3 vEyePosition;
+uniform vec4 vDiffuseColor;
+
+#ifdef SPECULARTERM
+uniform vec4 vSpecularColor;
+#endif
+
+// Input
+varying vec3 vPositionW;
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+// Lights
+#ifdef LIGHT0
+uniform vec4 vLightData0;
+uniform vec4 vLightDiffuse0;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular0;
+#endif
+#ifdef SHADOW0
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+varying vec4 vPositionFromLight0;
+uniform sampler2D shadowSampler0;
+#else
+uniform samplerCube shadowSampler0;
+#endif
+uniform vec3 shadowsInfo0;
+#endif
+#ifdef SPOTLIGHT0
+uniform vec4 vLightDirection0;
+#endif
+#ifdef HEMILIGHT0
+uniform vec3 vLightGround0;
+#endif
+#endif
+
+#ifdef LIGHT1
+uniform vec4 vLightData1;
+uniform vec4 vLightDiffuse1;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular1;
+#endif
+#ifdef SHADOW1
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+varying vec4 vPositionFromLight1;
+uniform sampler2D shadowSampler1;
+#else
+uniform samplerCube shadowSampler1;
+#endif
+uniform vec3 shadowsInfo1;
+#endif
+#ifdef SPOTLIGHT1
+uniform vec4 vLightDirection1;
+#endif
+#ifdef HEMILIGHT1
+uniform vec3 vLightGround1;
+#endif
+#endif
+
+#ifdef LIGHT2
+uniform vec4 vLightData2;
+uniform vec4 vLightDiffuse2;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular2;
+#endif
+#ifdef SHADOW2
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+varying vec4 vPositionFromLight2;
+uniform sampler2D shadowSampler2;
+#else
+uniform samplerCube shadowSampler2;
+#endif
+uniform vec3 shadowsInfo2;
+#endif
+#ifdef SPOTLIGHT2
+uniform vec4 vLightDirection2;
+#endif
+#ifdef HEMILIGHT2
+uniform vec3 vLightGround2;
+#endif
+#endif
+
+#ifdef LIGHT3
+uniform vec4 vLightData3;
+uniform vec4 vLightDiffuse3;
+#ifdef SPECULARTERM
+uniform vec3 vLightSpecular3;
+#endif
+#ifdef SHADOW3
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+varying vec4 vPositionFromLight3;
+uniform sampler2D shadowSampler3;
+#else
+uniform samplerCube shadowSampler3;
+#endif
+uniform vec3 shadowsInfo3;
+#endif
+#ifdef SPOTLIGHT3
+uniform vec4 vLightDirection3;
+#endif
+#ifdef HEMILIGHT3
+uniform vec3 vLightGround3;
+#endif
+#endif
+
+// Samplers
+#ifdef DIFFUSEX
+varying vec2 vTextureUVX;
+uniform sampler2D diffuseSamplerX;
+#ifdef BUMPX
+uniform sampler2D normalSamplerX;
+#endif
+#endif
+
+#ifdef DIFFUSEY
+varying vec2 vTextureUVY;
+uniform sampler2D diffuseSamplerY;
+#ifdef BUMPY
+uniform sampler2D normalSamplerY;
+#endif
+#endif
+
+#ifdef DIFFUSEZ
+varying vec2 vTextureUVZ;
+uniform sampler2D diffuseSamplerZ;
+#ifdef BUMPZ
+uniform sampler2D normalSamplerZ;
+#endif
+#endif
+
+#ifdef NORMAL
+varying mat3 tangentSpace;
+#endif
+
+// Shadows
+#ifdef SHADOWS
+
+float unpack(vec4 color)
+{
+	const vec4 bit_shift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
+	return dot(color, bit_shift);
+}
+
+#if defined(POINTLIGHT0) || defined(POINTLIGHT1) || defined(POINTLIGHT2) || defined(POINTLIGHT3)
+float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float bias)
+{
+	vec3 directionToLight = vPositionW - lightPosition;
+	float depth = length(directionToLight);
+	depth = clamp(depth, 0., 1.0);
+
+	directionToLight = normalize(directionToLight);
+	directionToLight.y = - directionToLight.y;
+
+	float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
+
+	if (depth > shadow)
+	{
+		return darkness;
+	}
+	return 1.0;
+}
+
+float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float bias, float darkness)
+{
+	vec3 directionToLight = vPositionW - lightPosition;
+	float depth = length(directionToLight);
+
+	depth = clamp(depth, 0., 1.0);
+	float diskScale = 2.0 / mapSize;
+
+	directionToLight = normalize(directionToLight);
+	directionToLight.y = -directionToLight.y;
+
+	float visibility = 1.;
+
+	vec3 poissonDisk[4];
+	poissonDisk[0] = vec3(-1.0, 1.0, -1.0);
+	poissonDisk[1] = vec3(1.0, -1.0, -1.0);
+	poissonDisk[2] = vec3(-1.0, -1.0, -1.0);
+	poissonDisk[3] = vec3(1.0, -1.0, 1.0);
+
+	// Poisson Sampling
+	float biasedDepth = depth - bias;
+
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[0] * diskScale)) < biasedDepth) visibility -= 0.25;
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[1] * diskScale)) < biasedDepth) visibility -= 0.25;
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[2] * diskScale)) < biasedDepth) visibility -= 0.25;
+	if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[3] * diskScale)) < biasedDepth) visibility -= 0.25;
+
+	return  min(1.0, visibility + darkness);
+}
+#endif
+
+#if defined(SPOTLIGHT0) || defined(SPOTLIGHT1) || defined(SPOTLIGHT2) || defined(SPOTLIGHT3) ||  defined(DIRLIGHT0) || defined(DIRLIGHT1) || defined(DIRLIGHT2) || defined(DIRLIGHT3)
+float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness, float bias)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	float shadow = unpack(texture2D(shadowSampler, uv)) + bias;
+
+	if (depth.z > shadow)
+	{
+		return darkness;
+	}
+	return 1.;
+}
+
+float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, float mapSize, float bias, float darkness)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	float visibility = 1.;
+
+	vec2 poissonDisk[4];
+	poissonDisk[0] = vec2(-0.94201624, -0.39906216);
+	poissonDisk[1] = vec2(0.94558609, -0.76890725);
+	poissonDisk[2] = vec2(-0.094184101, -0.92938870);
+	poissonDisk[3] = vec2(0.34495938, 0.29387760);
+
+	// Poisson Sampling
+	float biasedDepth = depth.z - bias;
+
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] / mapSize)) < biasedDepth) visibility -= 0.25;
+
+	return  min(1.0, visibility + darkness);
+}
+
+// Thanks to http://devmaster.net/
+float unpackHalf(vec2 color)
+{
+	return color.x + (color.y / 255.0);
+}
+
+float linstep(float low, float high, float v) {
+	return clamp((v - low) / (high - low), 0.0, 1.0);
+}
+
+float ChebychevInequality(vec2 moments, float compare, float bias)
+{
+	float p = smoothstep(compare - bias, compare, moments.x);
+	float variance = max(moments.y - moments.x * moments.x, 0.02);
+	float d = compare - moments.x;
+	float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
+
+	return clamp(max(p, p_max), 0.0, 1.0);
+}
+
+float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias, float darkness)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z >= 1.0)
+	{
+		return 1.0;
+	}
+
+	vec4 texel = texture2D(shadowSampler, uv);
+
+	vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
+	return min(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness);
+}
+#endif
+#endif
+
+
+#ifdef CLIPPLANE
+varying float fClipDistance;
+#endif
+
+// Fog
+#ifdef FOG
+
+#define FOGMODE_NONE    0.
+#define FOGMODE_EXP     1.
+#define FOGMODE_EXP2    2.
+#define FOGMODE_LINEAR  3.
+#define E 2.71828
+
+uniform vec4 vFogInfos;
+uniform vec3 vFogColor;
+varying float fFogDistance;
+
+float CalcFogFactor()
+{
+	float fogCoeff = 1.0;
+	float fogStart = vFogInfos.y;
+	float fogEnd = vFogInfos.z;
+	float fogDensity = vFogInfos.w;
+
+	if (FOGMODE_LINEAR == vFogInfos.x)
+	{
+		fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);
+	}
+	else if (FOGMODE_EXP == vFogInfos.x)
+	{
+		fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);
+	}
+	else if (FOGMODE_EXP2 == vFogInfos.x)
+	{
+		fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);
+	}
+
+	return clamp(fogCoeff, 0.0, 1.0);
+}
+#endif
+
+// Light Computing
+struct lightingInfo
+{
+	vec3 diffuse;
+#ifdef SPECULARTERM
+	vec3 specular;
+#endif
+};
+
+lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float glossiness) {
+	lightingInfo result;
+
+	vec3 lightVectorW;
+	float attenuation = 1.0;
+	if (lightData.w == 0.)
+	{
+		vec3 direction = lightData.xyz - vPositionW;
+
+		attenuation = max(0., 1.0 - length(direction) / range);
+		lightVectorW = normalize(direction);
+	}
+	else
+	{
+		lightVectorW = normalize(-lightData.xyz);
+	}
+
+	// diffuse
+	float ndl = max(0., dot(vNormal, lightVectorW));
+	result.diffuse = ndl * diffuseColor * attenuation;
+
+#ifdef SPECULARTERM
+	// Specular
+	vec3 angleW = normalize(viewDirectionW + lightVectorW);
+	float specComp = max(0., dot(vNormal, angleW));
+	specComp = pow(specComp, max(1., glossiness));
+
+	result.specular = specComp * specularColor * attenuation;
+#endif
+	return result;
+}
+
+lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float range, float glossiness) {
+	lightingInfo result;
+
+	vec3 direction = lightData.xyz - vPositionW;
+	vec3 lightVectorW = normalize(direction);
+	float attenuation = max(0., 1.0 - length(direction) / range);
+
+	// diffuse
+	float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));
+	float spotAtten = 0.0;
+
+	if (cosAngle >= lightDirection.w)
+	{
+		cosAngle = max(0., pow(cosAngle, lightData.w));
+		spotAtten = clamp((cosAngle - lightDirection.w) / (1. - cosAngle), 0.0, 1.0);
+
+		// Diffuse
+		float ndl = max(0., dot(vNormal, -lightDirection.xyz));
+		result.diffuse = ndl * spotAtten * diffuseColor * attenuation;
+
+#ifdef SPECULARTERM
+		// Specular
+		vec3 angleW = normalize(viewDirectionW - lightDirection.xyz);
+		float specComp = max(0., dot(vNormal, angleW));
+		specComp = pow(specComp, max(1., glossiness));
+
+		result.specular = specComp * specularColor * 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 specularColor, vec3 groundColor, float glossiness) {
+	lightingInfo result;
+
+	// Diffuse
+	float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+	result.diffuse = mix(groundColor, diffuseColor, ndl);
+
+#ifdef SPECULARTERM
+	// Specular
+	vec3 angleW = normalize(viewDirectionW + lightData.xyz);
+	float specComp = max(0., dot(vNormal, angleW));
+	specComp = pow(specComp, max(1., glossiness));
+
+	result.specular = specComp * specularColor;
+#endif
+
+	return result;
+}
+
+void main(void) {
+	// Clip plane
+#ifdef CLIPPLANE
+	if (fClipDistance > 0.0)
+		discard;
+#endif
+
+	vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
+
+	// Base color
+	vec4 baseColor = vec4(0., 0., 0., 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;
+	
+	// Bump
+#ifdef NORMAL
+	vec3 normalW = tangentSpace[2];
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+	vec4 baseNormal = vec4(0.0, 0.0, 0.0, 1.0);
+	normalW *= normalW;
+
+#ifdef DIFFUSEX
+	baseColor += texture2D(diffuseSamplerX, vTextureUVX) * normalW.x;
+#ifdef BUMPX
+	baseNormal += texture2D(normalSamplerX, vTextureUVX) * normalW.x;
+#endif
+#endif
+
+#ifdef DIFFUSEY
+	baseColor += texture2D(diffuseSamplerY, vTextureUVY) * normalW.y;
+#ifdef BUMPY
+	baseNormal += texture2D(normalSamplerY, vTextureUVY) * normalW.y;
+#endif
+#endif
+
+#ifdef DIFFUSEZ
+	baseColor += texture2D(diffuseSamplerZ, vTextureUVZ) * normalW.z;
+#ifdef BUMPZ
+	baseNormal += texture2D(normalSamplerZ, vTextureUVZ) * normalW.z;
+#endif
+#endif
+
+#ifdef NORMAL
+	normalW = normalize((2.0 * baseNormal.xyz - 1.0) * tangentSpace);
+#endif
+
+#ifdef ALPHATEST
+	if (baseColor.a < 0.4)
+		discard;
+#endif
+
+#ifdef VERTEXCOLOR
+	baseColor.rgb *= vColor.rgb;
+#endif
+
+	// 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, vLightSpecular0, vLightDiffuse0.a, glossiness);
+#endif
+#ifdef HEMILIGHT0
+	lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, glossiness);
+#endif
+#if defined(POINTLIGHT0) || defined(DIRLIGHT0)
+	lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, glossiness);
+#endif
+#ifdef SHADOW0
+#ifdef SHADOWVSM0
+	shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0, shadowsInfo0.z, shadowsInfo0.x);
+#else
+#ifdef SHADOWPCF0
+#if defined(POINTLIGHT0)
+	shadow = computeShadowWithPCFCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z, shadowsInfo0.x);
+#else
+	shadow = computeShadowWithPCF(vPositionFromLight0, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z, shadowsInfo0.x);
+#endif
+#else
+#if defined(POINTLIGHT0)
+	shadow = computeShadowCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
+#else
+	shadow = computeShadow(vPositionFromLight0, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
+#endif
+#endif
+#endif
+#else
+	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, vLightSpecular1, vLightDiffuse1.a, glossiness);
+#endif
+#ifdef HEMILIGHT1
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1, glossiness);
+#endif
+#if defined(POINTLIGHT1) || defined(DIRLIGHT1)
+	info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, glossiness);
+#endif
+#ifdef SHADOW1
+#ifdef SHADOWVSM1
+	shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1, shadowsInfo1.z, shadowsInfo1.x);
+#else
+#ifdef SHADOWPCF1
+#if defined(POINTLIGHT1)
+	shadow = computeShadowWithPCFCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z, shadowsInfo1.x);
+#else
+	shadow = computeShadowWithPCF(vPositionFromLight1, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z, shadowsInfo1.x);
+#endif
+#else
+#if defined(POINTLIGHT1)
+	shadow = computeShadowCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
+#else
+	shadow = computeShadow(vPositionFromLight1, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
+#endif
+#endif
+#endif
+#else
+	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, vLightSpecular2, vLightDiffuse2.a, glossiness);
+#endif
+#ifdef HEMILIGHT2
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, glossiness);
+#endif
+#if defined(POINTLIGHT2) || defined(DIRLIGHT2)
+	info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, glossiness);
+#endif
+#ifdef SHADOW2
+#ifdef SHADOWVSM2
+	shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2, shadowsInfo2.z, shadowsInfo2.x);
+#else
+#ifdef SHADOWPCF2
+#if defined(POINTLIGHT2)
+	shadow = computeShadowWithPCFCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z, shadowsInfo2.x);
+#else
+	shadow = computeShadowWithPCF(vPositionFromLight2, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z, shadowsInfo2.x);
+#endif
+#else
+#if defined(POINTLIGHT2)
+	shadow = computeShadowCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
+#else
+	shadow = computeShadow(vPositionFromLight2, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
+#endif
+#endif	
+#endif	
+#else
+	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, vLightSpecular3, vLightDiffuse3.a, glossiness);
+#endif
+#ifdef HEMILIGHT3
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, glossiness);
+#endif
+#if defined(POINTLIGHT3) || defined(DIRLIGHT3)
+	info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, glossiness);
+#endif
+#ifdef SHADOW3
+#ifdef SHADOWVSM3
+	shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3, shadowsInfo3.z, shadowsInfo3.x);
+#else
+#ifdef SHADOWPCF3
+#if defined(POINTLIGHT3)
+	shadow = computeShadowWithPCFCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z, shadowsInfo3.x);
+#else
+	shadow = computeShadowWithPCF(vPositionFromLight3, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z, shadowsInfo3.x);
+#endif
+#else
+#if defined(POINTLIGHT3)
+	shadow = computeShadowCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
+#else
+	shadow = computeShadow(vPositionFromLight3, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
+#endif
+#endif	
+#endif	
+#else
+	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 + finalSpecular, alpha);
+
+#ifdef FOG
+	float fog = CalcFogFactor();
+	color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;
+#endif
+
+	gl_FragColor = color;
+}

+ 190 - 0
materialsLibrary/materials/triPlanar/triplanar.vertex.fx

@@ -0,0 +1,190 @@
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+#ifdef NORMAL
+attribute vec3 normal;
+#endif
+#ifdef VERTEXCOLOR
+attribute vec4 color;
+#endif
+#ifdef BONES
+attribute vec4 matricesIndices;
+attribute vec4 matricesWeights;
+#endif
+
+// Uniforms
+
+#ifdef INSTANCES
+attribute vec4 world0;
+attribute vec4 world1;
+attribute vec4 world2;
+attribute vec4 world3;
+#else
+uniform mat4 world;
+#endif
+
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef DIFFUSEX
+varying vec2 vTextureUVX;
+#endif
+
+#ifdef DIFFUSEY
+varying vec2 vTextureUVY;
+#endif
+
+#ifdef DIFFUSEZ
+varying vec2 vTextureUVZ;
+#endif
+
+uniform float tileSize;
+
+#ifdef BONES
+uniform mat4 mBones[BonesPerMesh];
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying mat3 tangentSpace;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+#ifdef CLIPPLANE
+uniform vec4 vClipPlane;
+varying float fClipDistance;
+#endif
+
+#ifdef FOG
+varying float fFogDistance;
+#endif
+
+#ifdef SHADOWS
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+uniform mat4 lightMatrix0;
+varying vec4 vPositionFromLight0;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+uniform mat4 lightMatrix1;
+varying vec4 vPositionFromLight1;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+uniform mat4 lightMatrix2;
+varying vec4 vPositionFromLight2;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+uniform mat4 lightMatrix3;
+varying vec4 vPositionFromLight3;
+#endif
+#endif
+
+void main(void) {
+	mat4 finalWorld;
+
+#ifdef INSTANCES
+	finalWorld = mat4(world0, world1, world2, world3);
+#else
+	finalWorld = world;
+#endif
+
+#ifdef BONES
+	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
+	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
+	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
+
+#ifdef BONES4
+	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
+	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
+#else
+	finalWorld = finalWorld * (m0 + m1 + m2);
+#endif 
+
+#endif
+	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef DIFFUSEX
+	vTextureUVX = worldPos.zy / tileSize;
+#endif
+
+#ifdef DIFFUSEY
+	vTextureUVY = worldPos.xz / tileSize;
+#endif
+
+#ifdef DIFFUSEZ
+	vTextureUVZ = worldPos.xy / tileSize;
+#endif
+
+#ifdef NORMAL
+	// Compute tangent space (used for normal mapping + tri planar color mapping)
+	vec3 xtan = vec3(0,0,1);//tangent space for the X aligned plane
+   	vec3 xbin = vec3(0,1,0);
+   
+   	vec3 ytan = vec3(1,0,0);//tangent space for the Y aligned plane
+   	vec3 ybin = vec3(0,0,1);
+   
+   	vec3 ztan = vec3(1,0,0);//tangent space for the Z aligned plane
+   	vec3 zbin = vec3(0,1,0);
+	   
+	vec3 normalizedNormal = normalize(normal);
+   	normalizedNormal *= normalizedNormal;
+
+	vec3 worldBinormal = normalize(xbin * normalizedNormal.x + ybin * normalizedNormal.y + zbin * normalizedNormal.z);
+   	vec3 worldTangent = normalize(xtan * normalizedNormal.x + ytan * normalizedNormal.y + ztan * normalizedNormal.z);
+	   
+	worldTangent = (world * vec4(worldTangent, 1.0)).xyz;
+    worldBinormal = (world * vec4(worldBinormal, 1.0)).xyz;
+	vec3 worldNormal = normalize(cross(worldTangent, worldBinormal));
+
+	tangentSpace[0] = worldTangent;
+    tangentSpace[1] = worldBinormal;
+    tangentSpace[2] = worldNormal;
+#endif
+
+	// Clip plane
+#ifdef CLIPPLANE
+	fClipDistance = dot(worldPos, vClipPlane);
+#endif
+
+	// Fog
+#ifdef FOG
+	fFogDistance = (view * worldPos).z;
+#endif
+
+	// Shadows
+#ifdef SHADOWS
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+	vPositionFromLight0 = lightMatrix0 * worldPos;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+	vPositionFromLight1 = lightMatrix1 * worldPos;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+	vPositionFromLight2 = lightMatrix2 * worldPos;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+	vPositionFromLight3 = lightMatrix3 * worldPos;
+#endif
+#endif
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+
+	// Point size
+#ifdef POINTSIZE
+	gl_PointSize = pointSize;
+#endif
+}

+ 64 - 1
materialsLibrary/materials/water/babylon.waterMaterial.ts

@@ -128,7 +128,7 @@ module BABYLON {
 		/**
 		* Constructor
 		*/
-		constructor(name: string, scene: Scene, renderTargetSize: Vector2 = new Vector2(512, 512)) {
+		constructor(name: string, scene: Scene, public renderTargetSize: Vector2 = new Vector2(512, 512)) {
             super(name, scene);
 			
 			// Create render targets
@@ -720,6 +720,69 @@ module BABYLON {
             return newMaterial;
         }
         
+		public serialize(): any {
+		        		
+            var serializationObject = super.serialize();
+			
+             serializationObject.customType         = "BABYLON.WaterMaterial";
+            serializationObject.diffuseColor    	= this.diffuseColor.asArray();
+			serializationObject.specularColor   	= this.specularColor.asArray();
+            serializationObject.specularPower   	= this.specularPower;
+            serializationObject.disableLighting 	= this.disableLighting;
+            serializationObject.windForce     		= this.windForce;
+            serializationObject.windDirection 		= this.windDirection.asArray();
+            serializationObject.waveHeight      	= this.waveHeight;
+            serializationObject.bumpHeight 			= this.bumpHeight;
+			serializationObject.waterColor 			= this.waterColor.asArray();
+			serializationObject.colorBlendFactor	= this.colorBlendFactor;
+			serializationObject.waveLength 			= this.waveLength;
+			serializationObject.renderTargetSize	= this.renderTargetSize.asArray();
+			
+            if (this.bumpTexture) {
+                serializationObject.bumpTexture 	= this.bumpTexture.serialize();
+            }
+
+            return serializationObject;
+        }
+
+        public static Parse(source: any, scene: Scene, rootUrl: string): WaterMaterial {
+		
+			var renderTargetSize = source.renderTargetSize ? Vector2.FromArray(source.renderTargetSize) : null;
+		
+            var material = new WaterMaterial(source.name, scene, renderTargetSize);
+
+            material.diffuseColor    	= Color3.FromArray(source.diffuseColor);
+			material.specularColor   	= Color3.FromArray(source.specularColor);
+            material.specularPower   	= source.specularPower;
+            material.disableLighting 	= source.disableLighting;
+            material.windForce     		= source.windForce;
+            material.windDirection 		= Vector2.FromArray(source.windDirection);
+            material.waveHeight      	= source.waveHeight;
+            material.bumpHeight 		= source.bumpHeight;
+			material.waterColor 		= Color3.FromArray(source.waterColor);
+			material.colorBlendFactor	= source.colorBlendFactor;
+			material.waveLength 		= source.waveLength;
+			material.renderTargetSize	= Vector2.FromArray(source.renderTargetSize);
+
+            material.alpha          = source.alpha;
+
+            material.id             = source.id;
+
+            Tags.AddTagsTo(material, source.tags);
+            material.backFaceCulling = source.backFaceCulling;
+            material.wireframe = source.wireframe;
+
+            if (source.bumpTexture) {
+                material.bumpTexture = Texture.Parse(source.bumpTexture, scene, rootUrl);
+            }
+
+            if (source.checkReadyOnlyOnce) {
+                material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;
+            }
+
+            return material;
+        }
+		
 		public static CreateDefaultMesh(name: string, scene: Scene): Mesh {
 			var mesh = Mesh.CreateGround(name, 512, 512, 32, scene, false);
 			return mesh;

File diff suppressed because it is too large
+ 695 - 693
materialsLibrary/materials/water/water.fragment.fx


+ 209 - 209
materialsLibrary/materials/water/water.vertex.fx

@@ -1,209 +1,209 @@
-precision highp float;
-
-// Attributes
-attribute vec3 position;
-#ifdef NORMAL
-attribute vec3 normal;
-#endif
-#ifdef UV1
-attribute vec2 uv;
-#endif
-#ifdef UV2
-attribute vec2 uv2;
-#endif
-#ifdef VERTEXCOLOR
-attribute vec4 color;
-#endif
-#ifdef BONES
-attribute vec4 matricesIndices;
-attribute vec4 matricesWeights;
-#endif
-
-// Uniforms
-
-#ifdef INSTANCES
-attribute vec4 world0;
-attribute vec4 world1;
-attribute vec4 world2;
-attribute vec4 world3;
-#else
-uniform mat4 world;
-#endif
-
-uniform mat4 view;
-uniform mat4 viewProjection;
-
-#ifdef BUMP
-varying vec2 vNormalUV;
-uniform mat4 normalMatrix;
-uniform vec2 vNormalInfos;
-#endif
-
-#ifdef BONES
-uniform mat4 mBones[BonesPerMesh];
-#endif
-
-#ifdef POINTSIZE
-uniform float pointSize;
-#endif
-
-// Output
-varying vec3 vPositionW;
-#ifdef NORMAL
-varying vec3 vNormalW;
-#endif
-
-#ifdef VERTEXCOLOR
-varying vec4 vColor;
-#endif
-
-#ifdef CLIPPLANE
-uniform vec4 vClipPlane;
-varying float fClipDistance;
-#endif
-
-#ifdef FOG
-varying float fFogDistance;
-#endif
-
-#ifdef SHADOWS
-#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
-uniform mat4 lightMatrix0;
-varying vec4 vPositionFromLight0;
-#endif
-#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
-uniform mat4 lightMatrix1;
-varying vec4 vPositionFromLight1;
-#endif
-#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
-uniform mat4 lightMatrix2;
-varying vec4 vPositionFromLight2;
-#endif
-#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
-uniform mat4 lightMatrix3;
-varying vec4 vPositionFromLight3;
-#endif
-#endif
-
-// Water uniforms
-uniform mat4 worldReflectionViewProjection;
-uniform vec2 windDirection;
-uniform float waveLength;
-uniform float time;
-uniform float windForce;
-uniform float waveHeight;
-uniform float waveSpeed;
-
-// Water varyings
-varying vec3 vPosition;
-varying vec3 vRefractionMapTexCoord;
-varying vec3 vReflectionMapTexCoord;
-
-void main(void) {
-	mat4 finalWorld;
-
-#ifdef INSTANCES
-	finalWorld = mat4(world0, world1, world2, world3);
-#else
-	finalWorld = world;
-#endif
-
-#ifdef BONES
-	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
-	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
-	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
-
-#ifdef BONES4
-	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
-	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
-#else
-	finalWorld = finalWorld * (m0 + m1 + m2);
-#endif 
-
-#endif
-
-	vec4 worldPos = finalWorld * vec4(position, 1.0);
-	vPositionW = vec3(worldPos);
-
-#ifdef NORMAL
-	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
-#endif
-
-	// Texture coordinates
-#ifndef UV1
-	vec2 uv = vec2(0., 0.);
-#endif
-#ifndef UV2
-	vec2 uv2 = vec2(0., 0.);
-#endif
-
-#ifdef BUMP
-	if (vNormalInfos.x == 0.)
-	{
-		vNormalUV = vec2(normalMatrix * vec4((uv * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
-	}
-	else
-	{
-		vNormalUV = vec2(normalMatrix * vec4((uv2 * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
-	}
-#endif
-
-	// Clip plane
-#ifdef CLIPPLANE
-	fClipDistance = dot(worldPos, vClipPlane);
-#endif
-
-	// Fog
-#ifdef FOG
-	fFogDistance = (view * worldPos).z;
-#endif
-
-	// Shadows
-#ifdef SHADOWS
-#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
-	vPositionFromLight0 = lightMatrix0 * worldPos;
-#endif
-#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
-	vPositionFromLight1 = lightMatrix1 * worldPos;
-#endif
-#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
-	vPositionFromLight2 = lightMatrix2 * worldPos;
-#endif
-#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
-	vPositionFromLight3 = lightMatrix3 * worldPos;
-#endif
-#endif
-
-	// Vertex color
-#ifdef VERTEXCOLOR
-	vColor = color;
-#endif
-
-	// Point size
-#ifdef POINTSIZE
-	gl_PointSize = pointSize;
-#endif
-
-	vec3 p = position;
-	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);
-
-#ifdef REFLECTION
-	worldPos = viewProjection * finalWorld * vec4(p, 1.0);
-	
-	// Water
-	vPosition = position;
-	
-	vRefractionMapTexCoord.x = 0.5 * (worldPos.w + worldPos.x);
-	vRefractionMapTexCoord.y = 0.5 * (worldPos.w + worldPos.y);
-	vRefractionMapTexCoord.z = worldPos.w;
-	
-	worldPos = worldReflectionViewProjection * vec4(position, 1.0);
-	vReflectionMapTexCoord.x = 0.5 * (worldPos.w + worldPos.x);
-	vReflectionMapTexCoord.y = 0.5 * (worldPos.w + worldPos.y);
-	vReflectionMapTexCoord.z = worldPos.w;
-#endif
-}
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+#ifdef NORMAL
+attribute vec3 normal;
+#endif
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#ifdef VERTEXCOLOR
+attribute vec4 color;
+#endif
+#ifdef BONES
+attribute vec4 matricesIndices;
+attribute vec4 matricesWeights;
+#endif
+
+// Uniforms
+
+#ifdef INSTANCES
+attribute vec4 world0;
+attribute vec4 world1;
+attribute vec4 world2;
+attribute vec4 world3;
+#else
+uniform mat4 world;
+#endif
+
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef BUMP
+varying vec2 vNormalUV;
+uniform mat4 normalMatrix;
+uniform vec2 vNormalInfos;
+#endif
+
+#ifdef BONES
+uniform mat4 mBones[BonesPerMesh];
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+#ifdef CLIPPLANE
+uniform vec4 vClipPlane;
+varying float fClipDistance;
+#endif
+
+#ifdef FOG
+varying float fFogDistance;
+#endif
+
+#ifdef SHADOWS
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+uniform mat4 lightMatrix0;
+varying vec4 vPositionFromLight0;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+uniform mat4 lightMatrix1;
+varying vec4 vPositionFromLight1;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+uniform mat4 lightMatrix2;
+varying vec4 vPositionFromLight2;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+uniform mat4 lightMatrix3;
+varying vec4 vPositionFromLight3;
+#endif
+#endif
+
+// Water uniforms
+uniform mat4 worldReflectionViewProjection;
+uniform vec2 windDirection;
+uniform float waveLength;
+uniform float time;
+uniform float windForce;
+uniform float waveHeight;
+uniform float waveSpeed;
+
+// Water varyings
+varying vec3 vPosition;
+varying vec3 vRefractionMapTexCoord;
+varying vec3 vReflectionMapTexCoord;
+
+void main(void) {
+	mat4 finalWorld;
+
+#ifdef INSTANCES
+	finalWorld = mat4(world0, world1, world2, world3);
+#else
+	finalWorld = world;
+#endif
+
+#ifdef BONES
+	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
+	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
+	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
+
+#ifdef BONES4
+	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
+	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
+#else
+	finalWorld = finalWorld * (m0 + m1 + m2);
+#endif 
+
+#endif
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef NORMAL
+	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+#endif
+
+	// Texture coordinates
+#ifndef UV1
+	vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+	vec2 uv2 = vec2(0., 0.);
+#endif
+
+#ifdef BUMP
+	if (vNormalInfos.x == 0.)
+	{
+		vNormalUV = vec2(normalMatrix * vec4((uv * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
+	}
+	else
+	{
+		vNormalUV = vec2(normalMatrix * vec4((uv2 * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
+	}
+#endif
+
+	// Clip plane
+#ifdef CLIPPLANE
+	fClipDistance = dot(worldPos, vClipPlane);
+#endif
+
+	// Fog
+#ifdef FOG
+	fFogDistance = (view * worldPos).z;
+#endif
+
+	// Shadows
+#ifdef SHADOWS
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+	vPositionFromLight0 = lightMatrix0 * worldPos;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+	vPositionFromLight1 = lightMatrix1 * worldPos;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+	vPositionFromLight2 = lightMatrix2 * worldPos;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+	vPositionFromLight3 = lightMatrix3 * worldPos;
+#endif
+#endif
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+
+	// Point size
+#ifdef POINTSIZE
+	gl_PointSize = pointSize;
+#endif
+
+	vec3 p = position;
+	float newY = (sin(((p.x / 0.05) + time * waveSpeed)) * waveHeight * windDirection.x * 5.0)
+			   + (cos(((p.z / 0.05) +  time * waveSpeed)) * waveHeight * windDirection.y * 5.0);
+	p.y += abs(newY);
+	
+	gl_Position = viewProjection * finalWorld * vec4(p, 1.0);
+
+#ifdef REFLECTION
+	worldPos = viewProjection * finalWorld * vec4(p, 1.0);
+	
+	// Water
+	vPosition = position;
+	
+	vRefractionMapTexCoord.x = 0.5 * (worldPos.w + worldPos.x);
+	vRefractionMapTexCoord.y = 0.5 * (worldPos.w + worldPos.y);
+	vRefractionMapTexCoord.z = worldPos.w;
+	
+	worldPos = worldReflectionViewProjection * vec4(position, 1.0);
+	vReflectionMapTexCoord.x = 0.5 * (worldPos.w + worldPos.x);
+	vReflectionMapTexCoord.y = 0.5 * (worldPos.w + worldPos.y);
+	vReflectionMapTexCoord.z = worldPos.w;
+#endif
+}

+ 14 - 0
materialsLibrary/test/add/addfire.js

@@ -0,0 +1,14 @@
+window.prepareFire = function() {
+    var fire = new BABYLON.FireMaterial("fire", scene);
+    fire.diffuseTexture = new BABYLON.Texture("textures/fire/diffuse.png", scene);
+    fire.distortionTexture = new BABYLON.Texture("textures/fire/distortion.png", scene);
+    fire.opacityTexture = new BABYLON.Texture("textures/fire/opacity.png", scene);
+    
+    registerRangeUI("fire", "speed", 0, 20, function(value) {
+		fire.speed = value;
+	}, function() {
+		return fire.speed;
+	});
+    
+    return fire;
+};

+ 54 - 0
materialsLibrary/test/add/addfur.js

@@ -0,0 +1,54 @@
+window.prepareFur = function() {
+	var fur = new BABYLON.FurMaterial("fur", scene);
+	fur.furLength = 1;
+	fur.furAngle = 0;
+    fur.furColor = new BABYLON.Color3(0.44,0.21,0.02);
+
+
+// fur length
+    registerRangeUI("fur", "Fur length", 0, 15, function(value) {
+        fur.furLength = value;
+    }, function() {
+        return fur.furLength;
+    });
+	
+	// fur angle
+    registerRangeUI("fur", "Fur angle", 0, Math.PI/2, function(value) {
+        fur.furAngle = value;
+    }, function() {
+        return fur.furAngle;
+    });
+    
+    // fur color
+	registerColorPicker("fur", "Fur color", "#703605", function(value) {		
+		fur.furColor.r = value.r/255;
+		fur.furColor.g = value.g/255;
+		fur.furColor.b = value.b/255;
+	}, function() {
+		return fur.furColor;
+	});
+	
+	var DTON = false;
+	registerButtonUI("fur", "Tgl Diffuse Tex", function() {
+		DTON = !DTON;
+		if(DTON) {
+			fur.diffuseTexture = new BABYLON.Texture("textures/leopard_fur.jpg", scene);
+		}
+		else {
+			fur.diffuseTexture = null;
+		}
+	})
+	
+	var HTON = false;
+	registerButtonUI("fur", "Tgl Height Tex", function() {
+		HTON = !HTON;
+		if(HTON) {
+			fur.heightTexture = new BABYLON.Texture("textures/speckles.jpg", scene);
+		}
+		else {
+			fur.heightTexture = null;
+		}
+	})
+    
+    return fur;
+};

+ 71 - 61
materialsLibrary/test/add/addpbr.js

@@ -1,29 +1,30 @@
 window.preparePBR = function() {
 	var pbr = new BABYLON.PBRMaterial("pbr", scene);
-	pbr.diffuseTexture = new BABYLON.Texture("textures/amiga.jpg", scene);
-	pbr.diffuseTexture.uScale = 5;
-	pbr.diffuseTexture.vScale = 5;
+	pbr.albedoTexture = new BABYLON.Texture("textures/amiga.jpg", scene);
+	pbr.albedoTexture.uScale = 5;
+	pbr.albedoTexture.vScale = 5;
 	pbr.reflectionTexture = new BABYLON.CubeTexture("textures/skybox/TropicalSunnyDay", scene);	
-	pbr.specularColor = new BABYLON.Color3(0.3, 0.3, 0.3);
-	pbr.glossiness = 0.9;
+	pbr.reflectivityColor = new BABYLON.Color3(0.3, 0.3, 0.3);
+	pbr.microSurface = 0.9;
 	
 	registerButtonUI("pbr", "Default", function() {
 		setRangeValues({
 		  "directIntensity": 1,
 		  "emissiveIntensity": 1,
 		  "environmentIntensity": 1,
+		  "specularIntensity": 1,
 		  "ShadowIntensity": 1,
 		  "ShadeIntensity": 1,
 		  "cameraExposure": 1,
 		  "cameraContrast": 1,
-		  "glossiness": 0.9,
-		  "specularColorR": 0.3,
-		  "specularColorG": 0.3,
-		  "specularColorB": 0.3,
-		  "diffuseColorR": 1,
-		  "diffuseColorG": 1,
-		  "diffuseColorB": 1,
-		  "diffuseColorLevel": 0
+		  "microSurface": 0.9,
+		  "reflectivityColorR": 0.3,
+		  "reflectivityColorG": 0.3,
+		  "reflectivityColorB": 0.3,
+		  "albedoColorR": 1,
+		  "albedoColorG": 1,
+		  "albedoColorB": 1,
+		  "albedoColorLevel": 0
 		});
 	});
 	registerButtonUI("pbr", "Rough Gold", function() {
@@ -31,18 +32,19 @@ window.preparePBR = function() {
 		  "directIntensity": 1.3439461727881254,
 		  "emissiveIntensity": 1,
 		  "environmentIntensity": 0.3685013699580344,
+		  "specularIntensity": 1,
 		  "ShadowIntensity": 1,
 		  "ShadeIntensity": 1,
 		  "cameraExposure": 0.7153261887420668,
 		  "cameraContrast": 1.6474178892241538,
-		  "glossiness": 0.42269274789303946,
-		  "specularColorR": 1,
-		  "specularColorG": 0.8453854957860789,
-		  "specularColorB": 0.5093989525890475,
-		  "diffuseColorR": 0,
-		  "diffuseColorG": 0,
-		  "diffuseColorB": 0,
-		  "diffuseColorLevel": 1
+		  "microSurface": 0.42269274789303946,
+		  "reflectivityColorR": 1,
+		  "reflectivityColorG": 0.8453854957860789,
+		  "reflectivityColorB": 0.5093989525890475,
+		  "albedoColorR": 0,
+		  "albedoColorG": 0,
+		  "albedoColorB": 0,
+		  "albedoColorLevel": 1
 		});
 	});
 	registerButtonUI("pbr", "Plastic", function() {
@@ -50,18 +52,19 @@ window.preparePBR = function() {
 		  "directIntensity": 0.9971213540040931,
 		  "emissiveIntensity": 1,
 		  "environmentIntensity": 0.3685013699580344,
+		  "specularIntensity": 1,
 		  "ShadowIntensity": 0.975444802830091,
 		  "ShadeIntensity": 0.8020323934380749,
 		  "cameraExposure": 0.7586792910900708,
 		  "cameraContrast": 1.5823882357021477,
-		  "glossiness": 0.8562237713730799,
-		  "specularColorR": 0.05,
-		  "specularColorG": 0.05,
-		  "specularColorB": 0.05,
-		  "diffuseColorR": 0.20592723615301922,
-		  "diffuseColorG": 0.942929976069088,
-		  "diffuseColorB": 1,
-		  "diffuseColorLevel": 1
+		  "microSurface": 0.8562237713730799,
+		  "reflectivityColorR": 0.05,
+		  "reflectivityColorG": 0.05,
+		  "reflectivityColorB": 0.05,
+		  "albedoColorR": 0.20592723615301922,
+		  "albedoColorG": 0.942929976069088,
+		  "albedoColorB": 1,
+		  "albedoColorLevel": 1
 		});
 	});
 	registerButtonUI("pbr", "Shiny Copper", function() {
@@ -69,18 +72,19 @@ window.preparePBR = function() {
 		  "directIntensity": 1.2355634169181153,
 		  "emissiveIntensity": 0.910415149308085,
 		  "environmentIntensity": 0.21676551174002023,
+		  "specularIntensity": 1,
 		  "ShadowIntensity": 1.018797905178095,
 		  "ShadeIntensity": 0.975444802830091,
 		  "cameraExposure": 1.0621510075260991,
 		  "cameraContrast": 1.0404744563520971,
-		  "glossiness": 0.888738598134083,
-		  "specularColorR": 0.98,
-		  "specularColorG": 0.78,
-		  "specularColorB": 0.706,
-		  "diffuseColorR": 0.1,
-		  "diffuseColorG": 0.1,
-		  "diffuseColorB": 0.1,
-		  "diffuseColorLevel": 1
+		  "microSurface": 0.888738598134083,
+		  "reflectivityColorR": 0.98,
+		  "reflectivityColorG": 0.78,
+		  "reflectivityColorB": 0.706,
+		  "albedoColorR": 0.1,
+		  "albedoColorG": 0.1,
+		  "albedoColorB": 0.1,
+		  "albedoColorLevel": 1
 		});
 	});
 
@@ -101,6 +105,12 @@ window.preparePBR = function() {
 	}, function() {
 		return pbr.environmentIntensity;
 	});
+
+	registerRangeUI("pbr", "specularIntensity", 0, 2, function(value) {
+		pbr.specularIntensity = value;
+	}, function() {
+		return pbr.specularIntensity;
+	});
 	
 	registerRangeUI("pbr", "ShadowIntensity", 0, 2, function(value) {
 		pbr.overloadedShadowIntensity = value;
@@ -126,52 +136,52 @@ window.preparePBR = function() {
 		return pbr.cameraContrast;
 	});
 	
-	registerRangeUI("pbr", "glossiness", 0, 1, function(value) {
-		pbr.glossiness = value;
+	registerRangeUI("pbr", "microSurface", 0, 1, function(value) {
+		pbr.microSurface = value;
 	}, function() {
-		return pbr.glossiness;
+		return pbr.microSurface;
 	});
 
-	registerRangeUI("pbr", "specularColorR", 0, 1, function(value) {
-		pbr.specularColor.r = value;
+	registerRangeUI("pbr", "reflectivityColorR", 0, 1, function(value) {
+		pbr.reflectivityColor.r = value;
 	}, function() {
-		return pbr.specularColor.r;
+		return pbr.reflectivityColor.r;
 	});
 
-	registerRangeUI("pbr", "specularColorG", 0, 1, function(value) {
-		pbr.specularColor.g = value;
+	registerRangeUI("pbr", "reflectivityColorG", 0, 1, function(value) {
+		pbr.reflectivityColor.g = value;
 	}, function() {
-		return pbr.specularColor.g;
+		return pbr.reflectivityColor.g;
 	});
 
-	registerRangeUI("pbr", "specularColorB", 0, 1, function(value) {
-		pbr.specularColor.b = value;
+	registerRangeUI("pbr", "reflectivityColorB", 0, 1, function(value) {
+		pbr.reflectivityColor.b = value;
 	}, function() {
-		return pbr.specularColor.b;
+		return pbr.reflectivityColor.b;
 	});
 
-	registerRangeUI("pbr", "diffuseColorR", 0, 1, function(value) {
-		pbr.overloadedDiffuse.r = value;
+	registerRangeUI("pbr", "albedoColorR", 0, 1, function(value) {
+		pbr.overloadedAlbedo.r = value;
 	}, function() {
-		return pbr.overloadedDiffuse.r;
+		return pbr.overloadedAlbedo.r;
 	});
 
-	registerRangeUI("pbr", "diffuseColorG", 0, 1, function(value) {
-		pbr.overloadedDiffuse.g = value;
+	registerRangeUI("pbr", "albedoColorG", 0, 1, function(value) {
+		pbr.overloadedAlbedo.g = value;
 	}, function() {
-		return pbr.overloadedDiffuse.g;
+		return pbr.overloadedAlbedo.g;
 	});
 
-	registerRangeUI("pbr", "diffuseColorB", 0, 1, function(value) {
-		pbr.overloadedDiffuse.b = value;
+	registerRangeUI("pbr", "albedoColorB", 0, 1, function(value) {
+		pbr.overloadedAlbedo.b = value;
 	}, function() {
-		return pbr.overloadedDiffuse.b;
+		return pbr.overloadedAlbedo.b;
 	});
 
-	registerRangeUI("pbr", "diffuseColorLevel", 0, 1, function(value) {
-		pbr.overloadedDiffuseIntensity = value;
+	registerRangeUI("pbr", "albedoColorLevel", 0, 1, function(value) {
+		pbr.overloadedAlbedoIntensity = value;
 	}, function() {
-		return pbr.overloadedDiffuseIntensity;
+		return pbr.overloadedAlbedoIntensity;
 	});
 
 	return pbr;

+ 19 - 0
materialsLibrary/test/add/addterrain.js

@@ -0,0 +1,19 @@
+window.prepareTerrain = function() {
+    var terrain = new BABYLON.TerrainMaterial("terrain", scene);
+    terrain.specularColor = new BABYLON.Color3(0.5, 0.5, 0.5);
+    terrain.specularPower = 64;
+    terrain.mixTexture = new BABYLON.Texture("textures/mixMap.png", scene);
+    terrain.diffuseTexture1 = new BABYLON.Texture("textures/floor.png", scene);
+    terrain.diffuseTexture2 = new BABYLON.Texture("textures/rock.png", scene);
+    terrain.diffuseTexture3 = new BABYLON.Texture("textures/grass.png", scene);
+    
+    terrain.bumpTexture1 = new BABYLON.Texture("textures/floor_bump.png", scene);
+    terrain.bumpTexture2 = new BABYLON.Texture("textures/rockn.png", scene);
+    terrain.bumpTexture3 = new BABYLON.Texture("textures/grassn.png", scene);
+    
+    terrain.diffuseTexture1.uScale = terrain.diffuseTexture1.vScale = 10;
+    terrain.diffuseTexture2.uScale = terrain.diffuseTexture2.vScale = 10;
+    terrain.diffuseTexture3.uScale = terrain.diffuseTexture3.vScale = 10;
+    
+    return terrain;
+};

+ 19 - 0
materialsLibrary/test/add/addtriplanar.js

@@ -0,0 +1,19 @@
+window.prepareTriPlanar = function() {
+    var triPlanar = new BABYLON.TriPlanarMaterial("triplanar", scene);
+    triPlanar.diffuseTextureX = new BABYLON.Texture("textures/rock.png", scene);
+    triPlanar.diffuseTextureY = new BABYLON.Texture("textures/grass.png", scene);
+    triPlanar.diffuseTextureZ = triPlanar.diffuseTextureX;
+    triPlanar.normalTextureX = new BABYLON.Texture("textures/rockn.png", scene);
+    triPlanar.normalTextureY = new BABYLON.Texture("textures/grassn.png", scene);
+    triPlanar.normalTextureZ = triPlanar.normalTextureX;
+    triPlanar.specularPower = 64;
+    triPlanar.tileSize = 1.5;
+    
+    registerRangeUI("triPlanar", "tileSize", 0, 20, function(value) {
+		triPlanar.tileSize = value;
+	}, function() {
+		return triPlanar.tileSize;
+	});
+    
+    return triPlanar;
+};

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


+ 36 - 33
materialsLibrary/test/index.html

@@ -11,6 +11,8 @@
     <script src="../dist/babylon.lavaMaterial.js"></script>
 	<script src="../dist/babylon.terrainMaterial.js"></script>
 	<script src="../dist/babylon.pbrMaterial.js"></script>
+	<script src="../dist/babylon.furMaterial.js"></script>
+	<script src="../dist/babylon.triPlanarMaterial.js"></script>
 
 	<style>
 		html, body {
@@ -45,8 +47,14 @@
 	<canvas id="renderCanvas"></canvas>
 
 	<script src="index.js"></script>
-	<script src="add/addpbr.js"></script>
+    <script src="add/addpbr.js"></script>
+    <script src="add/addlava.js"></script>
+    <script src="add/addnormal.js"></script>
 	<script src="add/addwater.js"></script>
+	<script src="add/addfur.js"></script>
+	<script src="add/addterrain.js"></script>
+	<script src="add/addfire.js"></script>
+	<script src="add/addtriplanar.js"></script>
 	
 	<script>
 		if (BABYLON.Engine.isSupported()) {
@@ -58,6 +66,7 @@
 
 			var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 6, 50, BABYLON.Vector3.Zero(), scene);
 			camera.attachControl(canvas, true);
+			camera.minZ = 0.1;
 
 			// Lights
 			var hemisphericLight = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
@@ -69,7 +78,7 @@
 			spotLight.setEnabled(false);
 
 			// Create meshes
-			var sphere = BABYLON.Mesh.CreateSphere("sphere", 32, 30.0, scene);
+			var sphere = BABYLON.Mesh.CreateSphere("sphere", 48, 30.0, scene);
 			
 			var plane = BABYLON.MeshBuilder.CreateBox("plane", { width: 30, height: 1, depth:30 }, scene);
 			plane.setEnabled(false);
@@ -81,6 +90,9 @@
 			var knot = BABYLON.Mesh.CreateTorusKnot("knot", 10, 3, 128, 64, 2, 3, scene);
 			knot.setEnabled(false);
 			
+			var heightMap = BABYLON.Mesh.CreateGroundFromHeightMap("heightMap", "textures/heightMap.png", 100, 100, 100, 0, 10, scene, false);
+			heightMap.setEnabled(false);
+			
 			// Skybox
 			var skybox = BABYLON.Mesh.CreateBox("skyBox", 1000.0, scene);
 			var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
@@ -126,7 +138,8 @@
 				
 				var shadowGenerator3 = new BABYLON.ShadowGenerator(1024, pointLight);
 				shadowGenerator3.getShadowMap().renderList.push(shadowCaster3);
-				shadowGenerator3.usePoissonSampling = true;
+				shadowGenerator3.usePoissonSampling = false;
+				shadowGenerator3.bias = 0;
 
 				// Register a render loop to repeatedly render the scene
 				engine.runRenderLoop(function () {
@@ -159,20 +172,16 @@
 				std.diffuseTexture.vScale = 5;
 
                 // Lava
-                var lava = new BABYLON.LavaMaterial("lava", scene);
-                lava.diffuseTexture = new BABYLON.Texture("textures/lava/lavatile.jpg", scene);
-                lava.diffuseTexture.uScale = 0.5;
-                lava.diffuseTexture.vScale = 0.5;
-				lava.noiseTexture = new BABYLON.Texture("textures/lava/cloud.png", scene);
-				lava.fogColor = BABYLON.Color3.Black();
-				lava.speed = 2.5;
+                var lava = prepareLava();
 
 				var simple = new BABYLON.SimpleMaterial("simple", scene);
 				simple.diffuseTexture = new BABYLON.Texture("textures/amiga.jpg", scene);
 				simple.diffuseTexture.uScale = 5;
 				simple.diffuseTexture.vScale = 5;
 
-				var normal = new BABYLON.NormalMaterial("normal", scene);
+				var normal = prepareNormal();
+				
+				var fur = prepareFur();
 				
 				var water = prepareWater();
 				water.addToRenderList(skybox);
@@ -180,35 +189,20 @@
 				water.addToRenderList(shadowCaster2);
 				water.addToRenderList(shadowCaster3);
 				
-				var fire = new BABYLON.FireMaterial("fire", scene);
-				fire.diffuseTexture = new BABYLON.Texture("textures/fire/diffuse.png", scene);
-				fire.distortionTexture = new BABYLON.Texture("textures/fire/distortion.png", scene);
-				fire.opacityTexture = new BABYLON.Texture("textures/fire/opacity.png", scene);
+				var fire = prepareFire();
 				
-				var terrain = new BABYLON.TerrainMaterial("terrain", scene);
-				terrain.specularColor = new BABYLON.Color3(0.5, 0.5, 0.5);
-				terrain.specularPower = 64;
-				terrain.mixTexture = new BABYLON.Texture("textures/mixMap.png", scene);
-				terrain.diffuseTexture1 = new BABYLON.Texture("textures/grass.png", scene);
-				terrain.diffuseTexture2 = new BABYLON.Texture("textures/rock.png", scene);
-				terrain.diffuseTexture3 = new BABYLON.Texture("textures/floor.png", scene);
+				var terrain = prepareTerrain();
 				
-				terrain.bumpTexture1 = new BABYLON.Texture("textures/grassn.png", scene);
-				terrain.bumpTexture2 = new BABYLON.Texture("textures/rockn.png", scene);
-				terrain.bumpTexture3 = new BABYLON.Texture("textures/floor_bump.png", scene);
+				var pbr = preparePBR();
 				
-				terrain.diffuseTexture1.uScale = terrain.diffuseTexture1.vScale = 10;
-				terrain.diffuseTexture2.uScale = terrain.diffuseTexture2.vScale = 10;
-				terrain.diffuseTexture3.uScale = terrain.diffuseTexture3.vScale = 10;
+				var triPlanar = prepareTriPlanar();
 				
-				var pbr = preparePBR();
-								
 				// Default to std
 				var currentMaterial = std;
 				sphere.material = std;				
 				sphere.receiveShadows = true;
 
-				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr']).onFinishChange(function () {
+				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr', 'fur', 'triPlanar']).onFinishChange(function () {
 					water.enableRenderTargets(false);
 					
 					switch (options.material) {
@@ -234,7 +228,13 @@
 							break;
 						case "pbr":
 							currentMaterial = pbr;
-							break;													
+							break;
+						case "fur":
+							currentMaterial = fur;
+							break;
+						case "triPlanar":
+							currentMaterial = triPlanar;
+							break;
 						default:
 							currentMaterial = std;
 							break;
@@ -245,7 +245,7 @@
 					window.enableMaterial(options.material);
 				});
 
-				gui.add(options, 'mesh', ['sphere', 'knot', 'plane', 'ground', 'rabbit']).onFinishChange(function () {
+				gui.add(options, 'mesh', ['sphere', 'knot', 'plane', 'ground', 'heightMap', 'rabbit']).onFinishChange(function () {
 					currentMesh.setEnabled(false);
 					switch (options.mesh) {
 						case "sphere":
@@ -260,6 +260,9 @@
 						case "ground":
 							currentMesh = ground;
 							break;
+						case "heightMap":
+							currentMesh = heightMap;
+							break;
 						case "rabbit":
 							currentMesh = rabbit;
 							break;

+ 20 - 0
materialsLibrary/test/index.js

@@ -15,6 +15,20 @@ var options = {
 var registeredUIs = {};
 var materialgui;
 
+window.registerColorPicker = function(material, name, color, onChange, onSet) {
+    if (!registeredUIs[material]) {
+        registeredUIs[material] = [];
+    }
+
+    registeredUIs[material].push({
+        name: name,
+        color: "#ff0000",
+        onChange: onChange,
+        onSet: onSet,
+        type: "Color"
+    });
+};
+
 
 window.registerRangeUI = function(material, name, minValue, maxValue, onChange, onSet) {
 	if (!registeredUIs[material]) {
@@ -71,6 +85,12 @@ var setUi = function(ui) {
 			ui.onChange(value);
 		});
 	}
+    else if (ui.type == "Color") {
+        options[ui.name] = ui.onSet();
+        materialgui.addColor(options, ui.name).onChange(function (value) {
+            ui.onChange(value);
+        })
+    }
 	else if (ui.type == "Button") {
 		options[ui.name] = ui.onClick;
 		materialgui.add(options, ui.name);

BIN
materialsLibrary/test/textures/heightMap.png


BIN
materialsLibrary/test/textures/leopard_fur.JPG


BIN
materialsLibrary/test/textures/mixMap.png


BIN
materialsLibrary/test/textures/speckles.jpg


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


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


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


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


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


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


File diff suppressed because it is too large
+ 84 - 4
proceduralTexturesLibrary/dist/babylon.starfieldProceduralTexture.js


File diff suppressed because it is too large
+ 1 - 1
proceduralTexturesLibrary/dist/babylon.starfieldProceduralTexture.min.js


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


+ 73 - 5
proceduralTexturesLibrary/proceduralTextures/starfield/babylon.starfieldProceduralTexture.ts

@@ -6,6 +6,13 @@ module BABYLON {
         private _alpha = 0.5;
         private _beta = 0.8;
         private _zoom = 0.8;
+        private _formuparam = 0.53;
+        private _stepsize = 0.1;
+        private _tile = 0.850;
+        private _brightness = 0.0015;
+        private _darkmatter = 0.400;
+        private _distfading = 0.730;
+        private _saturation = 0.850;
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
             super(name, size, "starfieldProceduralTexture", scene, fallbackTexture, generateMipMaps);
@@ -17,6 +24,13 @@ module BABYLON {
             this.setFloat("alpha", this._alpha);  
             this.setFloat("beta", this._beta);  
             this.setFloat("zoom", this._zoom); 
+            this.setFloat("formuparam", this._formuparam); 
+            this.setFloat("stepsize", this._stepsize); 
+            this.setFloat("tile", this._tile); 
+            this.setFloat("brightness", this._brightness); 
+            this.setFloat("darkmatter", this._darkmatter); 
+            this.setFloat("distfading", this._distfading); 
+            this.setFloat("saturation", this._saturation); 
         }
 
         public get time(): number {
@@ -46,13 +60,67 @@ module BABYLON {
             this.updateShaderUniforms();
         } 
 
-        public get zoom(): number {
-            return this._zoom;
+        public get formuparam(): number {
+            return this._formuparam;
         }
 
-        public set zoom(value: number) {
-            this._zoom = value;
+        public set formuparam(value: number) {
+            this._formuparam = value;
             this.updateShaderUniforms();
-        } 
+        }
+        
+        public get stepsize(): number {
+            return this._stepsize;
+        }
+
+        public set stepsize(value: number) {
+            this._stepsize = value;
+            this.updateShaderUniforms();
+        }
+        
+        public get tile(): number {
+            return this._tile;
+        }
+
+        public set tile(value: number) {
+            this._tile = value;
+            this.updateShaderUniforms();
+        }
+        
+        public get brightness(): number {
+            return this._brightness;
+        }
+
+        public set brightness(value: number) {
+            this._brightness = value;
+            this.updateShaderUniforms();
+        }
+        
+        public get darkmatter(): number {
+            return this._darkmatter;
+        }
+
+        public set darkmatter(value: number) {
+            this._darkmatter = value;
+            this.updateShaderUniforms();
+        }
+        
+        public get distfading(): number {
+            return this._distfading;
+        }
+
+        public set distfading(value: number) {
+            this._distfading = value;
+            this.updateShaderUniforms();
+        }
+        
+        public get saturation(): number {
+            return this._saturation;
+        }
+
+        public set saturation(value: number) {
+            this._saturation = value;
+            this.updateShaderUniforms();
+        }
     }
 }

+ 9 - 11
proceduralTexturesLibrary/proceduralTextures/starfield/starfieldProceduralTexture.fragment.fx

@@ -1,17 +1,8 @@
 precision highp float;
 
-#define iterations 15
-#define formuparam 0.53
-
+//defined as const as fragment shaders does not support uniforms in loops
 #define volsteps 20
-#define stepsize 0.1
-
-#define tile 0.850
-
-#define brightness 0.0015
-#define darkmatter 0.400
-#define distfading 0.730
-#define saturation 0.850
+#define iterations 15
 
 varying vec2 vPosition;
 varying vec2 vUV;
@@ -20,6 +11,13 @@ uniform float time;
 uniform float alpha;
 uniform float beta;
 uniform float zoom;
+uniform float formuparam;
+uniform float stepsize;
+uniform float tile;
+uniform float brightness;
+uniform float darkmatter;
+uniform float distfading;
+uniform float saturation;
 
 void main()
 {

File diff suppressed because it is too large
+ 2170 - 1937
proceduralTexturesLibrary/test/babylon.max.js


+ 21 - 34
proceduralTexturesLibrary/test/index.html

@@ -160,89 +160,76 @@
 				
 				// Create shaders
 				var std = new BABYLON.StandardMaterial("std", scene);
-				std.diffuseTexture = new BABYLON.Texture("textures/amiga.jpg", scene);
-				std.diffuseTexture.uScale = 5;
-				std.diffuseTexture.vScale = 5;
+				std.specularColor = new BABYLON.Color3(0, 0, 0);
+				
+				var diffuseTexture = new BABYLON.Texture("textures/amiga.jpg", scene);
+				diffuseTexture.uScale = 5;
+				diffuseTexture.vScale = 5;
 
                 // Fire Procedural Texture
                 var firePT = addFirePT();
-				var fireMaterial =  new BABYLON.StandardMaterial("fire", scene);
-				fireMaterial.diffuseTexture = firePT;
 				
 				// Wood Procedural Texture
                 var woodPT = addWoodPT();
-				var woodMaterial =  new BABYLON.StandardMaterial("wood", scene);
-				woodMaterial.diffuseTexture = woodPT;
 				
 				// Cloud Procedural Texture
                 var cloudPT = addCloudPT();
-				var cloudMaterial =  new BABYLON.StandardMaterial("cloud", scene);
-				cloudMaterial.diffuseTexture = cloudPT;
 				
 				// Grass Procedural Texture
                 var grassPT = addGrassPT();
-				var grassMaterial =  new BABYLON.StandardMaterial("grass", scene);
-				grassMaterial.diffuseTexture = grassPT;
 				
 				// Road Procedural Texture
                 var roadPT = addRoadPT();
-				var roadMaterial =  new BABYLON.StandardMaterial("road", scene);
-				roadMaterial.diffuseTexture = roadPT;
 				
 				// Brick Procedural Texture
                 var brickPT = addBrickPT();
-				var brickMaterial =  new BABYLON.StandardMaterial("brick", scene);
-				brickMaterial.diffuseTexture = brickPT;
 				
 				// Marble Procedural Texture
                 var marblePT = addMarblePT();
-				var marbleMaterial =  new BABYLON.StandardMaterial("marble", scene);
-				marbleMaterial.diffuseTexture = marblePT;
 				
 				// Starfield Procedural Texture
                 var starfieldPT = addStarfieldPT();
-				var starfieldMaterial =  new BABYLON.StandardMaterial("starfield", scene);
-			 	starfieldMaterial.diffuseTexture = starfieldPT;
 								
 				// Default to std
-				var currentMaterial = std;
+				var currentTexture = diffuseTexture;
 				sphere.material = std;				
 				sphere.receiveShadows = true;
+				std.diffuseTexture = currentTexture;
 
-				gui.add(options, 'material', ['none', 'fire', 'wood', 'cloud', 'grass', 'road', 'brick', 'marble', 'starfield']).onFinishChange(function () {
-					switch (options.material) {
+				gui.add(options, 'texture', ['default', 'fire', 'wood', 'cloud', 'grass', 'road', 'brick', 'marble', 'starfield']).onFinishChange(function () {
+					switch (options.texture) {
 						case "fire":
-							currentMaterial = fireMaterial;
+							currentTexture = firePT;
 							break;
 						case "wood":
-							currentMaterial = woodMaterial;
+							currentTexture = woodPT;
 							break;
 						case "cloud":
-							currentMaterial = cloudMaterial;
+							currentTexture = cloudPT;
 							break;
 						case "grass":
-							currentMaterial = grassMaterial;
+							currentTexture = grassPT;
 							break;
 						case "road":
-							currentMaterial = roadMaterial;
+							currentTexture = roadPT;
 							break;
 						case "brick":
-							currentMaterial = brickMaterial;
+							currentTexture = brickPT;
 							break;
 						case "marble":
-							currentMaterial = marbleMaterial;
+							currentTexture = marblePT;
 							break;
 						case "starfield":
-							currentMaterial = starfieldMaterial;
+							currentTexture = starfieldPT;
 							break;
 						case "none":
 						default:
-							currentMaterial = std;
+							currentTexture = diffuseTexture;
 							break;
 					}
 
-					currentMesh.material = currentMaterial;
-					window.enableMaterial(options.material);
+					std.diffuseTexture = currentTexture;
+					window.enableTexture(options.texture);
 				});
 
 				gui.add(options, 'mesh', ['sphere', 'knot', 'plane', 'ground', 'rabbit']).onFinishChange(function () {
@@ -266,7 +253,7 @@
 					}
 					currentMesh.setEnabled(true);
 					currentMesh.receiveShadows = true;
-					currentMesh.material = currentMaterial;
+					currentMesh.material = std;
 				});
 
 				var f1 = gui.addFolder('lights');

+ 20 - 20
proceduralTexturesLibrary/test/index.js

@@ -1,7 +1,7 @@
 //UI
 var gui = new dat.GUI();
 var options = {
-	material: "standard",
+	texture: "standard",
 	mesh: "sphere",
 	hemisphericLight: true,
 	pointLight: false,
@@ -13,14 +13,14 @@ var options = {
 }
 
 var registeredUIs = {};
-var materialgui;
+var textureui;
 
-window.registerColorPicker = function(material, name, color, onChange, onSet) {
-    if (!registeredUIs[material]) {
-        registeredUIs[material] = [];
+window.registerColorPicker = function(texture, name, color, onChange, onSet) {
+    if (!registeredUIs[texture]) {
+        registeredUIs[texture] = [];
     }
 
-    registeredUIs[material].push({
+    registeredUIs[texture].push({
         name: name,
         color: "#ff0000",
         onChange: onChange,
@@ -29,12 +29,12 @@ window.registerColorPicker = function(material, name, color, onChange, onSet) {
 };
 
 
-window.registerRangeUI = function(material, name, minValue, maxValue, onChange, onSet) {
-	if (!registeredUIs[material]) {
-		registeredUIs[material] = [];
+window.registerRangeUI = function(texture, name, minValue, maxValue, onChange, onSet) {
+	if (!registeredUIs[texture]) {
+		registeredUIs[texture] = [];
 	}
 	
-	registeredUIs[material].push({
+	registeredUIs[texture].push({
 		name: name,
 		minValue: minValue,
 		maxValue: maxValue,
@@ -47,26 +47,26 @@ var setUi = function(ui) {
 	options[ui.name] = ui.onSet();
 
     if (ui.color) {
-        materialgui.addColor(options, ui.name).onChange(function(value) {
+        textureui.addColor(options, ui.name).onChange(function(value) {
             ui.onChange(value);
         });
     } else {
-        materialgui.add(options, ui.name, ui.minValue, ui.maxValue).onChange(function(value) {
+        textureui.add(options, ui.name, ui.minValue, ui.maxValue).onChange(function(value) {
             ui.onChange(value);
         });
     }
 }
 
-window.enableMaterial = function(material) {
-	if (materialgui) {
-		materialgui.domElement.parentElement.removeChild(materialgui.domElement);	
-		materialgui = null;
+window.enableTexture = function(texture) {
+	if (textureui) {
+		textureui.domElement.parentElement.removeChild(textureui.domElement);	
+		textureui = null;
 	}
 	
-	if (registeredUIs[material]) {
-		materialgui = new dat.GUI();
-		for (var index = 0; index < registeredUIs[material].length; index++) {
-			var ui = registeredUIs[material][index];
+	if (registeredUIs[texture]) {
+		textureui = new dat.GUI();
+		for (var index = 0; index < registeredUIs[texture].length; index++) {
+			var ui = registeredUIs[texture][index];
 			
 			setUi(ui);
 		}	

+ 1 - 91
readme.md

@@ -35,97 +35,7 @@ You can help by testing or contributing to the next version.
  - FBX command line [exporter](https://github.com/BabylonJS/Babylon.js/tree/master/Exporters/FBX) can be used to generate a .babylon file from .FBX file (animations are supported)
 
 ## Features
-- Complete scene graph with lights, cameras, materials and meshes
-- Collisions engine
-- Physics engine (thanks to [oimo.js](https://github.com/lo-th/Oimo.js))
-- Scene picking
-- Antialiasing
-- Animations engine
-- Audio engine
-- Particles Systems
-- Sprites and 2D layers
--  Optimizations engines: 
- - Frustum clipping
- - Sub-meshes clipping
- - Hardware scaling
- - Selection octrees
- - Offline mode via IndexedDB (Assets are saved locally to prevent reloading them)
- - Incremental loading 
- - Binary compressed format
- - Hardware accelerated instances
- - Level of details (LOD)
- - Automatic scene optimizer
- - Debug layer to help you optimize and debug scenes
- - SIMD.js support
- - Collisions can be offloaded on webworkers
- - Merge meshes
-- Standard material is a per pixel material that supports:
- - Diffuse lightning and texture
- - Ambient lightning and texture
- - Specular lightning
- - Opacity texture
- - Reflection texture (Spheric, planar, cubic and projection)
- - Mirror texture
- - Emissive texture
- - Specular texture
- - Bump texture
- - Fresnel term for diffuse, opacity, emissive and reflection
- - Up to 4 lights (points, directionals, spots, hemispherics)
- - Custom materials
- - Custom shaders
- - Skybox
- - Vertex color
- - Bones (Animations and shadows are supported)
- - Procedural textures
--  Special FX
- - Fog
- - Alpha blending
- - Alpha testing
- - Billboarding
- - Fullscreen mode
- - Shadow Maps and Variance Shadow Maps (with support for blurred shadows)
- - Rendering layers
- - Post-processes (blur, refraction, black'n'white, fxaa, customs...)
- - SSAO
- - Volumetric Light Scattering 
- - Depth of field and lens effects
- - HDR rendering pipeline
- - Lens flares
- - Multi-views
- - Edges renderer
--  Textures:
- - Render target textures
- - Dynamic textures (canvas)
- - Video textures
- - Compressed (DDS) textures
- - TGA textures
--  Cameras (Perspective and orthographic):
- - Arc rotate camera
- - Free camera
- - Touch camera
- - Anaglyph camera
- - Virtual Joysticks camera
- - Stereoscopic camera
- - Gamepad camera
- - VR Device Oriention camera
- - WebVR camera
- - Follow camera
--  Meshes: 
- - Mesh cloning
- - Dynamic meshes
- - Height maps
- - Constructive solid geometries
- - Parametric shapes (Ribbon, tube, etc.)
- - Hardware instances
--  Import: 
- - Babylon scene file can be converted from .FBX
- - Exporter for Blender
- - Exporter for Cheetah3d
- - Exporter for 3ds Max
- - Exporter for Unity 5
- - STL importer
- - OBJ importer
- - Assets manager
+To get a complete list of supported features, please visit our [website](http://www.babylonjs.com/#specifications).
 
 ## Apache License 2.0 (Apache)
 

+ 0 - 0
src/Actions/babylon.action.ts


Some files were not shown because too many files changed in this diff