From a0d7ce145e90a689ebb26b527d4ec9bcac9bc403 Mon Sep 17 00:00:00 2001
From: samcake <samuel.gateau@gmail.com>
Date: Wed, 24 Feb 2016 17:30:29 -0800
Subject: [PATCH] Adding support for emissive and occlusion maps, on to pr land

---
 .../utilities/tools/render/framebuffer.qml    |  3 +-
 libraries/fbx/src/FBXReader_Material.cpp      |  8 +++
 .../src/model-networking/ModelCache.cpp       |  9 ++++
 .../src/model-networking/ModelCache.h         |  2 +
 .../src/model-networking/TextureCache.h       |  4 +-
 libraries/model/src/model/Material.cpp        |  1 +
 libraries/model/src/model/Material.h          |  9 ++++
 libraries/model/src/model/Material.slh        |  3 +-
 .../render-utils/src/DebugDeferredBuffer.cpp  |  9 ++++
 .../render-utils/src/DebugDeferredBuffer.h    |  1 +
 libraries/render-utils/src/DeferredBuffer.slh | 27 +---------
 .../render-utils/src/DeferredBufferWrite.slh  | 10 ++--
 .../render-utils/src/DeferredGlobalLight.slh  | 17 ++++---
 .../render-utils/src/MaterialTextures.slh     | 51 ++++++++++++++++---
 .../render-utils/src/MeshPartPayload.cpp      | 36 ++++++++++---
 .../src/directional_ambient_light.slf         |  2 +-
 .../src/directional_ambient_light_shadow.slf  |  2 +-
 .../render-utils/src/directional_light.slf    |  2 +-
 .../src/directional_light_shadow.slf          |  2 +-
 .../src/directional_skybox_light.slf          |  2 +-
 .../src/directional_skybox_light_shadow.slf   |  2 +-
 libraries/render-utils/src/model.slf          | 25 ++++++---
 libraries/render-utils/src/model_lightmap.slf |  6 +--
 .../src/model_lightmap_normal_map.slf         |  7 ++-
 .../model_lightmap_normal_specular_map.slf    |  8 +--
 .../src/model_lightmap_specular_map.slf       | 10 ++--
 .../render-utils/src/model_normal_map.slf     | 27 +++++++---
 .../src/model_normal_specular_map.slf         | 22 ++++----
 .../render-utils/src/model_specular_map.slf   | 26 ++++++----
 .../render-utils/src/model_translucent.slf    |  4 +-
 libraries/render-utils/src/simple.slf         |  2 +-
 .../render-utils/src/simple_textured.slf      |  5 +-
 libraries/render/src/render/ShapePipeline.cpp |  6 ++-
 libraries/render/src/render/ShapePipeline.h   |  6 ++-
 tests/gpu-test/src/unlit.slf                  |  2 +-
 35 files changed, 241 insertions(+), 117 deletions(-)

diff --git a/examples/utilities/tools/render/framebuffer.qml b/examples/utilities/tools/render/framebuffer.qml
index 20b8b384d8..e31f986bc1 100644
--- a/examples/utilities/tools/render/framebuffer.qml
+++ b/examples/utilities/tools/render/framebuffer.qml
@@ -28,12 +28,13 @@ Column {
             model: [
                 "Off",
                 "Depth",
-                "Diffuse",
+                "Albedo",
                 "Normal",
                 "Roughness",
                 "Metallic",              
                 "Fresnel",
                 "Emissive",
+                "Occlusion",
                 "Lightmap",
                 "Lighting",
                 "Shadow",
diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp
index 2604d83423..188c50304d 100644
--- a/libraries/fbx/src/FBXReader_Material.cpp
+++ b/libraries/fbx/src/FBXReader_Material.cpp
@@ -149,6 +149,14 @@ void FBXReader::consolidateFBXMaterials() {
             material.emissiveTexture = emissiveTexture;
         }
 
+        FBXTexture occlusionTexture;
+        QString occlusionTextureID = occlusionTextures.value(material.materialID);
+        if (!occlusionTextureID.isNull()) {
+            occlusionTexture = getTexture(occlusionTextureID);
+            detectDifferentUVs |= (occlusionTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity());
+            material.occlusionTexture = occlusionTexture;
+        }
+
         glm::vec2 lightmapParams(0.f, 1.f);
         lightmapParams.x = _lightmapOffset;
         lightmapParams.y = _lightmapLevel;
diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp
index 2bb71ba855..7d59bb5028 100644
--- a/libraries/model-networking/src/model-networking/ModelCache.cpp
+++ b/libraries/model-networking/src/model-networking/ModelCache.cpp
@@ -363,6 +363,7 @@ static NetworkMaterial* buildNetworkMaterial(NetworkGeometry* geometry, const FB
         material._material->setTextureMap(model::MaterialKey::METALLIC_MAP, metallicMap);
     }
     if (!material.roughnessTexture.filename.isEmpty()) {
+        material.roughnessTexture.isGlossmap;
         networkMaterial->roughnessTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.roughnessTexture.filename)), ROUGHNESS_TEXTURE, material.roughnessTexture.content);
         networkMaterial->roughnessTextureName = material.roughnessTexture.name;
 
