diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts
index e206f78069a3b5e5ee5d37503fe029c62521ebc7..da4a273a98f6dede4ad3441d82bebf1ab8955fa0 100644
--- a/src/mol-gl/renderable/schema.ts
+++ b/src/mol-gl/renderable/schema.ts
@@ -169,6 +169,7 @@ export const GlobalUniformSchema = {
     uFogColor: UniformSpec('v3'),
 
     uPickingAlphaThreshold: UniformSpec('f'),
+    uInteriorDarkening: UniformSpec('f'),
 }
 export type GlobalUniformSchema = typeof GlobalUniformSchema
 export type GlobalUniformValues = Values<GlobalUniformSchema> // { [k in keyof GlobalUniformSchema]: ValueCell<any> }
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index 53968cc381ad2144680640e369e0c0b4ead71116..673b8854db3fa4c8d51dbf9e7eca0c5eff2e7fa3 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -47,6 +47,7 @@ interface Renderer {
 export const RendererParams = {
     backgroundColor: PD.Color(Color(0x000000)),
     pickingAlphaThreshold: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'The minimum opacity value needed for an object to be pickable.' }),
+    interiorDarkening: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }),
 
     lightIntensity: PD.Numeric(0.6, { min: 0.0, max: 1.0, step: 0.01 }),
     ambientIntensity: PD.Numeric(0.4, { min: 0.0, max: 1.0, step: 0.01 }),
@@ -107,6 +108,7 @@ namespace Renderer {
             uFogColor: ValueCell.create(bgColor),
 
             uPickingAlphaThreshold: ValueCell.create(p.pickingAlphaThreshold),
+            uInteriorDarkening: ValueCell.create(p.interiorDarkening),
         }
         const globalUniformList = Object.entries(globalUniforms)
 
@@ -232,6 +234,10 @@ namespace Renderer {
                     p.pickingAlphaThreshold = props.pickingAlphaThreshold
                     ValueCell.update(globalUniforms.uPickingAlphaThreshold, p.pickingAlphaThreshold)
                 }
