UNPKG

molstar

Version:

A comprehensive macromolecular library.

5 lines 10 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isosurface_frag = void 0; exports.isosurface_frag = "\nprecision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\n#if __VERSION__ == 100\n uniform sampler2D tActiveVoxelsPyramid;\n#else\n precision highp isampler2D;\n uniform isampler2D tActiveVoxelsPyramid;\n#endif\n\nuniform sampler2D tActiveVoxelsBase;\nuniform sampler2D tVolumeData;\nuniform sampler2D tTriIndices;\n\nuniform float uIsoValue;\nuniform float uLevels;\nuniform float uSize;\nuniform float uCount;\nuniform bool uInvert;\n\nuniform vec3 uGridDim;\nuniform vec3 uGridTexDim;\nuniform mat4 uGridTransform;\n\n// scale to volume data coord\nuniform vec2 uScale;\n\n#include common\n\n// cube corners (excluding origin)\nconst vec3 c1 = vec3(1., 0., 0.);\nconst vec3 c2 = vec3(1., 1., 0.);\nconst vec3 c3 = vec3(0., 1., 0.);\nconst vec3 c4 = vec3(0., 0., 1.);\nconst vec3 c5 = vec3(1., 0., 1.);\nconst vec3 c6 = vec3(1., 1., 1.);\nconst vec3 c7 = vec3(0., 1., 1.);\n\nvec3 index3dFrom2d(vec2 coord) {\n vec2 gridTexPos = coord * uGridTexDim.xy;\n vec2 columnRow = ivec2Div(gridTexPos, uGridDim.xy);\n vec2 posXY = gridTexPos - columnRow * uGridDim.xy;\n float posZ = columnRow.y * intDiv(uGridTexDim.x, uGridDim.x) + columnRow.x;\n return vec3(posXY, posZ);\n}\n\nvec4 texture3dFrom2dNearest(sampler2D tex, vec3 pos, vec3 gridDim, vec2 texDim) {\n float zSlice = floor(pos.z * gridDim.z + 0.5); // round to nearest z-slice\n float column = intDiv(intMod(zSlice * gridDim.x, texDim.x), gridDim.x);\n float row = intDiv(zSlice * gridDim.x, texDim.x);\n vec2 coord = (vec2(column * gridDim.x, row * gridDim.y) + (pos.xy * gridDim.xy)) / (texDim / uScale);\n return texture2D(tex, coord + 0.5 / (texDim / uScale));\n}\n\nvec4 voxel(vec3 pos) {\n pos = min(max(vec3(0.0), pos), uGridDim - vec3(1.0));\n return texture3dFrom2dNearest(tVolumeData, pos / uGridDim, uGridDim, uGridTexDim.xy);\n}\n\nvec4 voxelPadded(vec3 pos) {\n pos = min(max(vec3(0.0), pos), uGridDim - vec3(vec2(2.0), 1.0)); // remove xy padding\n return texture3dFrom2dNearest(tVolumeData, pos / uGridDim, uGridDim, uGridTexDim.xy);\n}\n\nint idot2(const in ivec2 a, const in ivec2 b) {\n return a.x * b.x + a.y * b.y;\n}\n\nint idot4(const in ivec4 a, const in ivec4 b) {\n return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;\n}\n\n#if __VERSION__ == 100\n int pyramidVoxel(vec2 pos) {\n return int(decodeFloatRGB(texture2D(tActiveVoxelsPyramid, pos / (vec2(1.0, 0.5) * uSize)).rgb));\n }\n#else\n int pyramidVoxel(vec2 pos) {\n return texture2D(tActiveVoxelsPyramid, pos / (vec2(1.0, 0.5) * uSize)).r;\n }\n#endif\n\nvec4 baseVoxel(vec2 pos) {\n return texture2D(tActiveVoxelsBase, pos / uSize);\n}\n\nvoid main(void) {\n // get 1D index\n int vI = int(gl_FragCoord.x) + int(gl_FragCoord.y) * int(uSize);\n\n // ignore 1D indices outside of the grid\n if(vI >= int(uCount)) discard;\n\n ivec2 offset = ivec2(int(uSize) - 2, 0);\n\n int start = 0;\n ivec4 starts = ivec4(0);\n ivec4 ends = ivec4(0);\n int diff = 2;\n ivec4 m = ivec4(0);\n ivec2 position = ivec2(0);\n ivec4 vI4 = ivec4(vI);\n\n ivec2 relativePosition = ivec2(0);\n int end = 0;\n ivec2 pos1 = ivec2(0);\n ivec2 pos2 = ivec2(0);\n ivec2 pos3 = ivec2(0);\n ivec2 pos4 = ivec2(0);\n ivec3 vI3 = ivec3(vI);\n ivec3 mask = ivec3(0);\n\n // traverse the different levels of the pyramid\n for(int i = 1; i < 14; i++) {\n if(float(i) >= uLevels) break;\n\n offset.x -= diff;\n diff *= 2;\n relativePosition = position + offset;\n\n end = start + pyramidVoxel(vec2(relativePosition));\n pos1 = ivec2(relativePosition);\n starts.x = start;\n ends.x = end;\n pos2 = ivec2(relativePosition + ivec2(1, 0));\n starts.y = ends.x;\n ends.y = ends.x + pyramidVoxel(vec2(pos2));\n pos3 = relativePosition + ivec2(0, 1);\n starts.z = ends.y;\n ends.z = ends.y + pyramidVoxel(vec2(pos3));\n pos4 = relativePosition + ivec2(1, 1);\n starts.w = ends.z;\n mask = ivec3(greaterThanEqual(vI3, starts.rgb)) * ivec3(lessThan(vI3, ends.rgb));\n m = ivec4(mask, 1 - int(any(bvec3(mask))));\n\n relativePosition = m.x * pos1 + m.y * pos2 + m.z * pos3 + m.w * pos4;\n start = idot4(m, starts);\n position = 2 * (relativePosition - offset);\n }\n\n end = start + int(baseVoxel(vec2(position)).r * 255.0);\n pos1 = position;\n starts.x = start;\n ends.x = end;\n pos2 = position + ivec2(1, 0);\n starts.y = ends.x;\n ends.y = ends.x + int(baseVoxel(vec2(pos2)).r * 255.0);\n pos3 = position + ivec2(0, 1);\n starts.z = ends.y;\n ends.z = ends.y + int(baseVoxel(vec2(pos3)).r * 255.0);\n pos4 = position + ivec2(1, 1);\n starts.w = ends.z;\n mask = ivec3(greaterThanEqual(vI3, starts.rgb)) * ivec3(lessThan(vI3, ends.rgb));\n m = ivec4(mask, 1 - int(any(bvec3(mask))));\n position = m.x * pos1 + m.y * pos2 + m.z * pos3 + m.w * pos4;\n\n vec2 coord2d = (vec2(position) / uSize) / uScale;\n vec3 coord3d = floor(index3dFrom2d(coord2d) + 0.5);\n\n float edgeIndex = floor(baseVoxel(vec2(position)).a * 255.0 + 0.5);\n\n // current vertex for the up to 15 MC cases\n int currentVertex = vI - idot4(m, starts);\n\n // ensure winding-order is the same for negative and positive iso-levels\n if (uInvert) {\n int v = imod(currentVertex + 1, 3);\n if (v == 1) currentVertex += 2;\n else if (v == 0) currentVertex -= 2;\n }\n\n // get index into triIndices table\n int mcIndex = 16 * int(edgeIndex) + currentVertex;\n vec4 mcData = texture2D(tTriIndices, vec2(imod(mcIndex, 64), mcIndex / 64) / 64.);\n\n // bit mask to avoid conditionals (see comment below) for getting MC case corner\n vec4 m0 = vec4(floor(mcData.a * 255.0 + 0.5));\n\n // get edge value masks\n vec4 m1 = vec4(equal(m0, vec4(0., 1., 2., 3.)));\n vec4 m2 = vec4(equal(m0, vec4(4., 5., 6., 7.)));\n vec4 m3 = vec4(equal(m0, vec4(8., 9., 10., 11.)));\n\n // apply bit masks\n vec3 b0 = coord3d +\n m1.y * c1 +\n m1.z * c2 +\n m1.w * c3 +\n m2.x * c4 +\n m2.y * c5 +\n m2.z * c6 +\n m2.w * c7 +\n m3.y * c1 +\n m3.z * c2 +\n m3.w * c3;\n vec3 b1 = coord3d +\n m1.x * c1 +\n m1.y * c2 +\n m1.z * c3 +\n m2.x * c5 +\n m2.y * c6 +\n m2.z * c7 +\n m2.w * c4 +\n m3.x * c4 +\n m3.y * c5 +\n m3.z * c6 +\n m3.w * c7;\n\n // the conditionals that are avoided by above bitmasks\n // vec3 b0 = coord3d;\n // vec3 b1 = coord3d;\n // if (mcIndex == 0.0) {\n // b1 += c1;\n // } else if (mcIndex == 1.0) {\n // b0 += c1; b1 += c2;\n // } else if (mcIndex == 2.0) {\n // b0 += c2; b1 += c3;\n // } else if (mcIndex == 3.0) {\n // b0 += c3;\n // } else if (mcIndex == 4.0) {\n // b0 += c4; b1 += c5;\n // } else if (mcIndex == 5.0) {\n // b0 += c5; b1 += c6;\n // } else if (mcIndex == 6.0) {\n // b0 += c6; b1 += c7;\n // } else if (mcIndex == 7.0) {\n // b0 += c7; b1 += c4;\n // } else if (mcIndex == 8.0) {\n // b1 += c4;\n // } else if (mcIndex == 9.0) {\n // b0 += c1; b1 += c5;\n // } else if (mcIndex == 10.0) {\n // b0 += c2; b1 += c6;\n // } else if (mcIndex == 11.0) {\n // b0 += c3; b1 += c7;\n // }\n // b0 = floor(b0 + 0.5);\n // b1 = floor(b1 + 0.5);\n\n vec4 d0 = voxel(b0);\n vec4 d1 = voxel(b1);\n\n float v0 = d0.a;\n float v1 = d1.a;\n\n float t = (uIsoValue - v0) / (v0 - v1);\n gl_FragData[0].xyz = (uGridTransform * vec4(b0 + t * (b0 - b1), 1.0)).xyz;\n\n // group id\n #if __VERSION__ == 100\n // webgl1 does not support 'flat' interpolation (i.e. no interpolation)\n // so we ensure a constant group id per triangle here\n #ifdef dPackedGroup\n gl_FragData[1] = vec4(voxel(coord3d).rgb, 1.0);\n #else\n vec3 gridDim = uGridDim - vec3(1.0, 1.0, 0.0); // remove xy padding\n float group = coord3d.z + coord3d.y * gridDim.z + coord3d.x * gridDim.z * gridDim.y;\n gl_FragData[1] = vec4(group > 16777215.5 ? vec3(1.0) : encodeFloatRGB(group), 1.0);\n #endif\n #else\n #ifdef dPackedGroup\n gl_FragData[1] = vec4(t < 0.5 ? d0.rgb : d1.rgb, 1.0);\n #else\n vec3 b = t < 0.5 ? b0 : b1;\n vec3 gridDim = uGridDim - vec3(1.0, 1.0, 0.0); // remove xy padding\n float group = b.z + b.y * gridDim.z + b.x * gridDim.z * gridDim.y;\n gl_FragData[1] = vec4(group > 16777215.5 ? vec3(1.0) : encodeFloatRGB(group), 1.0);\n #endif\n #endif\n\n // normals from gradients\n vec3 n0 = -normalize(vec3(\n voxelPadded(b0 - c1).a - voxelPadded(b0 + c1).a,\n voxelPadded(b0 - c3).a - voxelPadded(b0 + c3).a,\n voxelPadded(b0 - c4).a - voxelPadded(b0 + c4).a\n ));\n vec3 n1 = -normalize(vec3(\n voxelPadded(b1 - c1).a - voxelPadded(b1 + c1).a,\n voxelPadded(b1 - c3).a - voxelPadded(b1 + c3).a,\n voxelPadded(b1 - c4).a - voxelPadded(b1 + c4).a\n ));\n gl_FragData[2].xyz = -vec3(\n n0.x + t * (n0.x - n1.x),\n n0.y + t * (n0.y - n1.y),\n n0.z + t * (n0.z - n1.z)\n );\n\n // ensure normal-direction is the same for negative and positive iso-levels\n if (uInvert) {\n gl_FragData[2].xyz *= -1.0;\n }\n\n // apply normal matrix\n gl_FragData[2].xyz *= transpose3(inverse3(mat3(uGridTransform)));\n}\n"; //# sourceMappingURL=isosurface.frag.js.map