@@ -392,7 +393,15 @@ static NetworkMaterial* buildNetworkMaterial(NetworkGeometry* geometry, const FB
 
         material._material->setTextureMap(model::MaterialKey::LIGHTMAP_MAP, lightmapMap);
     }
+    if (!material.occlusionTexture.filename.isEmpty()) {
+        networkMaterial->occlusionTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.occlusionTexture.filename)), OCCLUSION_TEXTURE, material.occlusionTexture.content);
+        networkMaterial->occlusionTextureName = material.occlusionTexture.name;
 
+        auto occlusionMap = model::TextureMapPointer(new model::TextureMap());
+        occlusionMap->setTextureSource(networkMaterial->occlusionTexture->_textureSource);
+
+        material._material->setTextureMap(model::MaterialKey::OCCLUSION_MAP, occlusionMap);
+    }
     return networkMaterial;
 }
 
diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h
index c43a1e6d79..b517cc67ca 100644
--- a/libraries/model-networking/src/model-networking/ModelCache.h
+++ b/libraries/model-networking/src/model-networking/ModelCache.h
@@ -190,6 +190,8 @@ public:
     QSharedPointer<NetworkTexture> roughnessTexture;
     QString emissiveTextureName;
     QSharedPointer<NetworkTexture> emissiveTexture;
+    QString occlusionTextureName;
+    QSharedPointer<NetworkTexture> occlusionTexture;
     QString lightmapTextureName;
     QSharedPointer<NetworkTexture> lightmapTexture;
 
diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h
index 2cfd225889..e9c232c4b6 100644
--- a/libraries/model-networking/src/model-networking/TextureCache.h
+++ b/libraries/model-networking/src/model-networking/TextureCache.h
@@ -29,7 +29,9 @@ class NetworkTexture;
 
 typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
 
-enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, ROUGHNESS_TEXTURE, EMISSIVE_TEXTURE, CUBE_TEXTURE, LIGHTMAP_TEXTURE, CUSTOM_TEXTURE };
+enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, ROUGHNESS_TEXTURE, EMISSIVE_TEXTURE,
+    CUBE_TEXTURE, OCCLUSION_TEXTURE, LIGHTMAP_TEXTURE, CUSTOM_TEXTURE
+};
 
 /// Stores cached textures, including render-to-texture targets.
 class TextureCache : public ResourceCache, public Dependency {
diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp
index 522debad59..10fa15edd5 100755
--- a/libraries/model/src/model/Material.cpp
+++ b/libraries/model/src/model/Material.cpp
@@ -58,6 +58,7 @@ void Material::setOpacity(float opacity) {
 
 void Material::setAlbedo(const Color& albedo, bool isSRGB) {
     _key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f))));
+    _schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
     _schemaBuffer.edit<Schema>()._albedo = (isSRGB ? ColorUtils::toLinearVec3(albedo) : albedo);
 }
 
diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h
index a6b1cd3706..cdc3e4dc39 100755
--- a/libraries/model/src/model/Material.h
+++ b/libraries/model/src/model/Material.h
@@ -39,6 +39,7 @@ public:
         ROUGHNESS_MAP_BIT,
         TRANSPARENT_MAP_BIT,
         NORMAL_MAP_BIT,
+        OCCLUSION_MAP_BIT,
         LIGHTMAP_MAP_BIT,
 
         NUM_FLAGS,
@@ -52,6 +53,7 @@ public:
         ROUGHNESS_MAP,
         TRANSPARENT_MAP,
         NORMAL_MAP,
+        OCCLUSION_MAP,
         LIGHTMAP_MAP,
 
         NUM_MAP_CHANNELS,
@@ -83,6 +85,7 @@ public:
         Builder& withTransparentMap() { _flags.set(TRANSPARENT_MAP_BIT); return (*this); }
 
         Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); }
+        Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); }
         Builder& withLightmapMap() { _flags.set(LIGHTMAP_MAP_BIT); return (*this); }
 
         // Convenient standard keys that we will keep on using all over the place
@@ -124,6 +127,9 @@ public:
     void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); }
     bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; }
 
+    void setOcclusionMap(bool value) { _flags.set(OCCLUSION_MAP_BIT, value); }
+    bool isOcclusionMap() const { return _flags[OCCLUSION_MAP_BIT]; }
+
     void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); }
     bool isLightmapMap() const { return _flags[LIGHTMAP_MAP_BIT]; }
 
@@ -182,6 +188,9 @@ public:
         Builder& withoutNormalMap()       { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); }
         Builder& withNormalMap()        { _value.set(MaterialKey::NORMAL_MAP_BIT);  _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); }
 
