<NME> terrain_material.cpp
<BEF> #include <babylon/materialslibrary/terrain/terrain_material.h>

#include <nlohmann/json.hpp>

#include <babylon/cameras/camera.h>
#include <babylon/engines/engine.h>
#include <babylon/engines/scene.h>
#include <babylon/materials/effect.h>
#include <babylon/materials/effect_creation_options.h>
#include <babylon/materials/effect_fallbacks.h>
#include <babylon/materials/material_helper.h>
#include <babylon/materials/standard_material.h>
#include <babylon/materials/textures/base_texture.h>
#include <babylon/materials/textures/texture.h>
#include <babylon/materialslibrary/terrain/terrain_fragment_fx.h>
#include <babylon/materialslibrary/terrain/terrain_fragment_fx.h>
#include <babylon/materialslibrary/terrain/terrain_vertex_fx.h>
#include <babylon/meshes/mesh.h>
#include <babylon/meshes/sub_mesh.h>
#include <babylon/meshes/vertex_buffer.h>

namespace BABYLON {

TerrainMaterial::TerrainMaterial(const std::string& iName, Scene* scene)
    : PushMaterial{iName, scene}
    , mixTexture{this, &TerrainMaterial::get_mixTexture,
                 &TerrainMaterial::set_mixTexture}
    , diffuseTexture1{this, &TerrainMaterial::get_diffuseTexture1,
                      &TerrainMaterial::set_diffuseTexture1}
    , diffuseTexture2{this, &TerrainMaterial::get_diffuseTexture2,
                      &TerrainMaterial::set_diffuseTexture2}
    , diffuseTexture3{this, &TerrainMaterial::get_diffuseTexture3,
                      &TerrainMaterial::set_diffuseTexture3}
    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1,
                   &TerrainMaterial::set_bumpTexture1}
    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2,
                   &TerrainMaterial::set_bumpTexture2}
    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3,
                   &TerrainMaterial::set_bumpTexture3}
    , diffuseColor{Color3(1.f, 1.f, 1.f)}
    , specularColor{Color3(0.f, 0.f, 0.f)}
    , specularPower{64.f}
    , specularPower{64.f}
    , disableLighting{this, &TerrainMaterial::get_disableLighting,
                      &TerrainMaterial::set_disableLighting}
    , maxSimultaneousLights{this, &TerrainMaterial::get_maxSimultaneousLights,
                            &TerrainMaterial::set_maxSimultaneousLights}
    , _mixTexture{nullptr}
    , _diffuseTexture1{nullptr}
    , _diffuseTexture2{nullptr}
    , _diffuseTexture3{nullptr}
    , _bumpTexture1{nullptr}
    , _bumpTexture2{nullptr}
    , _bumpTexture3{nullptr}
    , _disableLighting{false}
    , _maxSimultaneousLights{4}
{
  // Vertex shader
  Effect::ShadersStore()["terrainVertexShader"] = terrainVertexShader;

  // Fragment shader
  Effect::ShadersStore()["terrainPixelShader"] = terrainPixelShader;
}

TerrainMaterial::~TerrainMaterial() = default;

BaseTexturePtr& TerrainMaterial::get_mixTexture()
{
  return _mixTexture;
}

void TerrainMaterial::set_mixTexture(const BaseTexturePtr& value)
{
  if (_mixTexture != value) {
    _mixTexture = value;
    _markAllSubMeshesAsTexturesDirty();
  }
}

TexturePtr& TerrainMaterial::get_diffuseTexture1()
{
  return _diffuseTexture1;
}

void TerrainMaterial::set_diffuseTexture1(const TexturePtr& value)
{
  if (_diffuseTexture1 != value) {
    _diffuseTexture1 = value;
    _markAllSubMeshesAsTexturesDirty();
  }
}

TexturePtr& TerrainMaterial::get_diffuseTexture2()
{
  return _diffuseTexture2;
}

void TerrainMaterial::set_diffuseTexture2(const TexturePtr& value)
{
  if (_diffuseTexture2 != value) {
    _diffuseTexture2 = value;
    _markAllSubMeshesAsTexturesDirty();
  }
}

TexturePtr& TerrainMaterial::get_diffuseTexture3()
{
  return _diffuseTexture3;
}

void TerrainMaterial::set_diffuseTexture3(const TexturePtr& value)
{
  if (_diffuseTexture3 != value) {
    _diffuseTexture3 = value;
    _markAllSubMeshesAsTexturesDirty();
  }
}

TexturePtr& TerrainMaterial::get_bumpTexture1()
{
  return _bumpTexture1;
}

void TerrainMaterial::set_bumpTexture1(const TexturePtr& value)
{
  if (_bumpTexture1 != value) {
    _bumpTexture1 = value;
    _markAllSubMeshesAsTexturesDirty();
  }
}

TexturePtr& TerrainMaterial::get_bumpTexture2()
{
  return _bumpTexture2;
}

void TerrainMaterial::set_bumpTexture2(const TexturePtr& value)
{
  if (_bumpTexture2 != value) {
    _bumpTexture2 = value;
    _markAllSubMeshesAsTexturesDirty();
  }
}

TexturePtr& TerrainMaterial::get_bumpTexture3()
{
  return _bumpTexture3;
}

void TerrainMaterial::set_bumpTexture3(const TexturePtr& value)
{
  if (_bumpTexture3 != value) {
    _bumpTexture3 = value;
    _markAllSubMeshesAsTexturesDirty();
  }
}

bool TerrainMaterial::get_disableLighting() const
{
  return _disableLighting;
}

void TerrainMaterial::set_disableLighting(bool value)
{
  if (_disableLighting != value) {
    _disableLighting = value;
    _markAllSubMeshesAsLightsDirty();
  }
}

unsigned int TerrainMaterial::get_maxSimultaneousLights() const
{
  return _maxSimultaneousLights;
}

void TerrainMaterial::set_maxSimultaneousLights(unsigned int value)
{
  if (_maxSimultaneousLights != value) {
    _maxSimultaneousLights = value;
    _markAllSubMeshesAsLightsDirty();
  }
}

bool TerrainMaterial::needAlphaBlending() const
{
  return (alpha < 1.f);
}

bool TerrainMaterial::needAlphaTesting() const
{
  return false;
}

BaseTexturePtr TerrainMaterial::getAlphaTestTexture()
{
  return nullptr;
}

bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
                                        BaseSubMesh* subMesh, bool useInstances)
{
  if (isFrozen()) {
    if (_wasPreviouslyReady && subMesh->effect()) {
      return true;
    }
  }

  if (!subMesh->_materialDefines) {
    subMesh->_materialDefines = std::make_shared<TerrainMaterialDefines>();
  }

  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(
    subMesh->_materialDefines);
  auto& defines = *definesPtr.get();
  auto scene    = getScene();

  if (!checkReadyOnEveryCall && subMesh->effect()) {
    if (_renderId == scene->getRenderId()) {
  }

  auto engine = scene->getEngine();

  // Textures

  // Textures
  if (scene->texturesEnabled()) {
    if (_mixTexture && StandardMaterial::DiffuseTextureEnabled()) {
      if (!_mixTexture->isReady()) {
        return false;
      }
      else {
        defines._needUVs           = true;
        defines.boolDef["DIFFUSE"] = true;
      }
    }
    if ((_bumpTexture1 || _bumpTexture2 || _bumpTexture3)
        && StandardMaterial::BumpTextureEnabled()) {
      defines._needUVs        = true;
      defines._needNormals    = true;
      defines.boolDef["BUMP"] = true;
    }
  }

  // Misc.
  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(),
                                        fogEnabled(),
                                        _shouldTurnAlphaTestOn(mesh), defines);

  // Lights

  // Values that need to be evaluated on every frame
  MaterialHelper::PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);

  // Attribs
  MaterialHelper::PrepareDefinesForAttributes(mesh, defines, true, true);

  // Get correct effect
  if (defines.isDirty()) {
    defines.markAsProcessed();
    scene->resetCachedMaterial();

    // Fallbacks
    auto fallbacks = std::make_unique<EffectFallbacks>();
    if (defines["FOG"]) {
      fallbacks->addFallback(1, "FOG");
    }
      fallbacks->addFallback(1, "FOG");
    }

    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks,
                                              maxSimultaneousLights());

    if (defines.intDef["NUM_BONE_INFLUENCERS"] > 0) {
      fallbacks->addCPUSkinningFallback(0, mesh);
    defines.boolDef["IMAGEPROCESSINGPOSTPROCESS"]
      = scene->imageProcessingConfiguration()->applyByPostProcess();

    // Attributes
    std::vector<std::string> attribs = {VertexBuffer::PositionKind};

    if (defines["NORMAL"]) {
      attribs.emplace_back(VertexBuffer::NormalKind);
    }

    if (defines["UV1"]) {
      attribs.emplace_back(VertexBuffer::UVKind);
    }

    if (defines["UV2"]) {
      attribs.emplace_back(VertexBuffer::UV2Kind);
    }

      attribs.emplace_back(VertexBuffer::ColorKind);
    }

    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines,
                                              *fallbacks);
    MaterialHelper::PrepareAttributesForInstances(attribs, defines);

    // Legacy browser patch
    // Legacy browser patch
    auto join = defines.toString();

    const std::vector<std::string> uniforms{
      "world",         "view",          "viewProjection", "vEyePosition",
      "vLightsType",   "vDiffuseColor", "vSpecularColor", "vFogInfos",
      "vFogColor",     "pointSize",     "vTextureInfos",  "mBones",
      "vClipPlane",    "vClipPlane2",   "vClipPlane3",    "vClipPlane4",
      "textureMatrix", "diffuse1Infos", "diffuse2Infos",  "diffuse3Infos"};

    const std::vector<std::string> samplers{
      "textureSampler", "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler",
      "bump1Sampler",   "bump2Sampler",    "bump3Sampler"};
    const std::vector<std::string> uniformBuffers{};

    EffectCreationOptions options;

    IEffectCreationOptions options;
    options.attributes            = std::move(attribs);
    options.uniformsNames         = std::move(uniforms);
    options.uniformBuffersNames   = std::move(uniformBuffers);
    options.samplers              = std::move(samplers);
    options.materialDefines       = &defines;
    options.fallbacks             = std::move(fallbacks);
    options.onCompiled            = onCompiled;
    options.onError               = onError;
    options.indexParameters
      = {{"maxSimultaneousLights", maxSimultaneousLights()}};

    MaterialHelper::PrepareUniformsAndSamplersList(options);
    subMesh->setEffect(
      scene->getEngine()->createEffect(shaderName, options, engine),
      definesPtr);
  }

  if (!subMesh->effect() || !subMesh->effect()->isReady()) {

  if (!subMesh->effect() || !subMesh->effect()->isReady()) {
    return false;
  }

  defines._renderId                      = scene->getRenderId();
  return true;
}

