diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp
index 6268cb3d0a..1e48a3c011 100644
--- a/libraries/fbx/src/FBXReader.cpp
+++ b/libraries/fbx/src/FBXReader.cpp
@@ -934,7 +934,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
                         _textureContent.insert(filename, content);
                     }
                 } else if (object.name == "Material") {
-                    FBXMaterial material(glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.02f), glm::vec3(), glm::vec2(0.f, 1.0f), 96.0f, 1.0f);
+                    FBXMaterial material;
                     foreach (const FBXNode& subobject, object.children) {
                         bool properties = false;
                         QByteArray propertyName;
@@ -954,9 +954,17 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
                                 if (property.name == propertyName) {
                                     if (property.properties.at(0) == "DiffuseColor") {
                                         material.diffuseColor = getVec3(property.properties, index);
+                                    } else if (property.properties.at(0) == "Diffuse") {
+                                        material.diffuseColor = getVec3(property.properties, index);
+                                    } else if (property.properties.at(0) == "DiffuseFactor") {
+         //                               material.diffuseFactor = property.properties.at(index).value<double>();
 
                                     } else if (property.properties.at(0) == "SpecularColor") {
                                         material.specularColor = getVec3(property.properties, index);
+                                    } else if (property.properties.at(0) == "Specular") {
+                                        material.specularColor = getVec3(property.properties, index);
+                                    } else if (property.properties.at(0) == "SpecularFactor") {
+         //                               material.specularFactor = property.properties.at(index).value<double>();
 
                                     } else if (property.properties.at(0) == "Emissive") {
                                         material.emissiveColor = getVec3(property.properties, index);
diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h
index 5cfff9826f..63d3c30a91 100644
--- a/libraries/fbx/src/FBXReader.h
+++ b/libraries/fbx/src/FBXReader.h
@@ -137,21 +137,24 @@ public:
 class FBXMaterial {
 public:
     FBXMaterial() {};
-    FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor, 
-                const glm::vec2& emissiveParams, float shininess, float opacity) :
-                    diffuseColor(diffuseColor),
-                    specularColor(specularColor),
-                    emissiveColor(emissiveColor),
-                    emissiveParams(emissiveParams),
-                    shininess(shininess),
-                    opacity(opacity)  {}
+    FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor,
+        const glm::vec2& emissiveParams, float shininess, float opacity) :
+        diffuseColor(diffuseColor),
+        specularColor(specularColor),
+        emissiveColor(emissiveColor),
+        emissiveParams(emissiveParams),
+        shininess(shininess),
+        opacity(opacity)  {}
 
-    glm::vec3 diffuseColor;
-    glm::vec3 specularColor;
-    glm::vec3 emissiveColor;
-    glm::vec2 emissiveParams;
-    float shininess;
-    float opacity;
+    glm::vec3 diffuseColor{ 1.0f };
+    float diffuseFactor{ 1.0f };
+    glm::vec3 specularColor{ 0.02f };
+    float specularFactor{ 1.0f };
+
+    glm::vec3 emissiveColor{ 0.0f };
+    glm::vec2 emissiveParams{ 0.0f, 1.0f };
+    float shininess{ 23.0f };
+    float opacity{ 1.0f };
 
     QString materialID;
     model::MaterialPointer _material;
diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp
index 7ba6e6d703..9c108fdc74 100644
--- a/libraries/fbx/src/FBXReader_Material.cpp
+++ b/libraries/fbx/src/FBXReader_Material.cpp
@@ -134,13 +134,17 @@ void FBXReader::consolidateFBXMaterials() {
         // Finally create the true material representation
         material._material = std::make_shared<model::Material>();
         material._material->setEmissive(material.emissiveColor);
-        if (glm::all(glm::equal(material.diffuseColor, glm::vec3(0.0f)))) {
-            material._material->setDiffuse(material.diffuseColor); 
+
+        auto diffuse = material.diffuseColor;
+        diffuse *= material.diffuseFactor;
+        if (glm::all(glm::equal(diffuse, glm::vec3(0.0f)))) {
+            material._material->setDiffuse(diffuse);
         } else {
-            material._material->setDiffuse(material.diffuseColor); 
+            material._material->setDiffuse(diffuse);
         }
 
         float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z));
+        metallic *= material.specularFactor;
         material._material->setMetallic(metallic);
         material._material->setGloss(material.shininess); 
 
diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp
index 0bdc0749f6..3e80b6c7aa 100644
--- a/libraries/model-networking/src/model-networking/TextureCache.cpp
+++ b/libraries/model-networking/src/model-networking/TextureCache.cpp
@@ -230,12 +230,15 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
             return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromBumpImage);
             break;
         }