+        Builder& withoutOcclusionMap()       { _value.reset(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT); return (*this); }
+        Builder& withOcclusionMap()        { _value.set(MaterialKey::OCCLUSION_MAP_BIT);  _mask.set(MaterialKey::OCCLUSION_MAP_BIT); return (*this); }
+
         Builder& withoutLightmapMap()       { _value.reset(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
         Builder& withLightmapMap()        { _value.set(MaterialKey::LIGHTMAP_MAP_BIT);  _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
 
diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh
index ac5d750bdd..d75f3df5e0 100644
--- a/libraries/model/src/model/Material.slh
+++ b/libraries/model/src/model/Material.slh
@@ -52,8 +52,9 @@ const int METALLIC_MAP_BIT = 0x00000080;
 const int ROUGHNESS_MAP_BIT = 0x00000100;
 const int TRANSPARENT_MAP_BIT = 0x00000200;
 const int NORMAL_MAP_BIT = 0x00000400;
+const int OCCLUSION_MAP_BIT = 0x00000800;
 
-const int LIGHTMAP_MAP_BIT = 0x00000800;
+const int LIGHTMAP_MAP_BIT = 0x00001000;
 
 
 
diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp
index 1126023f41..2360b6310f 100644
--- a/libraries/render-utils/src/DebugDeferredBuffer.cpp
+++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp
@@ -85,6 +85,13 @@ static const std::string DEFAULT_NORMAL_SHADER {
     " }"
 };
 
+static const std::string DEFAULT_OCCLUSION_SHADER{
+    "vec4 getFragmentColor() {"
+    "    DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
+    "    return vec4(vec3(frag.obscurance), 1.0);"
+    " }"
+};
+
 static const std::string DEFAULT_EMISSIVE_SHADER{
     "vec4 getFragmentColor() {"
     "    DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
@@ -184,6 +191,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust
             return DEFAULT_DEPTH_SHADER;
         case EmissiveMode:
             return DEFAULT_EMISSIVE_SHADER;
+        case OcclusionMode:
+            return DEFAULT_OCCLUSION_SHADER;
         case LightmapMode:
             return DEFAULT_LIGHTMAP_SHADER;
         case LightingMode:
diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h
index 0d72eeec8a..f4eacea5b6 100644
--- a/libraries/render-utils/src/DebugDeferredBuffer.h
+++ b/libraries/render-utils/src/DebugDeferredBuffer.h
@@ -54,6 +54,7 @@ protected:
         MetallicMode,
         FresnelMode,
         EmissiveMode,
+        OcclusionMode,
         LightmapMode,
         LightingMode,
         ShadowMode,
diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh
index f35fc12d1f..bfed92018a 100755
--- a/libraries/render-utils/src/DeferredBuffer.slh
+++ b/libraries/render-utils/src/DeferredBuffer.slh
@@ -104,43 +104,20 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {
     frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0));
     
     frag.mode = 0;
-    frag.emissive = vec3(0.0);
+    frag.emissive = frag.specularVal.xyz;
     if (frag.normalVal.a < 0.5) {
         frag.mode = 0;
         frag.roughness = 2.0 * frag.normalVal.a;
     } else {
         frag.mode = LIGHT_MAPPED;
         frag.roughness = 2.0 * frag.normalVal.a - 1.0;
-        frag.emissive = frag.specularVal.xyz;
     }
-    
-   // if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
-   //     frag.mode = LIGHT_MAPPED;
-   //     frag.emissive = frag.specularVal.xyz;
-   // }
 
     frag.metallic = frag.diffuseVal.a;
     frag.diffuse = frag.diffuseVal.xyz;
     frag.specular = vec3(frag.metallic);
-  /*  if (frag.metallic > 0.5) {
-        frag.diffuse = vec3(0);
-        //frag.metallic = length(frag.specularVal);
-        frag.specular = frag.diffuseVal.xyz;
-        
-    } else {
-        frag.diffuse = frag.diffuseVal.xyz;
-        //frag.metallic = length(frag.specularVal);
-        frag.specular = vec3(0.03);
-    }
-    */
-    // frag.diffuse = frag.diffuseVal.xyz;
-    //frag.metallic = length(frag.specularVal);
-    //frag.specular = frag.specularVal.xyz;
-    
-    
-    //frag.roughness = frag.specularVal.w;
+    frag.obscurance = min(frag.specularVal.w, frag.obscurance);
 
-    
     return frag;
 }
 
diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh
index a92ce1d26a..2a2c2883d3 100755
--- a/libraries/render-utils/src/DeferredBufferWrite.slh
+++ b/libraries/render-utils/src/DeferredBufferWrite.slh
@@ -44,25 +44,27 @@ const float DEFAULT_ROUGHNESS = 0.9;
 const float DEFAULT_SHININESS = 10;
 const float DEFAULT_METALLIC = 0;
 const vec3 DEFAULT_SPECULAR = vec3(0.1);
+const vec3 DEFAULT_EMISSIVE = vec3(0.0);
+const float DEFAULT_OCCLUSION = 1.0;
 
 
-void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel) {
+void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion) {
     if (alpha != 1.0) {
         discard;
     }
-   // vec3 baseColor = ((metallic < 0.5) ? albedo : fresnel);
     _fragColor0 = vec4(albedo, metallic);
     _fragColor1 = vec4(bestFitNormal(normal), 0.5 * clamp(roughness, 0.0, 1.0));
-    _fragColor2 = vec4(fresnel, roughness);
+    _fragColor2 = vec4(emissive, occlusion);
 }
 
+
 void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 emissive) {
     if (alpha != 1.0) {
         discard;
     }
     _fragColor0 = vec4(albedo, metallic);
     _fragColor1 = vec4(bestFitNormal(normal), 0.5 + 0.5 * clamp(roughness, 0.0, 1.0));
-    _fragColor2 = vec4(emissive, roughness);
+    _fragColor2 = vec4(emissive, 1.0);
 }
 
 void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {
diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh
index de4eb746ef..a3fb1de3ec 100755
--- a/libraries/render-utils/src/DeferredGlobalLight.slh
+++ b/libraries/render-utils/src/DeferredGlobalLight.slh
@@ -30,7 +30,7 @@ vec4 evalSkyboxLight(vec3 direction, float lod) {
 <@include model/Light.slh@>
 
 <@func declareEvalAmbientGlobalColor()@>
-vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness) {
+vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) {
 
     // Need the light now
     Light light = getLight();
@@ -41,9 +41,11 @@ vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obsc
 
     vec3 color = albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(light);
 
-    vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, fresnel, roughness);
+
+    vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, vec3(metallic), roughness);
 
     color += vec3(albedo * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light);
