diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae05abb51ae48b596525bbb267797a132c186c40..bca9400de92c552b79720ba8f223ec3520dde185 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ Note that since we don't clearly distinguish between a public and private interf
     - Fix cylinder near-clipping
     - Add interior cylinder caps
     - Add per-pixel object clipping
+    - Add `solidInterior` parameter
 - Fix `QualityAssessment` assignment bug for structures with different auth vs label sequence numbering
 - Refresh `ApplyActionControl`'s param definition when toggling expanded state
 
diff --git a/src/mol-gl/shader/cylinders.frag.ts b/src/mol-gl/shader/cylinders.frag.ts
index c1169f27a6d3c08ba47fbc71dba835b24d0cf1b3..b820b770948e38fe5af005bf613e57172ccc3dd1 100644
--- a/src/mol-gl/shader/cylinders.frag.ts
+++ b/src/mol-gl/shader/cylinders.frag.ts
@@ -28,6 +28,12 @@ uniform mat4 uInvView;
 #include light_frag_params
 #include common_clip
 
+#ifdef dSolidInterior
+    const bool solidInterior = true;
+#else
+    const bool solidInterior = false;
+#endif
+
 // adapted from https://www.shadertoy.com/view/4lcSRn
 // The MIT License, Copyright 2016 Inigo Quilez
 bool CylinderImpostor(
@@ -63,6 +69,9 @@ bool CylinderImpostor(
         bool bottomInterior = false;
     #endif
 
+    bool clipped = false;
+    bool objectClipped = false;
+
     // body outside
     h = sqrt(h);
     float t = (-k1 - h) / k2;
@@ -74,36 +83,76 @@ bool CylinderImpostor(
         viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
         fragmentDepth = calcDepth(viewPosition);
         #if defined(dClipVariant_pixel) && dClipObjectCount != 0
-            if (clipTest(vec4(modelPosition, 0.0))) fragmentDepth = -1.0;
+            if (clipTest(vec4(modelPosition, 0.0))) {
+                objectClipped = true;
+                fragmentDepth = -1.0;
+                #ifdef dSolidInterior
+                    topCap = !topInterior;
+                    bottomCap = !bottomInterior;
+                #endif
+            }
         #endif
         if (fragmentDepth > 0.0) return true;
+        clipped = true;
     }
 
-    if (topCap && y < 0.0) {
-        // top cap
-        t = -baoc / bard;
-        if (abs(k1 + k2 * t) < h) {
-            interior = topInterior;
-            cameraNormal = -ba / baba;
-            modelPosition = rayOrigin + t * rayDir;
-            viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
-            fragmentDepth = calcDepth(viewPosition);
-            if (fragmentDepth > 0.0) return true;
-        }
-    } else if (bottomCap && y >= 0.0) {
-        // bottom cap
-        t = (baba - baoc) / bard;
-        if (abs(k1 + k2 * t) < h) {
-            interior = bottomInterior;
-            cameraNormal = ba / baba;
-            modelPosition = rayOrigin + t * rayDir;
-            viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
-            fragmentDepth = calcDepth(viewPosition);
-            if (fragmentDepth > 0.0) return true;
+    if (!clipped) {
+        if (topCap && y < 0.0) {
+            // top cap
+            t = -baoc / bard;
+            if (abs(k1 + k2 * t) < h) {
+                interior = topInterior;
+                cameraNormal = -ba / baba;
+                modelPosition = rayOrigin + t * rayDir;
+                viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
+                fragmentDepth = calcDepth(viewPosition);
+                #if defined(dClipVariant_pixel) && dClipObjectCount != 0
+                    if (clipTest(vec4(modelPosition, 0.0))) {
+                        objectClipped = true;
+                        fragmentDepth = -1.0;
+                        #ifdef dSolidInterior
+                            topCap = !topInterior;
+                            bottomCap = !bottomInterior;
+                        #endif
+                    }
+                #endif
+                if (fragmentDepth > 0.0) {
+                    #ifdef dSolidInterior
+                        if (interior) cameraNormal = -rayDir;
+                    #endif
+                    return true;
+                }
+            }
+        } else if (bottomCap && y >= 0.0) {
+            // bottom cap
+            t = (baba - baoc) / bard;
+            if (abs(k1 + k2 * t) < h) {
+                interior = bottomInterior;
+                cameraNormal = ba / baba;
+                modelPosition = rayOrigin + t * rayDir;
+                viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
+                fragmentDepth = calcDepth(viewPosition);
+                #if defined(dClipVariant_pixel) && dClipObjectCount != 0
+                    if (clipTest(vec4(modelPosition, 0.0))) {
+                        objectClipped = true;
+                        fragmentDepth = -1.0;
+                        #ifdef dSolidInterior
+                            topCap = !topInterior;
+                            bottomCap = !bottomInterior;
+                        #endif
+                    }
+                #endif
+                if (fragmentDepth > 0.0) {
+                    #ifdef dSolidInterior
+                        if (interior) cameraNormal = -rayDir;
+                    #endif
+                    return true;
+                }
+            }
         }
     }
 
-    if (uDoubleSided) {
+    if (uDoubleSided || solidInterior) {
         // body inside
         h = -h;
         t = (-k1 - h) / k2;
@@ -116,8 +165,10 @@ bool CylinderImpostor(
             fragmentDepth = calcDepth(viewPosition);
             if (fragmentDepth > 0.0) {
                 #ifdef dSolidInterior
-                    fragmentDepth = 0.0 + (0.0000001 / vSize);
-                    cameraNormal = -rayDir;
+                    if (!objectClipped) {
+                        fragmentDepth = 0.0 + (0.0000002 / vSize);
+                        cameraNormal = -rayDir;
+                    }
                 #endif
                 return true;
             }
@@ -134,8 +185,10 @@ bool CylinderImpostor(
                 fragmentDepth = calcDepth(viewPosition);
                 if (fragmentDepth > 0.0) {
                     #ifdef dSolidInterior
-                        fragmentDepth = 0.0 + (0.0000001 / vSize);
-                        cameraNormal = -rayDir;
+                        if (!objectClipped) {
+                            fragmentDepth = 0.0 + (0.0000002 / vSize);
+                            cameraNormal = -rayDir;
+                        }
                     #endif
                     return true;
                 }
@@ -151,8 +204,10 @@ bool CylinderImpostor(
                 fragmentDepth = calcDepth(viewPosition);
                 if (fragmentDepth > 0.0) {
                     #ifdef dSolidInterior
-                        fragmentDepth = 0.0 + (0.0000001 / vSize);
-                        cameraNormal = -rayDir;
+                        if (!objectClipped) {
+                            fragmentDepth = 0.0 + (0.0000002 / vSize);
+                            cameraNormal = -rayDir;
+                        }
                     #endif
                     return true;
                 }
diff --git a/src/mol-gl/shader/cylinders.vert.ts b/src/mol-gl/shader/cylinders.vert.ts
index f9d1a0694409d57700e7624388b495217b119538..60b3f19328854456f0fdfccfbd6b985d29f0b8c6 100644
--- a/src/mol-gl/shader/cylinders.vert.ts
+++ b/src/mol-gl/shader/cylinders.vert.ts
@@ -57,10 +57,6 @@ void main() {
     // ensure cylinder 'dir' is pointing towards the camera
     if(dot(camDir, dir) < 0.0) {
         dir = -dir;
-        // TODO: revisit
-        // vec3 tmp = vStart;
-        // vStart = vEnd;
-        // vEnd = tmp;
     }
 
     vec3 left = cross(camDir, dir);
diff --git a/src/mol-gl/shader/spheres.frag.ts b/src/mol-gl/shader/spheres.frag.ts
index 9af2d9d39b2f81ce8fc3e20e0b653d19f282d6f3..9eaf356c7fd1ec4ecc0d0bddbab6d99059150e8c 100644
--- a/src/mol-gl/shader/spheres.frag.ts
+++ b/src/mol-gl/shader/spheres.frag.ts
@@ -23,7 +23,13 @@ varying float vRadiusSq;
 varying vec3 vPoint;
 varying vec3 vPointViewPosition;
 
-bool SphereImpostor(out vec3 modelPos, out vec3 cameraPos, out vec3 cameraNormal, out bool interior, out float fragmentDepth, out bool clipped){
+#ifdef dSolidInterior
+    const bool solidInterior = true;
+#else
+    const bool solidInterior = false;
+#endif
+
+bool SphereImpostor(out vec3 modelPos, out vec3 cameraPos, out vec3 cameraNormal, out bool interior, out float fragmentDepth){
     vec3 cameraSpherePos = -vPointViewPosition;
 
     vec3 rayOrigin = mix(vec3(0.0, 0.0, 0.0), vPoint, uIsOrtho);
@@ -43,9 +49,11 @@ bool SphereImpostor(out vec3 modelPos, out vec3 cameraPos, out vec3 cameraNormal
     modelPos = (uInvView * vec4(cameraPos, 1.0)).xyz;
     fragmentDepth = calcDepth(cameraPos);
 
+    bool objectClipped = false;
+
     #if defined(dClipVariant_pixel) && dClipObjectCount != 0
         if (clipTest(vec4(modelPos, 0.0))) {
-            clipped = true;
+            objectClipped = true;
             fragmentDepth = -1.0;
         }
     #endif
@@ -54,12 +62,18 @@ bool SphereImpostor(out vec3 modelPos, out vec3 cameraPos, out vec3 cameraNormal
         cameraNormal = normalize(cameraPos - cameraSpherePos);
         interior = false;
         return true;
-    } else if (uDoubleSided) {
+    } else if (uDoubleSided || solidInterior) {
         cameraPos = rayDirection * posT + rayOrigin;
         modelPos = (uInvView * vec4(cameraPos, 1.0)).xyz;
         fragmentDepth = calcDepth(cameraPos);
         cameraNormal = -normalize(cameraPos - cameraSpherePos);
         interior = true;
+        #ifdef dSolidInterior
+            if (!objectClipped) {
+                fragmentDepth = 0.0 + (0.0000001 / vRadius);
+                cameraNormal = -mix(normalize(vPoint), vec3(0.0, 0.0, 1.0), uIsOrtho);
+            }
+        #endif
         return true;
     }
 
@@ -72,7 +86,7 @@ void main(void){
     vec3 cameraNormal;
     float fragmentDepth;
     bool clipped = false;
-    bool hit = SphereImpostor(modelPos, cameraPos, cameraNormal, interior, fragmentDepth, clipped);
+    bool hit = SphereImpostor(modelPos, cameraPos, cameraNormal, interior, fragmentDepth);
     if (!hit) discard;
 
     if (fragmentDepth < 0.0) discard;
@@ -81,13 +95,6 @@ void main(void){
     vec3 vViewPosition = cameraPos;
     vec3 vModelPosition = modelPos;
 
-    #ifdef dSolidInterior
-        if (interior && !clipped) {
-            fragmentDepth = 0.0 + (0.0000001 / vRadius);
-            cameraNormal = -mix(normalize(vPoint), vec3(0.0, 0.0, 1.0), uIsOrtho);
-        }
-    #endif
-
     gl_FragDepthEXT = fragmentDepth;
 
     #include clip_pixel