diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 998ebf8836e305b0ce0db5065f6fd7ba39a72275..56aa8437de942eb9bd4353595694e2c8f17ff38d 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -27,6 +27,10 @@
 #define PBR_USE_IBL                1
 #define PBR_USE_SUN                1
 
+#define PBR_USE_LINEAR_ALBEDO      1
+#define PBR_USE_DEFAULT_IRRADIANCE 0 // PBR: irradiance, skins/default/textures/default_irradiance.png
+#define PBR_USE_IRRADIANCE_HACK    1
+
 #define DEBUG_PBR_LIGHT_TYPE       0 // Output no global light to make it easier to see pointLight and spotLight
 #define DEBUG_PBR_PACKORM0         0 // Rough=0, Metal=0
 #define DEBUG_PBR_PACKORM1         0 // Rough=1, Metal=1
@@ -135,6 +139,9 @@ uniform sampler2DRect diffuseRect;
 uniform sampler2DRect specularRect;
 uniform sampler2DRect normalMap;
 uniform sampler2DRect emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+uniform sampler2D altDiffuseMap; // PBR: irradiance, skins/default/textures/default_irradiance.png
+
+const float M_PI = 3.14159265;
 
 #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
 uniform sampler2DRect lightMap;
@@ -295,7 +302,11 @@ void main()
         float bv = clamp(dot(b,v),0,1);
 
         // Reference: getMetallicRoughnessInfo
+#if PBR_USE_LINEAR_ALBEDO
+        vec3  base            = diffuse.rgb;
+#else
         vec3  base            = linear_to_srgb(diffuse.rgb);
+#endif
         float perceptualRough = max(packedORM.g, 0.1);
         vec3 c_diff, reflect0, reflect90;
         float alphaRough, specWeight;
@@ -321,7 +332,14 @@ void main()
 #if DEBUG_PBR_IRRADIANCE_RAW
         vec3 debug_irradiance = irradiance;
 #endif
+
+#if PBR_USE_DEFAULT_IRRADIANCE
+        vec2 iruv  = vec2(0.5f + 0.5f * atan(reflectVN.z, reflectVN.x) / M_PI, 1.f - acos(reflectVN.y) / M_PI);
+        irradiance = texture2D(altDiffuseMap, iruv).rgb * ambocc;
+#endif
+#if PBR_USE_IRRADIANCE_HACK
         irradiance       = max(amblit,irradiance) * ambocc;
+#endif
         specLight        = srgb_to_linear(specLight);
 #if DEBUG_PBR_SPECLIGHT051
         specLight        = vec3(0,0.5,1.0);
@@ -365,8 +383,13 @@ void main()
 #endif
             // scol = sun shadow
             vec3 intensity  = ambocc * sunColor * nl * scol;
+#if PBR_USE_LINEAR_ALBEDO
+            vec3 sunDiffuse = intensity * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh);
+            vec3 sunSpec    = intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);
+#else
             vec3 sunDiffuse = base * intensity * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh);
             vec3 sunSpec    =        intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);
+#endif
             bloom = dot(sunSpec, sunSpec) / (scale * scale * scale);
 
     #if DEBUG_PBR_SUN_SPEC_FRESNEL
@@ -577,9 +600,11 @@ void main()
     #endif
     #if DEBUG_PBR_IRRADIANCE_RAW
         color.rgb = debug_irradiance;
+        bloom = 0;
     #endif
     #if DEBUG_PBR_IRRADIANCE
         color.rgb = irradiance;
+        bloom = 0;
     #endif
     #if DEBUG_PBR_KSPEC
         color.rgb = kSpec;
@@ -633,6 +658,7 @@ void main()
     #if DEBUG_PBR_LIGHT_TYPE
         color.rgb = vec3(0);
     #endif
+
         frag_color.rgb = color.rgb; // PBR is done in linear
     }
 else
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 0c23214b521bc842592e433eca589cbfeca3dcee..15d623257b7c8ac1074e04abf5dddcaadac09838 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -76,6 +76,7 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sFlatNormalImagep = NULL;
+LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultIrradiancePBRp;
 LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap;
 LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL;
 F32 LLViewerFetchedTexture::sMaxVirtualSize = F32_MAX/2.f;
@@ -458,6 +459,7 @@ void LLViewerTextureManager::cleanup()
 	LLViewerFetchedTexture::sWhiteImagep = NULL;
 	
 	LLViewerFetchedTexture::sFlatNormalImagep = NULL;
+	LLViewerFetchedTexture::sDefaultIrradiancePBRp = NULL;
 
 	LLViewerMediaTexture::cleanUpClass();	
 }
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 5893f549d023ad80284a827f432260a11369bd53..3cfdf0b6f165eed5cad7db6a089c23c8da3c226d 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -531,6 +531,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.
 	static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
 	static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface
+	static LLPointer<LLViewerFetchedTexture> sDefaultIrradiancePBRp; // PBR: irradiance
 };
 
 //
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 1a766dd4041eb9b7d112b1025375740bba98bc21..3d99e62e22d00039eecff1d66302f3356e13e6fc 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -120,7 +120,10 @@ void LLViewerTextureList::doPreloadImages()
 
 	// Set the default flat normal map
 	LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP);
-	
+
+	// PBR: irradiance
+	LLViewerFetchedTexture::sDefaultIrradiancePBRp = LLViewerTextureManager::getFetchedTextureFromFile("default_irradiance.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
+
 	image_list->initFromFile();
 	
 	// turn off clamping and bilinear filtering for uv picking images
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 91d276c8df6b34ee2dbab70c73e3ce95952c0ae0..67f0ea68c1367daf1c5dd9e9aad28c5c4ee37f55 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8643,6 +8643,11 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
             soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
             soften_shader.uniform4fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
 
+            if (!LLPipeline::sUnderWaterRender && LLPipeline::sRenderPBR)
+            {
+                soften_shader.bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, LLViewerFetchedTexture::sDefaultIrradiancePBRp); // PBR: irradiance
+            }
+
             if(LLPipeline::sRenderPBR)
             {
                 LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis();
diff --git a/indra/newview/skins/default/textures/default_irradiance.png b/indra/newview/skins/default/textures/default_irradiance.png
new file mode 100644
index 0000000000000000000000000000000000000000..899e0ddf2ac2702b27a6b32040516d5d770c3f93
Binary files /dev/null and b/indra/newview/skins/default/textures/default_irradiance.png differ