+    color += emissive;
 
     return color;
 }
@@ -52,7 +54,7 @@ vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obsc
 <@func declareEvalAmbientSphereGlobalColor()@>
 
 
-vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness) {
+vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) {
     // Need the light now
     Light light = getLight();
     
@@ -64,10 +66,10 @@ vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, floa
 
     vec3 color = albedo * evalSphericalLight(getLightAmbientSphere(light), ambientNormal).xyz * obscurance * getLightAmbientIntensity(light);
 
-    vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, fresnel, roughness);
+    vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, vec3(metallic), roughness);
 
     color += vec3(albedo * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light);
-
+    color += emissive;
     return color;
 }
 <@endfunc@>
@@ -76,7 +78,7 @@ vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, floa
 
 <$declareSkyboxMap()$>
 
-vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness) {
+vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) {
     // Need the light now
     Light light = getLight();
     
@@ -87,9 +89,10 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
 
     vec3 color = albedo * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light);
 
-    vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, fresnel, roughness);
+    vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, vec3(metallic), roughness);
 
     color += vec3(albedo * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light);
+    color += emissive;
 
     return color;
 }
diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh
index ab58b7cff5..d0f2563d43 100644
--- a/libraries/render-utils/src/MaterialTextures.slh
+++ b/libraries/render-utils/src/MaterialTextures.slh
@@ -11,7 +11,7 @@
 <@if not MODEL_MATERIAL_TEXTURES_SLH@>
 <@def MODEL_MATERIAL_TEXTURES_SLH@>
 
-<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic)@>
+<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion)@>
 
 <@if withAlbedo@>
 uniform sampler2D albedoMap;
@@ -41,21 +41,40 @@ float fetchMetallicMap(vec2 uv) {
 }
 <@endif@>
 
+<@if withEmissive@>
+uniform sampler2D emissiveMap;
+vec3 fetchEmissiveMap(vec2 uv) {
+    return texture(emissiveMap, uv).rgb;
+}
+<@endif@>
+
+<@if withOcclusion@>
+uniform sampler2D occlusionMap;
+float fetchOcclusionMap(vec2 uv) {
+    return texture(occlusionMap, uv).r;
+}
+<@endif@>
 <@endfunc@>
 
 
-<@func fetchMaterialTextures(texcoord0, albedo, roughness, normal, metallic)@>
+<@func fetchMaterialTextures(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, occlusion)@>
 <@if albedo@>
-    vec4 <$albedo$> = fetchAlbedoMap(<$texcoord0$>);
+    vec4 <$albedo$> = (((<$matKey$> & ALBEDO_MAP_BIT) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0));
 <@endif@>
 <@if roughness@>
-    float <$roughness$> = fetchRoughnessMap(<$texcoord0$>);
+    float <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(<$texcoord0$>) : 1.0);
 <@endif@>
 <@if normal@>
