diff --git a/interface/resources/images/normalFittingScale.dds b/interface/resources/images/normalFittingScale.dds
new file mode 100644
index 0000000000..8207ee0981
Binary files /dev/null and b/interface/resources/images/normalFittingScale.dds differ
diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh
index 91447cbf8b..9a3dda7076 100755
--- a/libraries/render-utils/src/DeferredBufferWrite.slh
+++ b/libraries/render-utils/src/DeferredBufferWrite.slh
@@ -21,6 +21,23 @@ uniform float glowIntensity;
 // the alpha threshold
 uniform float alphaThreshold;
 
+uniform sampler2D normalFittingMap;
+
+vec3 bestFitNormal(vec3 normal) {
+    vec3 absNorm = abs(normal);
+    float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y));
+
+    vec2 texcoord = (absNorm.z < maxNAbs ? 
+                        (absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) :
+                        absNorm.xy);
+    texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy);
+    texcoord.y /= texcoord.x;
+    vec3 cN = normal / maxNAbs;
+    float fittingScale = texture2D(normalFittingMap, texcoord).a;
+    cN *= fittingScale;
+    return (cN * 0.5 + 0.5);
+}
+
 float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
     return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold));
 }
@@ -33,7 +50,7 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular,
         discard;
     }
     _fragColor0 = vec4(diffuse.rgb, alpha);
-    _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
+    _fragColor1 = vec4(bestFitNormal(normal), 1.0);
     _fragColor2 = vec4(specular, shininess / 128.0);
 }
 
@@ -44,7 +61,7 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s
 
     _fragColor0 = vec4(diffuse.rgb, alpha);
     //_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
-    _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);
+    _fragColor1 = vec4(bestFitNormal(normal), 0.5);
     _fragColor2 = vec4(emissive, shininess / 128.0);
 }
 
diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp
index aaaa3b6d6a..08ab6e0cf6 100644
--- a/libraries/render-utils/src/DeferredLightingEffect.cpp
+++ b/libraries/render-utils/src/DeferredLightingEffect.cpp
@@ -86,6 +86,7 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
     _emissiveShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));
     
     gpu::Shader::BindingSet slotBindings;
+    slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));
     gpu::Shader::makeProgram(*_simpleShader, slotBindings);
     gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
 
@@ -151,6 +152,8 @@ void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured,
         // If it is not textured, bind white texture and keep using textured pipeline
         batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
     }
+
+    batch.setResourceTexture(NORMAL_FITTING_MAP_SLOT, DependencyManager::get<TextureCache>()->getNormalFittingTexture());
 }
 
 void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {
diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h
index ba4fbd6d69..62497851d7 100644
--- a/libraries/render-utils/src/DeferredLightingEffect.h
+++ b/libraries/render-utils/src/DeferredLightingEffect.h
@@ -30,7 +30,8 @@ class DeferredLightingEffect : public Dependency {
     SINGLETON_DEPENDENCY
     
 public:
-    
+    static const int NORMAL_FITTING_MAP_SLOT = 10;
+
     void init(AbstractViewStateInterface* viewState);
 
     /// Sets up the state necessary to render static untextured geometry with the simple program.
diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index cf0fb67d8c..43579892a7 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -105,6 +105,8 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
     slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));
     slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3));
     slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4));
+    slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));
+
 
     gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));
     gpu::Shader::makeProgram(*program, slotBindings);
@@ -180,6 +182,8 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model:
     locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
     locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
 
+    locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap");
+    
     locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
     locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
 
@@ -1864,6 +1868,10 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
         const float DEFAULT_GLOW_INTENSITY = 1.0f; // FIXME - glow is removed
         batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY);
     }
+
+    if ((locations->normalFittingMapUnit > -1)) {
+       batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get<TextureCache>()->getNormalFittingTexture());
+    }
 }
 
 bool Model::initWhenReady(render::ScenePointer scene) {
diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h
index 09504c7501..9fdb2f3691 100644
--- a/libraries/render-utils/src/Model.h
+++ b/libraries/render-utils/src/Model.h
@@ -350,6 +350,7 @@ private:
         int emissiveTextureUnit;
         int emissiveParams;
         int glowIntensity;
+        int normalFittingMapUnit;
         int materialBufferUnit;
         int clusterMatrices;
         int clusterIndices;
diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp
index d6a9bf5b36..deeec58f49 100644
--- a/libraries/render-utils/src/TextureCache.cpp
+++ b/libraries/render-utils/src/TextureCache.cpp
@@ -21,6 +21,7 @@
 #include <QRunnable>
 #include <QThreadPool>
 #include <qimagereader.h>
+#include "PathUtils.h"
 
 #include <gpu/Batch.h>
 
@@ -129,6 +130,14 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() {
     return _blackTexture;
 }
 
+
+const gpu::TexturePointer& TextureCache::getNormalFittingTexture() {
+    if (!_normalFittingTexture) {
+        _normalFittingTexture = getImageTexture(PathUtils::resourcesPath() + "images/normalFittingScale.dds");
+    }
+    return _normalFittingTexture;
+}
+
 /// Extra data for creating textures.
 class TextureExtra {
 public:
@@ -170,6 +179,7 @@ gpu::TexturePointer TextureCache::getImageTexture(const QString& path) {
     return texture;
 }
 
+
 QSharedPointer<Resource> TextureCache::createResource(const QUrl& url,
         const QSharedPointer<Resource>& fallback, bool delayLoad, const void* extra) {
     const TextureExtra* textureExtra = static_cast<const TextureExtra*>(extra);
diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h
index 8f60382e9b..eeb17f07b9 100644
--- a/libraries/render-utils/src/TextureCache.h
+++ b/libraries/render-utils/src/TextureCache.h
@@ -54,6 +54,9 @@ public:
     /// Returns the a black texture (useful for a default).
     const gpu::TexturePointer& getBlackTexture();
 
+    // Returns a map used to compress the normals through a fitting scale algorithm
+    const gpu::TexturePointer& getNormalFittingTexture();
+
     /// Returns a texture version of an image file
     static gpu::TexturePointer getImageTexture(const QString& path);
 
@@ -76,6 +79,7 @@ private:
     gpu::TexturePointer _grayTexture;
     gpu::TexturePointer _blueTexture;
     gpu::TexturePointer _blackTexture;
+    gpu::TexturePointer _normalFittingTexture;
 
     QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures;
 };