瀏覽代碼

add impostor solidInterior param

Alexander Rose 2 年之前
父節點
當前提交
86f7a8b273
共有 4 個文件被更改,包括 103 次插入44 次删除
  1. 1 0
      CHANGELOG.md
  2. 84 29
      src/mol-gl/shader/cylinders.frag.ts
  3. 0 4
      src/mol-gl/shader/cylinders.vert.ts
  4. 18 11
      src/mol-gl/shader/spheres.frag.ts

+ 1 - 0
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
 

+ 84 - 29
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;
                 }

+ 0 - 4
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);

+ 18 - 11
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