-    vec3 <$normal$> = fetchNormalMap(<$texcoord0$>);
+    vec3 <$normal$> = (((<$matKey$> & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(<$texcoord0$>) : vec3(0.0, 1.0, 0.0));
 <@endif@>
 <@if metallic@>
-    float <$metallic$> = fetchMetallicMap(<$texcoord0$>);
+    float <$metallic$> = (((<$matKey$> & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(<$texcoord0$>) : 0.0);
+<@endif@>
+<@if emissive@>
+    vec3 <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(<$texcoord0$>) : vec3(0.0));
+<@endif@>
+<@if occlusion@>
+    float <$occlusion$> = (((<$matKey$> & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(<$texcoord0$>) : 1.0);
 <@endif@>
 <@endfunc@>
 
@@ -83,6 +102,15 @@ vec3 fetchLightmapMap(vec2 uv) {
 }
 <@endfunc@>
 
+<@func evalMaterialAlbedo(fetchedAlbedo, materialAlbedo, matKey, albedo)@>
+{
+    <$albedo$>.xyz = (((<$matKey$> & ALBEDO_VAL_BIT) != 0) ? <$materialAlbedo$> : vec3(1.0));
+
+    if (((<$matKey$> & ALBEDO_MAP_BIT) != 0)) {
+        <$albedo$>.xyz *= <$fetchedAlbedo$>.xyz;
+    }
+}
+<@endfunc@>
 
 <@func evalMaterialRoughness(fetchedRoughness, materialRoughness, matKey, roughness)@>
 {
@@ -96,5 +124,16 @@ vec3 fetchLightmapMap(vec2 uv) {
 }
 <@endfunc@>
 
+<@func evalMaterialEmissive(fetchedEmissive, materialEmissive, matKey, emissive)@>
+{
+    <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? <$fetchedEmissive$> : <$materialEmissive$>);
+}
+<@endfunc@>
+
+<@func evalMaterialOcclusion(fetchedOcclusion, matKey, occlusion)@>
+{
+    <$occlusion$> = <$fetchedOcclusion$>;
+}
+<@endfunc@>
 
 <@endif@>
\ No newline at end of file
diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp
index ab2a969637..8bba58eae2 100644
--- a/libraries/render-utils/src/MeshPartPayload.cpp
+++ b/libraries/render-utils/src/MeshPartPayload.cpp
@@ -193,22 +193,36 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
     if (materialKey.isMetallicMap()) {
         auto specularMap = textureMaps[model::MaterialKey::METALLIC_MAP];
         if (specularMap && specularMap->isDefined()) {
-            batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, specularMap->getTextureView());
+            batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, specularMap->getTextureView());
 
             // texcoord are assumed to be the same has albedo
         } else {
-            batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture());
+            batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, textureCache->getBlackTexture());
         }
     } else {
-        batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, nullptr);
+        batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, nullptr);
     }
 
-    // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too
+    // Occlusion map
+    if (materialKey.isOcclusionMap()) {
+        auto specularMap = textureMaps[model::MaterialKey::OCCLUSION_MAP];
+        if (specularMap && specularMap->isDefined()) {
+            batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, specularMap->getTextureView());
+
+            // texcoord are assumed to be the same has albedo
+        } else {
+            batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, textureCache->getWhiteTexture());
+        }
+    } else {
+        batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, nullptr);
+    }
+
+    // Emissive / Lightmap
     if (materialKey.isLightmapMap()) {
         auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP];
 
         if (lightmapMap && lightmapMap->isDefined()) {
-            batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView());
+            batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, lightmapMap->getTextureView());
 
             auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale();
             batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y);
@@ -217,10 +231,18 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
                 lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]);
             }
         } else {
-            batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture());
+            batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, textureCache->getGrayTexture());
+        }
+    } else if (materialKey.isEmissiveMap()) {
+        auto emissiveMap = textureMaps[model::MaterialKey::EMISSIVE_MAP];
+
+        if (emissiveMap && emissiveMap->isDefined()) {
+            batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, emissiveMap->getTextureView());
+        } else {
+            batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, textureCache->getBlackTexture());
         }
     } else {
-        batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, nullptr);
+        batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, nullptr);
     }
 
     // Texcoord transforms ?
diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf
index 57f9c7e791..e1ec0d3ef0 100755
--- a/libraries/render-utils/src/directional_ambient_light.slf
+++ b/libraries/render-utils/src/directional_ambient_light.slf
@@ -45,7 +45,7 @@ void main(void) {
                         frag.normal,
                         frag.diffuse,
                         frag.metallic,
-                        frag.specular,
+                        frag.emissive,
                         frag.roughness);
         _fragColor = vec4(color, frag.normalVal.a);
     }
diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf
index a4d897044b..963a10d579 100644
--- a/libraries/render-utils/src/directional_ambient_light_shadow.slf
+++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf
@@ -47,7 +47,7 @@ void main(void) {
                         frag.normal,
                         frag.diffuse,
                         frag.metallic,
-                        frag.specular,
+                        frag.emissive,
                         frag.roughness);
         _fragColor = vec4(color, frag.normalVal.a);
     }
diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf
index eed3b94c91..1a739f9389 100644
--- a/libraries/render-utils/src/directional_light.slf
+++ b/libraries/render-utils/src/directional_light.slf
@@ -46,7 +46,7 @@ void main(void) {
                         frag.normal,
                         frag.diffuse,
                         frag.metallic,
-                        frag.specular,
+                        frag.emissive,
                         frag.roughness);
         _fragColor = vec4(color, frag.normalVal.a);
     }