void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,
                                     SubMesh* subMesh)
{
  auto scene = getScene();

  auto _defines
    = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());
  if (!_defines) {
    return;
  }
    return;
  }
  auto defines = *_defines;

  auto effect = subMesh->effect();
  if (!effect) {
    return;
  }
  _activeEffect = effect;

  // Matrices
  bindOnlyWorldMatrix(world);
  _activeEffect->setMatrix("viewProjection", scene->getTransformMatrix());

  // Bones
  MaterialHelper::BindBonesParameters(mesh, _activeEffect.get());
    // Textures
    if (_mixTexture) {
      _activeEffect->setTexture("textureSampler", _mixTexture);
      _activeEffect->setFloat2(
        "vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),
        _mixTexture->level);
      _activeEffect->setMatrix("textureMatrix",
                               *_mixTexture->getTextureMatrix());

      if (StandardMaterial::DiffuseTextureEnabled()) {
        if (_diffuseTexture1) {
          _activeEffect->setTexture("diffuse1Sampler", _diffuseTexture1);
          _activeEffect->setFloat2("diffuse1Infos", _diffuseTexture1->uScale,
          _activeEffect->setTexture("diffuse1Sampler", _diffuseTexture1);
          _activeEffect->setFloat2("diffuse1Infos", _diffuseTexture1->uScale,
                                   _diffuseTexture1->vScale);
        }
        if (_diffuseTexture2) {
          _activeEffect->setTexture("diffuse2Sampler", _diffuseTexture2);
          _activeEffect->setFloat2("diffuse2Infos", _diffuseTexture2->uScale,
                                   _diffuseTexture2->vScale);
        }
        if (_diffuseTexture3) {
          _activeEffect->setTexture("diffuse3Sampler", _diffuseTexture3);
        }
      }

      if (StandardMaterial::BumpTextureEnabled()
          && scene->getEngine()->getCaps().standardDerivatives) {
        if (_bumpTexture1) {
          _activeEffect->setTexture("bump1Sampler", _bumpTexture1);
        if (_bumpTexture1) {
          _activeEffect->setTexture("bump1Sampler", _bumpTexture1);
        }
        if (_bumpTexture2) {
          _activeEffect->setTexture("bump2Sampler", _bumpTexture2);
        }
        if (_bumpTexture3) {
          _activeEffect->setTexture("bump3Sampler", _bumpTexture3);
        }
      }
    }
    // Clip plane
    MaterialHelper::BindClipPlane(_activeEffect, scene);

    // Point size
    if (pointsCloud()) {
      _activeEffect->setFloat("pointSize", pointSize);
    MaterialHelper::BindEyePosition(effect, scene);
  }

  _activeEffect->setColor4("vDiffuseColor", diffuseColor,
                           alpha * mesh->visibility);

  if (defines["SPECULARTERM"]) {
    _activeEffect->setColor4("vSpecularColor", specularColor, specularPower);
  }

  if (scene->lightsEnabled() && !_disableLighting) {
    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines,
                               maxSimultaneousLights());
  }

  // View
  if (scene->fogEnabled() && mesh->applyFog()
      && scene->fogMode() != Scene::FOGMODE_NONE) {
    _activeEffect->setMatrix("view", scene->getViewMatrix());
  }

  }

  // Fog
  MaterialHelper::BindFogParameters(scene, mesh, _activeEffect);

  _afterBind(mesh, _activeEffect);
}

std::vector<IAnimatablePtr> TerrainMaterial::getAnimatables()
{
  std::vector<IAnimatablePtr> results;

  if (_mixTexture && _mixTexture->animations.size() > 0) {
    results.emplace_back(_mixTexture);
  }

  return results;
}

std::vector<BaseTexturePtr> TerrainMaterial::getActiveTextures() const
{
  auto activeTextures = PushMaterial::getActiveTextures();

  if (_mixTexture) {
    activeTextures.emplace_back(_mixTexture);
  }

  if (_diffuseTexture1) {
    activeTextures.emplace_back(_diffuseTexture1);
  }

  if (_diffuseTexture2) {
    activeTextures.emplace_back(_diffuseTexture2);
  }

  if (_diffuseTexture3) {
    activeTextures.emplace_back(_diffuseTexture3);
  }

  if (_bumpTexture1) {
    activeTextures.emplace_back(_bumpTexture1);
  }

  if (_bumpTexture2) {
    activeTextures.emplace_back(_bumpTexture2);
  }

  if (_bumpTexture3) {
    activeTextures.emplace_back(_bumpTexture3);
  }

  return activeTextures;
}

bool TerrainMaterial::hasTexture(const BaseTexturePtr& texture) const
{
  if (PushMaterial::hasTexture(texture)) {
    return true;
  }

  if (_mixTexture == texture) {
    return true;
  }

  if (_diffuseTexture1 == texture) {
    return true;
  }

  if (_diffuseTexture2 == texture) {
    return true;
  }

  if (_diffuseTexture3 == texture) {
    return true;
  }

  if (_bumpTexture1 == texture) {
    return true;
  }

  if (_bumpTexture2 == texture) {
    return true;
  }

  if (_bumpTexture3 == texture) {
    return true;
  return false;
}

void TerrainMaterial::dispose(bool forceDisposeEffect,
                              bool forceDisposeTextures,
                              bool /*notBoundToMesh*/)
{
  if (_mixTexture) {
{
  if (_mixTexture) {
    _mixTexture->dispose();
  PushMaterial::dispose(forceDisposeEffect, forceDisposeTextures);
}

MaterialPtr TerrainMaterial::clone(const std::string& /*name*/,
                                   bool /*cloneChildren*/) const
{
  return nullptr;
}
  return nullptr;
}

json TerrainMaterial::serialize() const
{
  return nullptr;
}

  return "TerrainMaterial";
}

TerrainMaterial* TerrainMaterial::Parse(const json& /*source*/,
                                        Scene* /*scene*/,
                                        const std::string& /*rootUrl*/)
{
  return nullptr;
{
  return nullptr;
}

} // end of namespace MaterialsLibrary
} // end of namespace BABYLON

<MSG> Updated Terrain Material to v4.1.0-alpha.17

<DFF> @@ -8,8 +8,8 @@
 #include <babylon/materials/effect.h>
 #include <babylon/materials/effect_creation_options.h>
 #include <babylon/materials/effect_fallbacks.h>
+#include <babylon/materials/material_flags.h>
 #include <babylon/materials/material_helper.h>
-#include <babylon/materials/standard_material.h>
 #include <babylon/materials/textures/base_texture.h>
 #include <babylon/materials/textures/texture.h>
 #include <babylon/materialslibrary/terrain/terrain_fragment_fx.h>
@@ -23,20 +23,16 @@ namespace MaterialsLibrary {
 
 TerrainMaterial::TerrainMaterial(const std::string& iName, Scene* scene)
     : PushMaterial{iName, scene}
-    , mixTexture{this, &TerrainMaterial::get_mixTexture,
-                 &TerrainMaterial::set_mixTexture}
+    , mixTexture{this, &TerrainMaterial::get_mixTexture, &TerrainMaterial::set_mixTexture}
     , diffuseTexture1{this, &TerrainMaterial::get_diffuseTexture1,
                       &TerrainMaterial::set_diffuseTexture1}
     , diffuseTexture2{this, &TerrainMaterial::get_diffuseTexture2,
                       &TerrainMaterial::set_diffuseTexture2}
     , diffuseTexture3{this, &TerrainMaterial::get_diffuseTexture3,
                       &TerrainMaterial::set_diffuseTexture3}
-    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1,
-                   &TerrainMaterial::set_bumpTexture1}
-    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2,
-                   &TerrainMaterial::set_bumpTexture2}
-    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3,
-                   &TerrainMaterial::set_bumpTexture3}
+    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1, &TerrainMaterial::set_bumpTexture1}
+    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2, &TerrainMaterial::set_bumpTexture2}
+    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3, &TerrainMaterial::set_bumpTexture3}
     , diffuseColor{Color3(1.f, 1.f, 1.f)}
     , specularColor{Color3(0.f, 0.f, 0.f)}
     , specularPower{64.f}
