@jbrowse/render-core 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/esm/OverlayCanvas.d.ts +29 -0
- package/esm/OverlayCanvas.js +43 -0
- package/esm/RenderCanvas.d.ts +76 -0
- package/esm/RenderCanvas.js +38 -0
- package/esm/RenderLifecycleMixin.d.ts +180 -0
- package/esm/RenderLifecycleMixin.js +279 -0
- package/esm/ScrollLockedOverlay.d.ts +28 -0
- package/esm/ScrollLockedOverlay.js +42 -0
- package/esm/blockClipUtils.d.ts +27 -0
- package/esm/blockClipUtils.js +101 -0
- package/esm/canvas2dUtils.d.ts +372 -0
- package/esm/canvas2dUtils.js +564 -0
- package/esm/canvasContext.d.ts +68 -0
- package/esm/canvasContext.js +74 -0
- package/esm/colorRampLut.d.ts +17 -0
- package/esm/colorRampLut.js +25 -0
- package/esm/coverageBand.d.ts +107 -0
- package/esm/coverageBand.js +109 -0
- package/esm/coverageBandBuffers.d.ts +30 -0
- package/esm/coverageBandBuffers.js +13 -0
- package/esm/createRenderingBackend.d.ts +52 -0
- package/esm/createRenderingBackend.js +58 -0
- package/esm/displayPhase.d.ts +155 -0
- package/esm/displayPhase.js +97 -0
- package/esm/globalRenderingBackend.d.ts +90 -0
- package/esm/globalRenderingBackend.js +53 -0
- package/esm/gpuDevice.d.ts +91 -0
- package/esm/gpuDevice.js +277 -0
- package/esm/graphicsCapabilities.d.ts +98 -0
- package/esm/graphicsCapabilities.js +165 -0
- package/esm/hal/createHal.d.ts +22 -0
- package/esm/hal/createHal.js +91 -0
- package/esm/hal/deviceGpuCache.d.ts +36 -0
- package/esm/hal/deviceGpuCache.js +120 -0
- package/esm/hal/gpuHalBase.d.ts +55 -0
- package/esm/hal/gpuHalBase.js +81 -0
- package/esm/hal/index.d.ts +7 -0
- package/esm/hal/index.js +5 -0
- package/esm/hal/mockHal.d.ts +153 -0
- package/esm/hal/mockHal.js +297 -0
- package/esm/hal/oomReporter.d.ts +15 -0
- package/esm/hal/oomReporter.js +22 -0
- package/esm/hal/passIds.d.ts +22 -0
- package/esm/hal/passIds.js +36 -0
- package/esm/hal/regionRegistry.d.ts +11 -0
- package/esm/hal/regionRegistry.js +66 -0
- package/esm/hal/types.d.ts +116 -0
- package/esm/hal/types.js +1 -0
- package/esm/hal/webgl2Hal.d.ts +47 -0
- package/esm/hal/webgl2Hal.js +490 -0
- package/esm/hal/webgpuHal.d.ts +169 -0
- package/esm/hal/webgpuHal.js +722 -0
- package/esm/installUpload.d.ts +91 -0
- package/esm/installUpload.js +94 -0
- package/esm/instanceCache.d.ts +43 -0
- package/esm/instanceCache.js +53 -0
- package/esm/instancePass.d.ts +50 -0
- package/esm/instancePass.js +34 -0
- package/esm/keyedRenderingBackend.d.ts +41 -0
- package/esm/keyedRenderingBackend.js +19 -0
- package/esm/mapUploadSync.d.ts +31 -0
- package/esm/mapUploadSync.js +45 -0
- package/esm/namedReactions.d.ts +29 -0
- package/esm/namedReactions.js +62 -0
- package/esm/perRegionRenderingBackend.d.ts +114 -0
- package/esm/perRegionRenderingBackend.js +93 -0
- package/esm/recoveryBudget.d.ts +40 -0
- package/esm/recoveryBudget.js +56 -0
- package/esm/regionDataMap.d.ts +60 -0
- package/esm/regionDataMap.js +98 -0
- package/esm/renderBlock.d.ts +25 -0
- package/esm/renderBlock.js +10 -0
- package/esm/renderingBackendBase.d.ts +71 -0
- package/esm/renderingBackendBase.js +50 -0
- package/esm/shaders/antialias.js.generated.d.ts +4 -0
- package/esm/shaders/antialias.js.generated.js +25 -0
- package/esm/shaders/capsule.generated.d.ts +1 -0
- package/esm/shaders/capsule.generated.js +3 -0
- package/esm/shaders/colorRampLut.generated.d.ts +1 -0
- package/esm/shaders/colorRampLut.generated.js +3 -0
- package/esm/shaders/coverageBand.generated.d.ts +2 -0
- package/esm/shaders/coverageBand.generated.js +4 -0
- package/esm/shaders/coverageBar.generated.d.ts +4 -0
- package/esm/shaders/coverageBar.generated.js +6 -0
- package/esm/shaders/coverageBar.iface.generated.d.ts +85 -0
- package/esm/shaders/coverageBar.iface.generated.js +114 -0
- package/esm/shaders/coverageIndicator.generated.d.ts +4 -0
- package/esm/shaders/coverageIndicator.generated.js +6 -0
- package/esm/shaders/coverageIndicator.iface.generated.d.ts +85 -0
- package/esm/shaders/coverageIndicator.iface.generated.js +114 -0
- package/esm/shaders/coverageInterbase.generated.d.ts +4 -0
- package/esm/shaders/coverageInterbase.generated.js +6 -0
- package/esm/shaders/coverageInterbase.iface.generated.d.ts +93 -0
- package/esm/shaders/coverageInterbase.iface.generated.js +134 -0
- package/esm/shaders/coverageMod.generated.d.ts +4 -0
- package/esm/shaders/coverageMod.generated.js +6 -0
- package/esm/shaders/coverageMod.iface.generated.d.ts +97 -0
- package/esm/shaders/coverageMod.iface.generated.js +144 -0
- package/esm/shaders/coverageSnp.generated.d.ts +4 -0
- package/esm/shaders/coverageSnp.generated.js +6 -0
- package/esm/shaders/coverageSnp.iface.generated.d.ts +97 -0
- package/esm/shaders/coverageSnp.iface.generated.js +144 -0
- package/esm/shaders/hpmath.js.generated.d.ts +3 -0
- package/esm/shaders/hpmath.js.generated.js +48 -0
- package/esm/shaders/pointGlyph.generated.d.ts +1 -0
- package/esm/shaders/pointGlyph.generated.js +3 -0
- package/esm/shaders/pointGlyph.js.generated.d.ts +1 -0
- package/esm/shaders/pointGlyph.js.generated.js +7 -0
- package/esm/shaders/rowRect.generated.d.ts +3 -0
- package/esm/shaders/rowRect.generated.js +5 -0
- package/esm/shaders/rowRect.js.generated.d.ts +2 -0
- package/esm/shaders/rowRect.js.generated.js +13 -0
- package/esm/shaders/scoreScale.js.generated.d.ts +1 -0
- package/esm/shaders/scoreScale.js.generated.js +46 -0
- package/esm/slangPass.d.ts +49 -0
- package/esm/slangPass.js +22 -0
- package/esm/useEventCallback.d.ts +1 -0
- package/esm/useEventCallback.js +19 -0
- package/esm/useGraphicsCapabilities.d.ts +17 -0
- package/esm/useGraphicsCapabilities.js +38 -0
- package/esm/useRenderingBackend.d.ts +83 -0
- package/esm/useRenderingBackend.js +422 -0
- package/esm/useTabVisibilityRerender.d.ts +13 -0
- package/esm/useTabVisibilityRerender.js +39 -0
- package/esm/webgpuUtils.d.ts +23 -0
- package/esm/webgpuUtils.js +76 -0
- package/package.json +91 -0
- package/src/shaders/antialias.js.generated.ts +33 -0
- package/src/shaders/antialias.slang +112 -0
- package/src/shaders/capsule.generated.ts +4 -0
- package/src/shaders/capsule.slang +62 -0
- package/src/shaders/colorPack.slang +26 -0
- package/src/shaders/colorRampLut.generated.ts +4 -0
- package/src/shaders/colorRampLut.slang +51 -0
- package/src/shaders/coverageBand.generated.ts +6 -0
- package/src/shaders/coverageBand.slang +276 -0
- package/src/shaders/coverageBar.generated.ts +10 -0
- package/src/shaders/coverageBar.iface.generated.ts +172 -0
- package/src/shaders/coverageBar.slang +37 -0
- package/src/shaders/coverageIndicator.generated.ts +10 -0
- package/src/shaders/coverageIndicator.iface.generated.ts +172 -0
- package/src/shaders/coverageIndicator.slang +61 -0
- package/src/shaders/coverageInterbase.generated.ts +10 -0
- package/src/shaders/coverageInterbase.iface.generated.ts +198 -0
- package/src/shaders/coverageInterbase.slang +63 -0
- package/src/shaders/coverageMod.generated.ts +10 -0
- package/src/shaders/coverageMod.iface.generated.ts +211 -0
- package/src/shaders/coverageMod.slang +36 -0
- package/src/shaders/coverageSnp.generated.ts +10 -0
- package/src/shaders/coverageSnp.iface.generated.ts +211 -0
- package/src/shaders/coverageSnp.slang +52 -0
- package/src/shaders/diagonalGrid.slang +25 -0
- package/src/shaders/glyphEdgeAlpha.test.ts +241 -0
- package/src/shaders/hpmath.js.generated.ts +47 -0
- package/src/shaders/hpmath.slang +226 -0
- package/src/shaders/pointGlyph.generated.ts +4 -0
- package/src/shaders/pointGlyph.js.generated.ts +9 -0
- package/src/shaders/pointGlyph.slang +93 -0
- package/src/shaders/rowRect.generated.ts +8 -0
- package/src/shaders/rowRect.js.generated.ts +17 -0
- package/src/shaders/rowRect.slang +160 -0
- package/src/shaders/scoreScale.js.generated.ts +51 -0
- package/src/shaders/scoreScale.slang +68 -0
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jbrowse/render-core",
|
|
3
|
+
"version": "4.3.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "GPU/Canvas2D rendering primitives for JBrowse displays: the HAL, the draw-lifecycle mixin, per-region/global backend bases, and the React backend hooks",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"jbrowse",
|
|
8
|
+
"jbrowse2",
|
|
9
|
+
"webgl",
|
|
10
|
+
"webgpu",
|
|
11
|
+
"rendering"
|
|
12
|
+
],
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"homepage": "https://jbrowse.org",
|
|
15
|
+
"bugs": "https://github.com/GMOD/jbrowse-components/issues",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/GMOD/jbrowse-components.git",
|
|
19
|
+
"directory": "packages/render-core"
|
|
20
|
+
},
|
|
21
|
+
"author": "JBrowse Team",
|
|
22
|
+
"//files": "src/shaders ships the shared .slang modules (hpmath, antialias, capsule, colorPack, coverageBand, diagonalGrid, pointGlyph, rowRect, scoreScale) that any shader imports, plus the coverage-band entry-point passes drawn by two plugins. @jbrowse/shader-tools resolves its include path here, so an out-of-tree plugin can compile its own .slang against them.",
|
|
23
|
+
"files": [
|
|
24
|
+
"esm",
|
|
25
|
+
"src/shaders"
|
|
26
|
+
],
|
|
27
|
+
"exports": {
|
|
28
|
+
"./RenderCanvas": "./esm/RenderCanvas.js",
|
|
29
|
+
"./RenderLifecycleMixin": "./esm/RenderLifecycleMixin.js",
|
|
30
|
+
"./blockClipUtils": "./esm/blockClipUtils.js",
|
|
31
|
+
"./canvas2dUtils": "./esm/canvas2dUtils.js",
|
|
32
|
+
"./canvasContext": "./esm/canvasContext.js",
|
|
33
|
+
"./colorRampLut": "./esm/colorRampLut.js",
|
|
34
|
+
"./coverageBand": "./esm/coverageBand.js",
|
|
35
|
+
"./coverageBandBuffers": "./esm/coverageBandBuffers.js",
|
|
36
|
+
"./createRenderingBackend": "./esm/createRenderingBackend.js",
|
|
37
|
+
"./displayPhase": "./esm/displayPhase.js",
|
|
38
|
+
"./globalRenderingBackend": "./esm/globalRenderingBackend.js",
|
|
39
|
+
"./gpuDevice": "./esm/gpuDevice.js",
|
|
40
|
+
"./graphicsCapabilities": "./esm/graphicsCapabilities.js",
|
|
41
|
+
"./hal": "./esm/hal/index.js",
|
|
42
|
+
"./installUpload": "./esm/installUpload.js",
|
|
43
|
+
"./instanceCache": "./esm/instanceCache.js",
|
|
44
|
+
"./instancePass": "./esm/instancePass.js",
|
|
45
|
+
"./keyedRenderingBackend": "./esm/keyedRenderingBackend.js",
|
|
46
|
+
"./namedReactions": "./esm/namedReactions.js",
|
|
47
|
+
"./OverlayCanvas": "./esm/OverlayCanvas.js",
|
|
48
|
+
"./perRegionRenderingBackend": "./esm/perRegionRenderingBackend.js",
|
|
49
|
+
"./regionDataMap": "./esm/regionDataMap.js",
|
|
50
|
+
"./renderBlock": "./esm/renderBlock.js",
|
|
51
|
+
"./renderingBackendBase": "./esm/renderingBackendBase.js",
|
|
52
|
+
"./ScrollLockedOverlay": "./esm/ScrollLockedOverlay.js",
|
|
53
|
+
"./shaders/antialias": "./esm/shaders/antialias.js.generated.js",
|
|
54
|
+
"./shaders/capsuleConsts": "./esm/shaders/capsule.generated.js",
|
|
55
|
+
"./shaders/colorRampLutConsts": "./esm/shaders/colorRampLut.generated.js",
|
|
56
|
+
"./shaders/coverageBar": "./esm/shaders/coverageBar.generated.js",
|
|
57
|
+
"./shaders/coverageIndicator": "./esm/shaders/coverageIndicator.generated.js",
|
|
58
|
+
"./shaders/coverageInterbase": "./esm/shaders/coverageInterbase.generated.js",
|
|
59
|
+
"./shaders/coverageMod": "./esm/shaders/coverageMod.generated.js",
|
|
60
|
+
"./shaders/coverageSnp": "./esm/shaders/coverageSnp.generated.js",
|
|
61
|
+
"./shaders/hpmath": "./esm/shaders/hpmath.js.generated.js",
|
|
62
|
+
"./shaders/pointGlyph": "./esm/shaders/pointGlyph.js.generated.js",
|
|
63
|
+
"./shaders/pointGlyphConsts": "./esm/shaders/pointGlyph.generated.js",
|
|
64
|
+
"./shaders/rowRect": "./esm/shaders/rowRect.js.generated.js",
|
|
65
|
+
"./shaders/rowRectConsts": "./esm/shaders/rowRect.generated.js",
|
|
66
|
+
"./shaders/scoreScale": "./esm/shaders/scoreScale.js.generated.js",
|
|
67
|
+
"./slangPass": "./esm/slangPass.js",
|
|
68
|
+
"./useGraphicsCapabilities": "./esm/useGraphicsCapabilities.js",
|
|
69
|
+
"./useRenderingBackend": "./esm/useRenderingBackend.js",
|
|
70
|
+
"./useTabVisibilityRerender": "./esm/useTabVisibilityRerender.js"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"@jbrowse/mobx-state-tree": "^6.5.1",
|
|
74
|
+
"mobx": "^7.0.3"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"react": ">=19.0.0"
|
|
78
|
+
},
|
|
79
|
+
"//publishConfig": "Generated from `exports` above by scripts/generate-publish-exports.ts (`pnpm autogen`) — edit that map, never this one. The two describe the same subpaths against different trees, and only this one is what an installed consumer resolves, so drift between them is invisible until someone unpacks the tarball. It used to end in a `./*` wildcard, which served every emitted file including the ones src/index.ts withholds as internal.",
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
82
|
+
},
|
|
83
|
+
"sideEffects": false,
|
|
84
|
+
"scripts": {
|
|
85
|
+
"build:esm": "node ../../node_modules/typescript7/bin/tsc --build tsconfig.build.esm.json",
|
|
86
|
+
"build": "pnpm build:esm",
|
|
87
|
+
"test": "cd ../..; jest --passWithNoTests packages/render-core",
|
|
88
|
+
"clean": "rimraf esm *.tsbuildinfo",
|
|
89
|
+
"prebuild": "pnpm clean"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// AUTO-GENERATED by packages/shader-tools/src/shader-codegen from antialias.slang.
|
|
2
|
+
// Do not edit. Run `pnpm gen:shaders` to regenerate.
|
|
3
|
+
|
|
4
|
+
// Scalar twins of antialias.slang, transliterated from slangc's WGSL so
|
|
5
|
+
// the Canvas2D and SVG paths run the shader's own math. See adr-051.
|
|
6
|
+
|
|
7
|
+
function _clamp(x: number, lo: number, hi: number) {
|
|
8
|
+
return _min(_max(x, lo), hi)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function _max(a: number, b: number) {
|
|
12
|
+
return b > a || Number.isNaN(a) ? b : a
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function _min(a: number, b: number) {
|
|
16
|
+
return b < a || Number.isNaN(a) ? b : a
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function aaPx(dpr: number): number {
|
|
20
|
+
return (1.0 / _max(dpr, 1.0))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function aaHalfPx(dpr: number): number {
|
|
24
|
+
return (0.5 * aaPx(dpr))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function aaRamp(signedInk: number, widthPx: number): number {
|
|
28
|
+
return _clamp(((signedInk / widthPx) + 0.5), 0.0, 1.0)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function edgeCoverage(signedInkCssPx: number, dpr: number): number {
|
|
32
|
+
return aaRamp(signedInkCssPx, aaPx(dpr))
|
|
33
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Shared edge-antialiasing ramps.
|
|
2
|
+
//
|
|
3
|
+
// Every GPU mark in the tree fades its edge over one OUTPUT pixel. What differs
|
|
4
|
+
// between shaders is how wide that is in the units the fragment measures in,
|
|
5
|
+
// and there are exactly two answers:
|
|
6
|
+
//
|
|
7
|
+
// - Analytic, when the fragment's distance is a true perpendicular distance
|
|
8
|
+
// in CSS px. The HAL sizes the backing store by getDpr() and sets the
|
|
9
|
+
// viewport to canvas.width/height (DEVICE px) while coordinates stay CSS
|
|
10
|
+
// px, so one output sample spans 1/dpr CSS px. `aaPx` is that number, and
|
|
11
|
+
// `edgeCoverage` is the only thing that should be spelling it.
|
|
12
|
+
// - Measured, when it is not — a quad-local SDF whose scale differs per
|
|
13
|
+
// shape, or a varying whose foreshortening the shader cannot state.
|
|
14
|
+
// `aaGradient` is that number.
|
|
15
|
+
//
|
|
16
|
+
// `aaGradient` is deliberately not `fwidth`. fwidth is |ddx| + |ddy|, which
|
|
17
|
+
// overshoots a true gradient by up to sqrt(2), worst on the diagonals — where
|
|
18
|
+
// a dotplot line, a synteny ribbon edge and a chevron arm all live. The dotplot
|
|
19
|
+
// capsule, the synteny fill and the glyph SDFs each found that separately, in
|
|
20
|
+
// three plugins, before this module existed.
|
|
21
|
+
//
|
|
22
|
+
// `aaRamp` — linear in the signed distance — is the shape every mark in the
|
|
23
|
+
// tree fades on, and that is measured rather than preferred. Scored against
|
|
24
|
+
// exact area coverage of a pixel by a straight edge, the linear ramp is closer
|
|
25
|
+
// at EVERY angle: exact on an axis-aligned edge, where the cubic is up to 0.096
|
|
26
|
+
// of full ink out, and 0.043 against 0.067 worst case at 45 degrees. A band
|
|
27
|
+
// built as a difference of two ramps is exact at every width with the linear
|
|
28
|
+
// one; the cubic over-inks a half-pixel band by 37% (0.688 where 0.500 is the
|
|
29
|
+
// coverage). `scripts/aa_ramp_coverage_study.ts` is the measurement.
|
|
30
|
+
//
|
|
31
|
+
// There WAS a second shape here, `aaSmoothRamp` — `smoothstep(-h, h, d)` — and
|
|
32
|
+
// it is gone rather than deprecated, because a shader function nothing calls is
|
|
33
|
+
// dead-code-eliminated out of every compiled shader and the js-skip check says
|
|
34
|
+
// so out loud. Four shaders took it: synteny's `perpCoverage` and
|
|
35
|
+
// `vertCoverage`, the dotplot capsule, and `glyphEdgeAlpha`, and through it
|
|
36
|
+
// every point glyph. It read softer on a curve, which is it carrying more ink
|
|
37
|
+
// on both sides of the half-max contour rather than resolving the curve better.
|
|
38
|
+
// Re-deriving that shape is the study's job, not this module's — it models both
|
|
39
|
+
// in JS and scores them, so the comparison survives the deletion.
|
|
40
|
+
//
|
|
41
|
+
// If you reintroduce a smoothstep here, note the two forms take DIFFERENT
|
|
42
|
+
// arguments: the smoothstep takes the HALF width where `aaRamp` takes the full.
|
|
43
|
+
// A conversion either way is a factor of two, and dropping it compiles.
|
|
44
|
+
//
|
|
45
|
+
// The floor on `aaGradient` exists for an SDF that is a constant, such as
|
|
46
|
+
// manhattan's SHAPE_BAR: zero gradient makes the ramp zero-wide and the
|
|
47
|
+
// division 0/0. A degenerate ramp saturates to alpha 1, which is the solid fill
|
|
48
|
+
// those shapes want.
|
|
49
|
+
// A test modelling a shader's geometry needs the ramp's reach and its shape, so
|
|
50
|
+
// both go to JS. Not for a Canvas2D twin — that side's rasterizer does its own
|
|
51
|
+
// edge AA — but because the alternative is every pad test re-spelling `0.5/dpr`
|
|
52
|
+
// and then agreeing with its own copy, which is what dotplotCapsulePad.test.ts
|
|
53
|
+
// and syntenyFillPad.test.ts each did.
|
|
54
|
+
//! js-export: aaPx, aaHalfPx, aaRamp, edgeCoverage
|
|
55
|
+
module antialias;
|
|
56
|
+
|
|
57
|
+
// Width of a ramp covering exactly one output pixel, in CSS px. THE conversion
|
|
58
|
+
// between the two units in this file: a fragment measuring in CSS px against a
|
|
59
|
+
// device-px grid asks for this and nothing else. `max(dpr, 1.0)` is defensive —
|
|
60
|
+
// getDpr() never returns less — and keeps a bogus uniform from inverting the
|
|
61
|
+
// ramp.
|
|
62
|
+
public float aaPx(float dpr) {
|
|
63
|
+
return 1.0 / max(dpr, 1.0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Half of it: how far past the ink a ramp reaches, and so exactly how far a
|
|
67
|
+
// vertex stage must pad its quad to hold one. A pad stated in CSS px instead
|
|
68
|
+
// over-reaches by dpr — 2x on a plain monitor, 4x on a retina one — and every
|
|
69
|
+
// fragment in the surplus shades to alpha 0.
|
|
70
|
+
public float aaHalfPx(float dpr) {
|
|
71
|
+
return 0.5 * aaPx(dpr);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
// One output pixel of `d`, in whatever units `d` is: the true gradient
|
|
76
|
+
// magnitude per device pixel. Takes derivatives, so uniform control flow only.
|
|
77
|
+
public float aaGradient(float d) {
|
|
78
|
+
return max(length(float2(ddx(d), ddy(d))), 1e-5);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Linear coverage over a ramp `widthPx` wide, centred on the edge. `signedInk`
|
|
82
|
+
// is positive inside the mark and zero on its boundary.
|
|
83
|
+
public float aaRamp(float signedInk, float widthPx) {
|
|
84
|
+
return clamp(signedInk / widthPx + 0.5, 0.0, 1.0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Coverage of a mark's edge for a fragment whose distance is a TRUE
|
|
88
|
+
// perpendicular distance in CSS px, so its gradient is analytically 1 and there
|
|
89
|
+
// is nothing for `aaGradient` to discover. `signedInkCssPx` is how far inside
|
|
90
|
+
// the ink the fragment is: positive within, zero on the boundary.
|
|
91
|
+
//
|
|
92
|
+
// One function, because there is one ramp. It carries no cap and no shape —
|
|
93
|
+
// a capsule, a butt-capped segment, a synteny ribbon edge and a wiggle bar all
|
|
94
|
+
// reduce to this once their own distance is in hand, and spelling the width
|
|
95
|
+
// again beside each of them is how `2.0 * aaHalfPx(dpr)` and
|
|
96
|
+
// `STROKE_AA_PX / max(dpr, 1.0)` came to be the same number under two
|
|
97
|
+
// constants, one of which no test could see double.
|
|
98
|
+
public float edgeCoverage(float signedInkCssPx, float dpr) {
|
|
99
|
+
return aaRamp(signedInkCssPx, aaPx(dpr));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// A glyph SDF's edge, measured. `coverage` is positive inside and zero on the
|
|
103
|
+
// edge, in whatever units the SDF uses — the gradient supplies the conversion,
|
|
104
|
+
// so one call covers a disc, an L1 diamond (whose gradient carries a sqrt(2)
|
|
105
|
+
// the others don't) and a constant-SDF bar with no per-shape constant.
|
|
106
|
+
//
|
|
107
|
+
// Callers that select between several SDFs must pick their coverage in the
|
|
108
|
+
// branch and call this once after it: WGSL rejects a derivative taken under a
|
|
109
|
+
// branch on a varying.
|
|
110
|
+
public float glyphEdgeAlpha(float coverage) {
|
|
111
|
+
return aaRamp(coverage, aaGradient(coverage));
|
|
112
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// A stroked segment's frame, its quad and its distance. The round cap lives in
|
|
2
|
+
// `capsuleDist` and nowhere else: the edge ramp over that distance is
|
|
3
|
+
// `antialias`'s one `edgeCoverage`, shared with every butt-capped stroke in the
|
|
4
|
+
// tree. Consumers, and which half each takes:
|
|
5
|
+
// agent-docs/reference/SHADER_SHAPE_LIBRARY.md.
|
|
6
|
+
//
|
|
7
|
+
// `capsuleQuadLocal` pads by exactly `aaHalfPx(dpr)` past the ink. Pad less and
|
|
8
|
+
// the ramp is clipped at the quad edge — coverage falls to 0.5 at the boundary,
|
|
9
|
+
// the rasterizer cuts it to 0, and the line reads a hard 50%-alpha edge about a
|
|
10
|
+
// pixel narrower than `lineWidth` asked for. Pad more and the surplus fragments
|
|
11
|
+
// shade to alpha 0.
|
|
12
|
+
//
|
|
13
|
+
// The distance is Euclidean in CSS px, so |grad d| = 1 at every angle and the
|
|
14
|
+
// ramp is analytic rather than differentiated — which it has to be, since `d`
|
|
15
|
+
// comes off a clamp and the 2x2 quads straddling the cap/body junction would be
|
|
16
|
+
// differentiating a discontinuity.
|
|
17
|
+
//! export-consts: CAPSULE_MIN_LEN_PX
|
|
18
|
+
module capsule;
|
|
19
|
+
|
|
20
|
+
import antialias;
|
|
21
|
+
import hpmath;
|
|
22
|
+
|
|
23
|
+
// Below this length a segment has no direction to speak of and `delta / len`
|
|
24
|
+
// is 0/0. Any positive threshold under a visible fraction of a pixel behaves
|
|
25
|
+
// the same (at that length the mark IS its cap); this was `1e-3` in dotplot
|
|
26
|
+
// and `1e-4` in the two others, and takes the majority spelling, which is also
|
|
27
|
+
// the one leaving the fallback the smallest reach.
|
|
28
|
+
public static const float CAPSULE_MIN_LEN_PX = 1e-4;
|
|
29
|
+
|
|
30
|
+
// The segment's own frame — x along it, y across it. Cap-agnostic, which is
|
|
31
|
+
// what lets the butt-capped linkedReadLine orient its diagonal through it. The
|
|
32
|
+
// degenerate guard exists only to keep a zero-length segment's 0/0 out of the
|
|
33
|
+
// frame.
|
|
34
|
+
public struct CapsuleFrame {
|
|
35
|
+
public float2 tangent;
|
|
36
|
+
public float2 normal;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
public CapsuleFrame capsuleFrame(float2 delta, float len) {
|
|
40
|
+
CapsuleFrame f;
|
|
41
|
+
f.tangent = len > CAPSULE_MIN_LEN_PX ? delta / len : float2(1.0, 0.0);
|
|
42
|
+
f.normal = float2(-f.tangent.y, f.tangent.x);
|
|
43
|
+
return f;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Quad corner `vid` in the segment's frame, for a capsule of half-length
|
|
47
|
+
// `halfLenPx` and stroke half-width `halfWidthPx`, grown by the pad the module
|
|
48
|
+
// header describes. Center-anchored: ±(halfLen + ext) along, ±ext across.
|
|
49
|
+
public float2 capsuleQuadLocal(
|
|
50
|
+
uint vid, float halfLenPx, float halfWidthPx, float dpr
|
|
51
|
+
) {
|
|
52
|
+
float ext = halfWidthPx + aaHalfPx(dpr);
|
|
53
|
+
float2 q = quadLocal(vid) * 2.0 - 1.0;
|
|
54
|
+
return float2(q.x * (halfLenPx + ext), q.y * ext);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// CSS-px distance from `local` (the segment's frame, center-anchored) to the
|
|
58
|
+
// segment {(-halfLen,0)..(halfLen,0)}. Collapses to distance-from-origin for a
|
|
59
|
+
// degenerate segment — the circular dot of radius halfWidth.
|
|
60
|
+
public float capsuleDist(float2 local, float halfLenPx) {
|
|
61
|
+
return length(float2(max(abs(local.x) - halfLenPx, 0.0), local.y));
|
|
62
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Shared color-packing helpers. A single `uint` holds an ABGR triplet as
|
|
2
|
+
// packed bytes, letting every shader carry color data as one vertex
|
|
3
|
+
// attribute instead of four floats. Pair with `cssColorToABGR` on the
|
|
4
|
+
// CPU side (see packages/core/src/util/colorBits.ts).
|
|
5
|
+
module colorPack;
|
|
6
|
+
|
|
7
|
+
// Don't put a SCALAR array in a uniform block and unpack it with this.
|
|
8
|
+
// slangc v2026.5.2's WGSL backend cannot compile it: a `uint palette[N]` member
|
|
9
|
+
// becomes a `_Array_std140_uintN` wrapper (std140 pads each element to 16
|
|
10
|
+
// bytes), and passing an element of one to a cross-module function SEGFAULTS the
|
|
11
|
+
// compiler — signal 11, no diagnostic. `[ForceInline]` here dodges the crash and
|
|
12
|
+
// then emits invalid WGSL (a bare `…data_0[i].x;` statement, which naga
|
|
13
|
+
// rejects), so there is no version of it that works. GLSL compiles the same
|
|
14
|
+
// source fine, so it is WGSL-specific.
|
|
15
|
+
//
|
|
16
|
+
// Declare such a palette as `float4[N]` instead — a vector element needs no
|
|
17
|
+
// wrapper struct, lowers correctly, AND costs the same 16 bytes per slot that
|
|
18
|
+
// std140 was padding the uint to anyway, so packing bought nothing here. Packing
|
|
19
|
+
// still earns its keep in VERTEX ATTRIBUTES, which is what this is for.
|
|
20
|
+
public float4 unpackRGBA(uint c) {
|
|
21
|
+
return float4(
|
|
22
|
+
float((c >> 0u) & 0xFFu),
|
|
23
|
+
float((c >> 8u) & 0xFFu),
|
|
24
|
+
float((c >> 16u) & 0xFFu),
|
|
25
|
+
float((c >> 24u) & 0xFFu)) / 255.0;
|
|
26
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Sampling a 256×1 colour-ramp LUT texture by a [0,1] scalar — the mechanism
|
|
2
|
+
// HiC's contact map and both LD heatmap variants reached independently, down to
|
|
3
|
+
// the binding slot, and wiggle density's third spelling. The module owns ONLY
|
|
4
|
+
// the sampling: each consumer keeps its own scale (`mapHicCount`, LD's signed
|
|
5
|
+
// remap plus `ldValueComputed` sentinel gate, wiggle's `normalizeScore` +
|
|
6
|
+
// `densityGradientT`) and declares its own `[[vk::binding(2, 0)]]
|
|
7
|
+
// Sampler2D<float4> colorRamp;` — a module can take a sampler as a parameter
|
|
8
|
+
// but not declare the binding for its importer. The TS half of the mechanism is
|
|
9
|
+
// `uploadColorRampLut` (../colorRampLut.ts), which puts the 256-entry
|
|
10
|
+
// `Uint8Array` behind these samplers; `buildColorRampLut`
|
|
11
|
+
// (@jbrowse/core/util/colorRamp) is what builds it on both backends.
|
|
12
|
+
//
|
|
13
|
+
// Two entry points because premultiplication follows the consumer's declared
|
|
14
|
+
// blend, and the `//! blend:` declaration stays per-shader: HiC and LD both
|
|
15
|
+
// draw under `//! blend: premultiplied` and both multiplied the sample through
|
|
16
|
+
// its own alpha, so that shared line lives here rather than surviving as a
|
|
17
|
+
// copy in each fragment — while wiggle density draws opaque ramps under the
|
|
18
|
+
// default straight-alpha blend, where a premultiplied return would be wrong
|
|
19
|
+
// the day a translucent ramp entry appears. The function name carries the
|
|
20
|
+
// contract, so a consumer picks the form that matches its blend declaration.
|
|
21
|
+
//! export-consts: RAMP_LUT_ENTRIES
|
|
22
|
+
module colorRampLut;
|
|
23
|
+
|
|
24
|
+
// Entries in the ramp texture. Exported because `buildColorRampLut` sizes the
|
|
25
|
+
// array by it and the mapping below divides by it: a table built to one number
|
|
26
|
+
// and sampled by another is a half-shade of drift at every entry.
|
|
27
|
+
public static const float RAMP_LUT_ENTRIES = 256.0;
|
|
28
|
+
|
|
29
|
+
// The colour at `t` in [0, 1], straight (non-premultiplied) alpha. Sampled at
|
|
30
|
+
// the texture's vertical center, mip level 0 — the ramp has no other row and no
|
|
31
|
+
// other level.
|
|
32
|
+
//
|
|
33
|
+
// `t` is remapped into texel space rather than passed through. The builder
|
|
34
|
+
// defines entry i as the colour at `i / (N - 1)`, while a linear-filtered
|
|
35
|
+
// texture puts entry i's center at `(i + 0.5) / N`, so sampling at `t` returns
|
|
36
|
+
// a blend of two neighbours at every entry but the ends — half a step off the
|
|
37
|
+
// table the Canvas2D and SVG twins index. `clamp` lands an out-of-range scalar
|
|
38
|
+
// on the end entry, which clamp-to-edge addressing also answers.
|
|
39
|
+
public float4 rampColor(Sampler2D<float4> ramp, float t) {
|
|
40
|
+
float u = (clamp(t, 0.0, 1.0) * (RAMP_LUT_ENTRIES - 1.0) + 0.5) / RAMP_LUT_ENTRIES;
|
|
41
|
+
return ramp.SampleLevel(float2(u, 0.5), 0.0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// The same sample with its colour multiplied through its alpha, for a fragment
|
|
45
|
+
// returned under `//! blend: premultiplied`. Alpha itself is unchanged, so a
|
|
46
|
+
// consumer's own alpha test (HiC's MIN_VISIBLE_ALPHA discard) reads the same
|
|
47
|
+
// number either side of this call.
|
|
48
|
+
public float4 rampColorPremultiplied(Sampler2D<float4> ramp, float t) {
|
|
49
|
+
float4 c = rampColor(ramp, t);
|
|
50
|
+
return float4(c.rgb * c.a, c.a);
|
|
51
|
+
}
|