diff --git a/libraries/render-utils/src/directional_light_shadow.slf b/libraries/render-utils/src/directional_light_shadow.slf
index 494046bcb3..3b9b4d22c6 100644
--- a/libraries/render-utils/src/directional_light_shadow.slf
+++ b/libraries/render-utils/src/directional_light_shadow.slf
@@ -48,7 +48,7 @@ void main(void) {
                         frag.normal,
                         frag.diffuse,
                         frag.metallic,
-                        frag.specular,
+                        frag.emissive,
                         frag.roughness);
         _fragColor = vec4(color, frag.normalVal.a);
     }
diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf
index 605d1de963..9e24a5f585 100755
--- a/libraries/render-utils/src/directional_skybox_light.slf
+++ b/libraries/render-utils/src/directional_skybox_light.slf
@@ -46,7 +46,7 @@ void main(void) {
                         frag.normal,
                         frag.diffuse,
                         frag.metallic,
-                        frag.specular,
+                        frag.emissive,
                         frag.roughness);
 
         _fragColor = vec4(color, frag.normalVal.a);
diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf
index 75a48caacf..c3008b5509 100644
--- a/libraries/render-utils/src/directional_skybox_light_shadow.slf
+++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf
@@ -48,7 +48,7 @@ void main(void) {
                         frag.normal,
                         frag.diffuse,
                         frag.metallic,
-                        frag.specular,
+                        frag.emissive,
                         frag.roughness);
 
         _fragColor = vec4(color, frag.normalVal.a);
diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf
index b43694bbb7..c9ca6d9eb7 100755
--- a/libraries/render-utils/src/model.slf
+++ b/libraries/render-utils/src/model.slf
@@ -16,7 +16,7 @@
 <@include model/Material.slh@>
 
 <@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
 
 in vec4 _position;
 in vec3 _normal;
@@ -25,15 +25,26 @@ in vec2 _texCoord0;
 
 
 void main(void) {
-    <$fetchMaterialTextures(_texCoord0, albedo, roughness)$>
-    
     Material mat = getMaterial();
+    int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$>
+
+    vec3 albedo = getMaterialAlbedo(mat);
+    <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
+    albedo *= _color;
+
+    float roughness = getMaterialRoughness(mat);
+    <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
+
+    vec3 emissive = getMaterialEmissive(mat);
+    <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
 
     packDeferredFragment(
         normalize(_normal.xyz), 
-        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
-        getMaterialAlbedo(mat) * albedo.rgb * _color,
-        getMaterialRoughness(mat) * roughness,
+        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
+        albedo,
+        roughness,
         getMaterialMetallic(mat),
-        getMaterialFresnel(mat));
+        emissive,
+        occlusionTex);
 }
diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf
index bfe809f472..46d81d39e1 100755
--- a/libraries/render-utils/src/model_lightmap.slf
+++ b/libraries/render-utils/src/model_lightmap.slf
@@ -27,11 +27,11 @@ in vec3 _normal;
 in vec3 _color;
 
 void main(void) {
-
-    <$fetchMaterialTextures(_texCoord0, albedo, roughness)$>
+    Material mat = getMaterial();
+    int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness)$>
     <$fetchMaterialLightmap(_texCoord1, emissive)$>
 