@@ -196,8 +192,7 @@ BaseTexturePtr TerrainMaterial::getAlphaTestTexture()
   return nullptr;
 }
 
-bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
-                                        BaseSubMesh* subMesh, bool useInstances)
+bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh, BaseSubMesh* subMesh, bool useInstances)
 {
   if (isFrozen()) {
     if (_wasPreviouslyReady && subMesh->effect()) {
@@ -209,10 +204,9 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
     subMesh->_materialDefines = std::make_shared<TerrainMaterialDefines>();
   }
 
-  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(
-    subMesh->_materialDefines);
-  auto& defines = *definesPtr.get();
-  auto scene    = getScene();
+  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(subMesh->_materialDefines);
+  auto& defines   = *definesPtr.get();
+  auto scene      = getScene();
 
   if (!checkReadyOnEveryCall && subMesh->effect()) {
     if (_renderId == scene->getRenderId()) {
@@ -224,26 +218,44 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
 
   // Textures
   if (scene->texturesEnabled()) {
-    if (_mixTexture && StandardMaterial::DiffuseTextureEnabled()) {
-      if (!_mixTexture->isReady()) {
+    if (!mixTexture() || !mixTexture()->isReady()) {
+      return false;
+    }
+
+    defines._needUVs = true;
+
+    if (MaterialFlags::DiffuseTextureEnabled()) {
+      if (!diffuseTexture1() || !diffuseTexture1()->isReady()) {
+        return false;
+      }
+      if (!diffuseTexture2() || !diffuseTexture2()->isReady()) {
         return false;
       }
-      else {
-        defines._needUVs           = true;
-        defines.boolDef["DIFFUSE"] = true;
+      if (!diffuseTexture3() || !diffuseTexture3()->isReady()) {
+        return false;
       }
+
+      defines.boolDef["DIFFUSE"] = true;
     }
-    if ((_bumpTexture1 || _bumpTexture2 || _bumpTexture3)
-        && StandardMaterial::BumpTextureEnabled()) {
-      defines._needUVs        = true;
+
+    if (bumpTexture1() && bumpTexture2() && bumpTexture3() && MaterialFlags::BumpTextureEnabled()) {
+      if (!bumpTexture1()->isReady()) {
+        return false;
+      }
+      if (!bumpTexture2()->isReady()) {
+        return false;
+      }
+      if (!bumpTexture3()->isReady()) {
+        return false;
+      }
+
       defines._needNormals    = true;
       defines.boolDef["BUMP"] = true;
     }
   }
 
   // Misc.
-  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(),
-                                        fogEnabled(),
+  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(), fogEnabled(),
                                         _shouldTurnAlphaTestOn(mesh), defines);
 
   // Lights
@@ -267,8 +279,7 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
       fallbacks->addFallback(1, "FOG");
     }
 
-    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks,
-                                              maxSimultaneousLights());
+    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks, maxSimultaneousLights());
 
     if (defines.intDef["NUM_BONE_INFLUENCERS"] > 0) {
       fallbacks->addCPUSkinningFallback(0, mesh);
@@ -293,8 +304,7 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
       attribs.emplace_back(VertexBuffer::ColorKind);
     }
 
-    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines,
-                                              *fallbacks);
+    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines, *fallbacks);
     MaterialHelper::PrepareAttributesForInstances(attribs, defines);
 
     // Legacy browser patch
@@ -302,15 +312,14 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
     auto join = defines.toString();
 
     const std::vector<std::string> uniforms{
-      "world",         "view",          "viewProjection", "vEyePosition",
-      "vLightsType",   "vDiffuseColor", "vSpecularColor", "vFogInfos",
-      "vFogColor",     "pointSize",     "vTextureInfos",  "mBones",
-      "vClipPlane",    "vClipPlane2",   "vClipPlane3",    "vClipPlane4",
-      "textureMatrix", "diffuse1Infos", "diffuse2Infos",  "diffuse3Infos"};
-
-    const std::vector<std::string> samplers{
-      "textureSampler", "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler",
-      "bump1Sampler",   "bump2Sampler",    "bump3Sampler"};
+      "world",         "view",           "viewProjection", "vEyePosition",  "vLightsType",
+      "vDiffuseColor", "vSpecularColor", "vFogInfos",      "vFogColor",     "pointSize",
+      "vTextureInfos", "mBones",         "vClipPlane",     "vClipPlane2",   "vClipPlane3",
+      "vClipPlane4",   "textureMatrix",  "diffuse1Infos",  "diffuse2Infos", "diffuse3Infos"};
+
+    const std::vector<std::string> samplers{"textureSampler",  "diffuse1Sampler", "diffuse2Sampler",
+                                            "diffuse3Sampler", "bump1Sampler",    "bump2Sampler",
+                                            "bump3Sampler"};
     const std::vector<std::string> uniformBuffers{};
 
     EffectCreationOptions options;
@@ -324,13 +333,10 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
     options.fallbacks             = std::move(fallbacks);
     options.onCompiled            = onCompiled;
     options.onError               = onError;
-    options.indexParameters
-      = {{"maxSimultaneousLights", maxSimultaneousLights()}};
+    options.indexParameters       = {{"maxSimultaneousLights", maxSimultaneousLights()}};
 
     MaterialHelper::PrepareUniformsAndSamplersList(options);
-    subMesh->setEffect(
-      scene->getEngine()->createEffect(shaderName, options, engine),
-      definesPtr);
+    subMesh->setEffect(scene->getEngine()->createEffect(shaderName, options, engine), definesPtr);
   }
 
   if (!subMesh->effect() || !subMesh->effect()->isReady()) {
@@ -343,13 +349,11 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,
   return true;
 }
 
-void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,
-                                     SubMesh* subMesh)
+void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh, SubMesh* subMesh)
 {
   auto scene = getScene();
 
-  auto _defines
-    = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());
+  auto _defines = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());
   if (!_defines) {
     return;
   }
