mirror of
https://github.com/molstar/molstar.git
synced 2026-06-05 14:04:36 +08:00
Compare commits
1 Commits
v3.27.0
...
safari-deb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1db0ada684 |
10
.github/pull_request_template.md
vendored
10
.github/pull_request_template.md
vendored
@@ -1,10 +0,0 @@
|
||||
<!-- Thank you for contributing to Mol* -->
|
||||
|
||||
# Description
|
||||
|
||||
|
||||
## Actions
|
||||
|
||||
- [ ] Added description of changes to the `[Unreleased]` section of `CHANGELOG.md`
|
||||
- [ ] Updated headers of modified files
|
||||
- [ ] Added my name to `package.json`'s `contributors`
|
||||
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
@@ -6,6 +6,7 @@
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"firsttris.vscode-jest-runner",
|
||||
"msjsdiag.debugger-for-chrome",
|
||||
"slevesque.shader",
|
||||
"stpn.vscode-graphql",
|
||||
"wayou.vscode-todo-highlight"
|
||||
|
||||
106
CHANGELOG.md
106
CHANGELOG.md
@@ -6,112 +6,6 @@ Note that since we don't clearly distinguish between a public and private interf
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
|
||||
## [v3.27.0] - 2022-12-15
|
||||
|
||||
- Add an `includeTransparent` parameter to hide/show outlines of components that are transparent
|
||||
- Fix 'once' for animations of systems with many frames
|
||||
- Better guard against issue (black fringes) with bumpiness in impostors
|
||||
- Improve impostor shaders
|
||||
- Fix sphere near-clipping with orthographic projection
|
||||
- Fix cylinder near-clipping
|
||||
- Add interior cylinder caps
|
||||
- Add per-pixel object clipping
|
||||
- Fix `QualityAssessment` assignment bug for structures with different auth vs label sequence numbering
|
||||
- Refresh `ApplyActionControl`'s param definition when toggling expanded state
|
||||
- Fix `struct_conn` bond assignment for ions
|
||||
- Ability to show only polar hydrogens
|
||||
|
||||
## [v3.26.0] - 2022-12-04
|
||||
|
||||
- Support for ``powerPreference`` webgl attribute. Add ``PluginConfig.General.PowerPreference`` and ``power-preference`` Viewer GET param.
|
||||
- Excluded common protein caps `NME` and `ACE` from the ligand selection query
|
||||
- Add screen-space shadow post-processing effect
|
||||
- Add "Structure Molecular Surface" visual
|
||||
- Add `external-volume` theme (coloring of arbitrary geometries by user-selected volume)
|
||||
|
||||
## [v3.25.1] - 2022-11-20
|
||||
|
||||
- Fix edge-case in `Structure.eachUnitPair` with single-element units
|
||||
- Fix 'auto' structure-quality for coarse models
|
||||
|
||||
## [v3.25.0] - 2022-11-16
|
||||
|
||||
- Fix handling of gzipped assets (reverts #615)
|
||||
|
||||
## [v3.24.0] - 2022-11-13
|
||||
|
||||
- Make `PluginContext.initContainer` checkered canvas background optional
|
||||
- Store URL of downloaded assets to detect zip/gzip based on extension (#615)
|
||||
- Add optional `operator.key`; can be referenced in `IndexPairBonds`
|
||||
- Add overpaint/transparency/substance theme strength to representations
|
||||
- Fix viewport color for transparent background
|
||||
|
||||
## [v3.23.0] - 2022-10-19
|
||||
|
||||
- Add `PluginContext.initContainer/mount/unmount` methods; these should make it easier to reuse a plugin context with both custom and built-in UI
|
||||
- Add `PluginContext.canvas3dInitialized`
|
||||
- `createPluginUI` now resolves after the 3d canvas has been initialized
|
||||
- Change EM Volume Streaming default from `Whole Structure` to `Auto`
|
||||
|
||||
## [v3.22.0] - 2022-10-17
|
||||
|
||||
- Replace `VolumeIsosurfaceParams.pickingGranularity` param with `Volume.PickingGranuality`
|
||||
|
||||
## [v3.21.0] - 2022-10-17
|
||||
|
||||
- Add `VolumeIsosurfaceParams.pickingGranularity` param
|
||||
- Prevent component controls collapsing when option is selected
|
||||
|
||||
## [v3.20.0] - 2022-10-16
|
||||
|
||||
- [Breaking] Rename the ``model-index`` color theme to ``trajectory-index``
|
||||
- Add a new ``model-index`` color theme that uniquely colors each loaded model
|
||||
- Add the new ``model-index`` and ``structure-index`` color themes as an option for the carbon color in the ``element-symbol`` and ``ilustrative`` color themes
|
||||
- Add ``structure-index`` color theme that uniquely colors each root structure
|
||||
- Add ``nearest`` method to ``Lookup3D``
|
||||
- Add mipmap-based blur for skybox backgrounds
|
||||
|
||||
## [v3.19.0] - 2022-10-01
|
||||
|
||||
- Fix "empty textures" error on empty canvas
|
||||
- Optimize BinaryCIF integer packing encoder
|
||||
- Fix dual depth peeling when post-processing is off or when rendering direct-volumes
|
||||
- Add ``cameraClipping.minNear`` parameter
|
||||
- Fix black artifacts on specular highlights with transparent background
|
||||
|
||||
## [v3.18.0] - 2022-09-17
|
||||
|
||||
- Integration of Dual depth peeling - OIT method
|
||||
- Stereo camera improvements
|
||||
- Fix param updates not applied
|
||||
- Better param ranges and description
|
||||
- Add timer.mark for left/right camera
|
||||
|
||||
## [v3.17.0] - 2022-09-11
|
||||
|
||||
- [Fix] Clone ``Canvas3DParams`` when creating a ``Canvas3D`` instance to prevent shared state between multiple instances
|
||||
- Add ``includeResidueTest`` option to ``alignAndSuperposeWithSIFTSMapping``
|
||||
- Add ``parentDisplay`` param for interactions representation.
|
||||
- [Experimental] Add support for PyMOL, VMD, and Jmol atom expressions in selection scripts
|
||||
- Support for ``failIfMajorPerformanceCaveat`` webgl attribute. Add ``PluginConfig.General.AllowMajorPerformanceCaveat`` and ``allow-major-performance-caveat`` Viewer GET param.
|
||||
- Fix handling of PDB TER records (#549)
|
||||
- Add support for getting multiple loci from a representation (``.getAllLoci()``)
|
||||
- Add ``key`` property to intra- and inter-bonds for referencing source data
|
||||
- Fix click event triggered after move
|
||||
|
||||
## [v3.16.0] - 2022-08-25
|
||||
|
||||
- Support ``globalColorParams`` and ``globalSymmetryParams`` in common representation params
|
||||
- Support ``label`` parameter in ``Viewer.loadStructureFromUrl``
|
||||
- Fix ``ViewportHelpContent`` Mouse Controls section
|
||||
|
||||
## [v3.15.0] - 2022-08-23
|
||||
|
||||
- Fix wboit in Safari >=15 (add missing depth renderbuffer to wboit pass)
|
||||
- Add 'Around Camera' option to Volume streaming
|
||||
- Avoid queuing more than one update in Volume streaming
|
||||
|
||||
## [v3.14.0] - 2022-08-20
|
||||
|
||||
- Expose inter-bonds compute params in structure
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
4849
package-lock.json
generated
4849
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
73
package.json
73
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "3.27.0",
|
||||
"version": "3.14.0",
|
||||
"description": "A comprehensive macromolecular library.",
|
||||
"homepage": "https://github.com/molstar/molstar#readme",
|
||||
"repository": {
|
||||
@@ -89,76 +89,71 @@
|
||||
"Ludovic Autin <autin@scripps.edu>",
|
||||
"Michal Malý <michal.maly@ibt.cas.cz>",
|
||||
"Jiří Černý <jiri.cerny@ibt.cas.cz>",
|
||||
"Panagiotis Tourlas <panagiot_tourlov@hotmail.com>",
|
||||
"Adam Midlik <midlik@gmail.com>",
|
||||
"Koya Sakuma <koya.sakuma.work@gmail.com>",
|
||||
"Gianluca Tomasello <giagitom@gmail.com>",
|
||||
"Jason Pattle <jpattle@exscientia.co.uk>",
|
||||
"David Williams <dwilliams@nobiastx.com>"
|
||||
"Panagiotis Tourlas <panagiot_tourlov@hotmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/add": "^3.2.1",
|
||||
"@graphql-codegen/cli": "^2.15.0",
|
||||
"@graphql-codegen/cli": "^2.11.6",
|
||||
"@graphql-codegen/time": "^3.2.1",
|
||||
"@graphql-codegen/typescript": "^2.8.3",
|
||||
"@graphql-codegen/typescript": "^2.7.3",
|
||||
"@graphql-codegen/typescript-graphql-files-modules": "^2.2.1",
|
||||
"@graphql-codegen/typescript-graphql-request": "^4.5.8",
|
||||
"@graphql-codegen/typescript-operations": "^2.5.8",
|
||||
"@graphql-codegen/typescript-graphql-request": "^4.5.3",
|
||||
"@graphql-codegen/typescript-operations": "^2.5.3",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/gl": "^6.0.2",
|
||||
"@types/jest": "^29.2.3",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"@types/gl": "^4.1.1",
|
||||
"@types/jest": "^28.1.7",
|
||||
"@types/react": "^18.0.17",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.33.1",
|
||||
"@typescript-eslint/parser": "^5.33.1",
|
||||
"benchmark": "^2.1.4",
|
||||
"concurrently": "^7.6.0",
|
||||
"concurrently": "^7.3.0",
|
||||
"cpx2": "^4.2.0",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"css-loader": "^6.7.2",
|
||||
"eslint": "^8.29.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"eslint": "^8.22.0",
|
||||
"extra-watch-webpack-plugin": "^1.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"fs-extra": "^11.1.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"graphql": "^16.6.0",
|
||||
"http-server": "^14.1.1",
|
||||
"jest": "^29.3.1",
|
||||
"mini-css-extract-plugin": "^2.7.1",
|
||||
"jest": "^28.1.3",
|
||||
"mini-css-extract-plugin": "^2.6.1",
|
||||
"path-browserify": "^1.0.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"sass": "^1.56.1",
|
||||
"sass-loader": "^13.2.0",
|
||||
"simple-git": "^3.15.1",
|
||||
"sass": "^1.54.5",
|
||||
"sass-loader": "^13.0.2",
|
||||
"simple-git": "^3.12.0",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.9.3",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.0"
|
||||
"ts-jest": "^28.0.8",
|
||||
"typescript": "^4.7.4",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/argparse": "^2.0.10",
|
||||
"@types/benchmark": "^2.1.2",
|
||||
"@types/benchmark": "^2.1.1",
|
||||
"@types/compression": "1.7.2",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/node": "^16.18.4",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/node": "^16.11.51",
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
"@types/swagger-ui-dist": "3.30.1",
|
||||
"argparse": "^2.0.1",
|
||||
"body-parser": "^1.20.1",
|
||||
"body-parser": "^1.20.0",
|
||||
"compression": "^1.7.4",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.18.2",
|
||||
"express": "^4.18.1",
|
||||
"h264-mp4-encoder": "^1.0.12",
|
||||
"immer": "^9.0.16",
|
||||
"immer": "^9.0.15",
|
||||
"immutable": "^4.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"rxjs": "^7.6.0",
|
||||
"swagger-ui-dist": "^4.15.5",
|
||||
"tslib": "^2.4.1",
|
||||
"rxjs": "^7.5.6",
|
||||
"swagger-ui-dist": "^4.14.0",
|
||||
"tslib": "^2.4.0",
|
||||
"util.promisify": "^1.1.1",
|
||||
"xhr2": "^0.2.1"
|
||||
},
|
||||
|
||||
@@ -58,22 +58,20 @@ class Viewer {
|
||||
}
|
||||
|
||||
static async create(elementOrId: string | HTMLElement, colors = [Color(0x992211), Color(0xDDDDDD)], showButtons = true) {
|
||||
const o = {
|
||||
...DefaultViewerOptions, ...{
|
||||
layoutIsExpanded: false,
|
||||
layoutShowControls: false,
|
||||
layoutShowRemoteState: false,
|
||||
layoutShowSequence: true,
|
||||
layoutShowLog: false,
|
||||
layoutShowLeftPanel: true,
|
||||
const o = { ...DefaultViewerOptions, ...{
|
||||
layoutIsExpanded: false,
|
||||
layoutShowControls: false,
|
||||
layoutShowRemoteState: false,
|
||||
layoutShowSequence: true,
|
||||
layoutShowLog: false,
|
||||
layoutShowLeftPanel: true,
|
||||
|
||||
viewportShowExpand: true,
|
||||
viewportShowControls: false,
|
||||
viewportShowSettings: false,
|
||||
viewportShowSelectionMode: false,
|
||||
viewportShowAnimation: false,
|
||||
}
|
||||
};
|
||||
viewportShowExpand: true,
|
||||
viewportShowControls: false,
|
||||
viewportShowSettings: false,
|
||||
viewportShowSelectionMode: false,
|
||||
viewportShowAnimation: false,
|
||||
} };
|
||||
const defaultSpec = DefaultPluginUISpec();
|
||||
|
||||
const spec: PluginUISpec = {
|
||||
@@ -137,16 +135,18 @@ class Viewer {
|
||||
}
|
||||
};
|
||||
|
||||
PluginCommands.Canvas3D.SetSettings(plugin, {
|
||||
settings: {
|
||||
renderer: {
|
||||
...plugin.canvas3d!.props.renderer,
|
||||
backgroundColor: ColorNames.white,
|
||||
},
|
||||
camera: {
|
||||
...plugin.canvas3d!.props.camera,
|
||||
helper: { axes: { name: 'off', params: {} } }
|
||||
}
|
||||
plugin.behaviors.canvas3d.initialized.subscribe(v => {
|
||||
if (v) {
|
||||
PluginCommands.Canvas3D.SetSettings(plugin, { settings: {
|
||||
renderer: {
|
||||
...plugin.canvas3d!.props.renderer,
|
||||
backgroundColor: ColorNames.white,
|
||||
},
|
||||
camera: {
|
||||
...plugin.canvas3d!.props.camera,
|
||||
helper: { axes: { name: 'off', params: {} } }
|
||||
}
|
||||
} });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -166,7 +166,7 @@ class Viewer {
|
||||
structures.push({ ref: structureProperties?.ref || structure.ref });
|
||||
}
|
||||
|
||||
// remove current structures from hierarchy as they will be merged
|
||||
// remove current structuresfrom hierarchy as they will be merged
|
||||
// TODO only works with using loadStructuresFromUrlsAndMerge once
|
||||
// need some more API metho to work with the hierarchy
|
||||
this.plugin.managers.structure.hierarchy.updateCurrent(this.plugin.managers.structure.hierarchy.current.structures, 'remove');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -31,8 +31,7 @@ function shinyStyle(plugin: PluginContext) {
|
||||
postprocessing: {
|
||||
...plugin.canvas3d!.props.postprocessing,
|
||||
occlusion: { name: 'off', params: {} },
|
||||
shadow: { name: 'off', params: {} },
|
||||
outline: { name: 'off', params: {} },
|
||||
outline: { name: 'off', params: {} }
|
||||
}
|
||||
} });
|
||||
}
|
||||
@@ -49,15 +48,13 @@ function occlusionStyle(plugin: PluginContext) {
|
||||
blurKernelSize: 15,
|
||||
radius: 5,
|
||||
samples: 32,
|
||||
resolutionScale: 1,
|
||||
resolutionScale: 1
|
||||
} },
|
||||
outline: { name: 'on', params: {
|
||||
scale: 1.0,
|
||||
threshold: 0.33,
|
||||
color: Color(0x0000),
|
||||
includeTransparent: true,
|
||||
} },
|
||||
shadow: { name: 'off', params: {} },
|
||||
} }
|
||||
}
|
||||
} });
|
||||
}
|
||||
@@ -205,14 +202,14 @@ const InteractionsPreset = StructureRepresentationPresetProvider({
|
||||
const components = {
|
||||
ligand: await presetStaticComponent(plugin, structureCell, 'ligand'),
|
||||
surroundings: await plugin.builders.structure.tryCreateComponentFromSelection(structureCell, ligandSurroundings, `surroundings`),
|
||||
interactions: await presetStaticComponent(plugin, structureCell, 'ligand'),
|
||||
interactions: await plugin.builders.structure.tryCreateComponentFromSelection(structureCell, ligandPlusSurroundings, `interactions`)
|
||||
};
|
||||
|
||||
const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
|
||||
const representations = {
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.3 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
ballAndStick: builder.buildRepresentation(update, components.surroundings, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.1, sizeAspectRatio: 1 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ball-and-stick' }),
|
||||
interactions: builder.buildRepresentation(update, components.interactions, { type: InteractionsRepresentationProvider, typeParams: { ...typeParams, material: CustomMaterial, includeParent: true, parentDisplay: 'between' }, color: InteractionTypeColorThemeProvider }, { tag: 'interactions' }),
|
||||
interactions: builder.buildRepresentation(update, components.interactions, { type: InteractionsRepresentationProvider, typeParams: { ...typeParams, material: CustomMaterial }, color: InteractionTypeColorThemeProvider }, { tag: 'interactions' }),
|
||||
label: builder.buildRepresentation(update, components.surroundings, { type: 'label', typeParams: { ...typeParams, material: CustomMaterial, background: false, borderWidth: 0.1 }, color: 'uniform', colorParams: { value: Color(0x000000) } }, { tag: 'label' }),
|
||||
};
|
||||
|
||||
|
||||
@@ -88,10 +88,7 @@ const DefaultViewerOptions = {
|
||||
pickScale: PluginConfig.General.PickScale.defaultValue,
|
||||
pickPadding: PluginConfig.General.PickPadding.defaultValue,
|
||||
enableWboit: PluginConfig.General.EnableWboit.defaultValue,
|
||||
enableDpoit: PluginConfig.General.EnableDpoit.defaultValue,
|
||||
preferWebgl1: PluginConfig.General.PreferWebGl1.defaultValue,
|
||||
allowMajorPerformanceCaveat: PluginConfig.General.AllowMajorPerformanceCaveat.defaultValue,
|
||||
powerPreference: PluginConfig.General.PowerPreference.defaultValue,
|
||||
|
||||
viewportShowExpand: PluginConfig.Viewport.ShowExpand.defaultValue,
|
||||
viewportShowControls: PluginConfig.Viewport.ShowControls.defaultValue,
|
||||
@@ -161,10 +158,7 @@ export class Viewer {
|
||||
[PluginConfig.General.PickScale, o.pickScale],
|
||||
[PluginConfig.General.PickPadding, o.pickPadding],
|
||||
[PluginConfig.General.EnableWboit, o.enableWboit],
|
||||
[PluginConfig.General.EnableDpoit, o.enableDpoit],
|
||||
[PluginConfig.General.PreferWebGl1, o.preferWebgl1],
|
||||
[PluginConfig.General.AllowMajorPerformanceCaveat, o.allowMajorPerformanceCaveat],
|
||||
[PluginConfig.General.PowerPreference, o.powerPreference],
|
||||
[PluginConfig.Viewport.ShowExpand, o.viewportShowExpand],
|
||||
[PluginConfig.Viewport.ShowControls, o.viewportShowControls],
|
||||
[PluginConfig.Viewport.ShowSettings, o.viewportShowSettings],
|
||||
@@ -205,7 +199,7 @@ export class Viewer {
|
||||
return PluginCommands.State.Snapshots.OpenUrl(this.plugin, { url, type });
|
||||
}
|
||||
|
||||
loadStructureFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false, options?: LoadStructureOptions & { label?: string }) {
|
||||
loadStructureFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false, options?: LoadStructureOptions) {
|
||||
const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
|
||||
return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
|
||||
source: {
|
||||
@@ -214,7 +208,6 @@ export class Viewer {
|
||||
url: Asset.Url(url),
|
||||
format: format as any,
|
||||
isBinary,
|
||||
label: options?.label,
|
||||
options: { ...params.source.params.options, representationParams: options?.representationParams as any },
|
||||
}
|
||||
}
|
||||
@@ -503,4 +496,4 @@ export const ViewerAutoPreset = StructureRepresentationPresetProvider({
|
||||
return await PresetStructureRepresentations.auto.apply(ref, params, plugin);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -38,15 +38,6 @@
|
||||
viewer.loadPdb('7bv2');
|
||||
viewer.loadEmdb('EMD-30210', { detail: 6 });
|
||||
// viewer.loadAllModelsOrAssemblyFromUrl('https://cs.litemol.org/5ire/full', 'mmcif', false, { representationParams: { theme: { globalName: 'operator-name' } } })
|
||||
// viewer.loadStructureFromUrl('my url', 'pdb', false, {
|
||||
// representationParams: {
|
||||
// theme: {
|
||||
// globalName: 'uniform',
|
||||
// globalColorParams: { value: 0xff0000 }
|
||||
// }
|
||||
// },
|
||||
// label: 'my structure'
|
||||
// });
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -60,10 +60,7 @@
|
||||
var pickScale = getParam('pick-scale', '[^&]+').trim();
|
||||
var pickPadding = getParam('pick-padding', '[^&]+').trim();
|
||||
var disableWboit = getParam('disable-wboit', '[^&]+').trim() === '1';
|
||||
var enableDpoit = getParam('enable-dpoit', '[^&]+').trim() === '1';
|
||||
var preferWebgl1 = getParam('prefer-webgl1', '[^&]+').trim() === '1' || void 0;
|
||||
var allowMajorPerformanceCaveat = getParam('allow-major-performance-caveat', '[^&]+').trim() === '1';
|
||||
var powerPreference = getParam('power-preference', '[^&]+').trim().toLowerCase();
|
||||
|
||||
molstar.Viewer.create('app', {
|
||||
layoutShowControls: !hideControls,
|
||||
@@ -77,11 +74,8 @@
|
||||
pixelScale: parseFloat(pixelScale) || 1,
|
||||
pickScale: parseFloat(pickScale) || 0.25,
|
||||
pickPadding: isNaN(parseFloat(pickPadding)) ? 1 : parseFloat(pickPadding),
|
||||
enableWboit: (disableWboit || enableDpoit) ? false : void 0, // use default value if disable-wboit is not set
|
||||
enableDpoit: enableDpoit ? true : void 0,
|
||||
enableWboit: disableWboit ? false : void 0, // use default value if disable-wboit is not set
|
||||
preferWebgl1: preferWebgl1,
|
||||
allowMajorPerformanceCaveat: allowMajorPerformanceCaveat,
|
||||
powerPreference: powerPreference || 'high-performance',
|
||||
}).then(viewer => {
|
||||
var snapshotId = getParam('snapshot-id', '[^&]+').trim();
|
||||
if (snapshotId) viewer.setRemoteSnapshot(snapshotId);
|
||||
|
||||
@@ -71,7 +71,6 @@ export function getFieldType(type: string, description: string, values?: string[
|
||||
case 'ec-type':
|
||||
case 'ucode-alphanum-csv':
|
||||
case 'id_list':
|
||||
case 'entity_id_list':
|
||||
return ListCol('str', ',', description);
|
||||
case 'id_list_spc':
|
||||
return ListCol('str', ' ', description);
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { AlphaOrbitalsExample } from '.';
|
||||
import { ParameterControls } from '../../mol-plugin-ui/controls/parameters';
|
||||
import { useBehavior } from '../../mol-plugin-ui/hooks/use-behavior';
|
||||
import { PluginContextContainer } from '../../mol-plugin-ui/plugin';
|
||||
|
||||
export function mountControls(orbitals: AlphaOrbitalsExample, parent: Element) {
|
||||
createRoot(parent).render(<PluginContextContainer plugin={orbitals.plugin}>
|
||||
ReactDOM.render(<PluginContextContainer plugin={orbitals.plugin}>
|
||||
<Controls orbitals={orbitals} />
|
||||
</PluginContextContainer>);
|
||||
</PluginContextContainer>, parent);
|
||||
}
|
||||
|
||||
function Controls({ orbitals }: { orbitals: AlphaOrbitalsExample }) {
|
||||
|
||||
@@ -82,20 +82,24 @@ export class AlphaOrbitalsExample {
|
||||
|
||||
this.plugin.managers.interactivity.setProps({ granularity: 'element' });
|
||||
|
||||
if (!canComputeGrid3dOnGPU(this.plugin.canvas3d?.webgl)) {
|
||||
PluginCommands.Toast.Show(this.plugin, {
|
||||
title: 'Error',
|
||||
message: `Browser/device does not support required WebGL extension (OES_texture_float).`
|
||||
this.plugin.behaviors.canvas3d.initialized.subscribe(init => {
|
||||
if (!init) return;
|
||||
|
||||
if (!canComputeGrid3dOnGPU(this.plugin.canvas3d?.webgl)) {
|
||||
PluginCommands.Toast.Show(this.plugin, {
|
||||
title: 'Error',
|
||||
message: `Browser/device does not support required WebGL extension (OES_texture_float).`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.load({
|
||||
moleculeSdf: DemoMoleculeSDF,
|
||||
...DemoOrbitals
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.load({
|
||||
moleculeSdf: DemoMoleculeSDF,
|
||||
...DemoOrbitals
|
||||
mountControls(this, document.getElementById('controls')!);
|
||||
});
|
||||
|
||||
mountControls(this, document.getElementById('controls')!);
|
||||
}
|
||||
|
||||
readonly params = new BehaviorSubject<ParamDefinition.For<Params>>({} as any);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -25,8 +25,7 @@ const Canvas3DPresets = {
|
||||
canvas3d: <Preset>{
|
||||
postprocessing: {
|
||||
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15, resolutionScale: 1 } },
|
||||
outline: { name: 'on', params: { scale: 1, threshold: 0.33, color: Color(0x000000), includeTransparent: true, } },
|
||||
shadow: { name: 'off', params: {} },
|
||||
outline: { name: 'on', params: { scale: 1, threshold: 0.33, color: Color(0x000000) } }
|
||||
},
|
||||
renderer: {
|
||||
ambientIntensity: 1.0,
|
||||
@@ -38,8 +37,7 @@ const Canvas3DPresets = {
|
||||
canvas3d: <Preset>{
|
||||
postprocessing: {
|
||||
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15, resolutionScale: 1 } },
|
||||
outline: { name: 'off', params: {} },
|
||||
shadow: { name: 'off', params: {} },
|
||||
outline: { name: 'off', params: {} }
|
||||
},
|
||||
renderer: {
|
||||
ambientIntensity: 0.4,
|
||||
@@ -52,8 +50,7 @@ const Canvas3DPresets = {
|
||||
canvas3d: <Preset>{
|
||||
postprocessing: {
|
||||
occlusion: { name: 'off', params: {} },
|
||||
outline: { name: 'off', params: {} },
|
||||
shadow: { name: 'off', params: {} },
|
||||
outline: { name: 'off', params: {} }
|
||||
},
|
||||
renderer: {
|
||||
ambientIntensity: 0.4,
|
||||
|
||||
@@ -72,7 +72,6 @@ export const Backgrounds = PluginBehavior.create<{ }>({
|
||||
lightness: 0,
|
||||
saturation: 0,
|
||||
opacity: 1,
|
||||
blur: 0.3,
|
||||
}
|
||||
}
|
||||
}, 'Purple Nebula Skybox'],
|
||||
|
||||
@@ -585,7 +585,7 @@ export const LoadCellPackModel = StateAction.build({
|
||||
... ctx.managers.structure.component.state.options,
|
||||
visualQuality: 'custom',
|
||||
ignoreLight: true,
|
||||
hydrogens: 'hide-all',
|
||||
showHydrogens: false,
|
||||
});
|
||||
ctx.canvas3d?.setProps({
|
||||
multiSample: { mode: 'off' },
|
||||
@@ -606,22 +606,12 @@ export const LoadCellPackModel = StateAction.build({
|
||||
resolutionScale: 1,
|
||||
}
|
||||
},
|
||||
shadow: {
|
||||
name: 'on',
|
||||
params: {
|
||||
bias: 0.6,
|
||||
maxDistance: 80,
|
||||
steps: 3,
|
||||
tolerance: 1.0,
|
||||
}
|
||||
},
|
||||
outline: {
|
||||
name: 'on',
|
||||
params: {
|
||||
scale: 1,
|
||||
threshold: 0.33,
|
||||
color: ColorNames.black,
|
||||
includeTransparent: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ export class GeometryExporterUI extends CollapsableControls<{}, State> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.plugin.canvas3d) return;
|
||||
|
||||
const merged = merge(
|
||||
this.controls.behaviors.params,
|
||||
this.plugin.canvas3d!.reprCount
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
|
||||
@@ -15,7 +14,6 @@ import { CustomPropSymbol } from '../../../mol-script/language/symbol';
|
||||
import { Type } from '../../../mol-script/language/type';
|
||||
import { CustomPropertyDescriptor } from '../../../mol-model/custom-property';
|
||||
import { MmcifFormat } from '../../../mol-model-formats/structure/mmcif';
|
||||
import { AtomicIndex } from '../../../mol-model/structure/model/properties/atomic';
|
||||
|
||||
export { QualityAssessment };
|
||||
|
||||
@@ -73,28 +71,14 @@ namespace QualityAssessment {
|
||||
localNames.set(ma_qa_metric.id.value(i), name);
|
||||
}
|
||||
|
||||
const residueKey: AtomicIndex.ResidueLabelKey = {
|
||||
label_entity_id: '',
|
||||
label_asym_id: '',
|
||||
label_seq_id: 0,
|
||||
pdbx_PDB_ins_code: undefined,
|
||||
};
|
||||
|
||||
for (let i = 0, il = ma_qa_metric_local._rowCount; i < il; i++) {
|
||||
if (model_id.value(i) !== model.modelNum) continue;
|
||||
|
||||
const labelAsymId = label_asym_id.value(i);
|
||||
const entityIndex = index.findEntity(labelAsymId);
|
||||
|
||||
residueKey.label_entity_id = model.entities.data.id.value(entityIndex);
|
||||
residueKey.label_asym_id = labelAsymId;
|
||||
residueKey.label_seq_id = label_seq_id.value(i);
|
||||
|
||||
const rI = index.findResidueLabel(residueKey);
|
||||
if (rI >= 0) {
|
||||
const name = localNames.get(metric_id.value(i))!;
|
||||
localMetrics.get(name)!.set(rI, metric_value.value(i));
|
||||
}
|
||||
const rI = index.findResidue(model.entities.data.id.value(entityIndex), labelAsymId, label_seq_id.value(i));
|
||||
const name = localNames.get(metric_id.value(i))!;
|
||||
localMetrics.get(name)!.set(rI, metric_value.value(i));
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -118,13 +118,11 @@ export class Mp4Controls extends PluginComponent {
|
||||
}
|
||||
|
||||
private init() {
|
||||
if (!this.plugin.canvas3d) return;
|
||||
|
||||
this.subscribe(this.plugin.managers.animation.events.updated.pipe(debounceTime(16)), () => {
|
||||
this.sync();
|
||||
});
|
||||
|
||||
this.subscribe(this.plugin.canvas3d.resized, () => this.syncInfo());
|
||||
this.subscribe(this.plugin.canvas3d?.resized!, () => this.syncInfo());
|
||||
this.subscribe(this.plugin.helpers.viewportScreenshot?.events.previewed!, () => this.syncInfo());
|
||||
|
||||
this.subscribe(this.plugin.behaviors.state.isBusy, b => this.updateCanApply(b));
|
||||
|
||||
@@ -4,7 +4,7 @@ export type InputMaybe<T> = Maybe<T>;
|
||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
|
||||
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
|
||||
// Generated on 2022-12-03T21:55:37-08:00
|
||||
// Generated on 2022-08-20T16:36:05-07:00
|
||||
|
||||
/** All built-in and custom scalars, mapped to their actual values */
|
||||
export type Scalars = {
|
||||
@@ -343,14 +343,6 @@ export type Citation = {
|
||||
*
|
||||
*/
|
||||
readonly journal_abbrev?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* Full name of the cited journal; relevant for journal articles.
|
||||
*
|
||||
* Examples:
|
||||
* Journal of Molecular Biology
|
||||
*
|
||||
*/
|
||||
readonly journal_full?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* The American Society for Testing and Materials (ASTM) code
|
||||
* assigned to the journal cited (also referred to as the CODEN
|
||||
@@ -558,7 +550,6 @@ export type CoreBranchedEntityInstance = {
|
||||
readonly rcsb_id: Scalars['String'];
|
||||
readonly rcsb_latest_revision?: Maybe<RcsbLatestRevision>;
|
||||
readonly rcsb_ligand_neighbors?: Maybe<ReadonlyArray<Maybe<RcsbLigandNeighbors>>>;
|
||||
readonly struct_asym?: Maybe<StructAsym>;
|
||||
};
|
||||
|
||||
export type CoreChemComp = {
|
||||
@@ -670,7 +661,6 @@ export type CoreEntry = {
|
||||
readonly exptl?: Maybe<ReadonlyArray<Maybe<Exptl>>>;
|
||||
readonly exptl_crystal?: Maybe<ReadonlyArray<Maybe<ExptlCrystal>>>;
|
||||
readonly exptl_crystal_grow?: Maybe<ReadonlyArray<Maybe<ExptlCrystalGrow>>>;
|
||||
readonly ma_data?: Maybe<ReadonlyArray<Maybe<MaData>>>;
|
||||
/** Get all non-polymer (non-solvent) entities for this PDB entry. */
|
||||
readonly nonpolymer_entities?: Maybe<ReadonlyArray<Maybe<CoreNonpolymerEntity>>>;
|
||||
readonly pdbx_SG_project?: Maybe<ReadonlyArray<Maybe<PdbxSgProject>>>;
|
||||
@@ -711,7 +701,6 @@ export type CoreEntry = {
|
||||
/** The list of content types associated with this entry. */
|
||||
readonly rcsb_associated_holdings?: Maybe<CurrentEntry>;
|
||||
readonly rcsb_binding_affinity?: Maybe<ReadonlyArray<Maybe<RcsbBindingAffinity>>>;
|
||||
readonly rcsb_comp_model_provenance?: Maybe<RcsbCompModelProvenance>;
|
||||
readonly rcsb_entry_container_identifiers: RcsbEntryContainerIdentifiers;
|
||||
readonly rcsb_entry_group_membership?: Maybe<ReadonlyArray<Maybe<RcsbEntryGroupMembership>>>;
|
||||
readonly rcsb_entry_info: RcsbEntryInfo;
|
||||
@@ -724,7 +713,6 @@ export type CoreEntry = {
|
||||
*
|
||||
*/
|
||||
readonly rcsb_id: Scalars['String'];
|
||||
readonly rcsb_ma_qa_metric_global?: Maybe<ReadonlyArray<Maybe<RcsbMaQaMetricGlobal>>>;
|
||||
readonly rcsb_primary_citation?: Maybe<RcsbPrimaryCitation>;
|
||||
readonly refine?: Maybe<ReadonlyArray<Maybe<Refine>>>;
|
||||
readonly refine_analyze?: Maybe<ReadonlyArray<Maybe<RefineAnalyze>>>;
|
||||
@@ -798,7 +786,6 @@ export type CoreNonpolymerEntityInstance = {
|
||||
readonly rcsb_nonpolymer_instance_validation_score?: Maybe<ReadonlyArray<Maybe<RcsbNonpolymerInstanceValidationScore>>>;
|
||||
readonly rcsb_nonpolymer_struct_conn?: Maybe<ReadonlyArray<Maybe<RcsbNonpolymerStructConn>>>;
|
||||
readonly rcsb_target_neighbors?: Maybe<ReadonlyArray<Maybe<RcsbTargetNeighbors>>>;
|
||||
readonly struct_asym?: Maybe<StructAsym>;
|
||||
};
|
||||
|
||||
export type CorePfam = {
|
||||
@@ -932,7 +919,6 @@ export type CorePolymerEntityInstance = {
|
||||
readonly rcsb_polymer_instance_feature?: Maybe<ReadonlyArray<Maybe<RcsbPolymerInstanceFeature>>>;
|
||||
readonly rcsb_polymer_instance_feature_summary?: Maybe<ReadonlyArray<Maybe<RcsbPolymerInstanceFeatureSummary>>>;
|
||||
readonly rcsb_polymer_struct_conn?: Maybe<ReadonlyArray<Maybe<RcsbPolymerStructConn>>>;
|
||||
readonly struct_asym?: Maybe<StructAsym>;
|
||||
};
|
||||
|
||||
export type CorePubmed = {
|
||||
@@ -1298,9 +1284,9 @@ export type Em2dCrystalEntity = {
|
||||
readonly id: Scalars['String'];
|
||||
/** pointer to _em_image_processing.id in the EM_IMAGE_PROCESSING category. */
|
||||
readonly image_processing_id: Scalars['String'];
|
||||
/** Unit-cell length a in angstroms. */
|
||||
/** Unit-cell length a in Angstroms. */
|
||||
readonly length_a?: Maybe<Scalars['Float']>;
|
||||
/** Unit-cell length b in angstroms. */
|
||||
/** Unit-cell length b in Angstroms. */
|
||||
readonly length_b?: Maybe<Scalars['Float']>;
|
||||
/** Thickness of 2D crystal */
|
||||
readonly length_c?: Maybe<Scalars['Float']>;
|
||||
@@ -1331,11 +1317,11 @@ export type Em3dCrystalEntity = {
|
||||
readonly id: Scalars['String'];
|
||||
/** pointer to _em_image_processing.id in the EM_IMAGE_PROCESSING category. */
|
||||
readonly image_processing_id: Scalars['String'];
|
||||
/** Unit-cell length a in angstroms. */
|
||||
/** Unit-cell length a in Angstroms. */
|
||||
readonly length_a?: Maybe<Scalars['Float']>;
|
||||
/** Unit-cell length b in angstroms. */
|
||||
/** Unit-cell length b in Angstroms. */
|
||||
readonly length_b?: Maybe<Scalars['Float']>;
|
||||
/** Unit-cell length c in angstroms. */
|
||||
/** Unit-cell length c in Angstroms. */
|
||||
readonly length_c?: Maybe<Scalars['Float']>;
|
||||
/**
|
||||
* Space group name.
|
||||
@@ -1496,7 +1482,7 @@ export type Em3dReconstruction = {
|
||||
*/
|
||||
readonly refinement_type?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* The final resolution (in angstroms)of the 3D reconstruction.
|
||||
* The final resolution (in Angstroms)of the 3D reconstruction.
|
||||
*
|
||||
* Examples:
|
||||
* null, null
|
||||
@@ -1572,7 +1558,7 @@ export type EmDiffractionShell = {
|
||||
*/
|
||||
readonly fourier_space_coverage?: Maybe<Scalars['Float']>;
|
||||
/**
|
||||
* High resolution limit for this shell (angstroms)
|
||||
* High resolution limit for this shell (Angstroms)
|
||||
*
|
||||
* Examples:
|
||||
* null
|
||||
@@ -1582,7 +1568,7 @@ export type EmDiffractionShell = {
|
||||
/** Unique identifier for the category em_diffraction_shell */
|
||||
readonly id: Scalars['String'];
|
||||
/**
|
||||
* Low resolution limit for this shell (angstroms)
|
||||
* Low resolution limit for this shell (Angstroms)
|
||||
*
|
||||
* Examples:
|
||||
* null
|
||||
@@ -1628,7 +1614,7 @@ export type EmDiffractionStats = {
|
||||
*/
|
||||
readonly fourier_space_coverage?: Maybe<Scalars['Float']>;
|
||||
/**
|
||||
* High resolution limit of the structure factor data, in angstroms
|
||||
* High resolution limit of the structure factor data, in Angstroms
|
||||
*
|
||||
* Examples:
|
||||
* null
|
||||
@@ -2012,12 +1998,12 @@ export type EmImaging = {
|
||||
/** The magnification indicated by the microscope readout. */
|
||||
readonly nominal_magnification?: Maybe<Scalars['Int']>;
|
||||
/**
|
||||
* The specimen temperature maximum (kelvin) for the duration
|
||||
* The specimen temperature maximum (degrees Kelvin) for the duration
|
||||
* of imaging.
|
||||
*/
|
||||
readonly recording_temperature_maximum?: Maybe<Scalars['Float']>;
|
||||
/**
|
||||
* The specimen temperature minimum (kelvin) for the duration
|
||||
* The specimen temperature minimum (degrees Kelvin) for the duration
|
||||
* of imaging.
|
||||
*/
|
||||
readonly recording_temperature_minimum?: Maybe<Scalars['Float']>;
|
||||
@@ -2042,7 +2028,7 @@ export type EmImaging = {
|
||||
/** Foreign key to the EM_SPECIMEN category */
|
||||
readonly specimen_id?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* The mean specimen stage temperature (in kelvin) during imaging
|
||||
* The mean specimen stage temperature (degrees Kelvin) during imaging
|
||||
* in the microscope.
|
||||
*/
|
||||
readonly temperature?: Maybe<Scalars['Float']>;
|
||||
@@ -2229,7 +2215,7 @@ export type EmStaining = {
|
||||
};
|
||||
|
||||
export type EmVitrification = {
|
||||
/** The temperature (in kelvin) of the sample just prior to vitrification. */
|
||||
/** The temperature (in degrees Kelvin) of the sample just prior to vitrification. */
|
||||
readonly chamber_temperature?: Maybe<Scalars['Float']>;
|
||||
/**
|
||||
* This is the name of the cryogen.
|
||||
@@ -2273,7 +2259,7 @@ export type EmVitrification = {
|
||||
/** This data item is a pointer to _em_specimen.id */
|
||||
readonly specimen_id: Scalars['String'];
|
||||
/**
|
||||
* The vitrification temperature (in kelvin), e.g.,
|
||||
* The vitrification temperature (in degrees Kelvin), e.g.,
|
||||
* temperature of the plunge instrument cryogen bath.
|
||||
*/
|
||||
readonly temp?: Maybe<Scalars['Float']>;
|
||||
@@ -2378,14 +2364,6 @@ export type EntityPoly = {
|
||||
*
|
||||
*/
|
||||
readonly pdbx_seq_one_letter_code_can?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* Evidence for the assignment of the polymer sequence.
|
||||
*
|
||||
* Allowable values:
|
||||
* depositor provided, derived from coordinates
|
||||
*
|
||||
*/
|
||||
readonly pdbx_sequence_evidence_code?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* The PDB strand/chain id(s) corresponding to this polymer entity.
|
||||
*
|
||||
@@ -3027,8 +3005,6 @@ export type Entry = {
|
||||
* identifier.
|
||||
*/
|
||||
readonly id: Scalars['String'];
|
||||
/** An identifier for the model collection associated with the entry. */
|
||||
readonly ma_collection_id?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type Exptl = {
|
||||
@@ -3287,29 +3263,6 @@ export type InterfacePartnerFeatureFeaturePositions = {
|
||||
readonly values?: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
||||
};
|
||||
|
||||
export type MaData = {
|
||||
/**
|
||||
* The type of data held in the dataset.
|
||||
*
|
||||
* Allowable values:
|
||||
* coevolution MSA, input structure, model coordinates, other, polymeric template library, spatial restraints, target, target-template alignment, template structure
|
||||
*
|
||||
*/
|
||||
readonly content_type?: Maybe<Scalars['String']>;
|
||||
/** Details for other content types. */
|
||||
readonly content_type_other_details?: Maybe<Scalars['String']>;
|
||||
/** A unique identifier for the data. */
|
||||
readonly id: Scalars['Int'];
|
||||
/**
|
||||
* An author-given name for the content held in the dataset.
|
||||
*
|
||||
* Examples:
|
||||
* NMR NOE Distances, Target Template Alignment, Coevolution Data
|
||||
*
|
||||
*/
|
||||
readonly name?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type MethodDetails = {
|
||||
/** A description of special aspects of the clustering process */
|
||||
readonly description?: Maybe<Scalars['String']>;
|
||||
@@ -4246,7 +4199,7 @@ export type PdbxNmrExptlSampleConditions = {
|
||||
*/
|
||||
readonly pressure_units?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* The temperature (in kelvin) at which NMR data were
|
||||
* The temperature (in Kelvin) at which NMR data were
|
||||
* collected.
|
||||
*/
|
||||
readonly temperature?: Maybe<Scalars['String']>;
|
||||
@@ -4500,7 +4453,7 @@ export type PdbxPrdAudit = {
|
||||
* An identifier for the wwPDB site creating or modifying the molecule.
|
||||
*
|
||||
* Allowable values:
|
||||
* BMRB, PDBC, PDBE, PDBJ, RCSB
|
||||
* BMRB, PDBC, PDBJ, PDBe, RCSB
|
||||
*
|
||||
*/
|
||||
readonly processing_site?: Maybe<Scalars['String']>;
|
||||
@@ -6864,7 +6817,7 @@ export type Query = {
|
||||
readonly assemblies?: Maybe<ReadonlyArray<Maybe<CoreAssembly>>>;
|
||||
/** Get an assembly given the PDB ID and ASSEMBLY ID. Here ASSEMBLY ID is '1', '2', '3', etc. or 'deposited' for deposited coordinates. */
|
||||
readonly assembly?: Maybe<CoreAssembly>;
|
||||
/** Get a list of PDB branched entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. Note that the ENTRY ID part must be upper case. */
|
||||
/** Get a list of PDB branched entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. */
|
||||
readonly branched_entities?: Maybe<ReadonlyArray<Maybe<CoreBranchedEntity>>>;
|
||||
/** Get a PDB branched entity, given the PDB ID and ENTITY ID. Here ENTITY ID is a '1', '2', '3', etc. */
|
||||
readonly branched_entity?: Maybe<CoreBranchedEntity>;
|
||||
@@ -6888,9 +6841,9 @@ export type Query = {
|
||||
readonly group_provenance?: Maybe<GroupProvenance>;
|
||||
/** Get a pairwise polymeric interface given the PDB ID, ASSEMBLY ID and INTERFACE ID. */
|
||||
readonly interface?: Maybe<CoreInterface>;
|
||||
/** Get a list of pairwise polymeric interfaces given a list of INTERFACE IDs. Here INTERFACE ID is a compound identifier that includes entry_id, assembly_id and interface_id e.g. 1XXX-1.1. Note that the ENTRY ID part must be upper case. */
|
||||
/** Get a list of pairwise polymeric interfaces given a list of INTERFACE IDs. Here INTERFACE ID is a compound identifier that includes entry_id, assembly_id and interface_id e.g. 1XXX-1.1. */
|
||||
readonly interfaces?: Maybe<ReadonlyArray<Maybe<CoreInterface>>>;
|
||||
/** Get a list of PDB non-polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. Note that the ENTRY ID part must be upper case. */
|
||||
/** Get a list of PDB non-polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. */
|
||||
readonly nonpolymer_entities?: Maybe<ReadonlyArray<Maybe<CoreNonpolymerEntity>>>;
|
||||
/** Get a PDB non-polymer entity, given the PDB ID and ENTITY ID. Here ENTITY ID is a '1', '2', '3', etc. */
|
||||
readonly nonpolymer_entity?: Maybe<CoreNonpolymerEntity>;
|
||||
@@ -6898,7 +6851,7 @@ export type Query = {
|
||||
readonly nonpolymer_entity_instance?: Maybe<CoreNonpolymerEntityInstance>;
|
||||
/** Get a list of PDB non-polymer entity instances (chains), given the list of ENTITY INSTANCE IDs. Here ENTITY INSTANCE ID identifies structural element in the asymmetric unit, e.g. 'A', 'B', etc. */
|
||||
readonly nonpolymer_entity_instances?: Maybe<ReadonlyArray<Maybe<CoreNonpolymerEntityInstance>>>;
|
||||
/** Get a list of PDB polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. Note that the ENTRY ID part must be upper case. */
|
||||
/** Get a list of PDB polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. */
|
||||
readonly polymer_entities?: Maybe<ReadonlyArray<Maybe<CorePolymerEntity>>>;
|
||||
/** Get a PDB polymer entity, given the PDB ID and ENTITY ID. Here ENTITY ID is a '1', '2', '3', etc. */
|
||||
readonly polymer_entity?: Maybe<CorePolymerEntity>;
|
||||
@@ -8468,29 +8421,6 @@ export type RcsbClusterMembership = {
|
||||
readonly identity?: Maybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
export type RcsbCompModelProvenance = {
|
||||
/**
|
||||
* Entry identifier corresponding to the computed structure model.
|
||||
*
|
||||
* Examples:
|
||||
* AF-P60325-F1, ma-bak-cepc-0019
|
||||
*
|
||||
*/
|
||||
readonly entry_id: Scalars['String'];
|
||||
/**
|
||||
* Source database for the computed structure model.
|
||||
*
|
||||
* Allowable values:
|
||||
* AlphaFoldDB, ModelArchive
|
||||
*
|
||||
*/
|
||||
readonly source_db?: Maybe<Scalars['String']>;
|
||||
/** Source filename for the computed structure model. */
|
||||
readonly source_filename?: Maybe<Scalars['String']>;
|
||||
/** Source URL for computed structure model file. */
|
||||
readonly source_url?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbEntityHostOrganism = {
|
||||
/**
|
||||
* The beginning polymer sequence position for the polymer section corresponding
|
||||
@@ -8727,7 +8657,7 @@ export type RcsbEntitySourceOrganism = {
|
||||
* A code indicating the provenance of the source organism details for the entity
|
||||
*
|
||||
* Allowable values:
|
||||
* PDB Primary Data, UniProt
|
||||
* PDB Primary Data
|
||||
*
|
||||
*/
|
||||
readonly provenance_source?: Maybe<Scalars['String']>;
|
||||
@@ -8801,7 +8731,7 @@ export type RcsbEntryContainerIdentifiers = {
|
||||
* Entry identifier for the container.
|
||||
*
|
||||
* Examples:
|
||||
* 4HHB, AF_AFP60325F1, MA_MABAKCEPC0019
|
||||
* 1KIP, 4HHB
|
||||
*
|
||||
*/
|
||||
readonly entry_id: Scalars['String'];
|
||||
@@ -8949,15 +8879,6 @@ export type RcsbEntryInfo = {
|
||||
*
|
||||
*/
|
||||
readonly na_polymer_entity_types?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* This data item identifies secondary structure
|
||||
* features of nucleic acids in the entry.
|
||||
*
|
||||
* Allowable values:
|
||||
* a-form double helix, b-form double helix, bulge loop, double helix, four-way junction, hairpin loop, internal loop, mismatched base pair, other right-handed double helix, parallel strands, quadruple helix, tetraloop, three-way junction, triple helix, two-way junction, z-form double helix
|
||||
*
|
||||
*/
|
||||
readonly ndb_struct_conf_na_feature_combined?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
|
||||
/** Bound nonpolymer components in this entry. */
|
||||
readonly nonpolymer_bound_components?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
|
||||
/** The number of distinct non-polymer entities in the structure entry exclusive of solvent. */
|
||||
@@ -9034,21 +8955,6 @@ export type RcsbEntryInfo = {
|
||||
readonly software_programs_combined?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
|
||||
/** The number of distinct solvent entities per deposited structure model. */
|
||||
readonly solvent_entity_count?: Maybe<Scalars['Int']>;
|
||||
/**
|
||||
* Indicates if the structure was determined using experimental or computational methods.
|
||||
*
|
||||
* Allowable values:
|
||||
* computational, experimental
|
||||
*
|
||||
*/
|
||||
readonly structure_determination_methodology: Scalars['String'];
|
||||
/**
|
||||
* Indicates the priority of the value in _rcsb_entry_info.structure_determination_methodology.
|
||||
* The lower the number the higher the priority.
|
||||
* Priority values for "experimental" structures is currently set to 10 and
|
||||
* the values for "computational" structures is set to 100.
|
||||
*/
|
||||
readonly structure_determination_methodology_priority?: Maybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
export type RcsbEntryInfoDiffrnResolutionHigh = {
|
||||
@@ -9388,49 +9294,6 @@ export type RcsbLigandNeighbors = {
|
||||
readonly seq_id?: Maybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
export type RcsbMaQaMetricGlobal = {
|
||||
readonly ma_qa_metric_global?: Maybe<ReadonlyArray<Maybe<RcsbMaQaMetricGlobalMaQaMetricGlobal>>>;
|
||||
/** The model identifier. */
|
||||
readonly model_id: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type RcsbMaQaMetricGlobalMaQaMetricGlobal = {
|
||||
/**
|
||||
* Description of the global QA metric.
|
||||
*
|
||||
* Examples:
|
||||
* confidence score predicting accuracy according to the CA-only Local Distance Difference Test (lDDT-CA) in [0,100]
|
||||
*
|
||||
*/
|
||||
readonly description?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* Name of the global QA metric.
|
||||
*
|
||||
* Examples:
|
||||
* pLDDT
|
||||
*
|
||||
*/
|
||||
readonly name: Scalars['String'];
|
||||
/**
|
||||
* The type of global QA metric.
|
||||
*
|
||||
* Allowable values:
|
||||
* PAE, contact probability, distance, energy, ipTM, normalized score, other, pLDDT, pLDDT all-atom, pLDDT all-atom in [0,1], pLDDT in [0,1], pTM, zscore
|
||||
*
|
||||
*/
|
||||
readonly type: Scalars['String'];
|
||||
/** Details for other type of global QA metric. */
|
||||
readonly type_other_details?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* Value of the global QA metric.
|
||||
*
|
||||
* Examples:
|
||||
* null
|
||||
*
|
||||
*/
|
||||
readonly value: Scalars['Float'];
|
||||
};
|
||||
|
||||
export type RcsbMembraneLineage = {
|
||||
/** Hierarchy depth. */
|
||||
readonly depth?: Maybe<Scalars['Int']>;
|
||||
@@ -10469,7 +10332,7 @@ export type RcsbPolymerEntityContainerIdentifiersReferenceSequenceIdentifiers =
|
||||
* Source of the reference database assignment
|
||||
*
|
||||
* Allowable values:
|
||||
* PDB, RCSB, SIFTS, UniProt
|
||||
* PDB, RCSB, SIFTS
|
||||
*
|
||||
*/
|
||||
readonly provenance_source?: Maybe<Scalars['String']>;
|
||||
@@ -10874,7 +10737,7 @@ export type RcsbPolymerInstanceFeature = {
|
||||
* A type or category of the feature.
|
||||
*
|
||||
* Allowable values:
|
||||
* ANGLE_OUTLIER, BEND, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, HELX_LH_PP_P, HELX_RH_3T_P, HELX_RH_AL_P, HELX_RH_PI_P, MA_QA_METRIC_LOCAL_TYPE_CONTACT_PROBABILITY, MA_QA_METRIC_LOCAL_TYPE_DISTANCE, MA_QA_METRIC_LOCAL_TYPE_ENERGY, MA_QA_METRIC_LOCAL_TYPE_IPTM, MA_QA_METRIC_LOCAL_TYPE_NORMALIZED_SCORE, MA_QA_METRIC_LOCAL_TYPE_OTHER, MA_QA_METRIC_LOCAL_TYPE_PAE, MA_QA_METRIC_LOCAL_TYPE_PLDDT, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM_[0,1], MA_QA_METRIC_LOCAL_TYPE_PLDDT_[0,1], MA_QA_METRIC_LOCAL_TYPE_PTM, MA_QA_METRIC_LOCAL_TYPE_ZSCORE, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SCOP, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, STRN, TURN_TY1_P, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ, ASA
|
||||
* ANGLE_OUTLIER, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SCOP, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ, ASA
|
||||
*
|
||||
*/
|
||||
readonly type?: Maybe<Scalars['String']>;
|
||||
@@ -10885,7 +10748,7 @@ export type RcsbPolymerInstanceFeatureAdditionalProperties = {
|
||||
* The additional property name.
|
||||
*
|
||||
* Allowable values:
|
||||
* CATH_DOMAIN_ID, CATH_NAME, ECOD_DOMAIN_ID, ECOD_FAMILY_NAME, MODELCIF_MODEL_ID, OMEGA_ANGLE, PARTNER_ASYM_ID, PARTNER_BOND_DISTANCE, PARTNER_COMP_ID, SCOP2_DOMAIN_ID, SCOP2_FAMILY_ID, SCOP2_FAMILY_NAME, SCOP2_SUPERFAMILY_ID, SCOP2_SUPERFAMILY_NAME, SCOP_DOMAIN_ID, SCOP_NAME, SCOP_SUN_ID, SHEET_SENSE
|
||||
* CATH_DOMAIN_ID, CATH_NAME, ECOD_DOMAIN_ID, ECOD_FAMILY_NAME, OMEGA_ANGLE, PARTNER_ASYM_ID, PARTNER_BOND_DISTANCE, PARTNER_COMP_ID, SCOP2_DOMAIN_ID, SCOP2_FAMILY_ID, SCOP2_FAMILY_NAME, SCOP2_SUPERFAMILY_ID, SCOP2_SUPERFAMILY_NAME, SCOP_DOMAIN_ID, SCOP_NAME, SCOP_SUN_ID, SHEET_SENSE
|
||||
*
|
||||
*/
|
||||
readonly name?: Maybe<Scalars['String']>;
|
||||
@@ -10955,7 +10818,7 @@ export type RcsbPolymerInstanceFeatureSummary = {
|
||||
* Type or category of the feature.
|
||||
*
|
||||
* Allowable values:
|
||||
* ANGLE_OUTLIER, BEND, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, HELX_LH_PP_P, HELX_RH_3T_P, HELX_RH_AL_P, HELX_RH_PI_P, MA_QA_METRIC_LOCAL_TYPE_CONTACT_PROBABILITY, MA_QA_METRIC_LOCAL_TYPE_DISTANCE, MA_QA_METRIC_LOCAL_TYPE_ENERGY, MA_QA_METRIC_LOCAL_TYPE_IPTM, MA_QA_METRIC_LOCAL_TYPE_NORMALIZED_SCORE, MA_QA_METRIC_LOCAL_TYPE_OTHER, MA_QA_METRIC_LOCAL_TYPE_PAE, MA_QA_METRIC_LOCAL_TYPE_PLDDT, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM_[0,1], MA_QA_METRIC_LOCAL_TYPE_PLDDT_[0,1], MA_QA_METRIC_LOCAL_TYPE_PTM, MA_QA_METRIC_LOCAL_TYPE_ZSCORE, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SCOP, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, STRN, TURN_TY1_P, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ
|
||||
* ANGLE_OUTLIER, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SAbDab Antibody Heavy Chain Subclass, SAbDab Antibody Light Chain Subclass, SAbDab Antibody Light Chain Type, SCOP, SCOP2 Family, SCOP2 Superfamily, SCOP2B Superfamily, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ
|
||||
*
|
||||
*/
|
||||
readonly type?: Maybe<Scalars['String']>;
|
||||
@@ -13514,11 +13377,6 @@ export type ReflnsShell = {
|
||||
};
|
||||
|
||||
export type Software = {
|
||||
/**
|
||||
* This data item is a pointer to _citation.id in the CITATION
|
||||
* category.
|
||||
*/
|
||||
readonly citation_id?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* The classification of the program according to its
|
||||
* major function.
|
||||
@@ -13669,37 +13527,6 @@ export type Struct = {
|
||||
readonly title?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type StructAsym = {
|
||||
/**
|
||||
* This data item is a pointer to _atom_site.pdbx_PDB_strand_id the
|
||||
* ATOM_SITE category.
|
||||
*
|
||||
* Examples:
|
||||
* 1ABC
|
||||
*
|
||||
*/
|
||||
readonly pdbx_PDB_id?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* This data item is a pointer to _atom_site.ndb_alias_strand_id the
|
||||
* ATOM_SITE category.
|
||||
*/
|
||||
readonly pdbx_alt_id?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* This data item gives the order of the structural elements in the
|
||||
* ATOM_SITE category.
|
||||
*/
|
||||
readonly pdbx_order?: Maybe<Scalars['Int']>;
|
||||
/**
|
||||
* This data item describes the general type of the structural elements
|
||||
* in the ATOM_SITE category.
|
||||
*
|
||||
* Allowable values:
|
||||
* ATOMN, ATOMP, ATOMS, HETAC, HETAD, HETAI, HETAIN, HETAS, HETIC
|
||||
*
|
||||
*/
|
||||
readonly pdbx_type?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type StructKeywords = {
|
||||
/**
|
||||
* Terms characterizing the macromolecular structure.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
@@ -260,8 +260,7 @@ namespace Camera {
|
||||
radius: 0,
|
||||
radiusMax: 10,
|
||||
fog: 50,
|
||||
clipFar: true,
|
||||
minNear: 5,
|
||||
clipFar: true
|
||||
};
|
||||
}
|
||||
|
||||
@@ -277,7 +276,6 @@ namespace Camera {
|
||||
radiusMax: number
|
||||
fog: number
|
||||
clipFar: boolean
|
||||
minNear: number
|
||||
}
|
||||
|
||||
export function copySnapshot(out: Snapshot, source?: Partial<Snapshot>) {
|
||||
@@ -294,7 +292,6 @@ namespace Camera {
|
||||
if (typeof source.radiusMax !== 'undefined') out.radiusMax = source.radiusMax;
|
||||
if (typeof source.fog !== 'undefined') out.fog = source.fog;
|
||||
if (typeof source.clipFar !== 'undefined') out.clipFar = source.clipFar;
|
||||
if (typeof source.minNear !== 'undefined') out.minNear = source.minNear;
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -306,7 +303,6 @@ namespace Camera {
|
||||
&& a.radiusMax === b.radiusMax
|
||||
&& a.fog === b.fog
|
||||
&& a.clipFar === b.clipFar
|
||||
&& a.minNear === b.minNear
|
||||
&& Vec3.exactEquals(a.position, b.position)
|
||||
&& Vec3.exactEquals(a.up, b.up)
|
||||
&& Vec3.exactEquals(a.target, b.target);
|
||||
@@ -374,7 +370,7 @@ function updatePers(camera: Camera) {
|
||||
}
|
||||
|
||||
function updateClip(camera: Camera) {
|
||||
let { radius, radiusMax, mode, fog, clipFar, minNear } = camera.state;
|
||||
let { radius, radiusMax, mode, fog, clipFar } = camera.state;
|
||||
if (radius < 0.01) radius = 0.01;
|
||||
|
||||
const normalizedFar = clipFar ? radius : radiusMax;
|
||||
@@ -388,12 +384,12 @@ function updateClip(camera: Camera) {
|
||||
|
||||
if (mode === 'perspective') {
|
||||
// set at least to 5 to avoid slow sphere impostor rendering
|
||||
near = Math.max(Math.min(radiusMax, minNear), near);
|
||||
far = Math.max(minNear, far);
|
||||
near = Math.max(Math.min(radiusMax, 5), near);
|
||||
far = Math.max(5, far);
|
||||
} else {
|
||||
// not too close to 0 as it causes issues with outline rendering
|
||||
near = Math.max(Math.min(radiusMax, minNear), near);
|
||||
far = Math.max(minNear, far);
|
||||
near = Math.max(Math.min(radiusMax, 5), near);
|
||||
far = Math.max(5, far);
|
||||
}
|
||||
|
||||
if (near === far) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
@@ -13,8 +13,8 @@ import { Camera, ICamera } from '../camera';
|
||||
import { Viewport } from './util';
|
||||
|
||||
export const StereoCameraParams = {
|
||||
eyeSeparation: PD.Numeric(0.062, { min: 0.02, max: 0.1, step: 0.001 }, { description: 'Distance between left and right camera.' }),
|
||||
focus: PD.Numeric(10, { min: 1, max: 20, step: 0.1 }, { description: 'Apparent object distance.' }),
|
||||
eyeSeparation: PD.Numeric(0.064, { min: 0.01, max: 0.5, step: 0.001 }),
|
||||
focus: PD.Numeric(10, { min: 1, max: 100, step: 0.01 }),
|
||||
};
|
||||
export const DefaultStereoCameraProps = PD.getDefaultValues(StereoCameraParams);
|
||||
export type StereoCameraProps = PD.Values<typeof StereoCameraParams>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||
@@ -40,10 +39,9 @@ import { Helper } from './helper/helper';
|
||||
import { Passes } from './passes/passes';
|
||||
import { shallowEqual } from '../mol-util';
|
||||
import { MarkingParams } from './passes/marking';
|
||||
import { GraphicsRenderVariantsBlended, GraphicsRenderVariantsWboit, GraphicsRenderVariantsDpoit } from '../mol-gl/webgl/render-item';
|
||||
import { GraphicsRenderVariantsBlended, GraphicsRenderVariantsWboit } from '../mol-gl/webgl/render-item';
|
||||
import { degToRad, radToDeg } from '../mol-math/misc';
|
||||
import { AssetManager } from '../mol-util/assets';
|
||||
import { deepClone } from '../mol-util/object';
|
||||
|
||||
export const Canvas3DParams = {
|
||||
camera: PD.Group({
|
||||
@@ -65,7 +63,6 @@ export const Canvas3DParams = {
|
||||
cameraClipping: PD.Group({
|
||||
radius: PD.Numeric(100, { min: 0, max: 99, step: 1 }, { label: 'Clipping', description: 'How much of the scene to show.' }),
|
||||
far: PD.Boolean(true, { description: 'Hide scene in the distance' }),
|
||||
minNear: PD.Numeric(5, { min: 0.1, max: 10, step: 0.1 }, { description: 'Note, may cause performance issues rendering impostors when set too small and cause issues with outline rendering when too close to 0.' }),
|
||||
}, { pivot: 'radius' }),
|
||||
viewport: PD.MappedStatic('canvas', {
|
||||
canvas: PD.Group({}),
|
||||
@@ -86,7 +83,6 @@ export const Canvas3DParams = {
|
||||
cameraResetDurationMs: PD.Numeric(250, { min: 0, max: 1000, step: 1 }, { description: 'The time it takes to reset the camera.' }),
|
||||
sceneRadiusFactor: PD.Numeric(1, { min: 1, max: 10, step: 0.1 }),
|
||||
transparentBackground: PD.Boolean(false),
|
||||
dpoitIterations: PD.Numeric(2, { min: 1, max: 10, step: 1 }),
|
||||
|
||||
multiSample: PD.Group(MultiSampleParams),
|
||||
postprocessing: PD.Group(PostprocessingParams),
|
||||
@@ -120,8 +116,6 @@ interface Canvas3DContext {
|
||||
|
||||
namespace Canvas3DContext {
|
||||
export const DefaultAttribs = {
|
||||
powerPreference: 'high-performance' as WebGLContextAttributes['powerPreference'],
|
||||
failIfMajorPerformanceCaveat: false,
|
||||
/** true by default to avoid issues with Safari (Jan 2021) */
|
||||
antialias: true,
|
||||
/** true to support multiple Canvas3D objects with a single context */
|
||||
@@ -131,20 +125,14 @@ namespace Canvas3DContext {
|
||||
/** extra pixels to around target to check in case target is empty */
|
||||
pickPadding: 1,
|
||||
enableWboit: true,
|
||||
enableDpoit: false,
|
||||
preferWebGl1: false
|
||||
};
|
||||
export type Attribs = typeof DefaultAttribs
|
||||
|
||||
export function fromCanvas(canvas: HTMLCanvasElement, assetManager: AssetManager, attribs: Partial<Attribs> = {}): Canvas3DContext {
|
||||
const a = { ...DefaultAttribs, ...attribs };
|
||||
|
||||
if (a.enableWboit && a.enableDpoit) throw new Error('Multiple transparency methods not allowed.');
|
||||
|
||||
const { powerPreference, failIfMajorPerformanceCaveat, antialias, preserveDrawingBuffer, pixelScale, preferWebGl1 } = a;
|
||||
const { antialias, preserveDrawingBuffer, pixelScale, preferWebGl1 } = a;
|
||||
const gl = getGLContext(canvas, {
|
||||
powerPreference,
|
||||
failIfMajorPerformanceCaveat,
|
||||
antialias,
|
||||
preserveDrawingBuffer,
|
||||
alpha: true, // the renderer requires an alpha channel
|
||||
@@ -297,7 +285,7 @@ namespace Canvas3D {
|
||||
export interface ClickEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, page?: Vec2, position?: Vec3 }
|
||||
|
||||
export function create({ webgl, input, passes, attribs, assetManager }: Canvas3DContext, props: Partial<Canvas3DProps> = {}): Canvas3D {
|
||||
const p: Canvas3DProps = { ...deepClone(DefaultCanvas3DParams), ...deepClone(props) };
|
||||
const p: Canvas3DProps = { ...DefaultCanvas3DParams, ...props };
|
||||
|
||||
const reprRenderObjects = new Map<Representation.Any, Set<GraphicsRenderObject>>();
|
||||
const reprUpdatedSubscriptions = new Map<Representation.Any, Subscription>();
|
||||
@@ -314,7 +302,8 @@ namespace Canvas3D {
|
||||
let width = 128;
|
||||
let height = 128;
|
||||
updateViewport();
|
||||
const scene = Scene.create(webgl, passes.draw.dpoitEnabled ? GraphicsRenderVariantsDpoit : (passes.draw.wboitEnabled ? GraphicsRenderVariantsWboit : GraphicsRenderVariantsBlended));
|
||||
|
||||
const scene = Scene.create(webgl, passes.draw.wboitEnabled ? GraphicsRenderVariantsWboit : GraphicsRenderVariantsBlended);
|
||||
|
||||
function getSceneRadius() {
|
||||
return scene.boundingSphere.radius * p.sceneRadiusFactor;
|
||||
@@ -325,7 +314,6 @@ namespace Canvas3D {
|
||||
mode: p.camera.mode,
|
||||
fog: p.cameraFog.name === 'on' ? p.cameraFog.params.intensity : 0,
|
||||
clipFar: p.cameraClipping.far,
|
||||
minNear: p.cameraClipping.minNear,
|
||||
fov: degToRad(p.camera.fov),
|
||||
}, { x, y, width, height }, { pixelScale: attribs.pixelScale });
|
||||
const stereoCamera = new StereoCamera(camera, p.camera.stereo.params);
|
||||
@@ -691,11 +679,10 @@ namespace Canvas3D {
|
||||
cameraFog: camera.state.fog > 0
|
||||
? { name: 'on' as const, params: { intensity: camera.state.fog } }
|
||||
: { name: 'off' as const, params: {} },
|
||||
cameraClipping: { far: camera.state.clipFar, radius, minNear: camera.state.minNear },
|
||||
cameraClipping: { far: camera.state.clipFar, radius },
|
||||
cameraResetDurationMs: p.cameraResetDurationMs,
|
||||
sceneRadiusFactor: p.sceneRadiusFactor,
|
||||
transparentBackground: p.transparentBackground,
|
||||
dpoitIterations: p.dpoitIterations,
|
||||
viewport: p.viewport,
|
||||
|
||||
postprocessing: { ...p.postprocessing },
|
||||
@@ -818,9 +805,6 @@ namespace Canvas3D {
|
||||
if (props.cameraClipping.far !== undefined && props.cameraClipping.far !== camera.state.clipFar) {
|
||||
cameraState.clipFar = props.cameraClipping.far;
|
||||
}
|
||||
if (props.cameraClipping.minNear !== undefined && props.cameraClipping.minNear !== camera.state.minNear) {
|
||||
cameraState.minNear = props.cameraClipping.minNear;
|
||||
}
|
||||
if (props.cameraClipping.radius !== undefined) {
|
||||
const radius = (getSceneRadius() / 100) * (100 - props.cameraClipping.radius);
|
||||
if (radius > 0 && radius !== cameraState.radius) {
|
||||
@@ -833,13 +817,9 @@ namespace Canvas3D {
|
||||
|
||||
if (props.camera?.helper) helper.camera.setProps(props.camera.helper);
|
||||
if (props.camera?.manualReset !== undefined) p.camera.manualReset = props.camera.manualReset;
|
||||
if (props.camera?.stereo !== undefined) {
|
||||
Object.assign(p.camera.stereo, props.camera.stereo);
|
||||
stereoCamera.setProps(p.camera.stereo.params);
|
||||
}
|
||||
if (props.camera?.stereo !== undefined) Object.assign(p.camera.stereo, props.camera.stereo);
|
||||
if (props.cameraResetDurationMs !== undefined) p.cameraResetDurationMs = props.cameraResetDurationMs;
|
||||
if (props.transparentBackground !== undefined) p.transparentBackground = props.transparentBackground;
|
||||
if (props.dpoitIterations !== undefined) p.dpoitIterations = props.dpoitIterations;
|
||||
if (props.viewport !== undefined) {
|
||||
const doNotUpdate = p.viewport === props.viewport ||
|
||||
(p.viewport.name === props.viewport.name && shallowEqual(p.viewport.params, props.viewport.params));
|
||||
@@ -875,7 +855,7 @@ namespace Canvas3D {
|
||||
}
|
||||
},
|
||||
getImagePass: (props: Partial<ImageProps> = {}) => {
|
||||
return new ImagePass(webgl, assetManager, renderer, scene, camera, helper, passes.draw.wboitEnabled, passes.draw.dpoitEnabled, props);
|
||||
return new ImagePass(webgl, assetManager, renderer, scene, camera, helper, passes.draw.wboitEnabled, props);
|
||||
},
|
||||
getRenderObjects(): GraphicsRenderObject[] {
|
||||
const renderObjects: GraphicsRenderObject[] = [];
|
||||
@@ -940,4 +920,4 @@ namespace Canvas3D {
|
||||
Viewport.set(controls.viewport, x, y, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,6 @@ const SkyboxParams = {
|
||||
pz: PD.File({ label: 'Positive Z / Front', accept: 'image/*' }),
|
||||
}, { isExpanded: true, label: 'Files' }),
|
||||
}),
|
||||
blur: PD.Numeric(0, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'Note, this only works in WebGL2 or when "EXT_shader_texture_lod" is available.' }),
|
||||
...SharedParams,
|
||||
};
|
||||
type SkyboxProps = PD.Values<typeof SkyboxParams>
|
||||
@@ -171,7 +170,6 @@ export class BackgroundPass {
|
||||
Mat4.invert(m, m);
|
||||
ValueCell.update(this.renderable.values.uViewDirectionProjectionInverse, m);
|
||||
|
||||
ValueCell.updateIfChanged(this.renderable.values.uBlur, props.blur);
|
||||
ValueCell.updateIfChanged(this.renderable.values.uOpacity, props.opacity);
|
||||
ValueCell.updateIfChanged(this.renderable.values.uSaturation, props.saturation);
|
||||
ValueCell.updateIfChanged(this.renderable.values.uLightness, props.lightness);
|
||||
@@ -369,7 +367,7 @@ function getSkyboxTexture(ctx: WebGLContext, assetManager: AssetManager, faces:
|
||||
const cubeAssets = getCubeAssets(assetManager, faces);
|
||||
const cubeFaces = getCubeFaces(assetManager, cubeAssets);
|
||||
const assets = [cubeAssets.nx, cubeAssets.ny, cubeAssets.nz, cubeAssets.px, cubeAssets.py, cubeAssets.pz];
|
||||
const texture = ctx.resources.cubeTexture(cubeFaces, true, onload);
|
||||
const texture = ctx.resources.cubeTexture(cubeFaces, false, onload);
|
||||
return { texture, assets };
|
||||
}
|
||||
|
||||
@@ -426,15 +424,12 @@ const BackgroundSchema = {
|
||||
uGradientColorA: UniformSpec('v3'),
|
||||
uGradientColorB: UniformSpec('v3'),
|
||||
uGradientRatio: UniformSpec('f'),
|
||||
uBlur: UniformSpec('f'),
|
||||
uOpacity: UniformSpec('f'),
|
||||
uSaturation: UniformSpec('f'),
|
||||
uLightness: UniformSpec('f'),
|
||||
dVariant: DefineSpec('string', ['skybox', 'image', 'verticalGradient', 'horizontalGradient', 'radialGradient']),
|
||||
};
|
||||
const SkyboxShaderCode = ShaderCode('background', background_vert, background_frag, {
|
||||
shaderTextureLod: 'optional'
|
||||
});
|
||||
const SkyboxShaderCode = ShaderCode('background', background_vert, background_frag);
|
||||
type BackgroundRenderable = ComputeRenderable<Values<typeof BackgroundSchema>>
|
||||
|
||||
function getBackgroundRenderable(ctx: WebGLContext, width: number, height: number): BackgroundRenderable {
|
||||
@@ -453,7 +448,6 @@ function getBackgroundRenderable(ctx: WebGLContext, width: number, height: numbe
|
||||
uGradientColorA: ValueCell.create(Vec3()),
|
||||
uGradientColorB: ValueCell.create(Vec3()),
|
||||
uGradientRatio: ValueCell.create(0.5),
|
||||
uBlur: ValueCell.create(0),
|
||||
uOpacity: ValueCell.create(1),
|
||||
uSaturation: ValueCell.create(0),
|
||||
uLightness: ValueCell.create(0),
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*
|
||||
* Adapted from https://github.com/tsherif/webgl2examples, The MIT License, Copyright © 2017 Tarek Sherif, Shuai Shao
|
||||
*/
|
||||
|
||||
import { QuadSchema, QuadValues } from '../../mol-gl/compute/util';
|
||||
import { ComputeRenderable, createComputeRenderable } from '../../mol-gl/renderable';
|
||||
import { TextureSpec, UniformSpec, Values } from '../../mol-gl/renderable/schema';
|
||||
import { ShaderCode } from '../../mol-gl/shader-code';
|
||||
import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
|
||||
import { Texture } from '../../mol-gl/webgl/texture';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
import { quad_vert } from '../../mol-gl/shader/quad.vert';
|
||||
import { evaluateDpoit_frag } from '../../mol-gl/shader/evaluate-dpoit.frag';
|
||||
import { blendBackDpoit_frag } from '../../mol-gl/shader/blend-back-dpoit.frag';
|
||||
import { Framebuffer } from '../../mol-gl/webgl/framebuffer';
|
||||
import { Vec2 } from '../../mol-math/linear-algebra';
|
||||
import { isDebugMode, isTimingMode } from '../../mol-util/debug';
|
||||
import { isWebGL2 } from '../../mol-gl/webgl/compat';
|
||||
|
||||
const BlendBackDpoitSchema = {
|
||||
...QuadSchema,
|
||||
tDpoitBackColor: TextureSpec('texture', 'rgba', 'float', 'nearest'),
|
||||
uTexSize: UniformSpec('v2'),
|
||||
};
|
||||
const BlendBackDpoitShaderCode = ShaderCode('blend-back-dpoit', quad_vert, blendBackDpoit_frag);
|
||||
type BlendBackDpoitRenderable = ComputeRenderable<Values<typeof BlendBackDpoitSchema>>
|
||||
|
||||
function getBlendBackDpoitRenderable(ctx: WebGLContext, dopitBlendBackTexture: Texture): BlendBackDpoitRenderable {
|
||||
const values: Values<typeof BlendBackDpoitSchema> = {
|
||||
...QuadValues,
|
||||
tDpoitBackColor: ValueCell.create(dopitBlendBackTexture),
|
||||
uTexSize: ValueCell.create(Vec2.create(dopitBlendBackTexture.getWidth(), dopitBlendBackTexture.getHeight())),
|
||||
};
|
||||
|
||||
const schema = { ...BlendBackDpoitSchema };
|
||||
const renderItem = createComputeRenderItem(ctx, 'triangles', BlendBackDpoitShaderCode, schema, values);
|
||||
|
||||
return createComputeRenderable(renderItem, values);
|
||||
}
|
||||
|
||||
const EvaluateDpoitSchema = {
|
||||
...QuadSchema,
|
||||
tDpoitFrontColor: TextureSpec('texture', 'rgba', 'float', 'nearest'),
|
||||
uTexSize: UniformSpec('v2'),
|
||||
};
|
||||
const EvaluateDpoitShaderCode = ShaderCode('evaluate-dpoit', quad_vert, evaluateDpoit_frag);
|
||||
type EvaluateDpoitRenderable = ComputeRenderable<Values<typeof EvaluateDpoitSchema>>
|
||||
|
||||
function getEvaluateDpoitRenderable(ctx: WebGLContext, dpoitFrontColorTexture: Texture): EvaluateDpoitRenderable {
|
||||
const values: Values<typeof EvaluateDpoitSchema> = {
|
||||
...QuadValues,
|
||||
tDpoitFrontColor: ValueCell.create(dpoitFrontColorTexture),
|
||||
uTexSize: ValueCell.create(Vec2.create(dpoitFrontColorTexture.getWidth(), dpoitFrontColorTexture.getHeight())),
|
||||
};
|
||||
|
||||
const schema = { ...EvaluateDpoitSchema };
|
||||
const renderItem = createComputeRenderItem(ctx, 'triangles', EvaluateDpoitShaderCode, schema, values);
|
||||
|
||||
return createComputeRenderable(renderItem, values);
|
||||
}
|
||||
|
||||
export class DpoitPass {
|
||||
private readonly DEPTH_CLEAR_VALUE = -99999.0; // NOTE same constant is set in shaders
|
||||
private readonly MAX_DEPTH = 1.0;
|
||||
private readonly MIN_DEPTH = 0.0;
|
||||
|
||||
private passCount = 0;
|
||||
private writeId: number;
|
||||
private readId: number;
|
||||
|
||||
private readonly blendBackRenderable: BlendBackDpoitRenderable;
|
||||
private readonly renderable: EvaluateDpoitRenderable;
|
||||
|
||||
private readonly depthFramebuffers: Framebuffer[];
|
||||
private readonly colorFramebuffers: Framebuffer[];
|
||||
|
||||
private readonly depthTextures: Texture[];
|
||||
private readonly colorFrontTextures: Texture[];
|
||||
private readonly colorBackTextures: Texture[];
|
||||
|
||||
private _supported = false;
|
||||
get supported() {
|
||||
return this._supported;
|
||||
}
|
||||
|
||||
bind() {
|
||||
const { state, gl, extensions: { blendMinMax } } = this.webgl;
|
||||
|
||||
// initialize
|
||||
this.passCount = 0;
|
||||
|
||||
this.depthFramebuffers[0].bind();
|
||||
state.clearColor(this.DEPTH_CLEAR_VALUE, this.DEPTH_CLEAR_VALUE, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.depthFramebuffers[1].bind();
|
||||
state.clearColor(-this.MIN_DEPTH, this.MAX_DEPTH, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.colorFramebuffers[0].bind();
|
||||
state.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.colorFramebuffers[1].bind();
|
||||
state.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.depthFramebuffers[0].bind();
|
||||
state.blendEquation(blendMinMax!.MAX);
|
||||
state.depthMask(false);
|
||||
|
||||
return {
|
||||
depth: this.depthTextures[1],
|
||||
frontColor: this.colorFrontTextures[1],
|
||||
backColor: this.colorBackTextures[1]
|
||||
};
|
||||
}
|
||||
|
||||
bindDualDepthPeeling() {
|
||||
const { state, gl, extensions: { blendMinMax } } = this.webgl;
|
||||
|
||||
this.readId = this.passCount % 2;
|
||||
this.writeId = 1 - this.readId; // ping-pong: 0 or 1
|
||||
|
||||
this.passCount += 1; // increment for next pass
|
||||
|
||||
this.depthFramebuffers[this.writeId].bind();
|
||||
state.clearColor(this.DEPTH_CLEAR_VALUE, this.DEPTH_CLEAR_VALUE, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.colorFramebuffers[this.writeId].bind();
|
||||
state.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.depthFramebuffers[this.writeId].bind();
|
||||
state.blendEquation(blendMinMax!.MAX);
|
||||
state.depthMask(false);
|
||||
|
||||
return {
|
||||
depth: this.depthTextures[this.readId],
|
||||
frontColor: this.colorFrontTextures[this.readId],
|
||||
backColor: this.colorBackTextures[this.readId]
|
||||
};
|
||||
}
|
||||
|
||||
renderBlendBack() {
|
||||
if (isTimingMode) this.webgl.timer.mark('DpoitPass.renderBlendBack');
|
||||
const { state, gl } = this.webgl;
|
||||
|
||||
state.blendEquation(gl.FUNC_ADD);
|
||||
state.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
ValueCell.update(this.blendBackRenderable.values.tDpoitBackColor, this.colorBackTextures[this.writeId]);
|
||||
|
||||
this.blendBackRenderable.update();
|
||||
this.blendBackRenderable.render();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('DpoitPass.renderBlendBack');
|
||||
}
|
||||
|
||||
render() {
|
||||
if (isTimingMode) this.webgl.timer.mark('DpoitPass.render');
|
||||
const { state, gl } = this.webgl;
|
||||
|
||||
state.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
ValueCell.update(this.renderable.values.tDpoitFrontColor, this.colorFrontTextures[this.writeId]);
|
||||
|
||||
this.renderable.update();
|
||||
this.renderable.render();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('DpoitPass.render');
|
||||
}
|
||||
|
||||
setSize(width: number, height: number) {
|
||||
const [w, h] = this.renderable.values.uTexSize.ref.value;
|
||||
if (width !== w || height !== h) {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
this.depthTextures[i].define(width, height);
|
||||
this.colorFrontTextures[i].define(width, height);
|
||||
this.colorBackTextures[i].define(width, height);
|
||||
}
|
||||
ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height));
|
||||
ValueCell.update(this.blendBackRenderable.values.uTexSize, Vec2.set(this.blendBackRenderable.values.uTexSize.ref.value, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
if (this._supported) this._init();
|
||||
}
|
||||
|
||||
private _init() {
|
||||
const { extensions: { drawBuffers } } = this.webgl;
|
||||
for (let i = 0; i < 2; i++) {
|
||||
// depth
|
||||
this.depthFramebuffers[i].bind();
|
||||
drawBuffers!.drawBuffers([
|
||||
drawBuffers!.COLOR_ATTACHMENT0,
|
||||
drawBuffers!.COLOR_ATTACHMENT1,
|
||||
drawBuffers!.COLOR_ATTACHMENT2
|
||||
]);
|
||||
|
||||
this.colorFrontTextures[i].attachFramebuffer(this.depthFramebuffers[i], 'color0');
|
||||
this.colorBackTextures[i].attachFramebuffer(this.depthFramebuffers[i], 'color1');
|
||||
this.depthTextures[i].attachFramebuffer(this.depthFramebuffers[i], 'color2');
|
||||
|
||||
// color
|
||||
this.colorFramebuffers[i].bind();
|
||||
drawBuffers!.drawBuffers([
|
||||
drawBuffers!.COLOR_ATTACHMENT0,
|
||||
drawBuffers!.COLOR_ATTACHMENT1
|
||||
]);
|
||||
|
||||
this.colorFrontTextures[i].attachFramebuffer(this.colorFramebuffers[i], 'color0');
|
||||
this.colorBackTextures[i].attachFramebuffer(this.colorFramebuffers[i], 'color1');
|
||||
}
|
||||
}
|
||||
|
||||
static isSupported(webgl: WebGLContext) {
|
||||
const { extensions: { drawBuffers, textureFloat, colorBufferFloat, blendMinMax } } = webgl;
|
||||
if (!textureFloat || !colorBufferFloat || !drawBuffers || !blendMinMax) {
|
||||
if (isDebugMode) {
|
||||
const missing: string[] = [];
|
||||
if (!textureFloat) missing.push('textureFloat');
|
||||
if (!colorBufferFloat) missing.push('colorBufferFloat');
|
||||
if (!drawBuffers) missing.push('drawBuffers');
|
||||
if (!blendMinMax) missing.push('blendMinMax');
|
||||
console.log(`Missing "${missing.join('", "')}" extensions required for "dpoit"`);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private webgl: WebGLContext, width: number, height: number) {
|
||||
if (!DpoitPass.isSupported(webgl)) return;
|
||||
|
||||
const { resources, extensions: { colorBufferHalfFloat, textureHalfFloat } } = webgl;
|
||||
|
||||
// textures
|
||||
|
||||
if (isWebGL2(webgl.gl)) {
|
||||
this.depthTextures = [
|
||||
resources.texture('image-float32', 'rg', 'float', 'nearest'),
|
||||
resources.texture('image-float32', 'rg', 'float', 'nearest')
|
||||
];
|
||||
|
||||
this.colorFrontTextures = colorBufferHalfFloat && textureHalfFloat ? [
|
||||
resources.texture('image-float16', 'rgba', 'fp16', 'nearest'),
|
||||
resources.texture('image-float16', 'rgba', 'fp16', 'nearest')
|
||||
] : [
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest')
|
||||
];
|
||||
|
||||
this.colorBackTextures = colorBufferHalfFloat && textureHalfFloat ? [
|
||||
resources.texture('image-float16', 'rgba', 'fp16', 'nearest'),
|
||||
resources.texture('image-float16', 'rgba', 'fp16', 'nearest')
|
||||
] : [
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest')
|
||||
];
|
||||
} else {
|
||||
// in webgl1 drawbuffers must be in the same format for some reason
|
||||
|
||||
this.depthTextures = [
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest')
|
||||
];
|
||||
|
||||
this.colorFrontTextures = [
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest')
|
||||
];
|
||||
|
||||
this.colorBackTextures = [
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
|
||||
resources.texture('image-float32', 'rgba', 'float', 'nearest')
|
||||
];
|
||||
}
|
||||
|
||||
this.depthTextures[0].define(width, height);
|
||||
this.depthTextures[1].define(width, height);
|
||||
|
||||
this.colorFrontTextures[0].define(width, height);
|
||||
this.colorFrontTextures[1].define(width, height);
|
||||
|
||||
this.colorBackTextures[0].define(width, height);
|
||||
this.colorBackTextures[1].define(width, height);
|
||||
|
||||
// framebuffers
|
||||
|
||||
this.depthFramebuffers = [resources.framebuffer(), resources.framebuffer()];
|
||||
this.colorFramebuffers = [resources.framebuffer(), resources.framebuffer()];
|
||||
|
||||
// renderables
|
||||
|
||||
this.blendBackRenderable = getBlendBackDpoitRenderable(webgl, this.colorBackTextures[0]);
|
||||
this.renderable = getEvaluateDpoitRenderable(webgl, this.colorFrontTextures[0]);
|
||||
|
||||
this._supported = true;
|
||||
this._init();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
@@ -18,7 +17,6 @@ import { Helper } from '../helper/helper';
|
||||
|
||||
import { StereoCamera } from '../camera/stereo';
|
||||
import { WboitPass } from './wboit';
|
||||
import { DpoitPass } from './dpoit';
|
||||
import { AntialiasingPass, PostprocessingPass, PostprocessingProps } from './postprocessing';
|
||||
import { MarkingPass, MarkingProps } from './marking';
|
||||
import { CopyRenderable, createCopyRenderable } from '../../mol-gl/compute/util';
|
||||
@@ -29,7 +27,6 @@ type Props = {
|
||||
postprocessing: PostprocessingProps;
|
||||
marking: MarkingProps;
|
||||
transparentBackground: boolean;
|
||||
dpoitIterations: number;
|
||||
}
|
||||
|
||||
type RenderContext = {
|
||||
@@ -55,7 +52,6 @@ export class DrawPass {
|
||||
private copyFboPostprocessing: CopyRenderable;
|
||||
|
||||
private readonly wboit: WboitPass | undefined;
|
||||
private readonly dpoit: DpoitPass | undefined;
|
||||
private readonly marking: MarkingPass;
|
||||
readonly postprocessing: PostprocessingPass;
|
||||
private readonly antialiasing: AntialiasingPass;
|
||||
@@ -64,12 +60,9 @@ export class DrawPass {
|
||||
return !!this.wboit?.supported;
|
||||
}
|
||||
|
||||
get dpoitEnabled() {
|
||||
return !!this.dpoit?.supported;
|
||||
}
|
||||
|
||||
constructor(private webgl: WebGLContext, assetManager: AssetManager, width: number, height: number, enableWboit: boolean, enableDpoit: boolean) {
|
||||
constructor(private webgl: WebGLContext, assetManager: AssetManager, width: number, height: number, enableWboit: boolean) {
|
||||
const { extensions, resources, isWebGL2 } = webgl;
|
||||
|
||||
this.drawTarget = createNullRenderTarget(webgl.gl);
|
||||
this.colorTarget = webgl.createRenderTarget(width, height, true, 'uint8', 'linear');
|
||||
this.packedDepth = !extensions.depthTexture;
|
||||
@@ -85,7 +78,6 @@ export class DrawPass {
|
||||
}
|
||||
|
||||
this.wboit = enableWboit ? new WboitPass(webgl, width, height) : undefined;
|
||||
this.dpoit = enableDpoit ? new DpoitPass(webgl, width, height) : undefined;
|
||||
this.marking = new MarkingPass(webgl, width, height);
|
||||
this.postprocessing = new PostprocessingPass(webgl, assetManager, this);
|
||||
this.antialiasing = new AntialiasingPass(webgl, this);
|
||||
@@ -96,7 +88,6 @@ export class DrawPass {
|
||||
|
||||
reset() {
|
||||
this.wboit?.reset();
|
||||
this.dpoit?.reset();
|
||||
}
|
||||
|
||||
setSize(width: number, height: number) {
|
||||
@@ -120,70 +111,12 @@ export class DrawPass {
|
||||
this.wboit.setSize(width, height);
|
||||
}
|
||||
|
||||
if (this.dpoit?.supported) {
|
||||
this.dpoit.setSize(width, height);
|
||||
}
|
||||
|
||||
this.marking.setSize(width, height);
|
||||
this.postprocessing.setSize(width, height);
|
||||
this.antialiasing.setSize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
private _renderDpoit(renderer: Renderer, camera: ICamera, scene: Scene, iterations: number, transparentBackground: boolean, postprocessingProps: PostprocessingProps) {
|
||||
if (!this.dpoit?.supported) throw new Error('expected dpoit to be supported');
|
||||
|
||||
this.depthTextureOpaque.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
renderer.clear(true);
|
||||
|
||||
// render opaque primitives
|
||||
if (scene.hasOpaque) {
|
||||
renderer.renderDpoitOpaque(scene.primitives, camera, null);
|
||||
}
|
||||
|
||||
if (PostprocessingPass.isEnabled(postprocessingProps)) {
|
||||
if (PostprocessingPass.isTransparentOutlineEnabled(postprocessingProps)) {
|
||||
this.depthTargetTransparent.bind();
|
||||
renderer.clearDepth(true);
|
||||
if (scene.opacityAverage < 1) {
|
||||
renderer.renderDepthTransparent(scene.primitives, camera, this.depthTextureOpaque);
|
||||
}
|
||||
}
|
||||
|
||||
this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps, renderer.light);
|
||||
}
|
||||
|
||||
this.depthTextureOpaque.detachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
|
||||
// render transparent primitives
|
||||
if (scene.opacityAverage < 1) {
|
||||
const target = PostprocessingPass.isEnabled(postprocessingProps)
|
||||
? this.postprocessing.target : this.colorTarget;
|
||||
|
||||
const dpoitTextures = this.dpoit.bind();
|
||||
renderer.renderDpoitTransparent(scene.primitives, camera, this.depthTextureOpaque, dpoitTextures);
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
if (isTimingMode) this.webgl.timer.mark('DpoitPass.layer');
|
||||
const dpoitTextures = this.dpoit.bindDualDepthPeeling();
|
||||
renderer.renderDpoitTransparent(scene.primitives, camera, this.depthTextureOpaque, dpoitTextures);
|
||||
|
||||
target.bind();
|
||||
this.dpoit.renderBlendBack();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('DpoitPass.layer');
|
||||
}
|
||||
|
||||
// evaluate dpoit
|
||||
target.bind();
|
||||
this.dpoit.render();
|
||||
}
|
||||
|
||||
// render transparent volumes
|
||||
if (scene.volumes.renderables.length > 0) {
|
||||
renderer.renderDpoitVolume(scene.volumes, camera, this.depthTextureOpaque);
|
||||
}
|
||||
}
|
||||
|
||||
private _renderWboit(renderer: Renderer, camera: ICamera, scene: Scene, transparentBackground: boolean, postprocessingProps: PostprocessingProps) {
|
||||
if (!this.wboit?.supported) throw new Error('expected wboit to be supported');
|
||||
|
||||
@@ -196,7 +129,7 @@ export class DrawPass {
|
||||
}
|
||||
|
||||
if (PostprocessingPass.isEnabled(postprocessingProps)) {
|
||||
if (PostprocessingPass.isTransparentOutlineEnabled(postprocessingProps)) {
|
||||
if (PostprocessingPass.isOutlineEnabled(postprocessingProps)) {
|
||||
this.depthTargetTransparent.bind();
|
||||
renderer.clearDepth(true);
|
||||
if (scene.opacityAverage < 1) {
|
||||
@@ -204,7 +137,7 @@ export class DrawPass {
|
||||
}
|
||||
}
|
||||
|
||||
this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps, renderer.light);
|
||||
this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps);
|
||||
}
|
||||
|
||||
// render transparent primitives and volumes
|
||||
@@ -260,7 +193,7 @@ export class DrawPass {
|
||||
this.colorTarget.depthRenderbuffer?.detachFramebuffer(this.postprocessing.target.framebuffer);
|
||||
}
|
||||
|
||||
if (PostprocessingPass.isTransparentOutlineEnabled(postprocessingProps)) {
|
||||
if (PostprocessingPass.isOutlineEnabled(postprocessingProps)) {
|
||||
this.depthTargetTransparent.bind();
|
||||
renderer.clearDepth(true);
|
||||
if (scene.opacityAverage < 1) {
|
||||
@@ -268,7 +201,7 @@ export class DrawPass {
|
||||
}
|
||||
}
|
||||
|
||||
this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps, renderer.light);
|
||||
this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps);
|
||||
|
||||
if (!this.packedDepth) {
|
||||
this.depthTextureOpaque.attachFramebuffer(this.postprocessing.target.framebuffer, 'depth');
|
||||
@@ -321,15 +254,13 @@ export class DrawPass {
|
||||
|
||||
if (this.wboitEnabled) {
|
||||
this._renderWboit(renderer, camera, scene, transparentBackground, props.postprocessing);
|
||||
} else if (this.dpoitEnabled) {
|
||||
this._renderDpoit(renderer, camera, scene, props.dpoitIterations, transparentBackground, props.postprocessing);
|
||||
} else {
|
||||
this._renderBlended(renderer, camera, scene, !volumeRendering && !postprocessingEnabled && !antialiasingEnabled && toDrawingBuffer, transparentBackground, props.postprocessing);
|
||||
}
|
||||
|
||||
const target = postprocessingEnabled
|
||||
? this.postprocessing.target
|
||||
: !toDrawingBuffer || volumeRendering || this.wboitEnabled || this.dpoitEnabled
|
||||
: !toDrawingBuffer || volumeRendering || this.wboitEnabled
|
||||
? this.colorTarget
|
||||
: this.drawTarget;
|
||||
|
||||
@@ -372,7 +303,7 @@ export class DrawPass {
|
||||
this.webgl.state.disable(this.webgl.gl.DEPTH_TEST);
|
||||
if (postprocessingEnabled) {
|
||||
this.copyFboPostprocessing.render();
|
||||
} else if (volumeRendering || this.wboitEnabled || this.dpoitEnabled) {
|
||||
} else if (volumeRendering || this.wboitEnabled) {
|
||||
this.copyFboTarget.render();
|
||||
}
|
||||
}
|
||||
@@ -392,12 +323,8 @@ export class DrawPass {
|
||||
renderer.setPixelRatio(this.webgl.pixelRatio);
|
||||
|
||||
if (StereoCamera.is(camera)) {
|
||||
if (isTimingMode) this.webgl.timer.mark('StereoCamera.left');
|
||||
this._render(renderer, camera.left, scene, helper, toDrawingBuffer, transparentBackground, props);
|
||||
if (isTimingMode) this.webgl.timer.markEnd('StereoCamera.left');
|
||||
if (isTimingMode) this.webgl.timer.mark('StereoCamera.right');
|
||||
this._render(renderer, camera.right, scene, helper, toDrawingBuffer, transparentBackground, props);
|
||||
if (isTimingMode) this.webgl.timer.markEnd('StereoCamera.right');
|
||||
} else {
|
||||
this._render(renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, props);
|
||||
}
|
||||
@@ -412,4 +339,4 @@ export class DrawPass {
|
||||
}
|
||||
return this.colorTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import { AssetManager } from '../../mol-util/assets';
|
||||
|
||||
export const ImageParams = {
|
||||
transparentBackground: PD.Boolean(false),
|
||||
dpoitIterations: PD.Numeric(2, { min: 1, max: 10, step: 1 }),
|
||||
multiSample: PD.Group(MultiSampleParams),
|
||||
postprocessing: PD.Group(PostprocessingParams),
|
||||
marking: PD.Group(MarkingParams),
|
||||
@@ -49,10 +48,10 @@ export class ImagePass {
|
||||
get width() { return this._width; }
|
||||
get height() { return this._height; }
|
||||
|
||||
constructor(private webgl: WebGLContext, assetManager: AssetManager, private renderer: Renderer, private scene: Scene, private camera: Camera, helper: Helper, enableWboit: boolean, enableDpoit: boolean, props: Partial<ImageProps>) {
|
||||
constructor(private webgl: WebGLContext, assetManager: AssetManager, private renderer: Renderer, private scene: Scene, private camera: Camera, helper: Helper, enableWboit: boolean, props: Partial<ImageProps>) {
|
||||
this.props = { ...PD.getDefaultValues(ImageParams), ...props };
|
||||
|
||||
this.drawPass = new DrawPass(webgl, assetManager, 128, 128, enableWboit, enableDpoit);
|
||||
this.drawPass = new DrawPass(webgl, assetManager, 128, 128, enableWboit);
|
||||
this.multiSamplePass = new MultiSamplePass(webgl, this.drawPass);
|
||||
this.multiSampleHelper = new MultiSampleHelper(this.multiSamplePass);
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@ type Props = {
|
||||
postprocessing: PostprocessingProps
|
||||
marking: MarkingProps
|
||||
transparentBackground: boolean;
|
||||
dpoitIterations: number;
|
||||
}
|
||||
|
||||
type RenderContext = {
|
||||
|
||||
@@ -15,19 +15,16 @@ export class Passes {
|
||||
readonly pick: PickPass;
|
||||
readonly multiSample: MultiSamplePass;
|
||||
|
||||
constructor(private webgl: WebGLContext, assetManager: AssetManager, attribs: Partial<{ pickScale: number, enableWboit: boolean, enableDpoit: boolean }> = {}) {
|
||||
constructor(private webgl: WebGLContext, assetManager: AssetManager, attribs: Partial<{ pickScale: number, enableWboit: boolean }> = {}) {
|
||||
const { gl } = webgl;
|
||||
this.draw = new DrawPass(webgl, assetManager, gl.drawingBufferWidth, gl.drawingBufferHeight, attribs.enableWboit || false, attribs.enableDpoit || false);
|
||||
this.draw = new DrawPass(webgl, assetManager, gl.drawingBufferWidth, gl.drawingBufferHeight, attribs.enableWboit || false);
|
||||
this.pick = new PickPass(webgl, this.draw, attribs.pickScale || 0.25);
|
||||
this.multiSample = new MultiSamplePass(webgl, this.draw);
|
||||
}
|
||||
|
||||
updateSize() {
|
||||
const { gl } = this.webgl;
|
||||
// Avoid setting dimensions to 0x0 because it causes "empty textures are not allowed" error.
|
||||
const width = Math.max(gl.drawingBufferWidth, 2);
|
||||
const height = Math.max(gl.drawingBufferHeight, 2);
|
||||
this.draw.setSize(width, height);
|
||||
this.draw.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
|
||||
this.pick.syncSize();
|
||||
this.multiSample.syncSize();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
|
||||
* @author Ludovic Autin <ludovic.autin@gmail.com>
|
||||
*/
|
||||
|
||||
import { CopyRenderable, createCopyRenderable, QuadSchema, QuadValues } from '../../mol-gl/compute/util';
|
||||
@@ -31,8 +30,6 @@ import { SmaaParams, SmaaPass } from './smaa';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
import { BackgroundParams, BackgroundPass } from './background';
|
||||
import { AssetManager } from '../../mol-util/assets';
|
||||
import { Light } from '../../mol-gl/renderer';
|
||||
import { shadows_frag } from '../../mol-gl/shader/shadows.frag';
|
||||
|
||||
const OutlinesSchema = {
|
||||
...QuadSchema,
|
||||
@@ -45,12 +42,10 @@ const OutlinesSchema = {
|
||||
uFar: UniformSpec('f'),
|
||||
|
||||
uMaxPossibleViewZDiff: UniformSpec('f'),
|
||||
|
||||
dTransparentOutline: DefineSpec('boolean'),
|
||||
};
|
||||
type OutlinesRenderable = ComputeRenderable<Values<typeof OutlinesSchema>>
|
||||
|
||||
function getOutlinesRenderable(ctx: WebGLContext, depthTextureOpaque: Texture, depthTextureTransparent: Texture, transparentOutline: boolean): OutlinesRenderable {
|
||||
function getOutlinesRenderable(ctx: WebGLContext, depthTextureOpaque: Texture, depthTextureTransparent: Texture): OutlinesRenderable {
|
||||
const width = depthTextureOpaque.getWidth();
|
||||
const height = depthTextureOpaque.getHeight();
|
||||
|
||||
@@ -65,8 +60,6 @@ function getOutlinesRenderable(ctx: WebGLContext, depthTextureOpaque: Texture, d
|
||||
uFar: ValueCell.create(10000),
|
||||
|
||||
uMaxPossibleViewZDiff: ValueCell.create(0.5),
|
||||
|
||||
dTransparentOutline: ValueCell.create(transparentOutline),
|
||||
};
|
||||
|
||||
const schema = { ...OutlinesSchema };
|
||||
@@ -76,64 +69,6 @@ function getOutlinesRenderable(ctx: WebGLContext, depthTextureOpaque: Texture, d
|
||||
return createComputeRenderable(renderItem, values);
|
||||
}
|
||||
|
||||
const ShadowsSchema = {
|
||||
...QuadSchema,
|
||||
tDepth: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
uTexSize: UniformSpec('v2'),
|
||||
|
||||
uProjection: UniformSpec('m4'),
|
||||
uInvProjection: UniformSpec('m4'),
|
||||
uBounds: UniformSpec('v4'),
|
||||
|
||||
dOrthographic: DefineSpec('number'),
|
||||
uNear: UniformSpec('f'),
|
||||
uFar: UniformSpec('f'),
|
||||
|
||||
dSteps: DefineSpec('number'),
|
||||
uMaxDistance: UniformSpec('f'),
|
||||
uTolerance: UniformSpec('f'),
|
||||
uBias: UniformSpec('f'),
|
||||
|
||||
uLightDirection: UniformSpec('v3[]'),
|
||||
uLightColor: UniformSpec('v3[]'),
|
||||
dLightCount: DefineSpec('number'),
|
||||
};
|
||||
type ShadowsRenderable = ComputeRenderable<Values<typeof ShadowsSchema>>
|
||||
|
||||
function getShadowsRenderable(ctx: WebGLContext, depthTexture: Texture): ShadowsRenderable {
|
||||
const width = depthTexture.getWidth();
|
||||
const height = depthTexture.getHeight();
|
||||
|
||||
const values: Values<typeof ShadowsSchema> = {
|
||||
...QuadValues,
|
||||
tDepth: ValueCell.create(depthTexture),
|
||||
uTexSize: ValueCell.create(Vec2.create(width, height)),
|
||||
|
||||
uProjection: ValueCell.create(Mat4.identity()),
|
||||
uInvProjection: ValueCell.create(Mat4.identity()),
|
||||
uBounds: ValueCell.create(Vec4()),
|
||||
|
||||
dOrthographic: ValueCell.create(0),
|
||||
uNear: ValueCell.create(1),
|
||||
uFar: ValueCell.create(10000),
|
||||
|
||||
dSteps: ValueCell.create(1),
|
||||
uMaxDistance: ValueCell.create(3.0),
|
||||
uTolerance: ValueCell.create(1.0),
|
||||
uBias: ValueCell.create(0.6),
|
||||
|
||||
uLightDirection: ValueCell.create([]),
|
||||
uLightColor: ValueCell.create([]),
|
||||
dLightCount: ValueCell.create(0),
|
||||
};
|
||||
|
||||
const schema = { ...ShadowsSchema };
|
||||
const shaderCode = ShaderCode('shadows', quad_vert, shadows_frag);
|
||||
const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values);
|
||||
|
||||
return createComputeRenderable(renderItem, values);
|
||||
}
|
||||
|
||||
const SsaoSchema = {
|
||||
...QuadSchema,
|
||||
tDepth: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
@@ -269,7 +204,6 @@ const PostprocessingSchema = {
|
||||
tColor: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tDepthOpaque: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tDepthTransparent: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tShadows: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tOutlines: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
uTexSize: UniformSpec('v2'),
|
||||
|
||||
@@ -287,25 +221,19 @@ const PostprocessingSchema = {
|
||||
dOcclusionEnable: DefineSpec('boolean'),
|
||||
uOcclusionOffset: UniformSpec('v2'),
|
||||
|
||||
dShadowEnable: DefineSpec('boolean'),
|
||||
|
||||
dOutlineEnable: DefineSpec('boolean'),
|
||||
dOutlineScale: DefineSpec('number'),
|
||||
uOutlineThreshold: UniformSpec('f'),
|
||||
|
||||
dTransparentOutline: DefineSpec('boolean'),
|
||||
};
|
||||
type PostprocessingRenderable = ComputeRenderable<Values<typeof PostprocessingSchema>>
|
||||
|
||||
|
||||
function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, depthTextureOpaque: Texture, depthTextureTransparent: Texture, shadowsTexture: Texture, outlinesTexture: Texture, ssaoDepthTexture: Texture, transparentOutline: boolean): PostprocessingRenderable {
|
||||
function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, depthTextureOpaque: Texture, depthTextureTransparent: Texture, outlinesTexture: Texture, ssaoDepthTexture: Texture): PostprocessingRenderable {
|
||||
const values: Values<typeof PostprocessingSchema> = {
|
||||
...QuadValues,
|
||||
tSsaoDepth: ValueCell.create(ssaoDepthTexture),
|
||||
tColor: ValueCell.create(colorTexture),
|
||||
tDepthOpaque: ValueCell.create(depthTextureOpaque),
|
||||
tDepthTransparent: ValueCell.create(depthTextureTransparent),
|
||||
tShadows: ValueCell.create(shadowsTexture),
|
||||
tOutlines: ValueCell.create(outlinesTexture),
|
||||
uTexSize: ValueCell.create(Vec2.create(colorTexture.getWidth(), colorTexture.getHeight())),
|
||||
|
||||
@@ -323,13 +251,9 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d
|
||||
dOcclusionEnable: ValueCell.create(true),
|
||||
uOcclusionOffset: ValueCell.create(Vec2.create(0, 0)),
|
||||
|
||||
dShadowEnable: ValueCell.create(false),
|
||||
|
||||
dOutlineEnable: ValueCell.create(false),
|
||||
dOutlineScale: ValueCell.create(1),
|
||||
uOutlineThreshold: ValueCell.create(0.33),
|
||||
|
||||
dTransparentOutline: ValueCell.create(transparentOutline),
|
||||
};
|
||||
|
||||
const schema = { ...PostprocessingSchema };
|
||||
@@ -350,21 +274,11 @@ export const PostprocessingParams = {
|
||||
}),
|
||||
off: PD.Group({})
|
||||
}, { cycle: true, description: 'Darken occluded crevices with the ambient occlusion effect' }),
|
||||
shadow: PD.MappedStatic('off', {
|
||||
on: PD.Group({
|
||||
steps: PD.Numeric(1, { min: 1, max: 64, step: 1 }),
|
||||
bias: PD.Numeric(0.6, { min: 0.0, max: 1.0, step: 0.01 }),
|
||||
maxDistance: PD.Numeric(3, { min: 0, max: 256, step: 1 }),
|
||||
tolerance: PD.Numeric(1.0, { min: 0.0, max: 10.0, step: 0.1 }),
|
||||
}),
|
||||
off: PD.Group({})
|
||||
}, { cycle: true, description: 'Simplistic shadows' }),
|
||||
outline: PD.MappedStatic('off', {
|
||||
on: PD.Group({
|
||||
scale: PD.Numeric(1, { min: 1, max: 5, step: 1 }),
|
||||
threshold: PD.Numeric(0.33, { min: 0.01, max: 1, step: 0.01 }),
|
||||
color: PD.Color(Color(0x000000)),
|
||||
includeTransparent: PD.Boolean(true, { description: 'Whether to show outline for transparent objects' }),
|
||||
}),
|
||||
off: PD.Group({})
|
||||
}, { cycle: true, description: 'Draw outline around 3D objects' }),
|
||||
@@ -375,16 +289,15 @@ export const PostprocessingParams = {
|
||||
}, { options: [['fxaa', 'FXAA'], ['smaa', 'SMAA'], ['off', 'Off']], description: 'Smooth pixel edges' }),
|
||||
background: PD.Group(BackgroundParams, { isFlat: true }),
|
||||
};
|
||||
|
||||
export type PostprocessingProps = PD.Values<typeof PostprocessingParams>
|
||||
|
||||
export class PostprocessingPass {
|
||||
static isEnabled(props: PostprocessingProps) {
|
||||
return props.occlusion.name === 'on' || props.shadow.name === 'on' || props.outline.name === 'on' || props.background.variant.name !== 'off';
|
||||
return props.occlusion.name === 'on' || props.outline.name === 'on' || props.background.variant.name !== 'off';
|
||||
}
|
||||
|
||||
static isTransparentOutlineEnabled(props: PostprocessingProps) {
|
||||
return props.outline.name === 'on' && props.outline.params.includeTransparent;
|
||||
static isOutlineEnabled(props: PostprocessingProps) {
|
||||
return props.outline.name === 'on';
|
||||
}
|
||||
|
||||
readonly target: RenderTarget;
|
||||
@@ -392,9 +305,6 @@ export class PostprocessingPass {
|
||||
private readonly outlinesTarget: RenderTarget;
|
||||
private readonly outlinesRenderable: OutlinesRenderable;
|
||||
|
||||
private readonly shadowsTarget: RenderTarget;
|
||||
private readonly shadowsRenderable: ShadowsRenderable;
|
||||
|
||||
private readonly ssaoFramebuffer: Framebuffer;
|
||||
private readonly ssaoBlurFirstPassFramebuffer: Framebuffer;
|
||||
private readonly ssaoBlurSecondPassFramebuffer: Framebuffer;
|
||||
@@ -438,10 +348,7 @@ export class PostprocessingPass {
|
||||
this.target = webgl.createRenderTarget(width, height, false, 'uint8', 'linear');
|
||||
|
||||
this.outlinesTarget = webgl.createRenderTarget(width, height, false);
|
||||
this.outlinesRenderable = getOutlinesRenderable(webgl, depthTextureOpaque, depthTextureTransparent, true);
|
||||
|
||||
this.shadowsTarget = webgl.createRenderTarget(width, height, false);
|
||||
this.shadowsRenderable = getShadowsRenderable(webgl, depthTextureOpaque);
|
||||
this.outlinesRenderable = getOutlinesRenderable(webgl, depthTextureOpaque, depthTextureTransparent);
|
||||
|
||||
this.ssaoFramebuffer = webgl.resources.framebuffer();
|
||||
this.ssaoBlurFirstPassFramebuffer = webgl.resources.framebuffer();
|
||||
@@ -466,7 +373,7 @@ export class PostprocessingPass {
|
||||
this.ssaoRenderable = getSsaoRenderable(webgl, this.downsampleFactor === 1 ? depthTextureOpaque : this.downsampledDepthTarget.texture);
|
||||
this.ssaoBlurFirstPassRenderable = getSsaoBlurRenderable(webgl, this.ssaoDepthTexture, 'horizontal');
|
||||
this.ssaoBlurSecondPassRenderable = getSsaoBlurRenderable(webgl, this.ssaoDepthBlurProxyTexture, 'vertical');
|
||||
this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTextureOpaque, depthTextureTransparent, this.shadowsTarget.texture, this.outlinesTarget.texture, this.ssaoDepthTexture, true);
|
||||
this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTextureOpaque, depthTextureTransparent, this.outlinesTarget.texture, this.ssaoDepthTexture);
|
||||
|
||||
this.background = new BackgroundPass(webgl, assetManager, width, height);
|
||||
}
|
||||
@@ -482,14 +389,12 @@ export class PostprocessingPass {
|
||||
const sh = Math.floor(height * this.ssaoScale);
|
||||
this.target.setSize(width, height);
|
||||
this.outlinesTarget.setSize(width, height);
|
||||
this.shadowsTarget.setSize(width, height);
|
||||
this.downsampledDepthTarget.setSize(sw, sh);
|
||||
this.ssaoDepthTexture.define(sw, sh);
|
||||
this.ssaoDepthBlurProxyTexture.define(sw, sh);
|
||||
|
||||
ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height));
|
||||
ValueCell.update(this.outlinesRenderable.values.uTexSize, Vec2.set(this.outlinesRenderable.values.uTexSize.ref.value, width, height));
|
||||
ValueCell.update(this.shadowsRenderable.values.uTexSize, Vec2.set(this.shadowsRenderable.values.uTexSize.ref.value, width, height));
|
||||
ValueCell.update(this.downsampleDepthRenderable.values.uTexSize, Vec2.set(this.downsampleDepthRenderable.values.uTexSize.ref.value, sw, sh));
|
||||
ValueCell.update(this.ssaoRenderable.values.uTexSize, Vec2.set(this.ssaoRenderable.values.uTexSize.ref.value, sw, sh));
|
||||
ValueCell.update(this.ssaoBlurFirstPassRenderable.values.uTexSize, Vec2.set(this.ssaoBlurFirstPassRenderable.values.uTexSize.ref.value, sw, sh));
|
||||
@@ -499,29 +404,25 @@ export class PostprocessingPass {
|
||||
}
|
||||
}
|
||||
|
||||
private updateState(camera: ICamera, transparentBackground: boolean, backgroundColor: Color, props: PostprocessingProps, light: Light) {
|
||||
let needsUpdateShadows = false;
|
||||
private updateState(camera: ICamera, transparentBackground: boolean, backgroundColor: Color, props: PostprocessingProps) {
|
||||
let needsUpdateMain = false;
|
||||
let needsUpdateSsao = false;
|
||||
let needsUpdateSsaoBlur = false;
|
||||
let needsUpdateOutlines = false;
|
||||
|
||||
const orthographic = camera.state.mode === 'orthographic' ? 1 : 0;
|
||||
const outlinesEnabled = props.outline.name === 'on';
|
||||
const shadowsEnabled = props.shadow.name === 'on';
|
||||
const occlusionEnabled = props.occlusion.name === 'on';
|
||||
|
||||
const invProjection = Mat4.identity();
|
||||
Mat4.invert(invProjection, camera.projection);
|
||||
|
||||
const [w, h] = this.renderable.values.uTexSize.ref.value;
|
||||
const v = camera.viewport;
|
||||
|
||||
if (props.occlusion.name === 'on') {
|
||||
ValueCell.update(this.ssaoRenderable.values.uProjection, camera.projection);
|
||||
ValueCell.update(this.ssaoRenderable.values.uInvProjection, invProjection);
|
||||
|
||||
const [w, h] = this.renderable.values.uTexSize.ref.value;
|
||||
const b = this.ssaoRenderable.values.uBounds;
|
||||
const v = camera.viewport;
|
||||
const s = this.ssaoScale;
|
||||
Vec4.set(b.ref.value,
|
||||
Math.floor(v.x * s) / (w * s),
|
||||
@@ -593,41 +494,8 @@ export class PostprocessingPass {
|
||||
}
|
||||
}
|
||||
|
||||
if (props.shadow.name === 'on') {
|
||||
ValueCell.update(this.shadowsRenderable.values.uProjection, camera.projection);
|
||||
ValueCell.update(this.shadowsRenderable.values.uInvProjection, invProjection);
|
||||
|
||||
Vec4.set(this.shadowsRenderable.values.uBounds.ref.value,
|
||||
v.x / w,
|
||||
v.y / h,
|
||||
(v.x + v.width) / w,
|
||||
(v.y + v.height) / h
|
||||
);
|
||||
ValueCell.update(this.shadowsRenderable.values.uBounds, this.shadowsRenderable.values.uBounds.ref.value);
|
||||
|
||||
ValueCell.updateIfChanged(this.shadowsRenderable.values.uNear, camera.near);
|
||||
ValueCell.updateIfChanged(this.shadowsRenderable.values.uFar, camera.far);
|
||||
ValueCell.updateIfChanged(this.shadowsRenderable.values.dOrthographic, orthographic);
|
||||
|
||||
ValueCell.updateIfChanged(this.shadowsRenderable.values.uMaxDistance, props.shadow.params.maxDistance);
|
||||
ValueCell.updateIfChanged(this.shadowsRenderable.values.uTolerance, props.shadow.params.tolerance);
|
||||
ValueCell.updateIfChanged(this.shadowsRenderable.values.uBias, props.shadow.params.bias);
|
||||
if (this.shadowsRenderable.values.dSteps.ref.value !== props.shadow.params.steps) {
|
||||
ValueCell.update(this.shadowsRenderable.values.dSteps, props.shadow.params.steps);
|
||||
needsUpdateShadows = true;
|
||||
}
|
||||
|
||||
ValueCell.update(this.shadowsRenderable.values.uLightDirection, light.direction);
|
||||
ValueCell.update(this.shadowsRenderable.values.uLightColor, light.color);
|
||||
if (this.shadowsRenderable.values.dLightCount.ref.value !== light.count) {
|
||||
ValueCell.update(this.shadowsRenderable.values.dLightCount, light.count);
|
||||
needsUpdateShadows = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (props.outline.name === 'on') {
|
||||
let { threshold, includeTransparent } = props.outline.params;
|
||||
const transparentOutline = includeTransparent ?? true;
|
||||
let { threshold } = props.outline.params;
|
||||
// orthographic needs lower threshold
|
||||
if (camera.state.mode === 'orthographic') threshold /= 5;
|
||||
const factor = Math.pow(1000, threshold) / 1000;
|
||||
@@ -638,16 +506,12 @@ export class PostprocessingPass {
|
||||
ValueCell.updateIfChanged(this.outlinesRenderable.values.uNear, camera.near);
|
||||
ValueCell.updateIfChanged(this.outlinesRenderable.values.uFar, camera.far);
|
||||
ValueCell.updateIfChanged(this.outlinesRenderable.values.uMaxPossibleViewZDiff, maxPossibleViewZDiff);
|
||||
if (this.renderable.values.dTransparentOutline.ref.value !== transparentOutline) { needsUpdateOutlines = true; }
|
||||
ValueCell.updateIfChanged(this.outlinesRenderable.values.dTransparentOutline, transparentOutline);
|
||||
|
||||
ValueCell.update(this.renderable.values.uOutlineColor, Color.toVec3Normalized(this.renderable.values.uOutlineColor.ref.value, props.outline.params.color));
|
||||
|
||||
ValueCell.updateIfChanged(this.renderable.values.uMaxPossibleViewZDiff, maxPossibleViewZDiff);
|
||||
if (this.renderable.values.dOutlineScale.ref.value !== outlineScale) { needsUpdateMain = true; }
|
||||
ValueCell.updateIfChanged(this.renderable.values.dOutlineScale, outlineScale);
|
||||
if (this.renderable.values.dTransparentOutline.ref.value !== transparentOutline) { needsUpdateMain = true; }
|
||||
ValueCell.updateIfChanged(this.renderable.values.dTransparentOutline, transparentOutline);
|
||||
}
|
||||
|
||||
ValueCell.updateIfChanged(this.renderable.values.uFar, camera.far);
|
||||
@@ -658,22 +522,11 @@ export class PostprocessingPass {
|
||||
ValueCell.updateIfChanged(this.renderable.values.uTransparentBackground, transparentBackground);
|
||||
if (this.renderable.values.dOrthographic.ref.value !== orthographic) { needsUpdateMain = true; }
|
||||
ValueCell.updateIfChanged(this.renderable.values.dOrthographic, orthographic);
|
||||
|
||||
if (this.renderable.values.dOutlineEnable.ref.value !== outlinesEnabled) { needsUpdateMain = true; }
|
||||
ValueCell.updateIfChanged(this.renderable.values.dOutlineEnable, outlinesEnabled);
|
||||
if (this.renderable.values.dShadowEnable.ref.value !== shadowsEnabled) { needsUpdateMain = true; }
|
||||
ValueCell.updateIfChanged(this.renderable.values.dShadowEnable, shadowsEnabled);
|
||||
if (this.renderable.values.dOcclusionEnable.ref.value !== occlusionEnabled) { needsUpdateMain = true; }
|
||||
ValueCell.updateIfChanged(this.renderable.values.dOcclusionEnable, occlusionEnabled);
|
||||
|
||||
if (needsUpdateOutlines) {
|
||||
this.outlinesRenderable.update();
|
||||
}
|
||||
|
||||
if (needsUpdateShadows) {
|
||||
this.shadowsRenderable.update();
|
||||
}
|
||||
|
||||
if (needsUpdateSsao) {
|
||||
this.ssaoRenderable.update();
|
||||
}
|
||||
@@ -711,20 +564,15 @@ export class PostprocessingPass {
|
||||
this.transparentBackground = value;
|
||||
}
|
||||
|
||||
render(camera: ICamera, toDrawingBuffer: boolean, transparentBackground: boolean, backgroundColor: Color, props: PostprocessingProps, light: Light) {
|
||||
render(camera: ICamera, toDrawingBuffer: boolean, transparentBackground: boolean, backgroundColor: Color, props: PostprocessingProps) {
|
||||
if (isTimingMode) this.webgl.timer.mark('PostprocessingPass.render');
|
||||
this.updateState(camera, transparentBackground, backgroundColor, props, light);
|
||||
this.updateState(camera, transparentBackground, backgroundColor, props);
|
||||
|
||||
if (props.outline.name === 'on') {
|
||||
this.outlinesTarget.bind();
|
||||
this.outlinesRenderable.render();
|
||||
}
|
||||
|
||||
if (props.shadow.name === 'on') {
|
||||
this.shadowsTarget.bind();
|
||||
this.shadowsRenderable.render();
|
||||
}
|
||||
|
||||
// don't render occlusion if offset is given,
|
||||
// which will reuse the existing occlusion
|
||||
if (props.occlusion.name === 'on' && this.occlusionOffset[0] === 0 && this.occlusionOffset[1] === 0) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -11,7 +11,7 @@ import { ShaderCode } from '../../mol-gl/shader-code';
|
||||
import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
|
||||
import { RenderTarget } from '../../mol-gl/webgl/render-target';
|
||||
import { loadImageTexture, Texture } from '../../mol-gl/webgl/texture';
|
||||
import { createTexture, loadImageTexture, Texture } from '../../mol-gl/webgl/texture';
|
||||
import { Vec2, Vec4 } from '../../mol-math/linear-algebra';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
||||
@@ -74,7 +74,6 @@ export class SmaaPass {
|
||||
state.viewport(x, y, width, height);
|
||||
state.scissor(x, y, width, height);
|
||||
|
||||
state.colorMask(true, true, true, true);
|
||||
state.clearColor(0, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
@@ -192,8 +191,8 @@ function getWeightsRenderable(ctx: WebGLContext, edgesTexture: Texture): Weights
|
||||
const width = edgesTexture.getWidth();
|
||||
const height = edgesTexture.getHeight();
|
||||
|
||||
const areaTexture = ctx.resources.texture('image-uint8', 'rgb', 'ubyte', 'linear');
|
||||
const searchTexture = ctx.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
const areaTexture = createTexture(ctx.gl, ctx.extensions, 'image-uint8', 'rgb', 'ubyte', 'linear');
|
||||
const searchTexture = createTexture(ctx.gl, ctx.extensions, 'image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
|
||||
const values: Values<typeof WeightsSchema> = {
|
||||
...QuadValues,
|
||||
|
||||
@@ -18,8 +18,6 @@ import { evaluateWboit_frag } from '../../mol-gl/shader/evaluate-wboit.frag';
|
||||
import { Framebuffer } from '../../mol-gl/webgl/framebuffer';
|
||||
import { Vec2 } from '../../mol-math/linear-algebra';
|
||||
import { isDebugMode, isTimingMode } from '../../mol-util/debug';
|
||||
import { isWebGL2 } from '../../mol-gl/webgl/compat';
|
||||
import { Renderbuffer } from '../../mol-gl/webgl/renderbuffer';
|
||||
|
||||
const EvaluateWboitSchema = {
|
||||
...QuadSchema,
|
||||
@@ -52,7 +50,6 @@ export class WboitPass {
|
||||
private readonly framebuffer: Framebuffer;
|
||||
private readonly textureA: Texture;
|
||||
private readonly textureB: Texture;
|
||||
private readonly depthRenderbuffer: Renderbuffer;
|
||||
|
||||
private _supported = false;
|
||||
get supported() {
|
||||
@@ -90,7 +87,6 @@ export class WboitPass {
|
||||
if (width !== w || height !== h) {
|
||||
this.textureA.define(width, height);
|
||||
this.textureB.define(width, height);
|
||||
this.depthRenderbuffer.setSize(width, height);
|
||||
ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height));
|
||||
}
|
||||
}
|
||||
@@ -110,8 +106,6 @@ export class WboitPass {
|
||||
|
||||
this.textureA.attachFramebuffer(this.framebuffer, 'color0');
|
||||
this.textureB.attachFramebuffer(this.framebuffer, 'color1');
|
||||
|
||||
this.depthRenderbuffer.attachFramebuffer(this.framebuffer);
|
||||
}
|
||||
|
||||
static isSupported(webgl: WebGLContext) {
|
||||
@@ -134,7 +128,7 @@ export class WboitPass {
|
||||
constructor(private webgl: WebGLContext, width: number, height: number) {
|
||||
if (!WboitPass.isSupported(webgl)) return;
|
||||
|
||||
const { resources, gl } = webgl;
|
||||
const { resources } = webgl;
|
||||
|
||||
this.textureA = resources.texture('image-float32', 'rgba', 'float', 'nearest');
|
||||
this.textureA.define(width, height);
|
||||
@@ -142,10 +136,6 @@ export class WboitPass {
|
||||
this.textureB = resources.texture('image-float32', 'rgba', 'float', 'nearest');
|
||||
this.textureB.define(width, height);
|
||||
|
||||
this.depthRenderbuffer = isWebGL2(gl)
|
||||
? resources.renderbuffer('depth32f', 'depth', width, height)
|
||||
: resources.renderbuffer('depth16', 'depth', width, height);
|
||||
|
||||
this.renderable = getEvaluateWboitRenderable(webgl, this.textureA, this.textureB);
|
||||
this.framebuffer = resources.framebuffer();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -21,7 +21,6 @@ export type OverpaintData = {
|
||||
uOverpaintGridDim: ValueCell<Vec3>,
|
||||
uOverpaintGridTransform: ValueCell<Vec4>,
|
||||
dOverpaintType: ValueCell<string>,
|
||||
uOverpaintStrength: ValueCell<number>,
|
||||
}
|
||||
|
||||
export function applyOverpaintColor(array: Uint8Array, start: number, end: number, color: Color) {
|
||||
@@ -55,7 +54,6 @@ export function createOverpaint(count: number, type: OverpaintType, overpaintDat
|
||||
uOverpaintGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
|
||||
uOverpaintGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
|
||||
dOverpaintType: ValueCell.create(type),
|
||||
uOverpaintStrength: ValueCell.create(1),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -76,7 +74,6 @@ export function createEmptyOverpaint(overpaintData?: OverpaintData): OverpaintDa
|
||||
uOverpaintGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
|
||||
uOverpaintGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
|
||||
dOverpaintType: ValueCell.create('groupInstance'),
|
||||
uOverpaintStrength: ValueCell.create(1),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2021-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -21,7 +21,6 @@ export type SubstanceData = {
|
||||
uSubstanceGridDim: ValueCell<Vec3>,
|
||||
uSubstanceGridTransform: ValueCell<Vec4>,
|
||||
dSubstanceType: ValueCell<string>,
|
||||
uSubstanceStrength: ValueCell<number>,
|
||||
}
|
||||
|
||||
export function applySubstanceMaterial(array: Uint8Array, start: number, end: number, material: Material) {
|
||||
@@ -55,7 +54,6 @@ export function createSubstance(count: number, type: SubstanceType, substanceDat
|
||||
uSubstanceGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
|
||||
uSubstanceGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
|
||||
dSubstanceType: ValueCell.create(type),
|
||||
uSubstanceStrength: ValueCell.create(1),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -76,7 +74,6 @@ export function createEmptySubstance(substanceData?: SubstanceData): SubstanceDa
|
||||
uSubstanceGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
|
||||
uSubstanceGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
|
||||
dSubstanceType: ValueCell.create('groupInstance'),
|
||||
uSubstanceStrength: ValueCell.create(1),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -88,7 +88,7 @@ export class FontAtlas {
|
||||
this.scratchCanvas.width = this.maxWidth;
|
||||
this.scratchCanvas.height = this.lineHeight;
|
||||
|
||||
this.scratchContext = this.scratchCanvas.getContext('2d', { willReadFrequently: true })!;
|
||||
this.scratchContext = this.scratchCanvas.getContext('2d')!;
|
||||
this.scratchContext.font = `${p.fontStyle} ${p.fontVariant} ${p.fontWeight} ${fontSize}px ${p.fontFamily}`;
|
||||
this.scratchContext.fillStyle = 'black';
|
||||
this.scratchContext.textBaseline = 'middle';
|
||||
|
||||
@@ -387,8 +387,6 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
|
||||
const type = isInstanceType ? 'volumeInstance' : 'volume';
|
||||
if (isTimingMode) webgl.timer.markEnd('calcTextureMeshColorSmoothing');
|
||||
|
||||
// printTextureImage(readTexture(webgl, texture), { scale: 0.75 });
|
||||
|
||||
return { texture, gridDim, gridTexDim: Vec2.create(width, height), gridTransform, type };
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { ValueCell } from '../../../mol-util';
|
||||
import { Sphere3D } from '../../../mol-math/geometry';
|
||||
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
|
||||
import { LocationIterator, PositionLocation } from '../../../mol-geo/util/location-iterator';
|
||||
import { LocationIterator } from '../../../mol-geo/util/location-iterator';
|
||||
import { TransformData } from '../transform-data';
|
||||
import { createColors } from '../color-data';
|
||||
import { createMarkers } from '../marker-data';
|
||||
@@ -20,12 +20,11 @@ import { createEmptyTransparency } from '../transparency-data';
|
||||
import { TextureMeshValues } from '../../../mol-gl/renderable/texture-mesh';
|
||||
import { calculateTransformBoundingSphere } from '../../../mol-gl/renderable/util';
|
||||
import { createNullTexture, Texture } from '../../../mol-gl/webgl/texture';
|
||||
import { Vec2, Vec3, Vec4 } from '../../../mol-math/linear-algebra';
|
||||
import { Vec2, Vec4 } from '../../../mol-math/linear-algebra';
|
||||
import { createEmptyClipping } from '../clipping-data';
|
||||
import { NullLocation } from '../../../mol-model/location';
|
||||
import { createEmptySubstance } from '../substance-data';
|
||||
import { RenderableState } from '../../../mol-gl/renderable';
|
||||
import { WebGLContext } from '../../../mol-gl/webgl/context';
|
||||
|
||||
export interface TextureMesh {
|
||||
readonly kind: 'texture-mesh',
|
||||
@@ -44,10 +43,7 @@ export interface TextureMesh {
|
||||
|
||||
readonly boundingSphere: Sphere3D
|
||||
|
||||
readonly meta: {
|
||||
webgl?: WebGLContext
|
||||
[k: string]: unknown
|
||||
}
|
||||
readonly meta: { [k: string]: unknown }
|
||||
}
|
||||
|
||||
export namespace TextureMesh {
|
||||
@@ -135,42 +131,9 @@ export namespace TextureMesh {
|
||||
updateBoundingSphere,
|
||||
createRenderableState,
|
||||
updateRenderableState,
|
||||
createPositionIterator,
|
||||
createPositionIterator: () => LocationIterator(1, 1, 1, () => NullLocation)
|
||||
};
|
||||
|
||||
const TextureMeshName = 'texture-mesh';
|
||||
|
||||
function createPositionIterator(textureMesh: TextureMesh, transform: TransformData): LocationIterator {
|
||||
const webgl = textureMesh.meta.webgl;
|
||||
if (!webgl) return LocationIterator(1, 1, 1, () => NullLocation);
|
||||
|
||||
if (!webgl.namedFramebuffers[TextureMeshName]) {
|
||||
webgl.namedFramebuffers[TextureMeshName] = webgl.resources.framebuffer();
|
||||
}
|
||||
const framebuffer = webgl.namedFramebuffers[TextureMeshName];
|
||||
const [width, height] = textureMesh.geoTextureDim.ref.value;
|
||||
const vertices = new Float32Array(width * height * 4);
|
||||
framebuffer.bind();
|
||||
textureMesh.vertexTexture.ref.value.attachFramebuffer(framebuffer, 0);
|
||||
webgl.readPixels(0, 0, width, height, vertices);
|
||||
|
||||
const groupCount = textureMesh.vertexCount;
|
||||
const instanceCount = transform.instanceCount.ref.value;
|
||||
const location = PositionLocation();
|
||||
const p = location.position;
|
||||
const v = vertices;
|
||||
const m = transform.aTransform.ref.value;
|
||||
const getLocation = (groupIndex: number, instanceIndex: number) => {
|
||||
if (instanceIndex < 0) {
|
||||
Vec3.fromArray(p, v, groupIndex * 4);
|
||||
} else {
|
||||
Vec3.transformMat4Offset(p, v, m, 0, groupIndex * 4, instanceIndex * 16);
|
||||
}
|
||||
return location;
|
||||
};
|
||||
return LocationIterator(groupCount, instanceCount, 1, getLocation);
|
||||
}
|
||||
|
||||
function createValues(textureMesh: TextureMesh, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): TextureMeshValues {
|
||||
const { instanceCount, groupCount } = locationIt;
|
||||
const positionIt = Utils.createPositionIterator(textureMesh, transform);
|
||||
|
||||
@@ -21,7 +21,6 @@ export type TransparencyData = {
|
||||
uTransparencyGridDim: ValueCell<Vec3>,
|
||||
uTransparencyGridTransform: ValueCell<Vec4>,
|
||||
dTransparencyType: ValueCell<string>,
|
||||
uTransparencyStrength: ValueCell<number>,
|
||||
}
|
||||
|
||||
export function applyTransparencyValue(array: Uint8Array, start: number, end: number, value: number) {
|
||||
@@ -64,7 +63,6 @@ export function createTransparency(count: number, type: TransparencyType, transp
|
||||
uTransparencyGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
|
||||
uTransparencyGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
|
||||
dTransparencyType: ValueCell.create(type),
|
||||
uTransparencyStrength: ValueCell.create(1),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -86,7 +84,6 @@ export function createEmptyTransparency(transparencyData?: TransparencyData): Tr
|
||||
uTransparencyGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
|
||||
uTransparencyGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
|
||||
dTransparencyType: ValueCell.create('groupInstance'),
|
||||
uTransparencyStrength: ValueCell.create(1),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -53,17 +53,17 @@ describe('renderer', () => {
|
||||
scene.commit();
|
||||
expect(ctx.stats.resourceCounts.attribute).toBe(ctx.isWebGL2 ? 4 : 5);
|
||||
expect(ctx.stats.resourceCounts.texture).toBe(9);
|
||||
expect(ctx.stats.resourceCounts.vertexArray).toBe(ctx.extensions.vertexArrayObject ? 6 : 0);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(6);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(12);
|
||||
expect(ctx.stats.resourceCounts.vertexArray).toBe(ctx.extensions.vertexArrayObject ? 5 : 0);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(5);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(10);
|
||||
|
||||
scene.remove(points);
|
||||
scene.commit();
|
||||
expect(ctx.stats.resourceCounts.attribute).toBe(0);
|
||||
expect(ctx.stats.resourceCounts.texture).toBe(1);
|
||||
expect(ctx.stats.resourceCounts.vertexArray).toBe(0);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(6);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(12);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(5);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(10);
|
||||
|
||||
ctx.resources.destroy();
|
||||
expect(ctx.stats.resourceCounts.program).toBe(0);
|
||||
|
||||
@@ -197,7 +197,7 @@ export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture,
|
||||
gl.finish();
|
||||
if (isTimingMode) ctx.timer.markEnd('createHistogramPyramid');
|
||||
|
||||
// printTextureImage(readTexture(ctx, pyramidTex), { scale: 0.75 });
|
||||
// printTexture(ctx, pyramidTex, 2)
|
||||
|
||||
//
|
||||
|
||||
|
||||
@@ -115,7 +115,6 @@ export function calcActiveVoxels(ctx: WebGLContext, volumeData: Texture, gridDim
|
||||
// console.log('gridScale', gridScale, 'gridTexDim', gridTexDim, 'gridDim', gridDim);
|
||||
// console.log('volumeData', volumeData);
|
||||
// console.log('at', readTexture(ctx, activeVoxelsTex));
|
||||
// printTextureImage(readTexture(ctx, activeVoxelsTex), { scale: 0.75 });
|
||||
|
||||
gl.finish();
|
||||
if (isTimingMode) ctx.timer.markEnd('calcActiveVoxels');
|
||||
|
||||
@@ -199,10 +199,6 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
|
||||
gl.finish();
|
||||
if (isTimingMode) ctx.timer.markEnd('createIsosurfaceBuffers');
|
||||
|
||||
// printTextureImage(readTexture(ctx, vertexTexture, new Float32Array(width * height * 4)), { scale: 0.75 });
|
||||
// printTextureImage(readTexture(ctx, groupTexture, new Uint8Array(width * height * 4)), { scale: 0.75 });
|
||||
// printTextureImage(readTexture(ctx, normalTexture, new Float32Array(width * height * 4)), { scale: 0.75 });
|
||||
|
||||
return { vertexTexture, groupTexture, normalTexture, vertexCount: count };
|
||||
}
|
||||
|
||||
|
||||
@@ -75,9 +75,9 @@ export function getSharedCopyRenderable(ctx: WebGLContext, texture: Texture) {
|
||||
const ReadTextureName = 'read-texture';
|
||||
const ReadAlphaTextureName = 'read-alpha-texture';
|
||||
|
||||
export function readTexture<T extends Uint8Array | Float32Array | Int32Array = Uint8Array>(ctx: WebGLContext, texture: Texture, array?: T) {
|
||||
export function readTexture(ctx: WebGLContext, texture: Texture) {
|
||||
const { gl, resources } = ctx;
|
||||
if (!array && texture.type !== gl.UNSIGNED_BYTE) throw new Error('unsupported texture type');
|
||||
if (texture.type !== gl.UNSIGNED_BYTE) throw new Error('unsupported texture type');
|
||||
|
||||
if (!ctx.namedFramebuffers[ReadTextureName]) {
|
||||
ctx.namedFramebuffers[ReadTextureName] = resources.framebuffer();
|
||||
@@ -86,7 +86,7 @@ export function readTexture<T extends Uint8Array | Float32Array | Int32Array = U
|
||||
|
||||
const width = texture.getWidth();
|
||||
const height = texture.getHeight();
|
||||
if (!array) array = new Uint8Array(width * height * 4) as T;
|
||||
const array = new Uint8Array(width * height * 4);
|
||||
framebuffer.bind();
|
||||
texture.attachFramebuffer(framebuffer, 0);
|
||||
ctx.readPixels(0, 0, width, height, array);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -168,11 +167,6 @@ export type GlobalUniformValues = Values<GlobalUniformSchema>
|
||||
|
||||
export const GlobalTextureSchema = {
|
||||
tDepth: TextureSpec('texture', 'depth', 'ushort', 'nearest'),
|
||||
|
||||
// dpoit
|
||||
tDpoitDepth: TextureSpec('texture', 'rg', 'float', 'nearest'),
|
||||
tDpoitFrontColor: TextureSpec('texture', 'rgba', 'float', 'nearest'),
|
||||
tDpoitBackColor: TextureSpec('texture', 'rgba', 'float', 'nearest')
|
||||
} as const;
|
||||
export type GlobalTextureSchema = typeof GlobalTextureSchema
|
||||
export type GlobalTextureValues = Values<GlobalTextureSchema>
|
||||
@@ -229,7 +223,6 @@ export const OverpaintSchema = {
|
||||
uOverpaintGridTransform: UniformSpec('v4'),
|
||||
tOverpaintGrid: TextureSpec('texture', 'rgba', 'ubyte', 'linear'),
|
||||
dOverpaintType: DefineSpec('string', ['instance', 'groupInstance', 'volumeInstance']),
|
||||
uOverpaintStrength: UniformSpec('f', 'material'),
|
||||
} as const;
|
||||
export type OverpaintSchema = typeof OverpaintSchema
|
||||
export type OverpaintValues = Values<OverpaintSchema>
|
||||
@@ -244,7 +237,6 @@ export const TransparencySchema = {
|
||||
uTransparencyGridTransform: UniformSpec('v4'),
|
||||
tTransparencyGrid: TextureSpec('texture', 'alpha', 'ubyte', 'linear'),
|
||||
dTransparencyType: DefineSpec('string', ['instance', 'groupInstance', 'volumeInstance']),
|
||||
uTransparencyStrength: UniformSpec('f', 'material'),
|
||||
} as const;
|
||||
export type TransparencySchema = typeof TransparencySchema
|
||||
export type TransparencyValues = Values<TransparencySchema>
|
||||
@@ -258,7 +250,6 @@ export const SubstanceSchema = {
|
||||
uSubstanceGridTransform: UniformSpec('v4'),
|
||||
tSubstanceGrid: TextureSpec('texture', 'rgba', 'ubyte', 'linear'),
|
||||
dSubstanceType: DefineSpec('string', ['instance', 'groupInstance', 'volumeInstance']),
|
||||
uSubstanceStrength: UniformSpec('f', 'material'),
|
||||
} as const;
|
||||
export type SubstanceSchema = typeof SubstanceSchema
|
||||
export type SubstanceValues = Values<SubstanceSchema>
|
||||
@@ -336,4 +327,4 @@ export const BaseSchema = {
|
||||
invariantBoundingSphere: ValueSpec('sphere'),
|
||||
} as const;
|
||||
export type BaseSchema = typeof BaseSchema
|
||||
export type BaseValues = Values<BaseSchema>
|
||||
export type BaseValues = Values<BaseSchema>
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -8,7 +8,6 @@ import { Sphere3D } from '../../mol-math/geometry';
|
||||
import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
|
||||
import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper';
|
||||
import { TextureFilter } from '../webgl/texture';
|
||||
import { arrayMinMax } from '../../mol-util/array';
|
||||
|
||||
export function calculateTextureInfo(n: number, itemSize: number) {
|
||||
n = Math.max(n, 2); // observed issues with 1 pixel textures
|
||||
@@ -43,8 +42,7 @@ export function createTextureImage<T extends Uint8Array | Float32Array>(n: numbe
|
||||
const DefaultPrintImageOptions = {
|
||||
scale: 1,
|
||||
pixelated: false,
|
||||
id: 'molstar.debug.image',
|
||||
normalize: false,
|
||||
id: 'molstar.debug.image'
|
||||
};
|
||||
export type PrintImageOptions = typeof DefaultPrintImageOptions
|
||||
|
||||
@@ -60,17 +58,7 @@ export function printTextureImage(textureImage: TextureImage<any>, options: Part
|
||||
}
|
||||
}
|
||||
} else if (itemSize === 4) {
|
||||
if (options.normalize) {
|
||||
const [min, max] = arrayMinMax(array);
|
||||
for (let i = 0, il = width * height * 4; i < il; i += 4) {
|
||||
data[i] = ((array[i] - min) / (max - min)) * 255;
|
||||
data[i + 1] = ((array[i + 1] - min) / (max - min)) * 255;
|
||||
data[i + 2] = ((array[i + 2] - min) / (max - min)) * 255;
|
||||
data[i + 3] = 255;
|
||||
}
|
||||
} else {
|
||||
data.set(array);
|
||||
}
|
||||
data.set(array);
|
||||
} else {
|
||||
console.warn(`itemSize '${itemSize}' not supported`);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { Viewport } from '../mol-canvas3d/camera/util';
|
||||
@@ -54,7 +53,6 @@ export const enum MarkingType {
|
||||
interface Renderer {
|
||||
readonly stats: RendererStats
|
||||
readonly props: Readonly<RendererProps>
|
||||
readonly light: Readonly<Light>
|
||||
|
||||
clear: (toBackgroundColor: boolean, ignoreTransparentBackground?: boolean) => void
|
||||
clearDepth: (packed?: boolean) => void
|
||||
@@ -72,9 +70,6 @@ interface Renderer {
|
||||
renderBlendedVolume: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderWboitOpaque: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderWboitTransparent: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderDpoitOpaque: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderDpoitTransparent: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null, dpoitTextures: { depth: Texture, frontColor: Texture, backColor: Texture }) => void
|
||||
renderDpoitVolume: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
|
||||
setProps: (props: Partial<RendererProps>) => void
|
||||
setViewport: (x: number, y: number, width: number, height: number) => void
|
||||
@@ -104,13 +99,13 @@ export const RendererParams = {
|
||||
xrayEdgeFalloff: PD.Numeric(1, { min: 0.0, max: 3.0, step: 0.1 }),
|
||||
|
||||
light: PD.ObjectList({
|
||||
inclination: PD.Numeric(150, { min: 0, max: 180, step: 1 }),
|
||||
azimuth: PD.Numeric(320, { min: 0, max: 360, step: 1 }),
|
||||
inclination: PD.Numeric(180, { min: 0, max: 180, step: 1 }),
|
||||
azimuth: PD.Numeric(0, { min: 0, max: 360, step: 1 }),
|
||||
color: PD.Color(Color.fromNormalizedRgb(1.0, 1.0, 1.0)),
|
||||
intensity: PD.Numeric(0.6, { min: 0.0, max: 1.0, step: 0.01 }),
|
||||
}, o => Color.toHexString(o.color), { defaultValue: [{
|
||||
inclination: 150,
|
||||
azimuth: 320,
|
||||
inclination: 180,
|
||||
azimuth: 0,
|
||||
color: Color.fromNormalizedRgb(1.0, 1.0, 1.0),
|
||||
intensity: 0.6
|
||||
}] }),
|
||||
@@ -119,7 +114,7 @@ export const RendererParams = {
|
||||
};
|
||||
export type RendererProps = PD.Values<typeof RendererParams>
|
||||
|
||||
export type Light = {
|
||||
type Light = {
|
||||
count: number
|
||||
direction: number[]
|
||||
color: number[]
|
||||
@@ -146,7 +141,7 @@ namespace Renderer {
|
||||
const enum Flag {
|
||||
None = 0,
|
||||
BlendedFront = 1,
|
||||
BlendedBack = 2,
|
||||
BlendedBack = 2
|
||||
}
|
||||
|
||||
const enum Mask {
|
||||
@@ -273,7 +268,7 @@ namespace Renderer {
|
||||
}
|
||||
|
||||
if (r.values.dGeometryType.ref.value === 'directVolume') {
|
||||
if (variant !== 'colorDpoit' && variant !== 'colorWboit' && variant !== 'colorBlended') {
|
||||
if (variant !== 'colorWboit' && variant !== 'colorBlended') {
|
||||
return; // only color supported
|
||||
}
|
||||
|
||||
@@ -607,71 +602,6 @@ namespace Renderer {
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderWboitTransparent');
|
||||
};
|
||||
|
||||
const renderDpoitOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderDpoitOpaque');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, Mask.Opaque, false);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
|
||||
// TODO: simplify, handle in renderable.state???
|
||||
// uAlpha is updated in "render" so we need to recompute it here
|
||||
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
|
||||
if ((alpha === 1 && r.values.transparencyAverage.ref.value !== 1 && r.values.dPointStyle?.ref.value !== 'fuzzy' && !r.values.dXrayShaded?.ref.value) || r.values.dTransparentBackfaces?.ref.value === 'opaque') {
|
||||
renderObject(r, 'colorDpoit', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDpoitOpaque');
|
||||
};
|
||||
|
||||
const renderDpoitTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null, dpoitTextures: { depth: Texture, frontColor: Texture, backColor: Texture }) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderDpoitTransparent');
|
||||
|
||||
state.enable(gl.BLEND);
|
||||
|
||||
arrayMapUpsert(sharedTexturesList, 'tDpoitDepth', dpoitTextures.depth);
|
||||
arrayMapUpsert(sharedTexturesList, 'tDpoitFrontColor', dpoitTextures.frontColor);
|
||||
arrayMapUpsert(sharedTexturesList, 'tDpoitBackColor', dpoitTextures.backColor);
|
||||
|
||||
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
|
||||
|
||||
const { renderables } = group;
|
||||
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
|
||||
// TODO: simplify, handle in renderable.state???
|
||||
// uAlpha is updated in "render" so we need to recompute it here
|
||||
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
|
||||
if (alpha < 1 || r.values.transparencyAverage.ref.value > 0 || r.values.dPointStyle?.ref.value === 'fuzzy' || !!r.values.uBackgroundColor || r.values.dXrayShaded?.ref.value) {
|
||||
renderObject(r, 'colorDpoit', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDpoitTransparent');
|
||||
};
|
||||
|
||||
const renderDpoitVolume = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderDpoitVolume');
|
||||
state.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
state.enable(gl.BLEND);
|
||||
|
||||
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
if (r.values.dGeometryType.ref.value === 'directVolume') {
|
||||
renderObject(r, 'colorDpoit', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDpoitVolume');
|
||||
};
|
||||
|
||||
return {
|
||||
clear: (toBackgroundColor: boolean, ignoreTransparentBackground?: boolean) => {
|
||||
state.enable(gl.SCISSOR_TEST);
|
||||
@@ -715,9 +645,6 @@ namespace Renderer {
|
||||
renderBlendedVolume,
|
||||
renderWboitOpaque,
|
||||
renderWboitTransparent,
|
||||
renderDpoitOpaque,
|
||||
renderDpoitTransparent,
|
||||
renderDpoitVolume,
|
||||
|
||||
setProps: (props: Partial<RendererProps>) => {
|
||||
if (props.backgroundColor !== undefined && props.backgroundColor !== p.backgroundColor) {
|
||||
@@ -828,9 +755,6 @@ namespace Renderer {
|
||||
instancedDrawCount: stats.instancedDrawCount,
|
||||
};
|
||||
},
|
||||
get light(): Light {
|
||||
return light;
|
||||
},
|
||||
dispose: () => {
|
||||
// TODO
|
||||
}
|
||||
@@ -838,4 +762,4 @@ namespace Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
export { Renderer };
|
||||
export { Renderer };
|
||||
@@ -45,8 +45,8 @@ function calculateBoundingSphere(renderables: GraphicsRenderable[], boundingSphe
|
||||
}
|
||||
|
||||
function renderableSort(a: GraphicsRenderable, b: GraphicsRenderable) {
|
||||
const drawProgramIdA = (a.getProgram('colorBlended') || a.getProgram('colorWboit') || a.getProgram('colorDpoit')).id;
|
||||
const drawProgramIdB = (b.getProgram('colorBlended') || b.getProgram('colorWboit') || b.getProgram('colorDpoit')).id;
|
||||
const drawProgramIdA = (a.getProgram('colorBlended') || a.getProgram('colorWboit')).id;
|
||||
const drawProgramIdB = (b.getProgram('colorBlended') || a.getProgram('colorWboit')).id;
|
||||
const materialIdA = a.materialId;
|
||||
const materialIdB = b.materialId;
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ import { texture3d_from_1d_trilinear } from './shader/chunks/texture3d-from-1d-t
|
||||
import { texture3d_from_2d_linear } from './shader/chunks/texture3d-from-2d-linear.glsl';
|
||||
import { texture3d_from_2d_nearest } from './shader/chunks/texture3d-from-2d-nearest.glsl';
|
||||
import { wboit_write } from './shader/chunks/wboit-write.glsl';
|
||||
import { dpoit_write } from './shader/chunks/dpoit-write.glsl';
|
||||
|
||||
const ShaderChunks: { [k: string]: string } = {
|
||||
apply_fog,
|
||||
@@ -100,8 +99,7 @@ const ShaderChunks: { [k: string]: string } = {
|
||||
texture3d_from_1d_trilinear,
|
||||
texture3d_from_2d_linear,
|
||||
texture3d_from_2d_nearest,
|
||||
wboit_write,
|
||||
dpoit_write
|
||||
wboit_write
|
||||
};
|
||||
|
||||
const reInclude = /^(?!\/\/)\s*#include\s+(\S+)/gm;
|
||||
|
||||
@@ -6,7 +6,6 @@ precision mediump sampler2D;
|
||||
#if defined(dVariant_skybox)
|
||||
uniform samplerCube tSkybox;
|
||||
uniform mat4 uViewDirectionProjectionInverse;
|
||||
uniform float uBlur;
|
||||
uniform float uOpacity;
|
||||
uniform float uSaturation;
|
||||
uniform float uLightness;
|
||||
@@ -50,11 +49,7 @@ vec3 lightenColor(vec3 c, float amount) {
|
||||
void main() {
|
||||
#if defined(dVariant_skybox)
|
||||
vec4 t = uViewDirectionProjectionInverse * vPosition;
|
||||
#ifdef enabledShaderTextureLod
|
||||
gl_FragColor = textureCubeLodEXT(tSkybox, normalize(t.xyz / t.w), uBlur * 8.0);
|
||||
#else
|
||||
gl_FragColor = textureCube(tSkybox, normalize(t.xyz / t.w));
|
||||
#endif
|
||||
gl_FragColor = textureCube(tSkybox, normalize(t.xyz / t.w));
|
||||
gl_FragColor.a = uOpacity;
|
||||
gl_FragColor.rgb = lightenColor(saturateColor(gl_FragColor.rgb, uSaturation), uLightness);
|
||||
#elif defined(dVariant_image)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
export const blendBackDpoit_frag = `
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D tDpoitBackColor;
|
||||
uniform vec2 uTexSize;
|
||||
|
||||
void main() {
|
||||
vec2 coords = gl_FragCoord.xy / uTexSize;
|
||||
gl_FragColor = texture2D(tDpoitBackColor, coords);
|
||||
if (gl_FragColor.a == 0.0) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -12,19 +12,8 @@ if (!uTransparentBackground) {
|
||||
gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor);
|
||||
}
|
||||
} else {
|
||||
#if defined(dRenderVariant_colorDpoit)
|
||||
if (gl_FragColor.a < 1.0) {
|
||||
// transparent objects are blended with background color
|
||||
gl_FragColor.a = fogAlpha;
|
||||
} else {
|
||||
// opaque objects need to be pre-multiplied alpha
|
||||
gl_FragColor.rgb *= fogAlpha;
|
||||
gl_FragColor.a = fogAlpha;
|
||||
}
|
||||
#else
|
||||
// pre-multiplied alpha expected for transparent background
|
||||
gl_FragColor.rgb *= fogAlpha;
|
||||
gl_FragColor.a = fogAlpha;
|
||||
#endif
|
||||
// pre-multiplied alpha expected for transparent background
|
||||
gl_FragColor.rgb *= fogAlpha;
|
||||
gl_FragColor.a = fogAlpha;
|
||||
}
|
||||
`;
|
||||
@@ -12,7 +12,7 @@ export const apply_light_color = `
|
||||
gl_FragColor = material;
|
||||
#else
|
||||
#ifdef bumpEnabled
|
||||
if (uBumpFrequency > 0.0 && uBumpAmplitude > 0.0 && bumpiness > 0.0) {
|
||||
if (uBumpFrequency > 0.0 && uBumpAmplitude > 0.0) {
|
||||
normal = perturbNormal(-vViewPosition, normal, fbm(vModelPosition * uBumpFrequency), (uBumpAmplitude * bumpiness) / uBumpFrequency);
|
||||
}
|
||||
#endif
|
||||
@@ -57,7 +57,6 @@ export const apply_light_color = `
|
||||
RE_IndirectSpecular_Physical(radiance, iblIrradiance, clearcoatRadiance, geometry, physicalMaterial, reflectedLight);
|
||||
|
||||
vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;
|
||||
outgoingLight = clamp(outgoingLight, 0.01, 0.99); // prevents black artifacts on specular highlight with transparent background
|
||||
|
||||
gl_FragColor = vec4(outgoingLight, color.a);
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,6 @@ export const assign_color_varying = `
|
||||
#else
|
||||
vOverpaint.rgb = mix(vColor.rgb, vOverpaint.rgb, vOverpaint.a);
|
||||
#endif
|
||||
vOverpaint *= uOverpaintStrength;
|
||||
#endif
|
||||
|
||||
#ifdef dSubstance
|
||||
@@ -59,7 +58,6 @@ export const assign_color_varying = `
|
||||
|
||||
// pre-mix to avoid artifacts due to empty substance
|
||||
vSubstance.rgb = mix(vec3(uMetalness, uRoughness, uBumpiness), vSubstance.rgb, vSubstance.a);
|
||||
vSubstance *= uSubstanceStrength;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
#ifdef requiredDrawBuffers
|
||||
@@ -88,6 +86,5 @@ export const assign_color_varying = `
|
||||
vec3 tgridPos = (uTransparencyGridTransform.w * (vModelPosition - uTransparencyGridTransform.xyz)) / uTransparencyGridDim;
|
||||
vTransparency = texture3dFrom2dLinear(tTransparencyGrid, tgridPos, uTransparencyGridDim, uTransparencyTexDim).a;
|
||||
#endif
|
||||
vTransparency *= uTransparencyStrength;
|
||||
#endif
|
||||
`;
|
||||
@@ -86,7 +86,7 @@ export const assign_material_color = `
|
||||
// apply per-group transparency
|
||||
#if defined(dTransparency) && (defined(dRenderVariant_pick) || defined(dRenderVariant_color))
|
||||
float ta = 1.0 - vTransparency;
|
||||
if (vTransparency < 0.09) ta = 1.0; // hard cutoff looks better
|
||||
if (vTransparency < 0.2) ta = 1.0; // hard cutoff looks better
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
if (ta < uPickingAlphaThreshold)
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
export const clip_instance = `
|
||||
#if defined(dClipVariant_instance) && dClipObjectCount != 0
|
||||
int flag = 0;
|
||||
#if defined(dClipping)
|
||||
flag = int(floor(vClipping * 255.0 + 0.5));
|
||||
#endif
|
||||
|
||||
vec4 mCenter = uModel * aTransform * vec4(uInvariantBoundingSphere.xyz, 1.0);
|
||||
if (clipTest(vec4(mCenter.xyz, uInvariantBoundingSphere.w)))
|
||||
if (clipTest(vec4(mCenter.xyz, uInvariantBoundingSphere.w), flag))
|
||||
// move out of [ -w, +w ] to 'discard' in vert shader
|
||||
gl_Position.z = 2.0 * gl_Position.w;
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
export const clip_pixel = `
|
||||
#if defined(dClipVariant_pixel) && dClipObjectCount != 0
|
||||
if (clipTest(vec4(vModelPosition, 0.0)))
|
||||
#if defined(dClipping)
|
||||
int clippingFlag = int(floor(vClipping * 255.0 + 0.5));
|
||||
#else
|
||||
int clippingFlag = 0;
|
||||
#endif
|
||||
|
||||
if (clipTest(vec4(vModelPosition, 0.0), clippingFlag))
|
||||
discard;
|
||||
#endif
|
||||
`;
|
||||
@@ -39,7 +39,6 @@ uniform float uBumpiness;
|
||||
uniform vec4 uOverpaintGridTransform;
|
||||
uniform sampler2D tOverpaintGrid;
|
||||
#endif
|
||||
uniform float uOverpaintStrength;
|
||||
#endif
|
||||
|
||||
#ifdef dSubstance
|
||||
@@ -54,7 +53,6 @@ uniform float uBumpiness;
|
||||
uniform vec4 uSubstanceGridTransform;
|
||||
uniform sampler2D tSubstanceGrid;
|
||||
#endif
|
||||
uniform float uSubstanceStrength;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
#if __VERSION__ == 100 || !defined(dVaryingGroup)
|
||||
@@ -88,6 +86,5 @@ uniform float uBumpiness;
|
||||
uniform vec4 uTransparencyGridTransform;
|
||||
uniform sampler2D tTransparencyGrid;
|
||||
#endif
|
||||
uniform float uTransparencyStrength;
|
||||
#endif
|
||||
`;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Ludovic Autin <autin@scripps.edu>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
@@ -7,45 +7,45 @@
|
||||
|
||||
export const common_clip = `
|
||||
#if dClipObjectCount != 0
|
||||
vec3 quaternionTransform(const in vec4 q, const in vec3 v) {
|
||||
vec3 quaternionTransform(vec4 q, vec3 v) {
|
||||
vec3 t = 2.0 * cross(q.xyz, v);
|
||||
return v + q.w * t + cross(q.xyz, t);
|
||||
}
|
||||
|
||||
vec4 computePlane(const in vec3 normal, const in vec3 inPoint) {
|
||||
vec4 computePlane(vec3 normal, vec3 inPoint) {
|
||||
return vec4(normalize(normal), -dot(normal, inPoint));
|
||||
}
|
||||
|
||||
float planeSD(const in vec4 plane, const in vec3 center) {
|
||||
float planeSD(vec4 plane, vec3 center) {
|
||||
return -dot(plane.xyz, center - plane.xyz * -plane.w);
|
||||
}
|
||||
|
||||
float sphereSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
|
||||
float sphereSD(vec3 position, vec4 rotation, vec3 size, vec3 center) {
|
||||
return (
|
||||
length(quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position) / size) - 1.0
|
||||
) * min(min(size.x, size.y), size.z);
|
||||
}
|
||||
|
||||
float cubeSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
|
||||
float cubeSD(vec3 position, vec4 rotation, vec3 size, vec3 center) {
|
||||
vec3 d = abs(quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position)) - size;
|
||||
return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));
|
||||
}
|
||||
|
||||
float cylinderSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
|
||||
float cylinderSD(vec3 position, vec4 rotation, vec3 size, vec3 center) {
|
||||
vec3 t = quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position);
|
||||
|
||||
vec2 d = abs(vec2(length(t.xz), t.y)) - size.xy;
|
||||
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
|
||||
}
|
||||
|
||||
float infiniteConeSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
|
||||
float infiniteConeSD(vec3 position, vec4 rotation, vec3 size, vec3 center) {
|
||||
vec3 t = quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position);
|
||||
|
||||
float q = length(t.xy);
|
||||
return dot(size.xy, vec2(q, t.z));
|
||||
}
|
||||
|
||||
float getSignedDistance(const in vec3 center, const in int type, const in vec3 position, const in vec4 rotation, const in vec3 scale) {
|
||||
float getSignedDistance(vec3 center, int type, vec3 position, vec4 rotation, vec3 scale) {
|
||||
if (type == 1) {
|
||||
vec3 normal = quaternionTransform(rotation, vec3(0.0, 1.0, 0.0));
|
||||
vec4 plane = computePlane(normal, position);
|
||||
@@ -65,7 +65,7 @@ export const common_clip = `
|
||||
|
||||
#if __VERSION__ == 100
|
||||
// 8-bit
|
||||
int bitwiseAnd(const in int a, const in int b) {
|
||||
int bitwiseAnd(int a, int b) {
|
||||
int d = 128;
|
||||
int result = 0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
@@ -78,23 +78,17 @@ export const common_clip = `
|
||||
return result;
|
||||
}
|
||||
|
||||
bool hasBit(const in int mask, const in int bit) {
|
||||
bool hasBit(int mask, int bit) {
|
||||
return bitwiseAnd(mask, bit) == 0;
|
||||
}
|
||||
#else
|
||||
bool hasBit(const in int mask, const in int bit) {
|
||||
bool hasBit(int mask, int bit) {
|
||||
return (mask & bit) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool clipTest(const in vec4 sphere) {
|
||||
// flag is a bit-flag for clip-objects to ignore (note, object ids start at 1 not 0)
|
||||
#if defined(dClipping)
|
||||
int flag = int(floor(vClipping * 255.0 + 0.5));
|
||||
#else
|
||||
int flag = 0;
|
||||
#endif
|
||||
|
||||
// flag is a bit-flag for clip-objects to ignore (note, object ids start at 1 not 0)
|
||||
bool clipTest(vec4 sphere, int flag) {
|
||||
#pragma unroll_loop_start
|
||||
for (int i = 0; i < dClipObjectCount; ++i) {
|
||||
if (flag == 0 || hasBit(flag, UNROLLED_LOOP_INDEX + 1)) {
|
||||
|
||||
@@ -39,12 +39,6 @@ uniform int uMarkingType;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(dRenderVariant_colorDpoit)
|
||||
#define MAX_DPOIT_DEPTH 99999.0 // NOTE constant also set in TypeScript
|
||||
uniform sampler2D tDpoitDepth;
|
||||
uniform sampler2D tDpoitFrontColor;
|
||||
#endif
|
||||
|
||||
varying vec3 vModelPosition;
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
|
||||
@@ -44,9 +44,10 @@ varying vec3 vModelPosition;
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
#if defined(noNonInstancedActiveAttribs)
|
||||
// int() is needed for some Safari versions
|
||||
// see https://bugs.webkit.org/show_bug.cgi?id=244152
|
||||
#define VertexID int(gl_VertexID)
|
||||
#define VertexID gl_VertexID // for testing
|
||||
// // int() is needed for some Safari versions
|
||||
// // see https://bugs.webkit.org/show_bug.cgi?id=244152
|
||||
// #define VertexID int(gl_VertexID)
|
||||
#else
|
||||
attribute float aVertex;
|
||||
#define VertexID int(aVertex)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const common = `
|
||||
// TODO find a better place for these convenience defines
|
||||
|
||||
#if defined(dRenderVariant_colorBlended) || defined(dRenderVariant_colorWboit) || defined(dRenderVariant_colorDpoit)
|
||||
#if defined(dRenderVariant_colorBlended) || defined(dRenderVariant_colorWboit)
|
||||
#define dRenderVariant_color
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
export const dpoit_write = `
|
||||
#if defined(dRenderVariant_colorDpoit)
|
||||
if (uRenderMask == MaskOpaque) {
|
||||
if (preFogAlpha < 1.0) {
|
||||
discard;
|
||||
}
|
||||
} else if (uRenderMask == MaskTransparent) {
|
||||
// the 'fragmentDepth > 0.99' check is to handle precision issues with packed depth
|
||||
vec2 coords = gl_FragCoord.xy / uDrawingBufferSize;
|
||||
if (preFogAlpha != 1.0 && (fragmentDepth < getDepth(coords) || fragmentDepth > 0.99)) {
|
||||
#ifdef dTransparentBackfaces_off
|
||||
if (interior) discard;
|
||||
#endif
|
||||
|
||||
// adapted from https://github.com/tsherif/webgl2examples
|
||||
// The MIT License, Copyright 2017 Tarek Sherif, Shuai Shao
|
||||
|
||||
vec2 lastDepth = texture2D(tDpoitDepth, coords).rg;
|
||||
vec4 lastFrontColor = texture2D(tDpoitFrontColor, coords);
|
||||
|
||||
vec4 fragColor = gl_FragColor;
|
||||
|
||||
// depth value always increases
|
||||
// so we can use MAX blend equation
|
||||
gl_FragData[2].rg = vec2(-MAX_DPOIT_DEPTH);
|
||||
|
||||
// front color always increases
|
||||
// so we can use MAX blend equation
|
||||
gl_FragColor = lastFrontColor;
|
||||
|
||||
// back color is separately blend afterwards each pass
|
||||
gl_FragData[1] = vec4(0.0);
|
||||
|
||||
float nearestDepth = -lastDepth.x;
|
||||
float furthestDepth = lastDepth.y;
|
||||
float alphaMultiplier = 1.0 - lastFrontColor.a;
|
||||
|
||||
if (fragmentDepth < nearestDepth || fragmentDepth > furthestDepth) {
|
||||
// Skip this depth since it's been peeled.
|
||||
return;
|
||||
}
|
||||
|
||||
if (fragmentDepth > nearestDepth && fragmentDepth < furthestDepth) {
|
||||
// This needs to be peeled.
|
||||
// The ones remaining after MAX blended for
|
||||
// all need-to-peel will be peeled next pass.
|
||||
gl_FragData[2].rg = vec2(-fragmentDepth, fragmentDepth);
|
||||
return;
|
||||
}
|
||||
|
||||
// write to back and front color buffer
|
||||
if (fragmentDepth == nearestDepth) {
|
||||
gl_FragColor.rgb += fragColor.rgb * fragColor.a * alphaMultiplier;
|
||||
gl_FragColor.a = 1.0 - alphaMultiplier * (1.0 - fragColor.a);
|
||||
} else {
|
||||
gl_FragData[1] += fragColor;
|
||||
}
|
||||
|
||||
} else {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
`;
|
||||
@@ -33,8 +33,7 @@ uniform mat4 uInvView;
|
||||
bool CylinderImpostor(
|
||||
in vec3 rayOrigin, in vec3 rayDir,
|
||||
in vec3 start, in vec3 end, in float radius,
|
||||
out vec3 cameraNormal, out bool interior,
|
||||
out vec3 modelPosition, out vec3 viewPosition, out float fragmentDepth
|
||||
out vec4 intersection, out bool interior
|
||||
){
|
||||
vec3 ba = end - start;
|
||||
vec3 oc = rayOrigin - start;
|
||||
@@ -43,7 +42,7 @@ bool CylinderImpostor(
|
||||
float bard = dot(ba, rayDir);
|
||||
float baoc = dot(ba, oc);
|
||||
|
||||
float k2 = baba - bard * bard;
|
||||
float k2 = baba - bard*bard;
|
||||
float k1 = baba * dot(oc, rayDir) - baoc * bard;
|
||||
float k0 = baba * dot(oc, oc) - baoc * baoc - radius * radius * baba;
|
||||
|
||||
@@ -59,14 +58,8 @@ bool CylinderImpostor(
|
||||
float y = baoc + t * bard;
|
||||
if (y > 0.0 && y < baba) {
|
||||
interior = false;
|
||||
cameraNormal = (oc + t * rayDir - ba * y / baba) / radius;
|
||||
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))) fragmentDepth = -1.0;
|
||||
#endif
|
||||
if (fragmentDepth > 0.0) return true;
|
||||
intersection = vec4(t, (oc + t * rayDir - ba * y / baba) / radius);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (topCap && y < 0.0) {
|
||||
@@ -74,22 +67,16 @@ bool CylinderImpostor(
|
||||
t = -baoc / bard;
|
||||
if (abs(k1 + k2 * t) < h) {
|
||||
interior = false;
|
||||
cameraNormal = -ba / baba;
|
||||
modelPosition = rayOrigin + t * rayDir;
|
||||
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
|
||||
fragmentDepth = calcDepth(viewPosition);
|
||||
if (fragmentDepth > 0.0) return true;
|
||||
intersection = vec4(t, ba * sign(y) / baba);
|
||||
return true;
|
||||
}
|
||||
} else if(bottomCap && y >= 0.0) {
|
||||
// bottom cap
|
||||
t = (baba - baoc) / bard;
|
||||
if (abs(k1 + k2 * t) < h) {
|
||||
interior = false;
|
||||
cameraNormal = ba / baba;
|
||||
modelPosition = rayOrigin + t * rayDir;
|
||||
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
|
||||
fragmentDepth = calcDepth(viewPosition);
|
||||
if (fragmentDepth > 0.0) return true;
|
||||
intersection = vec4(t, ba * sign(y) / baba);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,61 +87,36 @@ bool CylinderImpostor(
|
||||
y = baoc + t * bard;
|
||||
if (y > 0.0 && y < baba) {
|
||||
interior = true;
|
||||
cameraNormal = -(oc + t * rayDir - ba * y / baba) / radius;
|
||||
modelPosition = rayOrigin + t * rayDir;
|
||||
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
|
||||
fragmentDepth = calcDepth(viewPosition);
|
||||
intersection = vec4(t, (oc + t * rayDir - ba * y / baba) / radius);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (topCap && y < 0.0) {
|
||||
// top cap
|
||||
t = -baoc / bard;
|
||||
if (abs(k1 + k2 * t) < -h) {
|
||||
interior = true;
|
||||
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 = true;
|
||||
cameraNormal = -ba / baba;
|
||||
modelPosition = rayOrigin + t * rayDir;
|
||||
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
|
||||
fragmentDepth = calcDepth(viewPosition);
|
||||
if (fragmentDepth > 0.0) return true;
|
||||
}
|
||||
}
|
||||
// TODO: handle inside caps???
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 rayOrigin = vModelPosition;
|
||||
#include clip_pixel
|
||||
|
||||
vec3 rayDir = mix(normalize(vModelPosition - uCameraPosition), uCameraDir, uIsOrtho);
|
||||
|
||||
vec3 cameraNormal;
|
||||
vec3 modelPosition;
|
||||
vec3 viewPosition;
|
||||
float fragmentDepth;
|
||||
bool hit = CylinderImpostor(rayOrigin, rayDir, vStart, vEnd, vSize, cameraNormal, interior, modelPosition, viewPosition, fragmentDepth);
|
||||
vec4 intersection;
|
||||
bool interior;
|
||||
bool hit = CylinderImpostor(vModelPosition, rayDir, vStart, vEnd, vSize, intersection, interior);
|
||||
if (!hit) discard;
|
||||
|
||||
if (fragmentDepth < 0.0) discard;
|
||||
if (fragmentDepth > 1.0) discard;
|
||||
vec3 vViewPosition = vModelPosition + intersection.x * rayDir;
|
||||
vViewPosition = (uView * vec4(vViewPosition, 1.0)).xyz;
|
||||
gl_FragDepthEXT = calcDepth(vViewPosition);
|
||||
|
||||
gl_FragDepthEXT = fragmentDepth;
|
||||
vec3 vModelPosition = (uInvView * vec4(vViewPosition, 1.0)).xyz;
|
||||
|
||||
vec3 vViewPosition = viewPosition;
|
||||
vec3 vModelPosition = modelPosition;
|
||||
if (gl_FragDepthEXT < 0.0) discard;
|
||||
if (gl_FragDepthEXT > 1.0) discard;
|
||||
|
||||
#include clip_pixel
|
||||
float fragmentDepth = gl_FragDepthEXT;
|
||||
#include assign_material_color
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
@@ -173,14 +135,13 @@ void main() {
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_color)
|
||||
mat3 normalMatrix = transpose3(inverse3(mat3(uView)));
|
||||
vec3 normal = normalize(normalMatrix * -normalize(cameraNormal));
|
||||
vec3 normal = normalize(normalMatrix * -normalize(intersection.yzw));
|
||||
#include apply_light_color
|
||||
|
||||
#include apply_interior_color
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
#include dpoit_write
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -55,12 +55,7 @@ void main() {
|
||||
vec3 camDir = -mix(normalize(vModelPosition - uCameraPosition), uCameraDir, uIsOrtho);
|
||||
vec3 dir = vEnd - vStart;
|
||||
// ensure cylinder 'dir' is pointing towards the camera
|
||||
if(dot(camDir, dir) < 0.0) {
|
||||
dir = -dir;
|
||||
vec3 tmp = vStart;
|
||||
vStart = vEnd;
|
||||
vEnd = tmp;
|
||||
}
|
||||
if(dot(camDir, dir) < 0.0) dir = -dir;
|
||||
|
||||
vec3 left = cross(camDir, dir);
|
||||
vec3 up = cross(left, dir);
|
||||
@@ -74,9 +69,6 @@ void main() {
|
||||
vViewPosition = mvPosition.xyz;
|
||||
gl_Position = uProjection * mvPosition;
|
||||
|
||||
mvPosition.z -= 2.0 * (length(vEnd - vStart) + vSize); // avoid clipping
|
||||
gl_Position.z = (uProjection * mvPosition).z;
|
||||
|
||||
#include clip_instance
|
||||
}
|
||||
`;
|
||||
@@ -229,7 +229,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
|
||||
#if defined(dClipVariant_pixel) && dClipObjectCount != 0
|
||||
vec3 vModelPosition = v3m4(unitPos * uGridDim, modelTransform);
|
||||
if (clipTest(vec4(vModelPosition, 0.0))) {
|
||||
if (clipTest(vec4(vModelPosition, 0.0), 0)) {
|
||||
prevValue = value;
|
||||
pos += step;
|
||||
continue;
|
||||
@@ -270,16 +270,16 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
#elif defined(dColorType_groupInstance)
|
||||
material.rgb = readFromTexture(tColor, vInstance * float(uGroupCount) + group, uColorTexDim).rgb;
|
||||
#elif defined(dColorType_vertex)
|
||||
material.rgb = texture3dFrom1dTrilinear(tColor, unitPos, uGridDim, uColorTexDim, 0.0).rgb;
|
||||
material.rgb = texture3dFrom1dTrilinear(tColor, isoPos, uGridDim, uColorTexDim, 0.0).rgb;
|
||||
#elif defined(dColorType_vertexInstance)
|
||||
material.rgb = texture3dFrom1dTrilinear(tColor, unitPos, uGridDim, uColorTexDim, vInstance * float(uVertexCount)).rgb;
|
||||
material.rgb = texture3dFrom1dTrilinear(tColor, isoPos, uGridDim, uColorTexDim, vInstance * float(uVertexCount)).rgb;
|
||||
#endif
|
||||
|
||||
#ifdef dOverpaint
|
||||
#if defined(dOverpaintType_groupInstance)
|
||||
overpaint = readFromTexture(tOverpaint, vInstance * float(uGroupCount) + group, uOverpaintTexDim);
|
||||
#elif defined(dOverpaintType_vertexInstance)
|
||||
overpaint = texture3dFrom1dTrilinear(tOverpaint, unitPos, uGridDim, uOverpaintTexDim, vInstance * float(uVertexCount));
|
||||
overpaint = texture3dFrom1dTrilinear(tOverpaint, isoPos, uGridDim, uOverpaintTexDim, vInstance * float(uVertexCount));
|
||||
#endif
|
||||
|
||||
material.rgb = mix(material.rgb, overpaint.rgb, overpaint.a);
|
||||
@@ -356,4 +356,4 @@ void main() {
|
||||
float preFogAlpha = clamp(preFogAlphaBlended, 0.0, 1.0);
|
||||
#include wboit_write
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
export const evaluateDpoit_frag = `
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D tDpoitFrontColor;
|
||||
uniform vec2 uTexSize;
|
||||
|
||||
void main() {
|
||||
vec2 coords = gl_FragCoord.xy / uTexSize;
|
||||
gl_FragColor = texture2D(tDpoitFrontColor, coords);
|
||||
}
|
||||
`;
|
||||
@@ -159,7 +159,6 @@ void main() {
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
#include dpoit_write
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -39,7 +39,6 @@ void main(){
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
#include dpoit_write
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -62,7 +62,6 @@ void main() {
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
#include dpoit_write
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -38,11 +38,7 @@ float getDepthOpaque(const in vec2 coords) {
|
||||
}
|
||||
|
||||
float getDepthTransparent(const in vec2 coords) {
|
||||
#ifdef dTransparentOutline
|
||||
return unpackRGBAToDepth(texture2D(tDepthTransparent, coords));
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
return unpackRGBAToDepth(texture2D(tDepthTransparent, coords));
|
||||
}
|
||||
|
||||
bool isBackground(const in float depth) {
|
||||
|
||||
@@ -55,7 +55,6 @@ void main(){
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
#include dpoit_write
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -14,7 +14,6 @@ uniform sampler2D tSsaoDepth;
|
||||
uniform sampler2D tColor;
|
||||
uniform sampler2D tDepthOpaque;
|
||||
uniform sampler2D tDepthTransparent;
|
||||
uniform sampler2D tShadows;
|
||||
uniform sampler2D tOutlines;
|
||||
uniform vec2 uTexSize;
|
||||
|
||||
@@ -51,11 +50,7 @@ float getDepthOpaque(const in vec2 coords) {
|
||||
}
|
||||
|
||||
float getDepthTransparent(const in vec2 coords) {
|
||||
#ifdef dTransparentOutline
|
||||
return unpackRGBAToDepth(texture2D(tDepthTransparent, coords));
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
return unpackRGBAToDepth(texture2D(tDepthTransparent, coords));
|
||||
}
|
||||
|
||||
bool isBackground(const in float depth) {
|
||||
@@ -125,20 +120,7 @@ void main(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef dShadowEnable
|
||||
if (!isBackground(opaqueDepth)) {
|
||||
viewDist = abs(getViewZ(opaqueDepth));
|
||||
fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
|
||||
vec4 shadow = texture2D(tShadows, coords);
|
||||
if (!uTransparentBackground) {
|
||||
color.rgb = mix(mix(vec3(0), uFogColor, fogFactor), color.rgb, shadow.a);
|
||||
} else {
|
||||
color.rgb = mix(vec3(0) * (1.0 - fogFactor), color.rgb, shadow.a);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// outline needs to be handled after occlusion and shadow to keep them clean
|
||||
// outline needs to be handled after occlusion to keep them clean
|
||||
#ifdef dOutlineEnable
|
||||
float closestTexel;
|
||||
float outline = getOutline(coords, opaqueDepth, closestTexel);
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Ludovic Autin <ludovic.autin@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
export const shadows_frag = `
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
precision highp sampler2D;
|
||||
|
||||
#include common
|
||||
|
||||
uniform sampler2D tDepth;
|
||||
uniform vec2 uTexSize;
|
||||
uniform vec4 uBounds;
|
||||
|
||||
uniform float uNear;
|
||||
uniform float uFar;
|
||||
|
||||
#if dLightCount != 0
|
||||
uniform vec3 uLightDirection[dLightCount];
|
||||
uniform vec3 uLightColor[dLightCount];
|
||||
#endif
|
||||
|
||||
uniform mat4 uProjection;
|
||||
uniform mat4 uInvProjection;
|
||||
|
||||
uniform float uMaxDistance;
|
||||
uniform float uTolerance;
|
||||
uniform float uBias;
|
||||
|
||||
bool isBackground(const in float depth) {
|
||||
return depth == 1.0;
|
||||
}
|
||||
|
||||
bool outsideBounds(const in vec2 p) {
|
||||
return p.x < uBounds.x || p.y < uBounds.y || p.x > uBounds.z || p.y > uBounds.w;
|
||||
}
|
||||
|
||||
float getViewZ(const in float depth) {
|
||||
#if dOrthographic == 1
|
||||
return orthographicDepthToViewZ(depth, uNear, uFar);
|
||||
#else
|
||||
return perspectiveDepthToViewZ(depth, uNear, uFar);
|
||||
#endif
|
||||
}
|
||||
|
||||
float getDepth(const in vec2 coords) {
|
||||
#ifdef depthTextureSupport
|
||||
return texture2D(tDepth, coords).r;
|
||||
#else
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
#endif
|
||||
}
|
||||
|
||||
float screenFade(const in vec2 coords) {
|
||||
vec2 c = (coords - uBounds.xy) / (uBounds.zw - uBounds.xy);
|
||||
vec2 fade = max(12.0 * abs(c - 0.5) - 5.0, vec2(0.0));
|
||||
return saturate(1.0 - dot(fade, fade));
|
||||
}
|
||||
|
||||
// based on https://panoskarabelas.com/posts/screen_space_shadows/
|
||||
float screenSpaceShadow(const in vec3 position, const in vec3 lightDirection, const in float stepLength) {
|
||||
// Ray position and direction (in view-space)
|
||||
vec3 rayPos = position;
|
||||
vec3 rayDir = -lightDirection;
|
||||
|
||||
// Compute ray step
|
||||
vec3 rayStep = rayDir * stepLength;
|
||||
|
||||
// Ray march towards the light
|
||||
float occlusion = 0.0;
|
||||
vec4 rayCoords = vec4(0.0);
|
||||
for (int i = 0; i < dSteps; ++i) {
|
||||
// Step the ray
|
||||
rayPos += rayStep;
|
||||
|
||||
rayCoords = uProjection * vec4(rayPos, 1.0);
|
||||
rayCoords.xyz = (rayCoords.xyz / rayCoords.w) * 0.5 + 0.5;
|
||||
|
||||
if (outsideBounds(rayCoords.xy))
|
||||
return 1.0;
|
||||
|
||||
// Compute the difference between the ray's and the camera's depth
|
||||
float depth = getDepth(rayCoords.xy);
|
||||
float viewZ = getViewZ(depth);
|
||||
float zDelta = rayPos.z - viewZ;
|
||||
|
||||
if (zDelta < uTolerance) {
|
||||
occlusion = 1.0;
|
||||
|
||||
// Fade out as we approach the edges of the screen
|
||||
occlusion *= screenFade(rayCoords.xy);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0 - (uBias * occlusion);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec2 invTexSize = 1.0 / uTexSize;
|
||||
vec2 selfCoords = gl_FragCoord.xy * invTexSize;
|
||||
|
||||
float selfDepth = getDepth(selfCoords);
|
||||
|
||||
if (isBackground(selfDepth)) {
|
||||
gl_FragColor = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 selfViewPos = screenSpaceToViewSpace(vec3(selfCoords, selfDepth), uInvProjection);
|
||||
float stepLength = uMaxDistance / float(dSteps);
|
||||
|
||||
float o = 1.0;
|
||||
#if dLightCount != 0
|
||||
float sh[dLightCount];
|
||||
#pragma unroll_loop_start
|
||||
for (int i = 0; i < dLightCount; ++i) {
|
||||
sh[i] = screenSpaceShadow(selfViewPos, uLightDirection[i], stepLength);
|
||||
o = min(o, sh[i]);
|
||||
}
|
||||
#pragma unroll_loop_end
|
||||
#endif
|
||||
|
||||
gl_FragColor = vec4(o);
|
||||
}
|
||||
`;
|
||||
@@ -23,8 +23,12 @@ 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){
|
||||
vec3 cameraPos;
|
||||
vec3 cameraNormal;
|
||||
|
||||
bool Impostor(out vec3 cameraPos, out vec3 cameraNormal){
|
||||
vec3 cameraSpherePos = -vPointViewPosition;
|
||||
cameraSpherePos.z += vRadius;
|
||||
|
||||
vec3 rayOrigin = mix(vec3(0.0, 0.0, 0.0), vPoint, uIsOrtho);
|
||||
vec3 rayDirection = mix(normalize(vPoint), vec3(0.0, 0.0, 1.0), uIsOrtho);
|
||||
@@ -33,61 +37,50 @@ bool SphereImpostor(out vec3 modelPos, out vec3 cameraPos, out vec3 cameraNormal
|
||||
float B = dot(rayDirection, cameraSphereDir);
|
||||
float det = B * B + vRadiusSq - dot(cameraSphereDir, cameraSphereDir);
|
||||
|
||||
if (det < 0.0) return false;
|
||||
|
||||
float sqrtDet = sqrt(det);
|
||||
float posT = mix(B + sqrtDet, B - sqrtDet, uIsOrtho);
|
||||
float negT = mix(B - sqrtDet, B + sqrtDet, uIsOrtho);
|
||||
|
||||
cameraPos = rayDirection * negT + rayOrigin;
|
||||
modelPos = (uInvView * vec4(cameraPos, 1.0)).xyz;
|
||||
fragmentDepth = calcDepth(cameraPos);
|
||||
|
||||
#if defined(dClipVariant_pixel) && dClipObjectCount != 0
|
||||
if (clipTest(vec4(modelPos, 0.0))) {
|
||||
clipped = true;
|
||||
fragmentDepth = -1.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fragmentDepth > 0.0) {
|
||||
cameraNormal = normalize(cameraPos - cameraSpherePos);
|
||||
interior = false;
|
||||
return true;
|
||||
} else if (uDoubleSided) {
|
||||
cameraPos = rayDirection * posT + rayOrigin;
|
||||
modelPos = (uInvView * vec4(cameraPos, 1.0)).xyz;
|
||||
fragmentDepth = calcDepth(cameraPos);
|
||||
cameraNormal = -normalize(cameraPos - cameraSpherePos);
|
||||
interior = true;
|
||||
return true;
|
||||
if (det < 0.0){
|
||||
discard;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
float sqrtDet = sqrt(det);
|
||||
float posT = mix(B + sqrtDet, B + sqrtDet, uIsOrtho);
|
||||
float negT = mix(B - sqrtDet, sqrtDet - B, uIsOrtho);
|
||||
|
||||
cameraPos = rayDirection * negT + rayOrigin;
|
||||
|
||||
if (calcDepth(cameraPos) <= 0.0) {
|
||||
cameraPos = rayDirection * posT + rayOrigin;
|
||||
interior = true;
|
||||
} else {
|
||||
interior = false;
|
||||
}
|
||||
|
||||
cameraNormal = normalize(cameraPos - cameraSpherePos);
|
||||
cameraNormal *= float(!interior) * 2.0 - 1.0;
|
||||
|
||||
return !interior;
|
||||
}
|
||||
|
||||
void main(void){
|
||||
vec3 modelPos;
|
||||
vec3 cameraPos;
|
||||
vec3 cameraNormal;
|
||||
float fragmentDepth;
|
||||
bool clipped = false;
|
||||
bool hit = SphereImpostor(modelPos, cameraPos, cameraNormal, interior, fragmentDepth, clipped);
|
||||
if (!hit) discard;
|
||||
#include clip_pixel
|
||||
|
||||
if (fragmentDepth < 0.0) discard;
|
||||
if (fragmentDepth > 1.0) discard;
|
||||
|
||||
vec3 vViewPosition = cameraPos;
|
||||
vec3 vModelPosition = modelPos;
|
||||
|
||||
if (interior && !clipped) {
|
||||
fragmentDepth = 0.0 + (0.0000001 / vRadius);
|
||||
bool flag = Impostor(cameraPos, cameraNormal);
|
||||
if (!uDoubleSided) {
|
||||
if (interior) discard;
|
||||
}
|
||||
|
||||
gl_FragDepthEXT = fragmentDepth;
|
||||
vec3 vViewPosition = cameraPos;
|
||||
gl_FragDepthEXT = calcDepth(vViewPosition);
|
||||
if (!flag && gl_FragDepthEXT >= 0.0) {
|
||||
gl_FragDepthEXT = 0.0 + (0.0000001 / vRadius);
|
||||
}
|
||||
|
||||
#include clip_pixel
|
||||
vec3 vModelPosition = (uInvView * vec4(vViewPosition, 1.0)).xyz;
|
||||
|
||||
if (gl_FragDepthEXT < 0.0) discard;
|
||||
if (gl_FragDepthEXT > 1.0) discard;
|
||||
|
||||
float fragmentDepth = gl_FragDepthEXT;
|
||||
#include assign_material_color
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
@@ -112,7 +105,6 @@ void main(void){
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
#include dpoit_write
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -85,6 +85,7 @@ void main(void){
|
||||
|
||||
vec4 position4 = vec4(aPosition, 1.0);
|
||||
vec4 mvPosition = uModelView * aTransform * position4;
|
||||
mvPosition.z -= vRadius; // avoid clipping, added again in fragment shader
|
||||
|
||||
gl_Position = uProjection * vec4(mvPosition.xyz, 1.0);
|
||||
quadraticProjection(size, aPosition);
|
||||
@@ -96,9 +97,6 @@ void main(void){
|
||||
|
||||
vModelPosition = (uModel * aTransform * position4).xyz; // for clipping in frag shader
|
||||
|
||||
mvPosition.z -= 2.0 * vRadius; // avoid clipping
|
||||
gl_Position.z = (uProjection * vec4(mvPosition.xyz, 1.0)).z;
|
||||
|
||||
#include clip_instance
|
||||
}
|
||||
`;
|
||||
@@ -83,7 +83,6 @@ void main(){
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
#include dpoit_write
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
`;
|
||||
@@ -19,9 +19,6 @@ export function isWebGL2(gl: any): gl is WebGL2RenderingContext {
|
||||
return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/ANGLE_instanced_arrays/
|
||||
*/
|
||||
export interface COMPAT_instanced_arrays {
|
||||
drawArraysInstanced(mode: number, first: number, count: number, primcount: number): void;
|
||||
drawElementsInstanced(mode: number, count: number, type: number, offset: number, primcount: number): void;
|
||||
@@ -49,9 +46,6 @@ export function getInstancedArrays(gl: GLRenderingContext): COMPAT_instanced_arr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/OES_standard_derivatives/
|
||||
*/
|
||||
export interface COMPAT_standard_derivatives {
|
||||
readonly FRAGMENT_SHADER_DERIVATIVE_HINT: number;
|
||||
}
|
||||
@@ -66,9 +60,6 @@ export function getStandardDerivatives(gl: GLRenderingContext): COMPAT_standard_
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/OES_element_index_uint/
|
||||
*/
|
||||
export interface COMPAT_element_index_uint {
|
||||
}
|
||||
|
||||
@@ -76,9 +67,6 @@ export function getElementIndexUint(gl: GLRenderingContext): COMPAT_element_inde
|
||||
return isWebGL2(gl) ? {} : gl.getExtension('OES_element_index_uint');
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/OES_vertex_array_object/
|
||||
*/
|
||||
export interface COMPAT_vertex_array_object {
|
||||
readonly VERTEX_ARRAY_BINDING: number;
|
||||
bindVertexArray(arrayObject: WebGLVertexArrayObject | null): void;
|
||||
@@ -144,9 +132,6 @@ export function getTextureHalfFloatLinear(gl: GLRenderingContext): COMPAT_textur
|
||||
return gl.getExtension('OES_texture_half_float_linear');
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/EXT_blend_minmax/
|
||||
*/
|
||||
export interface COMPAT_blend_minmax {
|
||||
readonly MIN: number
|
||||
readonly MAX: number
|
||||
@@ -162,9 +147,6 @@ export function getBlendMinMax(gl: GLRenderingContext): COMPAT_blend_minmax | nu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/EXT_frag_depth/
|
||||
*/
|
||||
export interface COMPAT_frag_depth {
|
||||
}
|
||||
|
||||
@@ -214,9 +196,6 @@ export function getColorBufferHalfFloat(gl: GLRenderingContext): COMPAT_color_bu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/WEBGL_draw_buffers/
|
||||
*/
|
||||
export interface COMPAT_draw_buffers {
|
||||
drawBuffers(buffers: number[]): void;
|
||||
readonly COLOR_ATTACHMENT0: number;
|
||||
@@ -289,73 +268,6 @@ export function getDrawBuffers(gl: GLRenderingContext): COMPAT_draw_buffers | nu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/OES_draw_buffers_indexed/
|
||||
*/
|
||||
export interface COMPAT_draw_buffers_indexed {
|
||||
/**
|
||||
* Enables blending for an individual draw buffer.
|
||||
*
|
||||
* @param target must be BLEND.
|
||||
* @param index is an integer i specifying the draw buffer associated with the symbolic constant DRAW_BUFFERi.
|
||||
*/
|
||||
enablei: (target: number, index: number) => void;
|
||||
/**
|
||||
* Disables blending for an individual draw buffer.
|
||||
*
|
||||
* @param target must be BLEND.
|
||||
* @param index is an integer i specifying the draw buffer associated with the symbolic constant DRAW_BUFFERi.
|
||||
*/
|
||||
disablei: (buf: number, mode: number) => void;
|
||||
/**
|
||||
* The buf argument is an integer i that indicates that the blend equations should be modified for DRAW_BUFFERi.
|
||||
*
|
||||
* mode accepts the same tokens as mode in blendEquation.
|
||||
*/
|
||||
blendEquationi: (target: number, index: number) => void;
|
||||
/**
|
||||
* The buf argument is an integer i that indicates that the blend equations should be modified for DRAW_BUFFERi.
|
||||
*
|
||||
* modeRGB and modeAlpha accept the same tokens as modeRGB and modeAlpha in blendEquationSeparate.
|
||||
*/
|
||||
blendEquationSeparatei: (buf: number, modeRGB: number, modeAlpha: number) => void;
|
||||
/**
|
||||
* The buf argument is an integer i that indicates that the blend functions should be modified for DRAW_BUFFERi.
|
||||
*
|
||||
* src and dst accept the same tokens as src and dst in blendFunc.
|
||||
*/
|
||||
blendFunci: (buf: number, src: number, dst: number) => void;
|
||||
/**
|
||||
* The buf argument is an integer i that indicates that the blend functions should be modified for DRAW_BUFFERi.
|
||||
*
|
||||
* srcRGB, dstRGB, srcAlpha, and dstAlpha accept the same tokens as srcRGB, dstRGB, srcAlpha, and dstAlpha parameters in blendEquationSeparate.
|
||||
*/
|
||||
blendFuncSeparatei: (buf: number, srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number) => void;
|
||||
/**
|
||||
* The buf argument is an integer i that indicates that the write mask should be modified for DRAW_BUFFERi.
|
||||
*
|
||||
* r, g, b, and a indicate whether R, G, B, or A values, respectively, are written or not (a value of TRUE means that the corresponding value is written).
|
||||
*/
|
||||
colorMaski: (buf: number, r: boolean, g: boolean, b: boolean, a: boolean) => void;
|
||||
}
|
||||
|
||||
export function getDrawBuffersIndexed(gl: GLRenderingContext): COMPAT_draw_buffers_indexed | null {
|
||||
const ext = gl.getExtension('OES_draw_buffers_indexed');
|
||||
if (ext === null) return null;
|
||||
return {
|
||||
enablei: ext.enableiOES.bind(ext),
|
||||
disablei: ext.disableiOES.bind(ext),
|
||||
blendEquationi: ext.blendEquationiOES.bind(ext),
|
||||
blendEquationSeparatei: ext.blendEquationSeparateiOES.bind(ext),
|
||||
blendFunci: ext.blendFunciOES.bind(ext),
|
||||
blendFuncSeparatei: ext.blendFuncSeparateiOES.bind(ext),
|
||||
colorMaski: ext.colorMaskiOES.bind(ext),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/EXT_shader_texture_lod/
|
||||
*/
|
||||
export interface COMPAT_shader_texture_lod {
|
||||
}
|
||||
|
||||
@@ -363,9 +275,6 @@ export function getShaderTextureLod(gl: GLRenderingContext): COMPAT_shader_textu
|
||||
return isWebGL2(gl) ? {} : gl.getExtension('EXT_shader_texture_lod');
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/WEBGL_depth_texture/
|
||||
*/
|
||||
export interface COMPAT_depth_texture {
|
||||
readonly UNSIGNED_INT_24_8: number;
|
||||
}
|
||||
@@ -384,9 +293,6 @@ export function getDepthTexture(gl: GLRenderingContext): COMPAT_depth_texture |
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/EXT_sRGB/
|
||||
*/
|
||||
export interface COMPAT_sRGB {
|
||||
readonly FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: number;
|
||||
readonly SRGB8_ALPHA8: number;
|
||||
@@ -414,9 +320,6 @@ export function getSRGB(gl: GLRenderingContext): COMPAT_sRGB | null {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/EXT_disjoint_timer_query/ and https://registry.khronos.org/webgl/extensions/EXT_disjoint_timer_query_webgl2/
|
||||
*/
|
||||
export interface COMPAT_disjoint_timer_query {
|
||||
/** A GLint indicating the number of bits used to hold the query result for the given target. */
|
||||
QUERY_COUNTER_BITS: number
|
||||
@@ -498,31 +401,6 @@ export function getDisjointTimerQuery(gl: GLRenderingContext): COMPAT_disjoint_t
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/KHR_parallel_shader_compile/
|
||||
*/
|
||||
export interface COMPAT_parallel_shader_compile {
|
||||
readonly COMPLETION_STATUS: number;
|
||||
}
|
||||
|
||||
export function getParallelShaderCompile(gl: GLRenderingContext): COMPAT_parallel_shader_compile | null {
|
||||
const ext = gl.getExtension('KHR_parallel_shader_compile');
|
||||
if (ext === null) return null;
|
||||
return {
|
||||
COMPLETION_STATUS: ext.COMPLETION_STATUS_KHR,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://registry.khronos.org/webgl/extensions/OES_fbo_render_mipmap/
|
||||
*/
|
||||
export interface COMPAT_fboRenderMipmap {
|
||||
}
|
||||
|
||||
export function getFboRenderMipmap(gl: GLRenderingContext): COMPAT_fboRenderMipmap | null {
|
||||
return isWebGL2(gl) ? {} : gl.getExtension('OES_fbo_render_mipmap');
|
||||
}
|
||||
|
||||
export function getNoNonInstancedActiveAttribs(gl: GLRenderingContext): boolean {
|
||||
if (!isWebGL2(gl)) return false;
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat, getVertexArrayObject, getDisjointTimerQuery, COMPAT_disjoint_timer_query, getNoNonInstancedActiveAttribs, getDrawBuffersIndexed, COMPAT_draw_buffers_indexed, getParallelShaderCompile, COMPAT_parallel_shader_compile, getFboRenderMipmap, COMPAT_fboRenderMipmap } from './compat';
|
||||
import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat, getVertexArrayObject, getDisjointTimerQuery, COMPAT_disjoint_timer_query, getNoNonInstancedActiveAttribs } from './compat';
|
||||
import { isDebugMode } from '../../mol-util/debug';
|
||||
|
||||
export type WebGLExtensions = {
|
||||
instancedArrays: COMPAT_instanced_arrays
|
||||
elementIndexUint: COMPAT_element_index_uint
|
||||
standardDerivatives: COMPAT_standard_derivatives
|
||||
|
||||
standardDerivatives: COMPAT_standard_derivatives | null
|
||||
textureFloat: COMPAT_texture_float | null
|
||||
textureFloatLinear: COMPAT_texture_float_linear | null
|
||||
textureHalfFloat: COMPAT_texture_half_float | null
|
||||
@@ -23,12 +23,9 @@ export type WebGLExtensions = {
|
||||
colorBufferFloat: COMPAT_color_buffer_float | null
|
||||
colorBufferHalfFloat: COMPAT_color_buffer_half_float | null
|
||||
drawBuffers: COMPAT_draw_buffers | null
|
||||
drawBuffersIndexed: COMPAT_draw_buffers_indexed | null
|
||||
shaderTextureLod: COMPAT_shader_texture_lod | null
|
||||
sRGB: COMPAT_sRGB | null
|
||||
disjointTimerQuery: COMPAT_disjoint_timer_query | null
|
||||
parallelShaderCompile: COMPAT_parallel_shader_compile | null
|
||||
fboRenderMipmap: COMPAT_fboRenderMipmap | null
|
||||
|
||||
noNonInstancedActiveAttribs: boolean
|
||||
}
|
||||
@@ -97,10 +94,6 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
|
||||
if (isDebugMode && drawBuffers === null) {
|
||||
console.log('Could not find support for "draw_buffers"');
|
||||
}
|
||||
const drawBuffersIndexed = getDrawBuffersIndexed(gl);
|
||||
if (isDebugMode && drawBuffersIndexed === null) {
|
||||
console.log('Could not find support for "draw_buffers_indexed"');
|
||||
}
|
||||
const shaderTextureLod = getShaderTextureLod(gl);
|
||||
if (isDebugMode && shaderTextureLod === null) {
|
||||
console.log('Could not find support for "shader_texture_lod"');
|
||||
@@ -113,39 +106,28 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
|
||||
if (isDebugMode && disjointTimerQuery === null) {
|
||||
console.log('Could not find support for "disjoint_timer_query"');
|
||||
}
|
||||
const parallelShaderCompile = getParallelShaderCompile(gl);
|
||||
if (isDebugMode && parallelShaderCompile === null) {
|
||||
console.log('Could not find support for "parallel_shader_compile"');
|
||||
}
|
||||
const fboRenderMipmap = getFboRenderMipmap(gl);
|
||||
if (isDebugMode && fboRenderMipmap === null) {
|
||||
console.log('Could not find support for "fbo_render_mipmap"');
|
||||
}
|
||||
|
||||
const noNonInstancedActiveAttribs = getNoNonInstancedActiveAttribs(gl);
|
||||
|
||||
return {
|
||||
instancedArrays,
|
||||
standardDerivatives,
|
||||
elementIndexUint,
|
||||
|
||||
textureFloat,
|
||||
textureFloatLinear,
|
||||
textureHalfFloat,
|
||||
textureHalfFloatLinear,
|
||||
elementIndexUint,
|
||||
depthTexture,
|
||||
|
||||
blendMinMax,
|
||||
vertexArrayObject,
|
||||
fragDepth,
|
||||
colorBufferFloat,
|
||||
colorBufferHalfFloat,
|
||||
drawBuffers,
|
||||
drawBuffersIndexed,
|
||||
shaderTextureLod,
|
||||
sRGB,
|
||||
disjointTimerQuery,
|
||||
parallelShaderCompile,
|
||||
fboRenderMipmap,
|
||||
|
||||
noNonInstancedActiveAttribs,
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { createAttributeBuffers, ElementsBuffer, AttributeKind } from './buffer';
|
||||
@@ -50,12 +49,11 @@ export interface RenderItem<T extends string> {
|
||||
|
||||
//
|
||||
|
||||
const GraphicsRenderVariant = { colorBlended: '', colorWboit: '', colorDpoit: '', pick: '', depth: '', marking: '' };
|
||||
const GraphicsRenderVariant = { colorBlended: '', colorWboit: '', pick: '', depth: '', marking: '' };
|
||||
export type GraphicsRenderVariant = keyof typeof GraphicsRenderVariant
|
||||
export const GraphicsRenderVariants = Object.keys(GraphicsRenderVariant) as GraphicsRenderVariant[];
|
||||
export const GraphicsRenderVariantsBlended = GraphicsRenderVariants.filter(v => !['colorWboit', 'colorDpoit'].includes(v));
|
||||
export const GraphicsRenderVariantsWboit = GraphicsRenderVariants.filter(v => !['colorBlended', 'colorDpoit'].includes(v));
|
||||
export const GraphicsRenderVariantsDpoit = GraphicsRenderVariants.filter(v => !['colorWboit', 'colorBlended'].includes(v));
|
||||
export const GraphicsRenderVariantsBlended = GraphicsRenderVariants.filter(v => v !== 'colorWboit');
|
||||
export const GraphicsRenderVariantsWboit = GraphicsRenderVariants.filter(v => v !== 'colorBlended');
|
||||
|
||||
const ComputeRenderVariant = { compute: '' };
|
||||
export type ComputeRenderVariant = keyof typeof ComputeRenderVariant
|
||||
@@ -369,4 +367,4 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { WebGLContext } from './context';
|
||||
@@ -32,7 +31,7 @@ export type TextureKindValue = {
|
||||
export type TextureValueType = ValueOf<TextureKindValue>
|
||||
export type TextureKind = keyof TextureKindValue
|
||||
export type TextureType = 'ubyte' | 'ushort' | 'float' | 'fp16' | 'int'
|
||||
export type TextureFormat = 'alpha' | 'rg' | 'rgb' | 'rgba' | 'depth'
|
||||
export type TextureFormat = 'alpha' | 'rgb' | 'rgba' | 'depth'
|
||||
/** Numbers are shortcuts for color attachment */
|
||||
export type TextureAttachment = 'depth' | 'stencil' | 'color0' | 'color1' | 'color2' | 'color3' | 'color4' | 'color5' | 'color6' | 'color7' | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
|
||||
export type TextureFilter = 'nearest' | 'linear'
|
||||
@@ -64,10 +63,6 @@ export function getFormat(gl: GLRenderingContext, format: TextureFormat, type: T
|
||||
case 'rgb':
|
||||
if (isWebGL2(gl) && type === 'int') return gl.RGB_INTEGER;
|
||||
return gl.RGB;
|
||||
case 'rg':
|
||||
if (isWebGL2(gl) && type === 'float') return gl.RG;
|
||||
else if (isWebGL2(gl) && type === 'int') return gl.RG_INTEGER;
|
||||
else throw new Error('texture format "rg" requires webgl2 and type "float" or int"');
|
||||
case 'rgba':
|
||||
if (isWebGL2(gl) && type === 'int') return gl.RGBA_INTEGER;
|
||||
return gl.RGBA;
|
||||
@@ -85,13 +80,6 @@ export function getInternalFormat(gl: GLRenderingContext, format: TextureFormat,
|
||||
case 'fp16': return gl.R16F;
|
||||
case 'int': return gl.R32I;
|
||||
}
|
||||
case 'rg':
|
||||
switch (type) {
|
||||
case 'ubyte': return gl.RG;
|
||||
case 'float': return gl.RG32F;
|
||||
case 'fp16': return gl.RG16F;
|
||||
case 'int': return gl.RG32I;
|
||||
}
|
||||
case 'rgb':
|
||||
switch (type) {
|
||||
case 'ubyte': return gl.RGB;
|
||||
@@ -124,7 +112,6 @@ function getByteCount(format: TextureFormat, type: TextureType, width: number, h
|
||||
function getFormatSize(format: TextureFormat) {
|
||||
switch (format) {
|
||||
case 'alpha': return 1;
|
||||
case 'rg': return 2;
|
||||
case 'rgb': return 3;
|
||||
case 'rgba': return 4;
|
||||
case 'depth': return 4;
|
||||
|
||||
@@ -264,35 +264,28 @@ export namespace ArrayEncoding {
|
||||
return false;
|
||||
}
|
||||
|
||||
function packingSizeUnsigned(data: Int32Array, upperLimit: number) {
|
||||
let size = 0;
|
||||
for (let i = 0, n = data.length; i < n; i++) {
|
||||
size += (data[i] / upperLimit) | 0;
|
||||
}
|
||||
size += data.length;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
function packingSizeSigned(data: Int32Array, upperLimit: number) {
|
||||
function packingSize(data: Int32Array, upperLimit: number) {
|
||||
const lowerLimit = -upperLimit - 1;
|
||||
let size = 0;
|
||||
for (let i = 0, n = data.length; i < n; i++) {
|
||||
const value = data[i];
|
||||
if (value >= 0) {
|
||||
size += (value / upperLimit) | 0;
|
||||
if (value === 0) {
|
||||
size += 1;
|
||||
} else if (value > 0) {
|
||||
size += Math.ceil(value / upperLimit);
|
||||
if (value % upperLimit === 0) size += 1;
|
||||
} else {
|
||||
size += (value / lowerLimit) | 0;
|
||||
size += Math.ceil(value / lowerLimit);
|
||||
if (value % lowerLimit === 0) size += 1;
|
||||
}
|
||||
}
|
||||
size += data.length;
|
||||
return size;
|
||||
}
|
||||
|
||||
function determinePacking(data: Int32Array): { isSigned: boolean, size: number, bytesPerElement: number } {
|
||||
const signed = isSigned(data);
|
||||
const size8 = signed ? packingSizeSigned(data, 0x7F) : packingSizeUnsigned(data, 0xFF);
|
||||
const size16 = signed ? packingSizeSigned(data, 0x7FFF) : packingSizeUnsigned(data, 0xFFFF);
|
||||
const size8 = signed ? packingSize(data, 0x7F) : packingSize(data, 0xFF);
|
||||
const size16 = signed ? packingSize(data, 0x7FFF) : packingSize(data, 0xFFFF);
|
||||
|
||||
if (data.length * 4 < size16 * 2) {
|
||||
// 4 byte packing is the most effective
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.363, IHM 1.17, MA 1.4.3.
|
||||
* Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.360, IHM 1.17, MA 1.4.2.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.363, IHM 1.17, MA 1.4.3.
|
||||
* Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.360, IHM 1.17, MA 1.4.2.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.363, IHM 1.17, MA 1.4.3.
|
||||
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.360, IHM 1.17, MA 1.4.2.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { GridLookup3D } from '../../geometry';
|
||||
@@ -25,17 +24,9 @@ describe('GridLookup3d', () => {
|
||||
expect(r.count).toBe(1);
|
||||
expect(r.indices[0]).toBe(0);
|
||||
|
||||
r = grid.nearest(0, 0, 0, 1);
|
||||
expect(r.count).toBe(1);
|
||||
expect(r.indices[0]).toBe(0);
|
||||
|
||||
r = grid.find(0, 0, 0, 1);
|
||||
expect(r.count).toBe(3);
|
||||
expect(sortArray(r.indices)).toEqual([0, 1, 2]);
|
||||
|
||||
r = grid.nearest(0, 0, 0, 3);
|
||||
expect(r.count).toBe(3);
|
||||
expect(sortArray(r.indices)).toEqual([0, 1, 2]);
|
||||
});
|
||||
|
||||
it('radius', () => {
|
||||
@@ -47,17 +38,9 @@ describe('GridLookup3d', () => {
|
||||
expect(r.count).toBe(1);
|
||||
expect(r.indices[0]).toBe(0);
|
||||
|
||||
r = grid.nearest(0, 0, 0, 1);
|
||||
expect(r.count).toBe(1);
|
||||
expect(r.indices[0]).toBe(0);
|
||||
|
||||
r = grid.find(0, 0, 0, 0.5);
|
||||
expect(r.count).toBe(2);
|
||||
expect(sortArray(r.indices)).toEqual([0, 1]);
|
||||
|
||||
r = grid.nearest(0, 0, 0, 3);
|
||||
expect(r.count).toBe(3);
|
||||
expect(sortArray(r.indices)).toEqual([0, 1, 2]);
|
||||
});
|
||||
|
||||
it('indexed', () => {
|
||||
@@ -68,15 +51,8 @@ describe('GridLookup3d', () => {
|
||||
let r = grid.find(0, 0, 0, 0);
|
||||
expect(r.count).toBe(0);
|
||||
|
||||
r = grid.nearest(0, 0, 0, 1);
|
||||
expect(r.count).toBe(1);
|
||||
|
||||
r = grid.find(0, 0, 0, 0.5);
|
||||
expect(r.count).toBe(1);
|
||||
expect(sortArray(r.indices)).toEqual([0]);
|
||||
|
||||
r = grid.nearest(0, 0, 0, 3);
|
||||
expect(r.count).toBe(1);
|
||||
expect(sortArray(r.indices)).toEqual([0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -204,7 +204,7 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat
|
||||
render(texture, false);
|
||||
}
|
||||
|
||||
// printTextureImage(readTexture(webgl, minDistTex), { scale: 0.75 });
|
||||
// printTexture(webgl, minDistTex, 0.75);
|
||||
|
||||
return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale, radiusFactor, resolution, maxRadius };
|
||||
}
|
||||
|
||||
@@ -41,9 +41,8 @@ export namespace Result {
|
||||
export interface Lookup3D<T = number> {
|
||||
// The result is mutated with each call to find.
|
||||
find(x: number, y: number, z: number, radius: number, result?: Result<T>): Result<T>,
|
||||
nearest(x: number, y: number, z: number, k: number, stopIf?: Function, result?: Result<T>): Result<T>,
|
||||
check(x: number, y: number, z: number, radius: number): boolean,
|
||||
readonly boundary: { readonly box: Box3D, readonly sphere: Sphere3D }
|
||||
/** transient result */
|
||||
readonly result: Result<T>
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
import { Result, Lookup3D } from './common';
|
||||
@@ -13,7 +12,6 @@ import { PositionData } from '../common';
|
||||
import { Vec3 } from '../../linear-algebra';
|
||||
import { OrderedSet } from '../../../mol-data/int';
|
||||
import { Boundary } from '../boundary';
|
||||
import { FibonacciHeap } from '../../../mol-util/fibonacci-heap';
|
||||
|
||||
interface GridLookup3D<T = number> extends Lookup3D<T> {
|
||||
readonly buckets: { readonly offset: ArrayLike<number>, readonly count: ArrayLike<number>, readonly array: ArrayLike<number> }
|
||||
@@ -42,17 +40,6 @@ class GridLookup3DImpl<T extends number = number> implements GridLookup3D<T> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nearest(x: number, y: number, z: number, k: number = 1, stopIf?: Function, result?: Result<T>): Result<T> {
|
||||
this.ctx.x = x;
|
||||
this.ctx.y = y;
|
||||
this.ctx.z = z;
|
||||
this.ctx.k = k;
|
||||
this.ctx.stopIf = stopIf;
|
||||
const ret = result ?? this.result;
|
||||
queryNearest(this.ctx, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
check(x: number, y: number, z: number, radius: number): boolean {
|
||||
this.ctx.x = x;
|
||||
this.ctx.y = y;
|
||||
@@ -234,14 +221,12 @@ interface QueryContext {
|
||||
x: number,
|
||||
y: number,
|
||||
z: number,
|
||||
k: number,
|
||||
stopIf?: Function,
|
||||
radius: number,
|
||||
isCheck: boolean
|
||||
}
|
||||
|
||||
function createContext(grid: Grid3D): QueryContext {
|
||||
return { grid, x: 0.1, y: 0.1, z: 0.1, k: 1, stopIf: undefined, radius: 0.1, isCheck: false };
|
||||
return { grid, x: 0.1, y: 0.1, z: 0.1, radius: 0.1, isCheck: false };
|
||||
}
|
||||
|
||||
function query<T extends number = number>(ctx: QueryContext, result: Result<T>): boolean {
|
||||
@@ -292,152 +277,4 @@ function query<T extends number = number>(ctx: QueryContext, result: Result<T>):
|
||||
}
|
||||
}
|
||||
return result.count > 0;
|
||||
}
|
||||
|
||||
const tmpDirVec = Vec3();
|
||||
const tmpVec = Vec3();
|
||||
const tmpSetG = new Set<number>();
|
||||
const tmpSetG2 = new Set<number>();
|
||||
const tmpArrG1 = [0.1];
|
||||
const tmpArrG2 = [0.1];
|
||||
const tmpArrG3 = [0.1];
|
||||
const tmpHeapG = new FibonacciHeap();
|
||||
function queryNearest<T extends number = number>(ctx: QueryContext, result: Result<T>): boolean {
|
||||
const { min, expandedBox: box, boundingSphere: { center }, size: [sX, sY, sZ], bucketOffset, bucketCounts, bucketArray, grid, data: { x: px, y: py, z: pz, indices, radius }, delta, maxRadius } = ctx.grid;
|
||||
const { x, y, z, k, stopIf } = ctx;
|
||||
const indicesCount = OrderedSet.size(indices);
|
||||
Result.reset(result);
|
||||
if (indicesCount === 0 || k <= 0) return false;
|
||||
let gX, gY, gZ, stop = false, gCount = 1, expandGrid = true, nextGCount = 0, arrG = tmpArrG1, nextArrG = tmpArrG2, maxRange = 0, expandRange = true, gridId: number, gridPointsFinished = false;
|
||||
const expandedArrG = tmpArrG3, sqMaxRadius = maxRadius * maxRadius;
|
||||
arrG.length = 0;
|
||||
expandedArrG.length = 0;
|
||||
tmpSetG.clear();
|
||||
tmpHeapG.clear();
|
||||
Vec3.set(tmpVec, x, y, z);
|
||||
if (!Box3D.containsVec3(box, tmpVec)) {
|
||||
// intersect ray pointing to box center
|
||||
Box3D.nearestIntersectionWithRay(tmpVec, box, tmpVec, Vec3.normalize(tmpDirVec, Vec3.sub(tmpDirVec, center, tmpVec)));
|
||||
gX = Math.max(0, Math.min(sX - 1, Math.floor((tmpVec[0] - min[0]) / delta[0])));
|
||||
gY = Math.max(0, Math.min(sY - 1, Math.floor((tmpVec[1] - min[1]) / delta[1])));
|
||||
gZ = Math.max(0, Math.min(sZ - 1, Math.floor((tmpVec[2] - min[2]) / delta[2])));
|
||||
} else {
|
||||
gX = Math.floor((x - min[0]) / delta[0]);
|
||||
gY = Math.floor((y - min[1]) / delta[1]);
|
||||
gZ = Math.floor((z - min[2]) / delta[2]);
|
||||
}
|
||||
const dX = maxRadius !== 0 ? Math.max(1, Math.min(sX - 1, Math.ceil(maxRadius / delta[0]))) : 1;
|
||||
const dY = maxRadius !== 0 ? Math.max(1, Math.min(sY - 1, Math.ceil(maxRadius / delta[1]))) : 1;
|
||||
const dZ = maxRadius !== 0 ? Math.max(1, Math.min(sZ - 1, Math.ceil(maxRadius / delta[2]))) : 1;
|
||||
arrG.push(gX, gY, gZ, (((gX * sY) + gY) * sZ) + gZ);
|
||||
while (result.count < indicesCount) {
|
||||
const arrGLen = gCount * 4;
|
||||
for (let ig = 0; ig < arrGLen; ig += 4) {
|
||||
gridId = arrG[ig + 3];
|
||||
if (!tmpSetG.has(gridId)) {
|
||||
tmpSetG.add(gridId);
|
||||
gridPointsFinished = tmpSetG.size >= grid.length;
|
||||
const bucketIdx = grid[gridId];
|
||||
if (bucketIdx !== 0) {
|
||||
const _maxRange = maxRange;
|
||||
const ki = bucketIdx - 1;
|
||||
const offset = bucketOffset[ki];
|
||||
const count = bucketCounts[ki];
|
||||
const end = offset + count;
|
||||
for (let i = offset; i < end; i++) {
|
||||
const bIdx = bucketArray[i];
|
||||
const idx = OrderedSet.getAt(indices, bIdx);
|
||||
const dx = px[idx] - x;
|
||||
const dy = py[idx] - y;
|
||||
const dz = pz[idx] - z;
|
||||
let distSq = dx * dx + dy * dy + dz * dz;
|
||||
if (maxRadius !== 0) {
|
||||
const r = radius![idx];
|
||||
distSq -= r * r;
|
||||
}
|
||||
if (expandRange && distSq > maxRange) {
|
||||
maxRange = distSq;
|
||||
}
|
||||
tmpHeapG.insert(distSq, bIdx);
|
||||
}
|
||||
if (_maxRange < maxRange) expandRange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// find next grid points
|
||||
nextArrG.length = 0;
|
||||
nextGCount = 0;
|
||||
tmpSetG2.clear();
|
||||
for (let ig = 0; ig < arrGLen; ig += 4) {
|
||||
gX = arrG[ig];
|
||||
gY = arrG[ig + 1];
|
||||
gZ = arrG[ig + 2];
|
||||
// fill grid points array with valid adiacent positions
|
||||
for (let ix = -dX; ix <= dX; ix++) {
|
||||
const xPos = gX + ix;
|
||||
if (xPos < 0 || xPos >= sX) continue;
|
||||
for (let iy = -dY; iy <= dY; iy++) {
|
||||
const yPos = gY + iy;
|
||||
if (yPos < 0 || yPos >= sY) continue;
|
||||
for (let iz = -dZ; iz <= dZ; iz++) {
|
||||
const zPos = gZ + iz;
|
||||
if (zPos < 0 || zPos >= sZ) continue;
|
||||
gridId = (((xPos * sY) + yPos) * sZ) + zPos;
|
||||
if (tmpSetG2.has(gridId)) continue; // already scanned
|
||||
tmpSetG2.add(gridId);
|
||||
if (tmpSetG.has(gridId)) continue; // already visited
|
||||
if (!expandGrid) {
|
||||
const xP = min[0] + xPos * delta[0] - x;
|
||||
const yP = min[1] + yPos * delta[1] - y;
|
||||
const zP = min[2] + zPos * delta[2] - z;
|
||||
const distSqG = (xP * xP) + (yP * yP) + (zP * zP) - sqMaxRadius; // is sqMaxRadius necessary?
|
||||
if (distSqG > maxRange) {
|
||||
expandedArrG.push(xPos, yPos, zPos, gridId);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
nextArrG.push(xPos, yPos, zPos, gridId);
|
||||
nextGCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expandGrid = false;
|
||||
if (nextGCount === 0) {
|
||||
if (k === 1) {
|
||||
const node = tmpHeapG.findMinimum();
|
||||
if (node) {
|
||||
const { key: squaredDistance, value: index } = node!;
|
||||
// const squaredDistance = node!.key, index = node!.value;
|
||||
Result.add(result, index as number, squaredDistance as number);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
while (!tmpHeapG.isEmpty() && (gridPointsFinished || tmpHeapG.findMinimum()!.key as number <= maxRange) && result.count < k) {
|
||||
const node = tmpHeapG.extractMinimum();
|
||||
const squaredDistance = node!.key, index = node!.value;
|
||||
Result.add(result, index as number, squaredDistance as number);
|
||||
if (stopIf && !stop) {
|
||||
stop = stopIf(index, squaredDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.count >= k || stop || result.count >= indicesCount) return result.count > 0;
|
||||
expandGrid = true;
|
||||
expandRange = true;
|
||||
if (expandedArrG.length > 0) {
|
||||
for (let i = 0, l = expandedArrG.length; i < l; i++) {
|
||||
arrG.push(expandedArrG[i]);
|
||||
}
|
||||
expandedArrG.length = 0;
|
||||
gCount = arrG.length;
|
||||
}
|
||||
} else {
|
||||
const tmp = arrG;
|
||||
arrG = nextArrG;
|
||||
nextArrG = tmp;
|
||||
gCount = nextGCount;
|
||||
}
|
||||
}
|
||||
return result.count > 0;
|
||||
}
|
||||
}
|
||||
@@ -138,48 +138,6 @@ namespace Box3D {
|
||||
a.max[2] < b.min[2] || a.min[2] > b.max[2]
|
||||
);
|
||||
}
|
||||
|
||||
// const tmpTransformV = Vec3();
|
||||
export function nearestIntersectionWithRay(out: Vec3, box: Box3D, origin: Vec3, dir: Vec3): Vec3 {
|
||||
const [minX, minY, minZ] = box.min;
|
||||
const [maxX, maxY, maxZ] = box.max;
|
||||
const [x, y, z] = origin;
|
||||
const invDirX = 1.0 / dir[0];
|
||||
const invDirY = 1.0 / dir[1];
|
||||
const invDirZ = 1.0 / dir[2];
|
||||
let tmin, tmax, tymin, tymax, tzmin, tzmax;
|
||||
if (invDirX >= 0) {
|
||||
tmin = (minX - x) * invDirX;
|
||||
tmax = (maxX - x) * invDirX;
|
||||
} else {
|
||||
tmin = (maxX - x) * invDirX;
|
||||
tmax = (minX - x) * invDirX;
|
||||
}
|
||||
if (invDirY >= 0) {
|
||||
tymin = (minY - y) * invDirY;
|
||||
tymax = (maxY - y) * invDirY;
|
||||
} else {
|
||||
tymin = (maxY - y) * invDirY;
|
||||
tymax = (minY - y) * invDirY;
|
||||
}
|
||||
if (invDirZ >= 0) {
|
||||
tzmin = (minZ - z) * invDirZ;
|
||||
tzmax = (maxZ - z) * invDirZ;
|
||||
} else {
|
||||
tzmin = (maxZ - z) * invDirZ;
|
||||
tzmax = (minZ - z) * invDirZ;
|
||||
}
|
||||
if (tymin > tmin)
|
||||
tmin = tymin;
|
||||
if (tymax < tmax)
|
||||
tmax = tymax;
|
||||
if (tzmin > tmin)
|
||||
tmin = tzmin;
|
||||
if (tzmax < tmax)
|
||||
tmax = tzmax;
|
||||
Vec3.scale(out, dir, tmin);
|
||||
return Vec3.set(out, out[0] + x, out[1] + y, out[2] + z);
|
||||
}
|
||||
}
|
||||
|
||||
export { Box3D };
|
||||
export { Box3D };
|
||||
@@ -277,12 +277,6 @@ namespace Sphere3D {
|
||||
export function distance(a: Sphere3D, b: Sphere3D) {
|
||||
return Vec3.distance(a.center, b.center) - a.radius + b.radius;
|
||||
}
|
||||
|
||||
/** Get the distance of v from sphere. If negative, v is inside sphere */
|
||||
export function distanceToVec(sphere: Sphere3D, v: Vec3): number {
|
||||
const { center, radius } = sphere;
|
||||
return Vec3.distance(v, center) - radius;
|
||||
}
|
||||
}
|
||||
|
||||
export { Sphere3D };
|
||||
export { Sphere3D };
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { lerp as scalar_lerp } from '../../mol-math/interpolate';
|
||||
import { defaults } from '../../mol-util';
|
||||
import { Mat3 } from '../linear-algebra/3d/mat3';
|
||||
import { Mat4 } from '../linear-algebra/3d/mat4';
|
||||
import { Quat } from '../linear-algebra/3d/quat';
|
||||
@@ -29,13 +29,11 @@ interface SymmetryOperator {
|
||||
readonly hkl: Vec3,
|
||||
/** spacegroup symmetry operator index, -1 if not applicable */
|
||||
readonly spgrOp: number,
|
||||
/** unique (external) key, -1 if not available */
|
||||
readonly key: number,
|
||||
|
||||
readonly matrix: Mat4,
|
||||
/** cache the inverse of the transform */
|
||||
// cache the inverse of the transform
|
||||
readonly inverse: Mat4,
|
||||
/** optimize the identity case */
|
||||
// optimize the identity case
|
||||
readonly isIdentity: boolean,
|
||||
|
||||
/**
|
||||
@@ -53,20 +51,19 @@ namespace SymmetryOperator {
|
||||
|
||||
export const RotationTranslationEpsilon = 0.005;
|
||||
|
||||
export type CreateInfo = { assembly?: SymmetryOperator['assembly'], ncsId?: number, hkl?: Vec3, spgrOp?: number, key?: number }
|
||||
export type CreateInfo = { assembly?: SymmetryOperator['assembly'], ncsId?: number, hkl?: Vec3, spgrOp?: number }
|
||||
export function create(name: string, matrix: Mat4, info?: CreateInfo | SymmetryOperator): SymmetryOperator {
|
||||
let { assembly, ncsId, hkl, spgrOp, key } = info || { };
|
||||
let { assembly, ncsId, hkl, spgrOp } = info || { };
|
||||
const _hkl = hkl ? Vec3.clone(hkl) : Vec3();
|
||||
spgrOp = spgrOp ?? -1;
|
||||
key = key ?? -1;
|
||||
spgrOp = defaults(spgrOp, -1);
|
||||
ncsId = ncsId || -1;
|
||||
const isIdentity = Mat4.isIdentity(matrix);
|
||||
const suffix = getSuffix(info, isIdentity);
|
||||
if (isIdentity) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId, suffix, key };
|
||||
if (isIdentity) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId, suffix };
|
||||
if (!Mat4.isRotationAndTranslation(matrix, RotationTranslationEpsilon)) {
|
||||
console.warn(`Symmetry operator (${name}) should be a composition of rotation and translation.`);
|
||||
}
|
||||
return { name, assembly, matrix, inverse: Mat4.invert(Mat4(), matrix), isIdentity: false, hkl: _hkl, spgrOp, key, ncsId, suffix };
|
||||
return { name, assembly, matrix, inverse: Mat4.invert(Mat4(), matrix), isIdentity: false, hkl: _hkl, spgrOp, ncsId, suffix };
|
||||
}
|
||||
|
||||
function isSymmetryOperator(x: any): x is SymmetryOperator {
|
||||
|
||||
@@ -35,7 +35,7 @@ function Vec3() {
|
||||
|
||||
namespace Vec3 {
|
||||
export function zero(): Vec3 {
|
||||
const out = [0.1, 0.0, 0.0]; // ensure backing array of type double
|
||||
const out = [0.1, 0.0, 0.0];
|
||||
out[0] = 0;
|
||||
return out as any;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ const DnaAtomIdsList = [
|
||||
/** Used to reduce false positives for atom name-based type guessing */
|
||||
const NonPolymerNames = new Set([
|
||||
'FMN', 'NCN', 'FNS', 'FMA', 'ATP', 'ADP', 'AMP', 'GTP', 'GDP', 'GMP', // Mononucleotides
|
||||
'LIG'
|
||||
]);
|
||||
|
||||
const StandardComponents = (function () {
|
||||
|
||||
@@ -39,7 +39,7 @@ export function getAtomSiteTemplate(data: string, count: number) {
|
||||
};
|
||||
}
|
||||
|
||||
export function getAtomSite(sites: AtomSiteTemplate, terIndices: Set<number>): { [K in keyof mmCIF_Schema['atom_site'] | 'partial_charge']?: CifField } {
|
||||
export function getAtomSite(sites: AtomSiteTemplate, hasTer: boolean): { [K in keyof mmCIF_Schema['atom_site'] | 'partial_charge']?: CifField } {
|
||||
const pdbx_PDB_model_num = CifField.ofStrings(sites.pdbx_PDB_model_num);
|
||||
const auth_asym_id = CifField.ofTokens(sites.auth_asym_id);
|
||||
const auth_seq_id = CifField.ofTokens(sites.auth_seq_id);
|
||||
@@ -67,17 +67,21 @@ export function getAtomSite(sites: AtomSiteTemplate, terIndices: Set<number>): {
|
||||
const seqId = auth_seq_id.int(i);
|
||||
let atomId = auth_atom_id.str(i);
|
||||
|
||||
let asymIdChanged = false;
|
||||
|
||||
if (modelNum !== currModelNum) {
|
||||
asymIdCounts.clear();
|
||||
atomIdCounts.clear();
|
||||
currModelNum = modelNum;
|
||||
currAsymId = asymId;
|
||||
currSeqId = seqId;
|
||||
asymIdChanged = true;
|
||||
currLabelAsymId = asymId;
|
||||
} else if (currAsymId !== asymId) {
|
||||
atomIdCounts.clear();
|
||||
currAsymId = asymId;
|
||||
currSeqId = seqId;
|
||||
asymIdChanged = true;
|
||||
currLabelAsymId = asymId;
|
||||
} else if (currSeqId !== seqId) {
|
||||
atomIdCounts.clear();
|
||||
@@ -87,7 +91,7 @@ export function getAtomSite(sites: AtomSiteTemplate, terIndices: Set<number>): {
|
||||
if (asymIdCounts.has(asymId)) {
|
||||
// only change the chains name if there are TER records
|
||||
// otherwise assume repeated chain name use is from interleaved chains
|
||||
if (terIndices.has(i)) {
|
||||
if (hasTer && asymIdChanged) {
|
||||
const asymIdCount = asymIdCounts.get(asymId)! + 1;
|
||||
asymIdCounts.set(asymId, asymIdCount);
|
||||
currLabelAsymId = `${asymId}_${asymIdCount}`;
|
||||
|
||||
@@ -51,7 +51,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> {
|
||||
|
||||
let modelNum = 0, modelStr = '';
|
||||
let conectRange: [number, number] | undefined = undefined;
|
||||
const terIndices = new Set<number>();
|
||||
let hasTer = false;
|
||||
|
||||
for (let i = 0, _i = lines.count; i < _i; i++) {
|
||||
let s = indices[2 * i], e = indices[2 * i + 1];
|
||||
@@ -164,7 +164,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> {
|
||||
break;
|
||||
case 'T':
|
||||
if (substringStartsWith(data, s, e, 'TER')) {
|
||||
terIndices.add(atomSite.index);
|
||||
hasTer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> {
|
||||
atomSite.label_entity_id[i] = entityBuilder.getEntityId(compId, moleculeType, asymIds.value(i));
|
||||
}
|
||||
|
||||
const atom_site = getAtomSite(atomSite, terIndices);
|
||||
const atom_site = getAtomSite(atomSite, hasTer);
|
||||
if (!isPdbqt) delete atom_site.partial_charge;
|
||||
|
||||
if (conectRange) {
|
||||
|
||||
@@ -65,7 +65,7 @@ export namespace ComponentBond {
|
||||
return e;
|
||||
}
|
||||
|
||||
const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount, pdbx_ordinal } = data;
|
||||
const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount } = data;
|
||||
|
||||
let entry = addEntry(comp_id.value(0)!);
|
||||
for (let i = 0; i < _rowCount; i++) {
|
||||
@@ -74,7 +74,6 @@ export namespace ComponentBond {
|
||||
const nameB = atom_id_2.value(i)!;
|
||||
const order = value_order.value(i)!;
|
||||
const aromatic = pdbx_aromatic_flag.value(i) === 'y';
|
||||
const key = pdbx_ordinal.value(i);
|
||||
|
||||
if (entry.id !== id) {
|
||||
entry = addEntry(id);
|
||||
@@ -90,29 +89,29 @@ export namespace ComponentBond {
|
||||
case 'quad': ord = 4; break;
|
||||
}
|
||||
|
||||
entry.add(nameA, nameB, ord, flags, key);
|
||||
entry.add(nameA, nameB, ord, flags);
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
export class Entry {
|
||||
readonly map: Map<string, Map<string, { order: number, flags: number, key: number }>> = new Map();
|
||||
readonly map: Map<string, Map<string, { order: number, flags: number }>> = new Map();
|
||||
|
||||
add(a: string, b: string, order: number, flags: number, key: number, swap = true) {
|
||||
add(a: string, b: string, order: number, flags: number, swap = true) {
|
||||
const e = this.map.get(a);
|
||||
if (e !== void 0) {
|
||||
const f = e.get(b);
|
||||
if (f === void 0) {
|
||||
e.set(b, { order, flags, key });
|
||||
e.set(b, { order, flags });
|
||||
}
|
||||
} else {
|
||||
const map = new Map<string, { order: number, flags: number, key: number }>();
|
||||
map.set(b, { order, flags, key });
|
||||
const map = new Map<string, { order: number, flags: number }>();
|
||||
map.set(b, { order, flags });
|
||||
this.map.set(a, map);
|
||||
}
|
||||
|
||||
if (swap) this.add(b, a, order, flags, key, false);
|
||||
if (swap) this.add(b, a, order, flags, false);
|
||||
}
|
||||
|
||||
constructor(public readonly id: string) { }
|
||||
|
||||
@@ -14,8 +14,6 @@ import { ElementIndex } from '../../../../mol-model/structure';
|
||||
|
||||
export type IndexPairsProps = {
|
||||
readonly key: ArrayLike<number>
|
||||
readonly operatorA: ArrayLike<number>
|
||||
readonly operatorB: ArrayLike<number>
|
||||
readonly order: ArrayLike<number>
|
||||
readonly distance: ArrayLike<number>
|
||||
readonly flag: ArrayLike<BondType.Flag>
|
||||
@@ -26,22 +24,18 @@ export type IndexPairBonds = { bonds: IndexPairs, maxDistance: number }
|
||||
function getGraph(indexA: ArrayLike<ElementIndex>, indexB: ArrayLike<ElementIndex>, props: Partial<IndexPairsProps>, count: number): IndexPairs {
|
||||
const builder = new IntAdjacencyGraph.EdgeBuilder(count, indexA, indexB);
|
||||
const key = new Int32Array(builder.slotCount);
|
||||
const operatorA = new Array(builder.slotCount);
|
||||
const operatorB = new Array(builder.slotCount);
|
||||
const order = new Int8Array(builder.slotCount);
|
||||
const distance = new Array(builder.slotCount);
|
||||
const flag = new Array(builder.slotCount);
|
||||
for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
|
||||
builder.addNextEdge();
|
||||
builder.assignProperty(key, props.key ? props.key[i] : -1);
|
||||
builder.assignProperty(operatorA, props.operatorA ? props.operatorA[i] : -1);
|
||||
builder.assignProperty(operatorB, props.operatorB ? props.operatorB[i] : -1);
|
||||
builder.assignProperty(order, props.order ? props.order[i] : 1);
|
||||
builder.assignProperty(distance, props.distance ? props.distance[i] : -1);
|
||||
builder.assignProperty(flag, props.flag ? props.flag[i] : BondType.Flag.Covalent);
|
||||
}
|
||||
|
||||
return builder.createGraph({ key, operatorA, operatorB, order, distance, flag });
|
||||
return builder.createGraph({ key, order, distance, flag });
|
||||
}
|
||||
|
||||
export namespace IndexPairBonds {
|
||||
@@ -56,10 +50,6 @@ export namespace IndexPairBonds {
|
||||
indexA: Column<number>,
|
||||
indexB: Column<number>,
|
||||
key?: Column<number>,
|
||||
/** Operator key for indexA. Used in bond computation. */
|
||||
operatorA?: Column<number>,
|
||||
/** Operator key for indexB. Used in bond computation. */
|
||||
operatorB?: Column<number>,
|
||||
order?: Column<number>,
|
||||
/**
|
||||
* Useful for bonds in periodic cells. That is, only bonds within the given
|
||||
@@ -93,30 +83,12 @@ export namespace IndexPairBonds {
|
||||
const indexA = pairs.indexA.toArray() as ArrayLike<ElementIndex>;
|
||||
const indexB = pairs.indexB.toArray() as ArrayLike<ElementIndex>;
|
||||
const key = pairs.key && pairs.key.toArray();
|
||||
const operatorA = pairs.operatorA && pairs.operatorA.toArray();
|
||||
const operatorB = pairs.operatorB && pairs.operatorB.toArray();
|
||||
const order = pairs.order && pairs.order.toArray();
|
||||
const distance = pairs.distance && pairs.distance.toArray();
|
||||
const flag = pairs.flag && pairs.flag.toArray();
|
||||
return {
|
||||
bonds: getGraph(indexA, indexB, { key, operatorA, operatorB, order, distance, flag }, count),
|
||||
bonds: getGraph(indexA, indexB, { key, order, distance, flag }, count),
|
||||
maxDistance: p.maxDistance
|
||||
};
|
||||
}
|
||||
|
||||
/** Like `getEdgeIndex` but taking `edgeProps.operatorA` and `edgeProps.operatorB` into account */
|
||||
export function getEdgeIndexForOperators(bonds: IndexPairs, i: ElementIndex, j: ElementIndex, opI: number, opJ: number): number {
|
||||
let a, b, opA, opB;
|
||||
if (i < j) {
|
||||
a = i; b = j;
|
||||
opA = opI; opB = opJ;
|
||||
} else {
|
||||
a = j; b = i;
|
||||
opA = opJ; opB = opI;
|
||||
}
|
||||
for (let t = bonds.offset[a], _t = bonds.offset[a + 1]; t < _t; t++) {
|
||||
if (bonds.b[t] === b && bonds.edgeProps.operatorA[t] === opA && bonds.edgeProps.operatorB[t] === opB) return t;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -71,12 +71,12 @@ namespace CustomModelProperty {
|
||||
},
|
||||
ref: (data: Model, add: boolean) => data.customProperties.reference(builder.descriptor, add),
|
||||
get: (data: Model) => get(data)?.data,
|
||||
set: (data: Model, props: Partial<PD.Values<Params>> = {}, value?: Value) => {
|
||||
set: (data: Model, props: Partial<PD.Values<Params>> = {}) => {
|
||||
const property = get(data);
|
||||
const p = PD.merge(builder.defaultParams, property.props, props);
|
||||
if (!PD.areEqual(builder.defaultParams, property.props, p)) {
|
||||
// this invalidates property.value
|
||||
set(data, p, value);
|
||||
set(data, p, undefined);
|
||||
// dispose of assets
|
||||
data.customProperties.assets(builder.descriptor);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace CustomModelProperty {
|
||||
getParams: () => ({ value: PD.Value(defaultValue, { isHidden: true }) }),
|
||||
isApplicable: () => true,
|
||||
obtain: async (ctx: CustomProperty.Context, data: Model, props: Partial<PD.Values<typeof defaultParams>>) => {
|
||||
return { ...PD.getDefaultValues(defaultParams), ...props };
|
||||
return { value: props.value ?? defaultValue };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import { LocationIterator } from '../../../mol-geo/util/location-iterator';
|
||||
import { InteractionFlag } from '../interactions/common';
|
||||
import { Unit } from '../../../mol-model/structure/structure';
|
||||
import { Sphere3D } from '../../../mol-math/geometry';
|
||||
import { assertUnreachable } from '../../../mol-util/type-helpers';
|
||||
import { InteractionsSharedParams } from './shared';
|
||||
|
||||
function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<InteractionsInterUnitParams>, mesh?: Mesh) {
|
||||
if (!structure.hasAtomic) return Mesh.createEmpty(mesh);
|
||||
@@ -33,7 +31,7 @@ function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: S
|
||||
const { contacts, unitsFeatures } = interactions;
|
||||
|
||||
const { edgeCount, edges } = contacts;
|
||||
const { sizeFactor, parentDisplay } = props;
|
||||
const { sizeFactor } = props;
|
||||
|
||||
if (!edgeCount) return Mesh.createEmpty(mesh);
|
||||
|
||||
@@ -72,48 +70,14 @@ function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: S
|
||||
|
||||
if (child) {
|
||||
const b = edges[edgeIndex];
|
||||
const childUnitA = child.unitMap.get(b.unitA);
|
||||
if (!childUnitA) return true;
|
||||
|
||||
if (parentDisplay === 'stub') {
|
||||
const childUnitA = child.unitMap.get(b.unitA);
|
||||
if (!childUnitA) return true;
|
||||
|
||||
const unitA = structure.unitMap.get(b.unitA);
|
||||
const { offsets, members } = unitsFeatures.get(b.unitA);
|
||||
for (let i = offsets[b.indexA], il = offsets[b.indexA + 1]; i < il; ++i) {
|
||||
const eA = unitA.elements[members[i]];
|
||||
if (!SortedArray.has(childUnitA.elements, eA)) return true;
|
||||
}
|
||||
} else if (parentDisplay === 'full' || parentDisplay === 'between') {
|
||||
let flagA = false;
|
||||
let flagB = false;
|
||||
|
||||
const childUnitA = child.unitMap.get(b.unitA);
|
||||
if (!childUnitA) {
|
||||
flagA = true;
|
||||
} else {
|
||||
const unitA = structure.unitMap.get(b.unitA);
|
||||
const { offsets, members } = unitsFeatures.get(b.unitA);
|
||||
for (let i = offsets[b.indexA], il = offsets[b.indexA + 1]; i < il; ++i) {
|
||||
const eA = unitA.elements[members[i]];
|
||||
if (!SortedArray.has(childUnitA.elements, eA)) flagA = true;
|
||||
}
|
||||
}
|
||||
|
||||
const childUnitB = child.unitMap.get(b.unitB);
|
||||
if (!childUnitB) {
|
||||
flagB = true;
|
||||
} else {
|
||||
const unitB = structure.unitMap.get(b.unitB);
|
||||
const { offsets, members } = unitsFeatures.get(b.unitB);
|
||||
for (let i = offsets[b.indexB], il = offsets[b.indexB + 1]; i < il; ++i) {
|
||||
const eB = unitB.elements[members[i]];
|
||||
if (!SortedArray.has(childUnitB.elements, eB)) flagB = true;
|
||||
}
|
||||
}
|
||||
|
||||
return parentDisplay === 'full' ? flagA && flagB : flagA === flagB;
|
||||
} else {
|
||||
assertUnreachable(parentDisplay);
|
||||
const unitA = structure.unitMap.get(b.unitA);
|
||||
const { offsets, members } = unitsFeatures.get(b.unitA);
|
||||
for (let i = offsets[b.indexA], il = offsets[b.indexA + 1]; i < il; ++i) {
|
||||
const eA = unitA.elements[members[i]];
|
||||
if (!SortedArray.has(childUnitA.elements, eA)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +101,10 @@ function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: S
|
||||
export const InteractionsInterUnitParams = {
|
||||
...ComplexMeshParams,
|
||||
...LinkCylinderParams,
|
||||
...InteractionsSharedParams,
|
||||
sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }),
|
||||
dashCount: PD.Numeric(6, { min: 2, max: 10, step: 2 }),
|
||||
dashScale: PD.Numeric(0.4, { min: 0, max: 2, step: 0.1 }),
|
||||
includeParent: PD.Boolean(false),
|
||||
};
|
||||
export type InteractionsInterUnitParams = typeof InteractionsInterUnitParams
|
||||
|
||||
@@ -154,8 +121,7 @@ export function InteractionsInterUnitVisual(materialId: number): ComplexVisual<I
|
||||
newProps.dashCount !== currentProps.dashCount ||
|
||||
newProps.dashScale !== currentProps.dashScale ||
|
||||
newProps.dashCap !== currentProps.dashCap ||
|
||||
newProps.radialSegments !== currentProps.radialSegments ||
|
||||
newProps.parentDisplay !== currentProps.parentDisplay
|
||||
newProps.radialSegments !== currentProps.radialSegments
|
||||
);
|
||||
|
||||
const interactionsHash = InteractionsProvider.get(newStructure).version;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user