diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 4f6e01764ab550b3b36b63f6ae9551901b78a03f..14d9cf798f98278e83df11a78a3cadbc71f33494 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -686,17 +686,82 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit)
 #if defined(HERO_PROBES)
 
 uniform vec4 clipPlane;
-uniform samplerCubeArray heroProbes;
+
+uniform samplerCubeArray   heroProbes;
+
+layout (std140) uniform HeroProbeData
+{
+    mat4 heroBox[1];
+    vec4 heroSphere[1];
+    uint heroShape[1];
+    int heroMipCount;
+    int heroProbeCount;
+};
+
+vec3 boxIntersectHero(vec3 origin, vec3 dir, int i, out float d, float scale)
+{
+    // Intersection with OBB convert to unit box space
+    // Transform in local unit parallax cube space (scaled and rotated)
+    mat4 clipToLocal = heroBox[i];
+
+    vec3 RayLS = mat3(clipToLocal) * dir;
+    vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz;
+
+    d = 1.0-max(max(abs(PositionLS.x), abs(PositionLS.y)), abs(PositionLS.z));
+
+    vec3 Unitary = vec3(scale);
+    vec3 FirstPlaneIntersect  = (Unitary - PositionLS) / RayLS;
+    vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS;
+    vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect);
+    float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z));
+
+    // Use Distance in CS directly to recover intersection
+    vec3 IntersectPositionCS = origin + dir * Distance;
+
+    return IntersectPositionCS;
+}
+
+float sphereWeightHero(vec3 pos, vec3 dir, vec3 origin, float r, out float dw)
+{
+    float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
+    vec3 delta = pos.xyz - origin;
+    float d2 = max(length(delta), 0.001);
+
+    float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001);
+    float w = 1.0 / d2;
+
+    dw = w * atten * max(r, 1.0)*4;
+
+    w *= atten;
+
+    return w;
+}
 
 void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
 {
     float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w;
-    if (clipDist > 0.0 && clipDist < 0.1 && glossiness > 0.8)
+    float w = 0;
+    float dw = 0;
+    if (heroShape[0] < 1)
+    {
+        float d = 0;
+        boxIntersectHero(pos, norm, 0, d, 1.0);
+        
+        w = max(d, 0.001);
+    }
+    else
+    {
+        float r = heroSphere[0].w;
+        //v = sphereIntersect(pos, norm, heroSphere[0].xyz, 4096.0*4096.0);
+        
+        w = sphereWeightHero(pos, norm, heroSphere[0].xyz, r, dw);
+    }
+    
     {
         vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
         if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0)
         {
-            glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*10).xyz;
+            glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz * w;
         }
     }
 }
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index cc6e16c64f552605cec403b265353e259c542d8b..2f90249169abae7715bcd50495848ba387d7a0ba 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -32,16 +32,6 @@ uniform sampler2D specularRect;
 uniform sampler2D normalMap;
 uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
 
-uniform samplerCubeArray   heroProbes;
-
-#if defined(HERO_PROBES)
-layout (std140) uniform HeroProbeData
-{
-    vec4 heroPosition[1];
-    int heroProbeCount;
-};
-#endif
-
 const float M_PI = 3.14159265;
 
 #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp
index a00b6d6b5d96c311fb6f351a5a1ea4bf94f19acf..ee993c6ba1ad76b0b669328ac4ec4f9648b21654 100644
--- a/indra/newview/llheroprobemanager.cpp
+++ b/indra/newview/llheroprobemanager.cpp
@@ -417,7 +417,7 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe)
 
 void LLHeroProbeManager::updateUniforms()
 {
-    if (!LLPipeline::sReflectionProbesEnabled)
+    if (!gPipeline.RenderMirrors)
     {
         return;
     }
@@ -426,8 +426,11 @@ void LLHeroProbeManager::updateUniforms()
     
     struct HeroProbeData
     {
-        LLVector4 heroPosition[1];
-        GLint heroProbeCount = 1;
+        LLMatrix4 heroBox[1];
+        LLVector4 heroSphere[1];
+        GLint heroShape[1];
+        GLint heroMipCount;
+        GLint heroProbeCount;
     };
     
     HeroProbeData hpd;
@@ -437,8 +440,32 @@ void LLHeroProbeManager::updateUniforms()
     LLVector4a oa; // scratch space for transformed origin
     oa.set(0, 0, 0, 0);
     hpd.heroProbeCount = 1;
-    modelview.affineTransform(mProbes[0]->mOrigin, oa);
-    hpd.heroPosition[0].set(oa.getF32ptr());
+    
+    if (mNearestHero != nullptr)
+    {
+        mProbes[0]->mViewerObject = mNearestHero;
+        if (mNearestHero->getReflectionProbeIsBox())
+        {
+            LLVector3 s = mNearestHero->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f));
+            mProbes[0]->mRadius = s.magVec();
+        }
+        else
+        {
+            mProbes[0]->mRadius = mNearestHero->getScale().mV[0] * 0.5f;
+        }
+        
+        modelview.affineTransform(mProbes[0]->mOrigin, oa);
+        hpd.heroShape[0] = 0;
+        if (!mProbes[0]->getBox(hpd.heroBox[0]))
+        {
+            hpd.heroShape[0] = 1;
+        }
+        
+        hpd.heroSphere[0].set(oa.getF32ptr());
+        hpd.heroSphere[0].mV[3] = mProbes[0]->mRadius;
+    }
+    
+    hpd.heroMipCount = mMipChain.size();
 
     //copy rpd into uniform buffer object
     if (mUBO == 0)
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 8506886409461be2568f8b40a5e2b597afe33071..314426090585aadc38dc168fefe58ba84a534d29 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -1016,7 +1016,6 @@ void LLReflectionMapManager::updateUniforms()
                 {
                     refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f;
                 }
-
             }
             modelview.affineTransform(refmap->mOrigin, oa);
             rpd.refSphere[count].set(oa.getF32ptr());