@@ -372,13 +376,11 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,
     // Textures
     if (_mixTexture) {
       _activeEffect->setTexture("textureSampler", _mixTexture);
-      _activeEffect->setFloat2(
-        "vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),
-        _mixTexture->level);
-      _activeEffect->setMatrix("textureMatrix",
-                               *_mixTexture->getTextureMatrix());
+      _activeEffect->setFloat2("vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),
+                               _mixTexture->level);
+      _activeEffect->setMatrix("textureMatrix", *_mixTexture->getTextureMatrix());
 
-      if (StandardMaterial::DiffuseTextureEnabled()) {
+      if (MaterialFlags::DiffuseTextureEnabled()) {
         if (_diffuseTexture1) {
           _activeEffect->setTexture("diffuse1Sampler", _diffuseTexture1);
           _activeEffect->setFloat2("diffuse1Infos", _diffuseTexture1->uScale,
@@ -396,7 +398,7 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,
         }
       }
 
-      if (StandardMaterial::BumpTextureEnabled()
+      if (MaterialFlags::BumpTextureEnabled()
           && scene->getEngine()->getCaps().standardDerivatives) {
         if (_bumpTexture1) {
           _activeEffect->setTexture("bump1Sampler", _bumpTexture1);
@@ -420,21 +422,18 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,
     MaterialHelper::BindEyePosition(effect, scene);
   }
 
-  _activeEffect->setColor4("vDiffuseColor", diffuseColor,
-                           alpha * mesh->visibility);
+  _activeEffect->setColor4("vDiffuseColor", diffuseColor, alpha * mesh->visibility);
 
   if (defines["SPECULARTERM"]) {
     _activeEffect->setColor4("vSpecularColor", specularColor, specularPower);
   }
 
   if (scene->lightsEnabled() && !_disableLighting) {
-    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines,
-                               maxSimultaneousLights());
+    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines, maxSimultaneousLights());
   }
 
   // View
-  if (scene->fogEnabled() && mesh->applyFog()
-      && scene->fogMode() != Scene::FOGMODE_NONE) {
+  if (scene->fogEnabled() && mesh->applyFog() && scene->fogMode() != Scene::FOGMODE_NONE) {
     _activeEffect->setMatrix("view", scene->getViewMatrix());
   }
 
@@ -527,8 +526,7 @@ bool TerrainMaterial::hasTexture(const BaseTexturePtr& texture) const
   return false;
 }
 
-void TerrainMaterial::dispose(bool forceDisposeEffect,
-                              bool forceDisposeTextures,
+void TerrainMaterial::dispose(bool forceDisposeEffect, bool forceDisposeTextures,
                               bool /*notBoundToMesh*/)
 {
   if (_mixTexture) {
@@ -538,8 +536,7 @@ void TerrainMaterial::dispose(bool forceDisposeEffect,
   PushMaterial::dispose(forceDisposeEffect, forceDisposeTextures);
 }
 
-MaterialPtr TerrainMaterial::clone(const std::string& /*name*/,
-                                   bool /*cloneChildren*/) const
+MaterialPtr TerrainMaterial::clone(const std::string& /*name*/, bool /*cloneChildren*/) const
 {
   return nullptr;
 }
@@ -554,8 +551,7 @@ std::string TerrainMaterial::getClassName() const
   return "TerrainMaterial";
 }
 
-TerrainMaterial* TerrainMaterial::Parse(const json& /*source*/,
-                                        Scene* /*scene*/,
+TerrainMaterial* TerrainMaterial::Parse(const json& /*source*/, Scene* /*scene*/,
                                         const std::string& /*rootUrl*/)
 {
   return nullptr;

{'commit': 'diff --git a/src/MaterialsLibrary/src/materialslibrary/terrain/terrain_material.cpp b/src/MaterialsLibrary/src/materialslibrary/terrain/terrain_material.cpp\nindex 854973360..ab37e1adc 100644\n--- a/src/MaterialsLibrary/src/materialslibrary/terrain/terrain_material.cpp\n+++ b/src/MaterialsLibrary/src/materialslibrary/terrain/terrain_material.cpp\n@@ -8,8 +8,8 @@\n #include <babylon/materials/effect.h>\n #include <babylon/materials/effect_creation_options.h>\n #include <babylon/materials/effect_fallbacks.h>\n+#include <babylon/materials/material_flags.h>\n #include <babylon/materials/material_helper.h>\n-#include <babylon/materials/standard_material.h>\n #include <babylon/materials/textures/base_texture.h>\n #include <babylon/materials/textures/texture.h>\n #include <babylon/materialslibrary/terrain/terrain_fragment_fx.h>\n@@ -23,20 +23,16 @@ namespace MaterialsLibrary {\n \n TerrainMaterial::TerrainMaterial(const std::string& iName, Scene* scene)\n     : PushMaterial{iName, scene}\n-    , mixTexture{this, &TerrainMaterial::get_mixTexture,\n-                 &TerrainMaterial::set_mixTexture}\n+    , mixTexture{this, &TerrainMaterial::get_mixTexture, &TerrainMaterial::set_mixTexture}\n     , diffuseTexture1{this, &TerrainMaterial::get_diffuseTexture1,\n                       &TerrainMaterial::set_diffuseTexture1}\n     , diffuseTexture2{this, &TerrainMaterial::get_diffuseTexture2,\n                       &TerrainMaterial::set_diffuseTexture2}\n     , diffuseTexture3{this, &TerrainMaterial::get_diffuseTexture3,\n                       &TerrainMaterial::set_diffuseTexture3}\n-    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1,\n-                   &TerrainMaterial::set_bumpTexture1}\n-    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2,\n-                   &TerrainMaterial::set_bumpTexture2}\n-    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3,\n-                   &TerrainMaterial::set_bumpTexture3}\n+    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1, &TerrainMaterial::set_bumpTexture1}\n+    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2, &TerrainMaterial::set_bumpTexture2}\n+    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3, &TerrainMaterial::set_bumpTexture3}\n     , diffuseColor{Color3(1.f, 1.f, 1.f)}\n     , specularColor{Color3(0.f, 0.f, 0.f)}\n     , specularPower{64.f}\n@@ -196,8 +192,7 @@ BaseTexturePtr TerrainMaterial::getAlphaTestTexture()\n   return nullptr;\n }\n \n-bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n-                                        BaseSubMesh* subMesh, bool useInstances)\n+bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh, BaseSubMesh* subMesh, bool useInstances)\n {\n   if (isFrozen()) {\n     if (_wasPreviouslyReady && subMesh->effect()) {\n@@ -209,10 +204,9 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n     subMesh->_materialDefines = std::make_shared<TerrainMaterialDefines>();\n   }\n \n-  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(\n-    subMesh->_materialDefines);\n-  auto& defines = *definesPtr.get();\n-  auto scene    = getScene();\n+  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(subMesh->_materialDefines);\n+  auto& defines   = *definesPtr.get();\n+  auto scene      = getScene();\n \n   if (!checkReadyOnEveryCall && subMesh->effect()) {\n     if (_renderId == scene->getRenderId()) {\n@@ -224,26 +218,44 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n \n   // Textures\n   if (scene->texturesEnabled()) {\n-    if (_mixTexture && StandardMaterial::DiffuseTextureEnabled()) {\n-      if (!_mixTexture->isReady()) {\n+    if (!mixTexture() || !mixTexture()->isReady()) {\n+      return false;\n+    }\n+\n+    defines._needUVs = true;\n+\n+    if (MaterialFlags::DiffuseTextureEnabled()) {\n+      if (!diffuseTexture1() || !diffuseTexture1()->isReady()) {\n+        return false;\n+      }\n+      if (!diffuseTexture2() || !diffuseTexture2()->isReady()) {\n         return false;\n       }\n-      else {\n-        defines._needUVs           = true;\n-        defines.boolDef["DIFFUSE"] = true;\n+      if (!diffuseTexture3() || !diffuseTexture3()->isReady()) {\n+        return false;\n       }\n+\n+      defines.boolDef["DIFFUSE"] = true;\n     }\n-    if ((_bumpTexture1 || _bumpTexture2 || _bumpTexture3)\n-        && StandardMaterial::BumpTextureEnabled()) {\n-      defines._needUVs        = true;\n+\n+    if (bumpTexture1() && bumpTexture2() && bumpTexture3() && MaterialFlags::BumpTextureEnabled()) {\n+      if (!bumpTexture1()->isReady()) {\n+        return false;\n+      }\n+      if (!bumpTexture2()->isReady()) {\n+        return false;\n+      }\n+      if (!bumpTexture3()->isReady()) {\n+        return false;\n+      }\n+\n       defines._needNormals    = true;\n       defines.boolDef["BUMP"] = true;\n     }\n   }\n \n   // Misc.\n-  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(),\n-                                        fogEnabled(),\n+  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(), fogEnabled(),\n                                         _shouldTurnAlphaTestOn(mesh), defines);\n \n   // Lights\n@@ -267,8 +279,7 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n       fallbacks->addFallback(1, "FOG");\n     }\n \n-    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks,\n-                                              maxSimultaneousLights());\n+    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks, maxSimultaneousLights());\n \n     if (defines.intDef["NUM_BONE_INFLUENCERS"] > 0) {\n       fallbacks->addCPUSkinningFallback(0, mesh);\n@@ -293,8 +304,7 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n       attribs.emplace_back(VertexBuffer::ColorKind);\n     }\n \n-    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines,\n-                                              *fallbacks);\n+    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines, *fallbacks);\n     MaterialHelper::PrepareAttributesForInstances(attribs, defines);\n \n     // Legacy browser patch\n@@ -302,15 +312,14 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n     auto join = defines.toString();\n \n     const std::vector<std::string> uniforms{\n-      "world",         "view",          "viewProjection", "vEyePosition",\n-      "vLightsType",   "vDiffuseColor", "vSpecularColor", "vFogInfos",\n-      "vFogColor",     "pointSize",     "vTextureInfos",  "mBones",\n-      "vClipPlane",    "vClipPlane2",   "vClipPlane3",    "vClipPlane4",\n-      "textureMatrix", "diffuse1Infos", "diffuse2Infos",  "diffuse3Infos"};\n-\n-    const std::vector<std::string> samplers{\n-      "textureSampler", "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler",\n-      "bump1Sampler",   "bump2Sampler",    "bump3Sampler"};\n+      "world",         "view",           "viewProjection", "vEyePosition",  "vLightsType",\n+      "vDiffuseColor", "vSpecularColor", "vFogInfos",      "vFogColor",     "pointSize",\n+      "vTextureInfos", "mBones",         "vClipPlane",     "vClipPlane2",   "vClipPlane3",\n+      "vClipPlane4",   "textureMatrix",  "diffuse1Infos",  "diffuse2Infos", "diffuse3Infos"};\n+\n+    const std::vector<std::string> samplers{"textureSampler",  "diffuse1Sampler", "diffuse2Sampler",\n+                                            "diffuse3Sampler", "bump1Sampler",    "bump2Sampler",\n+                                            "bump3Sampler"};\n     const std::vector<std::string> uniformBuffers{};\n \n     EffectCreationOptions options;\n@@ -324,13 +333,10 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n     options.fallbacks             = std::move(fallbacks);\n     options.onCompiled            = onCompiled;\n     options.onError               = onError;\n-    options.indexParameters\n-      = {{"maxSimultaneousLights", maxSimultaneousLights()}};\n+    options.indexParameters       = {{"maxSimultaneousLights", maxSimultaneousLights()}};\n \n     MaterialHelper::PrepareUniformsAndSamplersList(options);\n-    subMesh->setEffect(\n-      scene->getEngine()->createEffect(shaderName, options, engine),\n-      definesPtr);\n+    subMesh->setEffect(scene->getEngine()->createEffect(shaderName, options, engine), definesPtr);\n   }\n \n   if (!subMesh->effect() || !subMesh->effect()->isReady()) {\n@@ -343,13 +349,11 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n   return true;\n }\n \n-void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n-                                     SubMesh* subMesh)\n+void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh, SubMesh* subMesh)\n {\n   auto scene = getScene();\n \n-  auto _defines\n-    = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());\n+  auto _defines = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());\n   if (!_defines) {\n     return;\n   }\n@@ -372,13 +376,11 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n     // Textures\n     if (_mixTexture) {\n       _activeEffect->setTexture("textureSampler", _mixTexture);\n-      _activeEffect->setFloat2(\n-        "vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),\n-        _mixTexture->level);\n-      _activeEffect->setMatrix("textureMatrix",\n-                               *_mixTexture->getTextureMatrix());\n+      _activeEffect->setFloat2("vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),\n+                               _mixTexture->level);\n+      _activeEffect->setMatrix("textureMatrix", *_mixTexture->getTextureMatrix());\n \n-      if (StandardMaterial::DiffuseTextureEnabled()) {\n+      if (MaterialFlags::DiffuseTextureEnabled()) {\n         if (_diffuseTexture1) {\n           _activeEffect->setTexture("diffuse1Sampler", _diffuseTexture1);\n           _activeEffect->setFloat2("diffuse1Infos", _diffuseTexture1->uScale,\n@@ -396,7 +398,7 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n         }\n       }\n \n-      if (StandardMaterial::BumpTextureEnabled()\n+      if (MaterialFlags::BumpTextureEnabled()\n           && scene->getEngine()->getCaps().standardDerivatives) {\n         if (_bumpTexture1) {\n           _activeEffect->setTexture("bump1Sampler", _bumpTexture1);\n@@ -420,21 +422,18 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n     MaterialHelper::BindEyePosition(effect, scene);\n   }\n \n-  _activeEffect->setColor4("vDiffuseColor", diffuseColor,\n-                           alpha * mesh->visibility);\n+  _activeEffect->setColor4("vDiffuseColor", diffuseColor, alpha * mesh->visibility);\n \n   if (defines["SPECULARTERM"]) {\n     _activeEffect->setColor4("vSpecularColor", specularColor, specularPower);\n   }\n \n   if (scene->lightsEnabled() && !_disableLighting) {\n-    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines,\n-                               maxSimultaneousLights());\n+    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines, maxSimultaneousLights());\n   }\n \n   // View\n-  if (scene->fogEnabled() && mesh->applyFog()\n-      && scene->fogMode() != Scene::FOGMODE_NONE) {\n+  if (scene->fogEnabled() && mesh->applyFog() && scene->fogMode() != Scene::FOGMODE_NONE) {\n     _activeEffect->setMatrix("view", scene->getViewMatrix());\n   }\n \n@@ -527,8 +526,7 @@ bool TerrainMaterial::hasTexture(const BaseTexturePtr& texture) const\n   return false;\n }\n \n-void TerrainMaterial::dispose(bool forceDisposeEffect,\n-                              bool forceDisposeTextures,\n+void TerrainMaterial::dispose(bool forceDisposeEffect, bool forceDisposeTextures,\n                               bool /*notBoundToMesh*/)\n {\n   if (_mixTexture) {\n@@ -538,8 +536,7 @@ void TerrainMaterial::dispose(bool forceDisposeEffect,\n   PushMaterial::dispose(forceDisposeEffect, forceDisposeTextures);\n }\n \n-MaterialPtr TerrainMaterial::clone(const std::string& /*name*/,\n-                                   bool /*cloneChildren*/) const\n+MaterialPtr TerrainMaterial::clone(const std::string& /*name*/, bool /*cloneChildren*/) const\n {\n   return nullptr;\n }\n@@ -554,8 +551,7 @@ std::string TerrainMaterial::getClassName() const\n   return "TerrainMaterial";\n }\n \n-TerrainMaterial* TerrainMaterial::Parse(const json& /*source*/,\n-                                        Scene* /*scene*/,\n+TerrainMaterial* TerrainMaterial::Parse(const json& /*source*/, Scene* /*scene*/,\n                                         const std::string& /*rootUrl*/)\n {\n   return nullptr;\n', 'commit_subject': 'Updated Terrain Material to v4.1.0-alpha.17', 'repo_name': 'samdauwe/BabylonCpp', 'committer': {'name': 'samdauwe', 'email': '637c8055e0642816555907e78ef80a031b1d7a65@gmail.com', 'time_sec': '1575353234', 'tz_offset': '60', 'date': {'seconds': '1575353234'}}, 'commit_tree': '4e0439b64f51b15c062e2eb3a0c07a7dadfdc1b8', 'commit_message': 'Updated Terrain Material to v4.1.0-alpha.17\n', 'language_name': 'HTML', 'license': 'apache-2.0', 'hunks': '@@ -8,8 +8,8 @@\n #include <babylon/materials/effect.h>\n #include <babylon/materials/effect_creation_options.h>\n #include <babylon/materials/effect_fallbacks.h>\n+#include <babylon/materials/material_flags.h>\n #include <babylon/materials/material_helper.h>\n-#include <babylon/materials/standard_material.h>\n #include <babylon/materials/textures/base_texture.h>\n #include <babylon/materials/textures/texture.h>\n #include <babylon/materialslibrary/terrain/terrain_fragment_fx.h>\n@@ -23,20 +23,16 @@ namespace MaterialsLibrary {\n \n TerrainMaterial::TerrainMaterial(const std::string& iName, Scene* scene)\n     : PushMaterial{iName, scene}\n-    , mixTexture{this, &TerrainMaterial::get_mixTexture,\n-                 &TerrainMaterial::set_mixTexture}\n+    , mixTexture{this, &TerrainMaterial::get_mixTexture, &TerrainMaterial::set_mixTexture}\n     , diffuseTexture1{this, &TerrainMaterial::get_diffuseTexture1,\n                       &TerrainMaterial::set_diffuseTexture1}\n     , diffuseTexture2{this, &TerrainMaterial::get_diffuseTexture2,\n                       &TerrainMaterial::set_diffuseTexture2}\n     , diffuseTexture3{this, &TerrainMaterial::get_diffuseTexture3,\n                       &TerrainMaterial::set_diffuseTexture3}\n-    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1,\n-                   &TerrainMaterial::set_bumpTexture1}\n-    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2,\n-                   &TerrainMaterial::set_bumpTexture2}\n-    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3,\n-                   &TerrainMaterial::set_bumpTexture3}\n+    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1, &TerrainMaterial::set_bumpTexture1}\n+    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2, &TerrainMaterial::set_bumpTexture2}\n+    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3, &TerrainMaterial::set_bumpTexture3}\n     , diffuseColor{Color3(1.f, 1.f, 1.f)}\n     , specularColor{Color3(0.f, 0.f, 0.f)}\n     , specularPower{64.f}\n@@ -196,8 +192,7 @@ BaseTexturePtr TerrainMaterial::getAlphaTestTexture()\n   return nullptr;\n }\n \n-bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n-                                        BaseSubMesh* subMesh, bool useInstances)\n+bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh, BaseSubMesh* subMesh, bool useInstances)\n {\n   if (isFrozen()) {\n     if (_wasPreviouslyReady && subMesh->effect()) {\n@@ -209,10 +204,9 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n     subMesh->_materialDefines = std::make_shared<TerrainMaterialDefines>();\n   }\n \n-  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(\n-    subMesh->_materialDefines);\n-  auto& defines = *definesPtr.get();\n-  auto scene    = getScene();\n+  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(subMesh->_materialDefines);\n+  auto& defines   = *definesPtr.get();\n+  auto scene      = getScene();\n \n   if (!checkReadyOnEveryCall && subMesh->effect()) {\n     if (_renderId == scene->getRenderId()) {\n@@ -224,26 +218,44 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n \n   // Textures\n   if (scene->texturesEnabled()) {\n-    if (_mixTexture && StandardMaterial::DiffuseTextureEnabled()) {\n-      if (!_mixTexture->isReady()) {\n+    if (!mixTexture() || !mixTexture()->isReady()) {\n+      return false;\n+    }\n+\n+    defines._needUVs = true;\n+\n+    if (MaterialFlags::DiffuseTextureEnabled()) {\n+      if (!diffuseTexture1() || !diffuseTexture1()->isReady()) {\n+        return false;\n+      }\n+      if (!diffuseTexture2() || !diffuseTexture2()->isReady()) {\n         return false;\n       }\n-      else {\n-        defines._needUVs           = true;\n-        defines.boolDef["DIFFUSE"] = true;\n+      if (!diffuseTexture3() || !diffuseTexture3()->isReady()) {\n+        return false;\n       }\n+\n+      defines.boolDef["DIFFUSE"] = true;\n     }\n-    if ((_bumpTexture1 || _bumpTexture2 || _bumpTexture3)\n-        && StandardMaterial::BumpTextureEnabled()) {\n-      defines._needUVs        = true;\n+\n+    if (bumpTexture1() && bumpTexture2() && bumpTexture3() && MaterialFlags::BumpTextureEnabled()) {\n+      if (!bumpTexture1()->isReady()) {\n+        return false;\n+      }\n+      if (!bumpTexture2()->isReady()) {\n+        return false;\n+      }\n+      if (!bumpTexture3()->isReady()) {\n+        return false;\n+      }\n+\n       defines._needNormals    = true;\n       defines.boolDef["BUMP"] = true;\n     }\n   }\n \n   // Misc.\n-  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(),\n-                                        fogEnabled(),\n+  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(), fogEnabled(),\n                                         _shouldTurnAlphaTestOn(mesh), defines);\n \n   // Lights\n@@ -267,8 +279,7 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n       fallbacks->addFallback(1, "FOG");\n     }\n \n-    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks,\n-                                              maxSimultaneousLights());\n+    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks, maxSimultaneousLights());\n \n     if (defines.intDef["NUM_BONE_INFLUENCERS"] > 0) {\n       fallbacks->addCPUSkinningFallback(0, mesh);\n@@ -293,8 +304,7 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n       attribs.emplace_back(VertexBuffer::ColorKind);\n     }\n \n-    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines,\n-                                              *fallbacks);\n+    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines, *fallbacks);\n     MaterialHelper::PrepareAttributesForInstances(attribs, defines);\n \n     // Legacy browser patch\n@@ -302,15 +312,14 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n     auto join = defines.toString();\n \n     const std::vector<std::string> uniforms{\n-      "world",         "view",          "viewProjection", "vEyePosition",\n-      "vLightsType",   "vDiffuseColor", "vSpecularColor", "vFogInfos",\n-      "vFogColor",     "pointSize",     "vTextureInfos",  "mBones",\n-      "vClipPlane",    "vClipPlane2",   "vClipPlane3",    "vClipPlane4",\n-      "textureMatrix", "diffuse1Infos", "diffuse2Infos",  "diffuse3Infos"};\n-\n-    const std::vector<std::string> samplers{\n-      "textureSampler", "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler",\n-      "bump1Sampler",   "bump2Sampler",    "bump3Sampler"};\n+      "world",         "view",           "viewProjection", "vEyePosition",  "vLightsType",\n+      "vDiffuseColor", "vSpecularColor", "vFogInfos",      "vFogColor",     "pointSize",\n+      "vTextureInfos", "mBones",         "vClipPlane",     "vClipPlane2",   "vClipPlane3",\n+      "vClipPlane4",   "textureMatrix",  "diffuse1Infos",  "diffuse2Infos", "diffuse3Infos"};\n+\n+    const std::vector<std::string> samplers{"textureSampler",  "diffuse1Sampler", "diffuse2Sampler",\n+                                            "diffuse3Sampler", "bump1Sampler",    "bump2Sampler",\n+                                            "bump3Sampler"};\n     const std::vector<std::string> uniformBuffers{};\n \n     EffectCreationOptions options;\n@@ -324,13 +333,10 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n     options.fallbacks             = std::move(fallbacks);\n     options.onCompiled            = onCompiled;\n     options.onError               = onError;\n-    options.indexParameters\n-      = {{"maxSimultaneousLights", maxSimultaneousLights()}};\n+    options.indexParameters       = {{"maxSimultaneousLights", maxSimultaneousLights()}};\n \n     MaterialHelper::PrepareUniformsAndSamplersList(options);\n-    subMesh->setEffect(\n-      scene->getEngine()->createEffect(shaderName, options, engine),\n-      definesPtr);\n+    subMesh->setEffect(scene->getEngine()->createEffect(shaderName, options, engine), definesPtr);\n   }\n \n   if (!subMesh->effect() || !subMesh->effect()->isReady()) {\n@@ -343,13 +349,11 @@ bool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n   return true;\n }\n \n-void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n-                                     SubMesh* subMesh)\n+void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh, SubMesh* subMesh)\n {\n   auto scene = getScene();\n \n-  auto _defines\n-    = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());\n+  auto _defines = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());\n   if (!_defines) {\n     return;\n   }\n@@ -372,13 +376,11 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n     // Textures\n     if (_mixTexture) {\n       _activeEffect->setTexture("textureSampler", _mixTexture);\n-      _activeEffect->setFloat2(\n-        "vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),\n-        _mixTexture->level);\n-      _activeEffect->setMatrix("textureMatrix",\n-                               *_mixTexture->getTextureMatrix());\n+      _activeEffect->setFloat2("vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),\n+                               _mixTexture->level);\n+      _activeEffect->setMatrix("textureMatrix", *_mixTexture->getTextureMatrix());\n \n-      if (StandardMaterial::DiffuseTextureEnabled()) {\n+      if (MaterialFlags::DiffuseTextureEnabled()) {\n         if (_diffuseTexture1) {\n           _activeEffect->setTexture("diffuse1Sampler", _diffuseTexture1);\n           _activeEffect->setFloat2("diffuse1Infos", _diffuseTexture1->uScale,\n@@ -396,7 +398,7 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n         }\n       }\n \n-      if (StandardMaterial::BumpTextureEnabled()\n+      if (MaterialFlags::BumpTextureEnabled()\n           && scene->getEngine()->getCaps().standardDerivatives) {\n         if (_bumpTexture1) {\n           _activeEffect->setTexture("bump1Sampler", _bumpTexture1);\n@@ -420,21 +422,18 @@ void TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n     MaterialHelper::BindEyePosition(effect, scene);\n   }\n \n-  _activeEffect->setColor4("vDiffuseColor", diffuseColor,\n-                           alpha * mesh->visibility);\n+  _activeEffect->setColor4("vDiffuseColor", diffuseColor, alpha * mesh->visibility);\n \n   if (defines["SPECULARTERM"]) {\n     _activeEffect->setColor4("vSpecularColor", specularColor, specularPower);\n   }\n \n   if (scene->lightsEnabled() && !_disableLighting) {\n-    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines,\n-                               maxSimultaneousLights());\n+    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines, maxSimultaneousLights());\n   }\n \n   // View\n-  if (scene->fogEnabled() && mesh->applyFog()\n-      && scene->fogMode() != Scene::FOGMODE_NONE) {\n+  if (scene->fogEnabled() && mesh->applyFog() && scene->fogMode() != Scene::FOGMODE_NONE) {\n     _activeEffect->setMatrix("view", scene->getViewMatrix());\n   }\n \n@@ -527,8 +526,7 @@ bool TerrainMaterial::hasTexture(const BaseTexturePtr& texture) const\n   return false;\n }\n \n-void TerrainMaterial::dispose(bool forceDisposeEffect,\n-                              bool forceDisposeTextures,\n+void TerrainMaterial::dispose(bool forceDisposeEffect, bool forceDisposeTextures,\n                               bool /*notBoundToMesh*/)\n {\n   if (_mixTexture) {\n@@ -538,8 +536,7 @@ void TerrainMaterial::dispose(bool forceDisposeEffect,\n   PushMaterial::dispose(forceDisposeEffect, forceDisposeTextures);\n }\n \n-MaterialPtr TerrainMaterial::clone(const std::string& /*name*/,\n-                                   bool /*cloneChildren*/) const\n+MaterialPtr TerrainMaterial::clone(const std::string& /*name*/, bool /*cloneChildren*/) const\n {\n   return nullptr;\n }\n@@ -554,8 +551,7 @@ std::string TerrainMaterial::getClassName() const\n   return "TerrainMaterial";\n }\n \n-TerrainMaterial* TerrainMaterial::Parse(const json& /*source*/,\n-                                        Scene* /*scene*/,\n+TerrainMaterial* TerrainMaterial::Parse(const json& /*source*/, Scene* /*scene*/,\n                                         const std::string& /*rootUrl*/)\n {\n   return nullptr;\n', 'addition_count': 62, 'deletion_count': 66, 'src_file': 'a/src/MaterialsLibrary/src/materialslibrary/terrain/terrain_material.cpp', 'tgt_file': 'b/src/MaterialsLibrary/src/materialslibrary/terrain/terrain_material.cpp', 'file_extension': '.cpp', 'before_file': '#include <babylon/materialslibrary/terrain/terrain_material.h>\n\n#include <nlohmann/json.hpp>\n\n#include <babylon/cameras/camera.h>\n#include <babylon/engines/engine.h>\n#include <babylon/engines/scene.h>\n#include <babylon/materials/effect.h>\n#include <babylon/materials/effect_creation_options.h>\n#include <babylon/materials/effect_fallbacks.h>\n#include <babylon/materials/material_helper.h>\n#include <babylon/materials/standard_material.h>\n#include <babylon/materials/textures/base_texture.h>\n#include <babylon/materials/textures/texture.h>\n#include <babylon/materialslibrary/terrain/terrain_fragment_fx.h>\n#include <babylon/materialslibrary/terrain/terrain_fragment_fx.h>\n#include <babylon/materialslibrary/terrain/terrain_vertex_fx.h>\n#include <babylon/meshes/mesh.h>\n#include <babylon/meshes/sub_mesh.h>\n#include <babylon/meshes/vertex_buffer.h>\n\nnamespace BABYLON {\n\nTerrainMaterial::TerrainMaterial(const std::string& iName, Scene* scene)\n    : PushMaterial{iName, scene}\n    , mixTexture{this, &TerrainMaterial::get_mixTexture,\n                 &TerrainMaterial::set_mixTexture}\n    , diffuseTexture1{this, &TerrainMaterial::get_diffuseTexture1,\n                      &TerrainMaterial::set_diffuseTexture1}\n    , diffuseTexture2{this, &TerrainMaterial::get_diffuseTexture2,\n                      &TerrainMaterial::set_diffuseTexture2}\n    , diffuseTexture3{this, &TerrainMaterial::get_diffuseTexture3,\n                      &TerrainMaterial::set_diffuseTexture3}\n    , bumpTexture1{this, &TerrainMaterial::get_bumpTexture1,\n                   &TerrainMaterial::set_bumpTexture1}\n    , bumpTexture2{this, &TerrainMaterial::get_bumpTexture2,\n                   &TerrainMaterial::set_bumpTexture2}\n    , bumpTexture3{this, &TerrainMaterial::get_bumpTexture3,\n                   &TerrainMaterial::set_bumpTexture3}\n    , diffuseColor{Color3(1.f, 1.f, 1.f)}\n    , specularColor{Color3(0.f, 0.f, 0.f)}\n    , specularPower{64.f}\n    , specularPower{64.f}\n    , disableLighting{this, &TerrainMaterial::get_disableLighting,\n                      &TerrainMaterial::set_disableLighting}\n    , maxSimultaneousLights{this, &TerrainMaterial::get_maxSimultaneousLights,\n                            &TerrainMaterial::set_maxSimultaneousLights}\n    , _mixTexture{nullptr}\n    , _diffuseTexture1{nullptr}\n    , _diffuseTexture2{nullptr}\n    , _diffuseTexture3{nullptr}\n    , _bumpTexture1{nullptr}\n    , _bumpTexture2{nullptr}\n    , _bumpTexture3{nullptr}\n    , _disableLighting{false}\n    , _maxSimultaneousLights{4}\n{\n  // Vertex shader\n  Effect::ShadersStore()["terrainVertexShader"] = terrainVertexShader;\n\n  // Fragment shader\n  Effect::ShadersStore()["terrainPixelShader"] = terrainPixelShader;\n}\n\nTerrainMaterial::~TerrainMaterial() = default;\n\nBaseTexturePtr& TerrainMaterial::get_mixTexture()\n{\n  return _mixTexture;\n}\n\nvoid TerrainMaterial::set_mixTexture(const BaseTexturePtr& value)\n{\n  if (_mixTexture != value) {\n    _mixTexture = value;\n    _markAllSubMeshesAsTexturesDirty();\n  }\n}\n\nTexturePtr& TerrainMaterial::get_diffuseTexture1()\n{\n  return _diffuseTexture1;\n}\n\nvoid TerrainMaterial::set_diffuseTexture1(const TexturePtr& value)\n{\n  if (_diffuseTexture1 != value) {\n    _diffuseTexture1 = value;\n    _markAllSubMeshesAsTexturesDirty();\n  }\n}\n\nTexturePtr& TerrainMaterial::get_diffuseTexture2()\n{\n  return _diffuseTexture2;\n}\n\nvoid TerrainMaterial::set_diffuseTexture2(const TexturePtr& value)\n{\n  if (_diffuseTexture2 != value) {\n    _diffuseTexture2 = value;\n    _markAllSubMeshesAsTexturesDirty();\n  }\n}\n\nTexturePtr& TerrainMaterial::get_diffuseTexture3()\n{\n  return _diffuseTexture3;\n}\n\nvoid TerrainMaterial::set_diffuseTexture3(const TexturePtr& value)\n{\n  if (_diffuseTexture3 != value) {\n    _diffuseTexture3 = value;\n    _markAllSubMeshesAsTexturesDirty();\n  }\n}\n\nTexturePtr& TerrainMaterial::get_bumpTexture1()\n{\n  return _bumpTexture1;\n}\n\nvoid TerrainMaterial::set_bumpTexture1(const TexturePtr& value)\n{\n  if (_bumpTexture1 != value) {\n    _bumpTexture1 = value;\n    _markAllSubMeshesAsTexturesDirty();\n  }\n}\n\nTexturePtr& TerrainMaterial::get_bumpTexture2()\n{\n  return _bumpTexture2;\n}\n\nvoid TerrainMaterial::set_bumpTexture2(const TexturePtr& value)\n{\n  if (_bumpTexture2 != value) {\n    _bumpTexture2 = value;\n    _markAllSubMeshesAsTexturesDirty();\n  }\n}\n\nTexturePtr& TerrainMaterial::get_bumpTexture3()\n{\n  return _bumpTexture3;\n}\n\nvoid TerrainMaterial::set_bumpTexture3(const TexturePtr& value)\n{\n  if (_bumpTexture3 != value) {\n    _bumpTexture3 = value;\n    _markAllSubMeshesAsTexturesDirty();\n  }\n}\n\nbool TerrainMaterial::get_disableLighting() const\n{\n  return _disableLighting;\n}\n\nvoid TerrainMaterial::set_disableLighting(bool value)\n{\n  if (_disableLighting != value) {\n    _disableLighting = value;\n    _markAllSubMeshesAsLightsDirty();\n  }\n}\n\nunsigned int TerrainMaterial::get_maxSimultaneousLights() const\n{\n  return _maxSimultaneousLights;\n}\n\nvoid TerrainMaterial::set_maxSimultaneousLights(unsigned int value)\n{\n  if (_maxSimultaneousLights != value) {\n    _maxSimultaneousLights = value;\n    _markAllSubMeshesAsLightsDirty();\n  }\n}\n\nbool TerrainMaterial::needAlphaBlending() const\n{\n  return (alpha < 1.f);\n}\n\nbool TerrainMaterial::needAlphaTesting() const\n{\n  return false;\n}\n\nBaseTexturePtr TerrainMaterial::getAlphaTestTexture()\n{\n  return nullptr;\n}\n\nbool TerrainMaterial::isReadyForSubMesh(AbstractMesh* mesh,\n                                        BaseSubMesh* subMesh, bool useInstances)\n{\n  if (isFrozen()) {\n    if (_wasPreviouslyReady && subMesh->effect()) {\n      return true;\n    }\n  }\n\n  if (!subMesh->_materialDefines) {\n    subMesh->_materialDefines = std::make_shared<TerrainMaterialDefines>();\n  }\n\n  auto definesPtr = std::static_pointer_cast<TerrainMaterialDefines>(\n    subMesh->_materialDefines);\n  auto& defines = *definesPtr.get();\n  auto scene    = getScene();\n\n  if (!checkReadyOnEveryCall && subMesh->effect()) {\n    if (_renderId == scene->getRenderId()) {\n  }\n\n  auto engine = scene->getEngine();\n\n  // Textures\n\n  // Textures\n  if (scene->texturesEnabled()) {\n    if (_mixTexture && StandardMaterial::DiffuseTextureEnabled()) {\n      if (!_mixTexture->isReady()) {\n        return false;\n      }\n      else {\n        defines._needUVs           = true;\n        defines.boolDef["DIFFUSE"] = true;\n      }\n    }\n    if ((_bumpTexture1 || _bumpTexture2 || _bumpTexture3)\n        && StandardMaterial::BumpTextureEnabled()) {\n      defines._needUVs        = true;\n      defines._needNormals    = true;\n      defines.boolDef["BUMP"] = true;\n    }\n  }\n\n  // Misc.\n  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(),\n                                        fogEnabled(),\n                                        _shouldTurnAlphaTestOn(mesh), defines);\n\n  // Lights\n\n  // Values that need to be evaluated on every frame\n  MaterialHelper::PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);\n\n  // Attribs\n  MaterialHelper::PrepareDefinesForAttributes(mesh, defines, true, true);\n\n  // Get correct effect\n  if (defines.isDirty()) {\n    defines.markAsProcessed();\n    scene->resetCachedMaterial();\n\n    // Fallbacks\n    auto fallbacks = std::make_unique<EffectFallbacks>();\n    if (defines["FOG"]) {\n      fallbacks->addFallback(1, "FOG");\n    }\n      fallbacks->addFallback(1, "FOG");\n    }\n\n    MaterialHelper::HandleFallbacksForShadows(defines, *fallbacks,\n                                              maxSimultaneousLights());\n\n    if (defines.intDef["NUM_BONE_INFLUENCERS"] > 0) {\n      fallbacks->addCPUSkinningFallback(0, mesh);\n    defines.boolDef["IMAGEPROCESSINGPOSTPROCESS"]\n      = scene->imageProcessingConfiguration()->applyByPostProcess();\n\n    // Attributes\n    std::vector<std::string> attribs = {VertexBuffer::PositionKind};\n\n    if (defines["NORMAL"]) {\n      attribs.emplace_back(VertexBuffer::NormalKind);\n    }\n\n    if (defines["UV1"]) {\n      attribs.emplace_back(VertexBuffer::UVKind);\n    }\n\n    if (defines["UV2"]) {\n      attribs.emplace_back(VertexBuffer::UV2Kind);\n    }\n\n      attribs.emplace_back(VertexBuffer::ColorKind);\n    }\n\n    MaterialHelper::PrepareAttributesForBones(attribs, mesh, defines,\n                                              *fallbacks);\n    MaterialHelper::PrepareAttributesForInstances(attribs, defines);\n\n    // Legacy browser patch\n    // Legacy browser patch\n    auto join = defines.toString();\n\n    const std::vector<std::string> uniforms{\n      "world",         "view",          "viewProjection", "vEyePosition",\n      "vLightsType",   "vDiffuseColor", "vSpecularColor", "vFogInfos",\n      "vFogColor",     "pointSize",     "vTextureInfos",  "mBones",\n      "vClipPlane",    "vClipPlane2",   "vClipPlane3",    "vClipPlane4",\n      "textureMatrix", "diffuse1Infos", "diffuse2Infos",  "diffuse3Infos"};\n\n    const std::vector<std::string> samplers{\n      "textureSampler", "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler",\n      "bump1Sampler",   "bump2Sampler",    "bump3Sampler"};\n    const std::vector<std::string> uniformBuffers{};\n\n    EffectCreationOptions options;\n\n    IEffectCreationOptions options;\n    options.attributes            = std::move(attribs);\n    options.uniformsNames         = std::move(uniforms);\n    options.uniformBuffersNames   = std::move(uniformBuffers);\n    options.samplers              = std::move(samplers);\n    options.materialDefines       = &defines;\n    options.fallbacks             = std::move(fallbacks);\n    options.onCompiled            = onCompiled;\n    options.onError               = onError;\n    options.indexParameters\n      = {{"maxSimultaneousLights", maxSimultaneousLights()}};\n\n    MaterialHelper::PrepareUniformsAndSamplersList(options);\n    subMesh->setEffect(\n      scene->getEngine()->createEffect(shaderName, options, engine),\n      definesPtr);\n  }\n\n  if (!subMesh->effect() || !subMesh->effect()->isReady()) {\n\n  if (!subMesh->effect() || !subMesh->effect()->isReady()) {\n    return false;\n  }\n\n  defines._renderId                      = scene->getRenderId();\n  return true;\n}\n\nvoid TerrainMaterial::bindForSubMesh(Matrix& world, Mesh* mesh,\n                                     SubMesh* subMesh)\n{\n  auto scene = getScene();\n\n  auto _defines\n    = static_cast<TerrainMaterialDefines*>(subMesh->_materialDefines.get());\n  if (!_defines) {\n    return;\n  }\n    return;\n  }\n  auto defines = *_defines;\n\n  auto effect = subMesh->effect();\n  if (!effect) {\n    return;\n  }\n  _activeEffect = effect;\n\n  // Matrices\n  bindOnlyWorldMatrix(world);\n  _activeEffect->setMatrix("viewProjection", scene->getTransformMatrix());\n\n  // Bones\n  MaterialHelper::BindBonesParameters(mesh, _activeEffect.get());\n    // Textures\n    if (_mixTexture) {\n      _activeEffect->setTexture("textureSampler", _mixTexture);\n      _activeEffect->setFloat2(\n        "vTextureInfos", static_cast<float>(_mixTexture->coordinatesIndex),\n        _mixTexture->level);\n      _activeEffect->setMatrix("textureMatrix",\n                               *_mixTexture->getTextureMatrix());\n\n      if (StandardMaterial::DiffuseTextureEnabled()) {\n        if (_diffuseTexture1) {\n          _activeEffect->setTexture("diffuse1Sampler", _diffuseTexture1);\n          _activeEffect->setFloat2("diffuse1Infos", _diffuseTexture1->uScale,\n          _activeEffect->setTexture("diffuse1Sampler", _diffuseTexture1);\n          _activeEffect->setFloat2("diffuse1Infos", _diffuseTexture1->uScale,\n                                   _diffuseTexture1->vScale);\n        }\n        if (_diffuseTexture2) {\n          _activeEffect->setTexture("diffuse2Sampler", _diffuseTexture2);\n          _activeEffect->setFloat2("diffuse2Infos", _diffuseTexture2->uScale,\n                                   _diffuseTexture2->vScale);\n        }\n        if (_diffuseTexture3) {\n          _activeEffect->setTexture("diffuse3Sampler", _diffuseTexture3);\n        }\n      }\n\n      if (StandardMaterial::BumpTextureEnabled()\n          && scene->getEngine()->getCaps().standardDerivatives) {\n        if (_bumpTexture1) {\n          _activeEffect->setTexture("bump1Sampler", _bumpTexture1);\n        if (_bumpTexture1) {\n          _activeEffect->setTexture("bump1Sampler", _bumpTexture1);\n        }\n        if (_bumpTexture2) {\n          _activeEffect->setTexture("bump2Sampler", _bumpTexture2);\n        }\n        if (_bumpTexture3) {\n          _activeEffect->setTexture("bump3Sampler", _bumpTexture3);\n        }\n      }\n    }\n    // Clip plane\n    MaterialHelper::BindClipPlane(_activeEffect, scene);\n\n    // Point size\n    if (pointsCloud()) {\n      _activeEffect->setFloat("pointSize", pointSize);\n    MaterialHelper::BindEyePosition(effect, scene);\n  }\n\n  _activeEffect->setColor4("vDiffuseColor", diffuseColor,\n                           alpha * mesh->visibility);\n\n  if (defines["SPECULARTERM"]) {\n    _activeEffect->setColor4("vSpecularColor", specularColor, specularPower);\n  }\n\n  if (scene->lightsEnabled() && !_disableLighting) {\n    MaterialHelper::BindLights(scene, mesh, _activeEffect, defines,\n                               maxSimultaneousLights());\n  }\n\n  // View\n  if (scene->fogEnabled() && mesh->applyFog()\n      && scene->fogMode() != Scene::FOGMODE_NONE) {\n    _activeEffect->setMatrix("view", scene->getViewMatrix());\n  }\n\n  }\n\n  // Fog\n  MaterialHelper::BindFogParameters(scene, mesh, _activeEffect);\n\n  _afterBind(mesh, _activeEffect);\n}\n\nstd::vector<IAnimatablePtr> TerrainMaterial::getAnimatables()\n{\n  std::vector<IAnimatablePtr> results;\n\n  if (_mixTexture && _mixTexture->animations.size() > 0) {\n    results.emplace_back(_mixTexture);\n  }\n\n  return results;\n}\n\nstd::vector<BaseTexturePtr> TerrainMaterial::getActiveTextures() const\n{\n  auto activeTextures = PushMaterial::getActiveTextures();\n\n  if (_mixTexture) {\n    activeTextures.emplace_back(_mixTexture);\n  }\n\n  if (_diffuseTexture1) {\n    activeTextures.emplace_back(_diffuseTexture1);\n  }\n\n  if (_diffuseTexture2) {\n    activeTextures.emplace_back(_diffuseTexture2);\n  }\n\n  if (_diffuseTexture3) {\n    activeTextures.emplace_back(_diffuseTexture3);\n  }\n\n  if (_bumpTexture1) {\n    activeTextures.emplace_back(_bumpTexture1);\n  }\n\n  if (_bumpTexture2) {\n    activeTextures.emplace_back(_bumpTexture2);\n  }\n\n  if (_bumpTexture3) {\n    activeTextures.emplace_back(_bumpTexture3);\n  }\n\n  return activeTextures;\n}\n\nbool TerrainMaterial::hasTexture(const BaseTexturePtr& texture) const\n{\n  if (PushMaterial::hasTexture(texture)) {\n    return true;\n  }\n\n  if (_mixTexture == texture) {\n    return true;\n  }\n\n  if (_diffuseTexture1 == texture) {\n    return true;\n  }\n\n  if (_diffuseTexture2 == texture) {\n    return true;\n  }\n\n  if (_diffuseTexture3 == texture) {\n    return true;\n  }\n\n  if (_bumpTexture1 == texture) {\n    return true;\n  }\n\n  if (_bumpTexture2 == texture) {\n    return true;\n  }\n\n  if (_bumpTexture3 == texture) {\n    return true;\n  return false;\n}\n\nvoid TerrainMaterial::dispose(bool forceDisposeEffect,\n                              bool forceDisposeTextures,\n                              bool /*notBoundToMesh*/)\n{\n  if (_mixTexture) {\n{\n  if (_mixTexture) {\n    _mixTexture->dispose();\n  PushMaterial::dispose(forceDisposeEffect, forceDisposeTextures);\n}\n\nMaterialPtr TerrainMaterial::clone(const std::string& /*name*/,\n                                   bool /*cloneChildren*/) const\n{\n  return nullptr;\n}\n  return nullptr;\n}\n\njson TerrainMaterial::serialize() const\n{\n  return nullptr;\n}\n\n  return "TerrainMaterial";\n}\n\nTerrainMaterial* TerrainMaterial::Parse(const json& /*source*/,\n                                        Scene* /*scene*/,\n                                        const std::string& /*rootUrl*/)\n{\n  return nullptr;\n{\n  return nullptr;\n}\n\n} // end of namespace MaterialsLibrary\n} // end of namespace BABYLON\n', 'message': 'Updated Terrain Material to v4.1.0-alpha.17\n', 'author_name': 'samdauwe', 'lang': 'cpp'}