From 86f7a8b273cdd72eda54164c2d8f5ce1e4ce1748 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Wed, 14 Dec 2022 22:50:15 -0800 Subject: [PATCH] add impostor solidInterior param --- CHANGELOG.md | 1 + src/mol-gl/shader/cylinders.frag.ts | 113 +++++++++++++++++++++------- src/mol-gl/shader/cylinders.vert.ts | 4 - src/mol-gl/shader/spheres.frag.ts | 29 ++++--- 4 files changed, 103 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae05abb51..bca9400de 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 c1169f27a..b820b7709 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 f9d1a0694..60b3f1932 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 9af2d9d39..9eaf356c7 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 -- GitLab