-    Material mat = getMaterial();
 
     packDeferredFragmentLightmap(
         normalize(_normal), 
diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf
index 1d305541fa..9ccc6e5352 100755
--- a/libraries/render-utils/src/model_lightmap_normal_map.slf
+++ b/libraries/render-utils/src/model_lightmap_normal_map.slf
@@ -28,11 +28,10 @@ in vec3 _tangent;
 in vec3 _color;
 
 void main(void) {
-
-    <$fetchMaterialTextures(_texCoord0, albedo, roughness, normalTexel)$>
-    <$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
-
     Material mat = getMaterial();
+    int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel)$>
+    <$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
 
     vec3 viewNormal;
     <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$>
diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf
index 93bb3a793e..71909a789f 100755
--- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf
+++ b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf
@@ -28,10 +28,10 @@ in vec3 _tangent;
 in vec3 _color;
 
 void main(void) {
-    <$fetchMaterialTextures(_texCoord0, albedo, roughness, normalTexel, metalllicTex)$>
-    <$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
-    
     Material mat = getMaterial();
+    int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
+    <$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
     
     vec3 viewNormal;
     <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$>
@@ -41,7 +41,7 @@ void main(void) {
         evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
         getMaterialAlbedo(mat) * albedo.rgb * _color,
         getMaterialRoughness(mat) * roughness,
-        getMaterialMetallic(mat) * metalllicTex,
+        getMaterialMetallic(mat) * metallicTex,
         /*specular, // no use of */ getMaterialFresnel(mat),
         lightmapVal);
 }
diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf
index 23d3a8e2b3..5eefefdc29 100755
--- a/libraries/render-utils/src/model_lightmap_specular_map.slf
+++ b/libraries/render-utils/src/model_lightmap_specular_map.slf
@@ -27,17 +27,17 @@ in vec3 _normal;
 in vec3 _color;
 
 void main(void) {
-    <$fetchMaterialTextures(_texCoord0, albedo, roughness, _SCRIBE_NULL, specular)$>
-    <$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
-    
     Material mat = getMaterial();
+    int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
+    <$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
 
     packDeferredFragmentLightmap(
         normalize(_normal), 
         evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
         getMaterialAlbedo(mat) * albedo.rgb * _color,
         getMaterialRoughness(mat) * roughness,
-        getMaterialMetallic(mat),
-        /*specular, // no use of */getMaterialFresnel(mat),
+        getMaterialMetallic(mat) * metallicTex,
+        /*metallicTex, // no use of */getMaterialFresnel(mat),
         lightmapVal);
 }
diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf
index 13cb63d322..a584427005 100755
--- a/libraries/render-utils/src/model_normal_map.slf
+++ b/libraries/render-utils/src/model_normal_map.slf
@@ -17,7 +17,7 @@
 <@include model/Material.slh@>
 
 <@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
 
 in vec4 _position;
 in vec2 _texCoord0;
@@ -26,18 +26,29 @@ in vec3 _tangent;
 in vec3 _color;
 
 void main(void) {
-    <$fetchMaterialTextures(_texCoord0, albedo, roughness, normalTexel)$>
-    
     Material mat = getMaterial();
+    int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, occlusionTex)$>
+
+    vec3 albedo = getMaterialAlbedo(mat);
+    <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
+    albedo *= _color;
+
+    float roughness = getMaterialRoughness(mat);
+    <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
+
+    vec3 emissive = getMaterialEmissive(mat);
+    <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
 
     vec3 viewNormal;
-    <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$>
+    <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
 
     packDeferredFragment(
         viewNormal, 
-        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
-        getMaterialAlbedo(mat) * albedo.rgb * _color,
-        getMaterialRoughness(mat) * roughness,
+        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
+        albedo,
+        roughness,
         getMaterialMetallic(mat),
-        getMaterialFresnel(mat));
+        emissive,
+        occlusionTex);
 }
diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf
index 66fe0cd67e..cf461db7ef 100755
--- a/libraries/render-utils/src/model_normal_specular_map.slf
+++ b/libraries/render-utils/src/model_normal_specular_map.slf
@@ -17,7 +17,7 @@
 <@include model/Material.slh@>
 
 <@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
 
 in vec4 _position;
 in vec2 _texCoord0;
@@ -26,18 +26,22 @@ in vec3 _tangent;
 in vec3 _color;
 
 void main(void) {
-    
-    <$fetchMaterialTextures(_texCoord0, albedo, roughnessTex, normalTexel, metallicTex)$>
-    
     Material mat = getMaterial();
     int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, occlusionTex)$>
+
+    vec3 albedo = getMaterialAlbedo(mat);
+    <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
+    albedo *= _color;
 
     float roughness = getMaterialRoughness(mat);
     <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
 
+    vec3 emissive = getMaterialEmissive(mat);
+    <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
 
     vec3 viewNormal;
-    <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$>
+    <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
 
     float metallic = getMaterialMetallic(mat);
     <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
@@ -45,10 +49,10 @@ void main(void) {
 
     packDeferredFragment(
         normalize(viewNormal.xyz), 
-        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
-        getMaterialAlbedo(mat) * albedo.rgb * _color,
+        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
+        albedo,
         roughness,
         metallic,
-        /*vec3(specular) //*/getMaterialFresnel(mat)
-        );
+        emissive,
+        occlusionTex);
 }
diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf
index cfdf023ae3..32e5823430 100755
--- a/libraries/render-utils/src/model_specular_map.slf
+++ b/libraries/render-utils/src/model_specular_map.slf
@@ -17,7 +17,7 @@
 <@include model/Material.slh@>
 
 <@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
 
 in vec4 _position;
 in vec2 _texCoord0;
@@ -26,21 +26,29 @@ in vec3 _color;
 
 
 void main(void) {
- 
-    <$fetchMaterialTextures(_texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
- 
     Material mat = getMaterial();
     int matKey = getMaterialKey(mat);
+    <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, occlusionTex)$>
+
+    vec3 albedo = getMaterialAlbedo(mat);
+    <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
+    albedo *= _color;
+
+    float roughness = getMaterialRoughness(mat);
+    <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
+
+    vec3 emissive = getMaterialEmissive(mat);
+    <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
 
     float metallic = getMaterialMetallic(mat);
     <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
 
     packDeferredFragment(
         normalize(_normal), 
-        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
-        getMaterialAlbedo(mat) * albedo.rgb * _color,
-        getMaterialRoughness(mat) * roughness,
+        evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
+        albedo,
+        roughness,
         metallic,
-        /*vec3(specular) //*/ getMaterialFresnel(mat)
-        );
+        emissive,
+        occlusionTex);
 }
diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf
index 3efa523434..086f9fe168 100755
--- a/libraries/render-utils/src/model_translucent.slf
+++ b/libraries/render-utils/src/model_translucent.slf
@@ -38,7 +38,7 @@ void main(void) {
     vec3 fragNormal = normalize(_normal);
     vec3 fragAlbedo = getMaterialAlbedo(mat) * albedo.rgb * _color;
     float fragMetallic = getMaterialMetallic(mat);
-    vec3 fragFresnel = getMaterialFresnel(mat);
+    vec3 fragEmissive = getMaterialEmissive(mat);
     float fragRoughness = getMaterialRoughness(mat);
     float fragOpacity = getMaterialOpacity(mat) * albedo.a * _alpha;
 
@@ -52,7 +52,7 @@ void main(void) {
         fragNormal,
         fragAlbedo,
         fragMetallic,
-        fragFresnel,
+        fragEmissive,
         fragRoughness),
         fragOpacity);
 }
diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf
index 4b5cdfb5ce..5ad9dc174f 100644
--- a/libraries/render-utils/src/simple.slf
+++ b/libraries/render-utils/src/simple.slf
@@ -54,6 +54,6 @@ void main(void) {
             normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular);
     } else {
         packDeferredFragment(
-            normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular);
+            normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), length(specular), DEFAULT_EMISSIVE, DEFAULT_OCCLUSION);
     }
 }
diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf
index b2bc15dbad..0832b22214 100644
--- a/libraries/render-utils/src/simple_textured.slf
+++ b/libraries/render-utils/src/simple_textured.slf
@@ -2,7 +2,7 @@
 <$VERSION_HEADER$>
 //  Generated on <$_SCRIBE_DATE$>
 //
-//  simple.frag
+//  simple_textured.slf
 //  fragment shader
 //
 //  Created by Clément Brisset on 5/29/15.
@@ -33,5 +33,6 @@ void main(void) {
         _color.rgb * texel.rgb,
         DEFAULT_ROUGHNESS,
         DEFAULT_METALLIC,
-        DEFAULT_SPECULAR);
+        DEFAULT_EMISSIVE,
+        DEFAULT_OCCLUSION);
 }
\ No newline at end of file
diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp
index 68c0b94766..f20b5144d3 100644
--- a/libraries/render/src/render/ShapePipeline.cpp
+++ b/libraries/render/src/render/ShapePipeline.cpp
@@ -56,8 +56,9 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
     slotBindings.insert(gpu::Shader::Binding(std::string("albedoMap"), Slot::ALBEDO_MAP));
     slotBindings.insert(gpu::Shader::Binding(std::string("roughnessMap"), Slot::ROUGHNESS_MAP));
     slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slot::NORMAL_MAP));
-    slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Slot::SPECULAR_MAP));
-    slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::LIGHTMAP_MAP));
+    slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Slot::METALLIC_MAP));
+    slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::EMISSIVE_LIGHTMAP_MAP));
+    slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::OCCLUSION_MAP));
     slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::LIGHT_BUFFER));
     slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING_MAP));
 
@@ -72,6 +73,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
     locations->normalTextureUnit = program->getTextures().findLocation("normalMap");
     locations->specularTextureUnit = program->getTextures().findLocation("specularMap");
     locations->emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
+    locations->occlusionTextureUnit = program->getTextures().findLocation("occlusionMap");
     locations->skinClusterBufferUnit = program->getBuffers().findLocation("skinClusterBuffer");
     locations->materialBufferUnit = program->getBuffers().findLocation("materialBuffer");
     locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h
index b4fb622b39..963a3c76d4 100644
--- a/libraries/render/src/render/ShapePipeline.h
+++ b/libraries/render/src/render/ShapePipeline.h
@@ -197,9 +197,10 @@ public:
         static const int MATERIAL_GPU = 3;
         static const int ALBEDO_MAP = 0;
         static const int NORMAL_MAP = 1;
-        static const int SPECULAR_MAP = 2;
-        static const int LIGHTMAP_MAP = 3;
+        static const int METALLIC_MAP = 2;
+        static const int EMISSIVE_LIGHTMAP_MAP = 3;
         static const int ROUGHNESS_MAP = 4;
+        static const int OCCLUSION_MAP = 5;
 
         static const int LIGHT_BUFFER = 4;
         static const int NORMAL_FITTING_MAP = 10;
@@ -213,6 +214,7 @@ public:
         int roughnessTextureUnit;
         int specularTextureUnit;
         int emissiveTextureUnit;
+        int occlusionTextureUnit;
         int emissiveParams;
         int normalFittingMapUnit;
         int skinClusterBufferUnit;
diff --git a/tests/gpu-test/src/unlit.slf b/tests/gpu-test/src/unlit.slf
index d070662495..f88fcb510b 100644
--- a/tests/gpu-test/src/unlit.slf
+++ b/tests/gpu-test/src/unlit.slf
@@ -24,5 +24,5 @@ void main(void) {
         normalize(_normal.xyz), 
         1.0,
         _color.rgb,
-        DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_SPECULAR);
+        DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION);
 }