+        case NORMAL_TEXTURE: {
+            return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromNormalImage);
+            break;
+        }
         case CUSTOM_TEXTURE: {
             return _textureLoader;
             break;
         }
         case DEFAULT_TEXTURE:
-        case NORMAL_TEXTURE:
         case SPECULAR_TEXTURE:
         case EMISSIVE_TEXTURE:
         default: {
diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp
index e3031e2b4d..4d0ccc27f8 100755
--- a/libraries/model/src/model/TextureMap.cpp
+++ b/libraries/model/src/model/TextureMap.cpp
@@ -137,6 +137,93 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con
     return theTexture;
 }
 
+
+gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) {
+    QImage image = srcImage;
+
+    int imageArea = image.width() * image.height();
+
+    int opaquePixels = 0;
+    int translucentPixels = 0;
+    //bool isTransparent = false;
+    int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
+    const int EIGHT_BIT_MAXIMUM = 255;
+    QColor averageColor(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM);
+
+    if (!image.hasAlphaChannel()) {
+        if (image.format() != QImage::Format_RGB888) {
+            image = image.convertToFormat(QImage::Format_RGB888);
+        }
+        // int redTotal = 0, greenTotal = 0, blueTotal = 0;
+        for (int y = 0; y < image.height(); y++) {
+            for (int x = 0; x < image.width(); x++) {
+                QRgb rgb = image.pixel(x, y);
+                redTotal += qRed(rgb);
+                greenTotal += qGreen(rgb);
+                blueTotal += qBlue(rgb);
+            }
+        }
+        if (imageArea > 0) {
+            averageColor.setRgb(redTotal / imageArea, greenTotal / imageArea, blueTotal / imageArea);
+        }
+    }
+    else {
+        if (image.format() != QImage::Format_ARGB32) {
+            image = image.convertToFormat(QImage::Format_ARGB32);
+        }
+
+        // check for translucency/false transparency
+        // int opaquePixels = 0;
+        // int translucentPixels = 0;
+        // int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
+        for (int y = 0; y < image.height(); y++) {
+            for (int x = 0; x < image.width(); x++) {
+                QRgb rgb = image.pixel(x, y);
+                redTotal += qRed(rgb);
+                greenTotal += qGreen(rgb);
+                blueTotal += qBlue(rgb);
+                int alpha = qAlpha(rgb);
+                alphaTotal += alpha;
+                if (alpha == EIGHT_BIT_MAXIMUM) {
+                    opaquePixels++;
+                }
+                else if (alpha != 0) {
+                    translucentPixels++;
+                }
+            }
+        }
+        if (opaquePixels == imageArea) {
+            qCDebug(modelLog) << "Image with alpha channel is completely opaque:" << QString(srcImageName.c_str());
+            image = image.convertToFormat(QImage::Format_RGB888);
+        }
+
+        averageColor = QColor(redTotal / imageArea,
+            greenTotal / imageArea, blueTotal / imageArea, alphaTotal / imageArea);
+
+        //isTransparent = (translucentPixels >= imageArea / 2);
+    }
+
+    gpu::Texture* theTexture = nullptr;
+    if ((image.width() > 0) && (image.height() > 0)) {
+
+        bool isLinearRGB = true;
+
+        gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
+        gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
+        if (image.hasAlphaChannel()) {
+            formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
+            formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
+        }
+
+
+        theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
+        theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
+        theTexture->autoGenerateMips(-1);
+    }
+
+    return theTexture;
+}
+
 int clampPixelCoordinate(int coordinate, int maxCoordinate) {
     return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate));
 }
diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h
index 343ef1f481..107ca2e879 100755
--- a/libraries/model/src/model/TextureMap.h
+++ b/libraries/model/src/model/TextureMap.h
@@ -32,6 +32,7 @@ public:
     int _environmentUsage = 0;
 
     static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName);
+    static gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName);
     static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName);
     static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName);
 };