+                if (props.interiorDarkening !== undefined && props.interiorDarkening !== p.interiorDarkening) {
+                    p.interiorDarkening = props.interiorDarkening
+                    ValueCell.update(globalUniforms.uInteriorDarkening, p.interiorDarkening)
+                }
                 if (props.backgroundColor !== undefined && props.backgroundColor !== p.backgroundColor) {
                     p.backgroundColor = props.backgroundColor
                     Color.toVec3Normalized(bgColor, p.backgroundColor)
diff --git a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts
index c4daf6f6108a8e0065c096fe2a040740d35ed191..789f6e0491fe03f57e51c6ebc75b86d17fe0eadf 100644
--- a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts
+++ b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts
@@ -13,6 +13,12 @@ export default `
     #endif
 #endif
 
+#if defined(dColorType_uniform) || defined(dColorType_attribute) || defined(dColorType_instance) || defined(dColorType_group) || defined(dColorType_groupInstance)
+    if (gl_FrontFacing == false) {
+        material.rgb *= 1.0 - uInteriorDarkening;
+    }
+#endif
+
 // mix material with overpaint
 #if defined(dOverpaint) && (defined(dColorType_uniform) || defined(dColorType_attribute) || defined(dColorType_instance) || defined(dColorType_group) || defined(dColorType_groupInstance))
     material.rgb = mix(material.rgb, vOverpaint.rgb, vOverpaint.a);
diff --git a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts
index 1d9aedc449b568f80b33f13ce460b86d865bdb4c..290312d1c8fe74d6b57c6955a8123dce68b0a54e 100644
--- a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts
+++ b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts
@@ -18,4 +18,6 @@ uniform vec3 uFogColor;
 uniform float uAlpha;
 uniform float uPickingAlphaThreshold;
 uniform int uPickable;
+
+uniform float uInteriorDarkening;
 `
\ No newline at end of file
diff --git a/src/mol-gl/shader/spheres.frag.ts b/src/mol-gl/shader/spheres.frag.ts
index e40b9f15e4f6decffe7bf381c574149d23b66990..2a584f7efd1565be7f294e6f071c264705518609 100644
--- a/src/mol-gl/shader/spheres.frag.ts
+++ b/src/mol-gl/shader/spheres.frag.ts
@@ -14,10 +14,6 @@ precision highp int;
 #include light_frag_params
 
 uniform mat4 uProjection;
-// uniform vec3 uInteriorColor;
-// uniform float uInteriorDarkening;
-vec3 uInteriorColor = vec3(0.5, 0.5, 0.5);
-float uInteriorDarkening = 0.0;
 
 uniform float uClipNear;
 uniform float uIsOrtho;
@@ -53,7 +49,7 @@ bool Impostor(out vec3 cameraPos, out vec3 cameraNormal){
     float B = dot(rayDirection, cameraSphereDir);
     float det = B * B + vRadiusSq - dot(cameraSphereDir, cameraSphereDir);
 
-    if(det < 0.0){
+    if (det < 0.0){
         discard;
         return false;
     }
@@ -65,16 +61,16 @@ bool Impostor(out vec3 cameraPos, out vec3 cameraNormal){
     cameraPos = rayDirection * negT + rayOrigin;
 
     #ifdef NEAR_CLIP
-        if(calcDepth(cameraPos) <= 0.0){
+        if (calcDepth(cameraPos) <= 0.0){
             cameraPos = rayDirection * posT + rayOrigin;
             interior = true;
-        }else if(calcClip(cameraPos) > 0.0){
+        } else if(calcClip(cameraPos) > 0.0) {
             cameraPos = rayDirection * posT + rayOrigin;
             interior = true;
             flag2 = true;
         }
     #else
-        if(calcDepth(cameraPos) <= 0.0){
+        if (calcDepth(cameraPos) <= 0.0) {
             cameraPos = rayDirection * posT + rayOrigin;
             interior = true;
         }
@@ -90,24 +86,24 @@ void main(void){
     bool flag = Impostor(cameraPos, cameraNormal);
 
     #ifdef NEAR_CLIP
-        if(calcClip(cameraPos) > 0.0)
+        if (calcClip(cameraPos) > 0.0)
             discard;
     #endif
 
     // FIXME not compatible with custom clipping plane
     // Set the depth based on the new cameraPos.
     gl_FragDepthEXT = calcDepth(cameraPos);
-    if(!flag){
+    if (!flag) {
         // clamp to near clipping plane and add a tiny value to
         // make spheres with a greater radius occlude smaller ones
         #ifdef NEAR_CLIP
-            if( flag2 ){
+            if (flag2) {
                 gl_FragDepthEXT = max(0.0, calcDepth(vec3(-(uClipNear - 0.5))) + (0.0000001 / vRadius));
-            }else if(gl_FragDepthEXT >= 0.0){
+            } else if (gl_FragDepthEXT >= 0.0) {
                 gl_FragDepthEXT = 0.0 + (0.0000001 / vRadius);
             }
         #else
-            if(gl_FragDepthEXT >= 0.0){
+            if (gl_FragDepthEXT >= 0.0) {
                 gl_FragDepthEXT = 0.0 + (0.0000001 / vRadius);
             }
         #endif
@@ -132,11 +128,8 @@ void main(void){
         vec3 vViewPosition = -cameraPos;
         #include apply_light_color
 
-        if(interior){
-            #ifdef USE_INTERIOR_COLOR
-                gl_FragColor.rgb = uInteriorColor;
-            #endif
-            gl_FragColor.rgb *= 1.0 - uInteriorDarkening;
+        if (interior) {
+            gl_FragColor.rgb = material.rgb * (1.0 - uInteriorDarkening);
         }
 
         #include apply_marker_color