mirror of
https://github.com/molstar/molstar.git
synced 2026-06-06 06:34:23 +08:00
Compare commits
106 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5659529d7 | ||
|
|
f6e06ab16e | ||
|
|
4245eaf1b2 | ||
|
|
c41bd702e2 | ||
|
|
350f5c4266 | ||
|
|
ed4056bc8b | ||
|
|
0d96fa21b7 | ||
|
|
0ee8d33d36 | ||
|
|
64cedec12b | ||
|
|
366b3b1b75 | ||
|
|
33963c085a | ||
|
|
0f5a6194ff | ||
|
|
9266faec59 | ||
|
|
94347c6dde | ||
|
|
7a07701be0 | ||
|
|
42519a4f75 | ||
|
|
c898c16430 | ||
|
|
318863bd18 | ||
|
|
ce94760d02 | ||
|
|
d9d8562ed9 | ||
|
|
dee55ea874 | ||
|
|
da413cc9e6 | ||
|
|
c72e93a13d | ||
|
|
21f910a3ca | ||
|
|
e7ce693e50 | ||
|
|
29e8fe7904 | ||
|
|
baf3a6077e | ||
|
|
e030e7a32d | ||
|
|
125566ed75 | ||
|
|
c51cb67519 | ||
|
|
57f086b530 | ||
|
|
d1e17785b8 | ||
|
|
774328a1d8 | ||
|
|
175a0f48fa | ||
|
|
60b91ff032 | ||
|
|
2b003bc5b0 | ||
|
|
029a2fcab1 | ||
|
|
a828113d9b | ||
|
|
ab4d509eda | ||
|
|
1296f32fa8 | ||
|
|
5aa1ec9876 | ||
|
|
f2cf1ab226 | ||
|
|
2d34c2a40b | ||
|
|
a7181e865c | ||
|
|
0a71b788b3 | ||
|
|
1ed3d84043 | ||
|
|
f472b75d0d | ||
|
|
072a9d1ccd | ||
|
|
8e26d1be68 | ||
|
|
c5871e9025 | ||
|
|
f26911b358 | ||
|
|
3a595b80b5 | ||
|
|
45760ddd41 | ||
|
|
447d068bf1 | ||
|
|
7e1642a4a3 | ||
|
|
7781267e78 | ||
|
|
f824fdcfed | ||
|
|
79dd441967 | ||
|
|
9dcf9c0785 | ||
|
|
83569462c6 | ||
|
|
947e169c3a | ||
|
|
e6b36c52d1 | ||
|
|
7fed3b84fa | ||
|
|
cbc941f193 | ||
|
|
a7ef0fb85f | ||
|
|
d10c36eaf5 | ||
|
|
e4c3a66753 | ||
|
|
f58f2cdc90 | ||
|
|
8f2676e91e | ||
|
|
89d397898e | ||
|
|
2dc32be9ee | ||
|
|
769220bd82 | ||
|
|
c75aa5dd52 | ||
|
|
88f1cfd8c4 | ||
|
|
108279c1aa | ||
|
|
8150490aac | ||
|
|
9497aa6362 | ||
|
|
3769da48a1 | ||
|
|
3c21fcd53a | ||
|
|
102ef2795d | ||
|
|
0befa253c2 | ||
|
|
87189cee58 | ||
|
|
3284f13fc6 | ||
|
|
70d219b120 | ||
|
|
a5ed3a08ea | ||
|
|
3665e7e999 | ||
|
|
9b583b23ae | ||
|
|
d602415e98 | ||
|
|
2c49a423e2 | ||
|
|
8a266e70c8 | ||
|
|
0df3bcd65d | ||
|
|
f5ecf5648e | ||
|
|
821f82fc3f | ||
|
|
92305fe628 | ||
|
|
17fe57b8a5 | ||
|
|
47433a51d3 | ||
|
|
e090827ced | ||
|
|
856e6a8b74 | ||
|
|
a813b4d40e | ||
|
|
98afc27442 | ||
|
|
9d4f28a395 | ||
|
|
50266d9a56 | ||
|
|
602a532cf2 | ||
|
|
b23d610c94 | ||
|
|
119c43d527 | ||
|
|
124feeb790 |
69
CHANGELOG.md
69
CHANGELOG.md
@@ -6,6 +6,71 @@ Note that since we don't clearly distinguish between a public and private interf
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v3.10.2] - 2022-06-26
|
||||
|
||||
- Fix superfluous shader varying
|
||||
- Improve use of gl_VertexID when possible
|
||||
|
||||
## [v3.10.1] - 2022-06-26
|
||||
|
||||
- Fix groupCount when updating TextureMesh-based visuals
|
||||
|
||||
## [v3.10.0] - 2022-06-24
|
||||
|
||||
- Add support for Glycam saccharide names
|
||||
- Add ``PluginConfig.Viewport.ShowTrajectoryControls`` config option
|
||||
|
||||
## [v3.9.1] - 2022-06-19
|
||||
|
||||
- Fix missing ``super.componentWillUnmount()`` calls (@simeonborko)
|
||||
- Fix missing ``uGroupCount`` update for visuals
|
||||
- Fix missing aromatic bond display
|
||||
|
||||
## [v3.9.0] - 2022-05-30
|
||||
|
||||
- Improve picking by using drawbuffers (when available) to reduce number of drawcalls
|
||||
- GPU timing support
|
||||
- Add ``timing-mode`` Viewer GET param
|
||||
- Add support for webgl timer queries
|
||||
- Add timer marks around GPU render & compute operations
|
||||
- Volume Server CIF: Add check that a data block contains volume data before parsing
|
||||
- Fix ``Scene.clear`` not clearing primitives & volumes arrays (@JonStargaryen)
|
||||
- Fix rendering volumes when wboit is switched off and postprocessing is enabled
|
||||
|
||||
## [v3.8.2] - 2022-05-22
|
||||
|
||||
- Fix ``Scene.opacityAverage`` not taking xray shaded into account
|
||||
|
||||
## [v3.8.1] - 2022-05-14
|
||||
|
||||
- Fix issues with marking camera/handle helper (#433)
|
||||
- Fix issues with array uniforms when running with headless-gl
|
||||
- Fix Polymer Chain Instance coloring
|
||||
- Improve performance of scene marker/opacity average calculation
|
||||
|
||||
## [v3.8.0] - 2022-04-30
|
||||
|
||||
- Add support for outlines around transparent objects
|
||||
- Improve per-group transparency when wboit is switched off
|
||||
- Improve ``ColorTheme`` typing with ``ColorType`` generic.
|
||||
- Defaults to ``ColorTypeLocation``
|
||||
- Set when using ``ColorTypeDirect`` or ``ColorTypeGrid``
|
||||
- Fix case handling of ``struct_conf`` mmCIF enumeration field (#425)
|
||||
- Fix ``allowTransparentBackfaces`` for per-group transparency
|
||||
- Fix ``FormatRegistry.isApplicable`` returning true for unregistered formats
|
||||
- Fix: handle building of ``GridLookup3D`` with zero cell size
|
||||
- Fix ``ignoreLight`` for direct-volume rendering with webgl1
|
||||
- Fix (non-black) outlines when using transparent background
|
||||
|
||||
## [v3.7.0] - 2022-04-13
|
||||
|
||||
- Fix ``xrayShaded`` for texture-mesh geometries
|
||||
- [Breaking] Change ``allowTransparentBackfaces`` to ``transparentBackfaces`` with options ``off``, ``on``, ``opaque``. This was only added in 3.6.0, so allowing a breaking change here.
|
||||
- ``off``: don't show (default)
|
||||
- ``on``: show with transparency
|
||||
- ``opaque``: show fully opaque
|
||||
- Add option to disable file drop overlay.
|
||||
|
||||
## [v3.6.2] - 2022-04-05
|
||||
|
||||
- ModelServer ligand queries: fixes for alternate locations, additional atoms & UNL ligand
|
||||
@@ -27,8 +92,8 @@ Note that since we don't clearly distinguish between a public and private interf
|
||||
- Fix handling of case insensitive mmCIF enumeration fields (including entity.type)
|
||||
- Fix ``disable-wboit`` Viewer GET param
|
||||
- Add support for React 18.
|
||||
- Used by importing ``createPluginUI`` from ``mol-plugin-ui/react18``;
|
||||
- In Mol* 4.0, React 18 will become the default option.
|
||||
- Used by importing ``createPluginUI`` from ``mol-plugin-ui/react18``;
|
||||
- In Mol* 4.0, React 18 will become the default option.
|
||||
|
||||
## [v3.5.0] - 2022-03-25
|
||||
|
||||
|
||||
44
docs/file-formats.md
Normal file
44
docs/file-formats.md
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
Support file formats and their extensions.
|
||||
|
||||
## Structure
|
||||
|
||||
- MMCIF and CIFCORE (mmCIF and coreCIF schemas): cif, bcif, mmcif, mcif
|
||||
- GRO: gro
|
||||
- MOL: mol
|
||||
- MOL2: mol2
|
||||
- PDB/PDBQT: pdb, ent, pdbqt
|
||||
- SDF: sdf, sd
|
||||
- XYZ: xyz
|
||||
|
||||
|
||||
## Topology
|
||||
|
||||
Need to be loaded together with Coordinates.
|
||||
|
||||
- PRMTOP: prmtop, parm7
|
||||
- PSF: psf
|
||||
- TOP: top
|
||||
|
||||
## Coordinates
|
||||
|
||||
Need to be loaded together with a Structure or Topology.
|
||||
|
||||
- DCD: dcd
|
||||
- NCTRAJ: nc, nctraj
|
||||
- TRR: trr
|
||||
- XTC: xtc
|
||||
|
||||
|
||||
## Volume
|
||||
|
||||
- CCP4/MRC/MAP: ccp4, mrc, map
|
||||
- CUBE (may include a Structure): cub, cube
|
||||
- DSN6/BRIX: dsn6, brix
|
||||
- DX and DXBIN: dx, dxbin
|
||||
- DSCIF (DensityServer CIF schema): cif, bcif
|
||||
|
||||
|
||||
## Shape
|
||||
|
||||
- PLY
|
||||
@@ -13,6 +13,7 @@
|
||||
* DZ has C1 instead of N1 (e.g. 6I4N)
|
||||
* DP has N5 instead of C5 and C7 instead of N7 (e.g. 6I4N)
|
||||
* Beta & Gamma peptides (e.g. 1GAC, 6PQF)
|
||||
* Helices of D-amino acids (e.g. 7QDI)
|
||||
* Mixed (heterogeneous) all-atom/trace-only RNA model (1JGQ)
|
||||
* Polymers with residues with missing trace atoms (e.g. 2QFJ)
|
||||
* Modified RNA bases (1y26, 5L4O)
|
||||
|
||||
44138
package-lock.json
generated
44138
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
70
package.json
70
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "3.6.2",
|
||||
"version": "3.10.2",
|
||||
"description": "A comprehensive macromolecular library.",
|
||||
"homepage": "https://github.com/molstar/molstar#readme",
|
||||
"repository": {
|
||||
@@ -94,69 +94,69 @@
|
||||
"@graphql-codegen/add": "^3.1.1",
|
||||
"@graphql-codegen/cli": "^2.6.2",
|
||||
"@graphql-codegen/time": "^3.1.1",
|
||||
"@graphql-codegen/typescript": "^2.4.7",
|
||||
"@graphql-codegen/typescript": "^2.5.1",
|
||||
"@graphql-codegen/typescript-graphql-files-modules": "^2.1.1",
|
||||
"@graphql-codegen/typescript-graphql-request": "^4.4.2",
|
||||
"@graphql-codegen/typescript-operations": "^2.3.4",
|
||||
"@graphql-codegen/typescript-graphql-request": "^4.4.10",
|
||||
"@graphql-codegen/typescript-operations": "^2.4.2",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/gl": "^4.1.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/react": "^17.0.43",
|
||||
"@types/react-dom": "^17.0.14",
|
||||
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
||||
"@typescript-eslint/parser": "^5.14.0",
|
||||
"@types/jest": "^28.1.3",
|
||||
"@types/react": "^18.0.14",
|
||||
"@types/react-dom": "^18.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.29.0",
|
||||
"@typescript-eslint/parser": "^5.29.0",
|
||||
"benchmark": "^2.1.4",
|
||||
"concurrently": "^7.0.0",
|
||||
"concurrently": "^7.2.2",
|
||||
"cpx2": "^4.2.0",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint": "^8.18.0",
|
||||
"extra-watch-webpack-plugin": "^1.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"fs-extra": "^10.0.1",
|
||||
"graphql": "^16.3.0",
|
||||
"http-server": "^14.1.0",
|
||||
"jest": "^27.5.1",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"graphql": "^16.5.0",
|
||||
"http-server": "^14.1.1",
|
||||
"jest": "^28.1.1",
|
||||
"mini-css-extract-plugin": "^2.6.1",
|
||||
"path-browserify": "^1.0.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"sass": "^1.49.9",
|
||||
"sass-loader": "^12.6.0",
|
||||
"simple-git": "^3.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"sass": "^1.53.0",
|
||||
"sass-loader": "^13.0.1",
|
||||
"simple-git": "^3.10.0",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.6.3",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^4.9.2"
|
||||
"ts-jest": "^28.0.5",
|
||||
"typescript": "^4.7.4",
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/argparse": "^2.0.10",
|
||||
"@types/benchmark": "^2.1.1",
|
||||
"@types/compression": "1.7.2",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/node-fetch": "^2.6.1",
|
||||
"@types/node": "^16.11.41",
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
"@types/swagger-ui-dist": "3.30.1",
|
||||
"argparse": "^2.0.1",
|
||||
"body-parser": "^1.19.2",
|
||||
"body-parser": "^1.20.0",
|
||||
"compression": "^1.7.4",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.3",
|
||||
"express": "^4.18.1",
|
||||
"h264-mp4-encoder": "^1.0.12",
|
||||
"immer": "^9.0.12",
|
||||
"immutable": "^4.0.0",
|
||||
"immer": "^9.0.15",
|
||||
"immutable": "^4.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"rxjs": "^7.5.5",
|
||||
"swagger-ui-dist": "^4.6.2",
|
||||
"tslib": "^2.3.1",
|
||||
"swagger-ui-dist": "^4.12.0",
|
||||
"tslib": "^2.4.0",
|
||||
"util.promisify": "^1.1.1",
|
||||
"xhr2": "^0.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^17.0.2 || ^16.14.0",
|
||||
"react-dom": "^18.0.0 || ^17.0.2 || ^16.14.0"
|
||||
"react": "^18.1.0 || ^17.0.2 || ^16.14.0",
|
||||
"react-dom": "^18.1.0 || ^17.0.2 || ^16.14.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,10 @@ import { Asset } from '../../mol-util/assets';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import '../../mol-util/polyfill';
|
||||
import { ObjectKeys } from '../../mol-util/type-helpers';
|
||||
import { SaccharideCompIdMapType } from '../../mol-model/structure/structure/carbohydrates/constants';
|
||||
|
||||
export { PLUGIN_VERSION as version } from '../../mol-plugin/version';
|
||||
export { setDebugMode, setProductionMode } from '../../mol-util/debug';
|
||||
export { setDebugMode, setProductionMode, setTimingMode } from '../../mol-util/debug';
|
||||
|
||||
const CustomFormats = [
|
||||
['g3d', G3dProvider] as const
|
||||
@@ -92,11 +93,13 @@ const DefaultViewerOptions = {
|
||||
viewportShowSettings: PluginConfig.Viewport.ShowSettings.defaultValue,
|
||||
viewportShowSelectionMode: PluginConfig.Viewport.ShowSelectionMode.defaultValue,
|
||||
viewportShowAnimation: PluginConfig.Viewport.ShowAnimation.defaultValue,
|
||||
viewportShowTrajectoryControls: PluginConfig.Viewport.ShowTrajectoryControls.defaultValue,
|
||||
pluginStateServer: PluginConfig.State.DefaultServer.defaultValue,
|
||||
volumeStreamingServer: PluginConfig.VolumeStreaming.DefaultServer.defaultValue,
|
||||
volumeStreamingDisabled: !PluginConfig.VolumeStreaming.Enabled.defaultValue,
|
||||
pdbProvider: PluginConfig.Download.DefaultPdbProvider.defaultValue,
|
||||
emdbProvider: PluginConfig.Download.DefaultEmdbProvider.defaultValue,
|
||||
saccharideCompIdMapType: 'default' as SaccharideCompIdMapType,
|
||||
};
|
||||
type ViewerOptions = typeof DefaultViewerOptions;
|
||||
|
||||
@@ -159,6 +162,7 @@ export class Viewer {
|
||||
[PluginConfig.Viewport.ShowSettings, o.viewportShowSettings],
|
||||
[PluginConfig.Viewport.ShowSelectionMode, o.viewportShowSelectionMode],
|
||||
[PluginConfig.Viewport.ShowAnimation, o.viewportShowAnimation],
|
||||
[PluginConfig.Viewport.ShowTrajectoryControls, o.viewportShowTrajectoryControls],
|
||||
[PluginConfig.State.DefaultServer, o.pluginStateServer],
|
||||
[PluginConfig.State.CurrentServer, o.pluginStateServer],
|
||||
[PluginConfig.VolumeStreaming.DefaultServer, o.volumeStreamingServer],
|
||||
@@ -166,6 +170,7 @@ export class Viewer {
|
||||
[PluginConfig.Download.DefaultPdbProvider, o.pdbProvider],
|
||||
[PluginConfig.Download.DefaultEmdbProvider, o.emdbProvider],
|
||||
[PluginConfig.Structure.DefaultRepresentationPreset, ViewerAutoPreset.id],
|
||||
[PluginConfig.Structure.SaccharideCompIdMapType, o.saccharideCompIdMapType],
|
||||
]
|
||||
};
|
||||
|
||||
@@ -397,7 +402,7 @@ export class Viewer {
|
||||
async loadTrajectory(params: LoadTrajectoryParams) {
|
||||
const plugin = this.plugin;
|
||||
|
||||
let model: StateObjectSelector, coords: StateObjectSelector;
|
||||
let model: StateObjectSelector;
|
||||
|
||||
if (params.model.kind === 'model-data' || params.model.kind === 'model-url') {
|
||||
const data = params.model.kind === 'model-data'
|
||||
@@ -415,14 +420,12 @@ export class Viewer {
|
||||
model = await provider!.parse(plugin, data);
|
||||
}
|
||||
|
||||
{
|
||||
const data = params.coordinates.kind === 'coordinates-data'
|
||||
? await plugin.builders.data.rawData({ data: params.coordinates.data, label: params.coordinatesLabel })
|
||||
: await plugin.builders.data.download({ url: params.coordinates.url, isBinary: params.coordinates.isBinary, label: params.coordinatesLabel });
|
||||
const data = params.coordinates.kind === 'coordinates-data'
|
||||
? await plugin.builders.data.rawData({ data: params.coordinates.data, label: params.coordinatesLabel })
|
||||
: await plugin.builders.data.download({ url: params.coordinates.url, isBinary: params.coordinates.isBinary, label: params.coordinatesLabel });
|
||||
|
||||
const provider = plugin.dataFormats.get(params.coordinates.format);
|
||||
coords = await provider!.parse(plugin, data);
|
||||
}
|
||||
const provider = plugin.dataFormats.get(params.coordinates.format);
|
||||
const coords = await provider!.parse(plugin, data);
|
||||
|
||||
const trajectory = await plugin.build().toRoot()
|
||||
.apply(TrajectoryFromModelAndCoordinates, {
|
||||
|
||||
@@ -46,7 +46,10 @@
|
||||
}
|
||||
|
||||
var debugMode = getParam('debug-mode', '[^&]+').trim() === '1';
|
||||
if (debugMode) molstar.setDebugMode(debugMode, debugMode);
|
||||
if (debugMode) molstar.setDebugMode(debugMode);
|
||||
|
||||
var timingMode = getParam('timing-mode', '[^&]+').trim() === '1';
|
||||
if (timingMode) molstar.setTimingMode(timingMode);
|
||||
|
||||
var hideControls = getParam('hide-controls', '[^&]+').trim() === '1';
|
||||
var collapseLeftPanel = getParam('collapse-left-panel', '[^&]+').trim() === '1';
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Josh McMenemy <josh.mcmenemy@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import * as argparse from 'argparse';
|
||||
@@ -31,11 +32,11 @@ function extractIonNames(ccd: DatabaseCollection<CCD_Schema>) {
|
||||
|
||||
function writeIonNamesFile(filePath: string, ionNames: string[]) {
|
||||
const output = `/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated ion names params file. Names extracted from CCD components.
|
||||
*
|
||||
* @author molstar/chem-comp-dict/create-table cli
|
||||
* @author molstar/chem-comp-dict/create-ions cli
|
||||
*/
|
||||
|
||||
export const IonNames = new Set(${JSON.stringify(ionNames).replace(/"/g, "'").replace(/,/g, ', ')});
|
||||
|
||||
@@ -161,7 +161,7 @@ const MMCIF_DIC_URL = 'http://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.
|
||||
const IHM_DIC_PATH = `${DIC_DIR}/ihm-extension.dic`;
|
||||
const IHM_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/IHM-dictionary/master/ihm-extension.dic';
|
||||
const MA_DIC_PATH = `${DIC_DIR}/ma-extension.dic`;
|
||||
const MA_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/MA-dictionary/master/mmcif_ma.dic';
|
||||
const MA_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/ModelCIF/master/dist/mmcif_ma.dic';
|
||||
|
||||
const CIF_CORE_DIC_PATH = `${DIC_DIR}/cif_core.dic`;
|
||||
const CIF_CORE_DIC_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/cif_core.dic';
|
||||
|
||||
@@ -51,6 +51,7 @@ export function getFieldType(type: string, description: string, values?: string[
|
||||
case 'operation_expression':
|
||||
case 'point_symmetry':
|
||||
case '4x3_matrix':
|
||||
case '3x4_matrix':
|
||||
case '3x4_matrices':
|
||||
case 'point_group':
|
||||
case 'point_group_helical':
|
||||
|
||||
@@ -55,6 +55,17 @@
|
||||
</a>
|
||||
</div>
|
||||
<script>
|
||||
function getParam(name, regex) {
|
||||
var r = new RegExp(name + '=' + '(' + regex + ')[&]?', 'i');
|
||||
return decodeURIComponent(((window.location.search || '').match(r) || [])[1] || '');
|
||||
}
|
||||
|
||||
var debugMode = getParam('debug-mode', '[^&]+').trim() === '1';
|
||||
if (debugMode) AlphaOrbitalsExample.setDebugMode(debugMode);
|
||||
|
||||
var timingMode = getParam('timing-mode', '[^&]+').trim() === '1';
|
||||
if (timingMode) AlphaOrbitalsExample.setTimingMode(timingMode);
|
||||
|
||||
AlphaOrbitalsExample.init('app')
|
||||
</script>
|
||||
<!-- __MOLSTAR_ANALYTICS__ -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
@@ -25,6 +25,8 @@ import { DemoMoleculeSDF, DemoOrbitals } from './example-data';
|
||||
import './index.html';
|
||||
require('mol-plugin-ui/skin/light.scss');
|
||||
|
||||
import { setDebugMode, setTimingMode } from '../../mol-util/debug';
|
||||
|
||||
interface DemoInput {
|
||||
moleculeSdf: string,
|
||||
basis: Basis,
|
||||
@@ -222,4 +224,6 @@ export class AlphaOrbitalsExample {
|
||||
}
|
||||
}
|
||||
|
||||
(window as any).AlphaOrbitalsExample = new AlphaOrbitalsExample();
|
||||
(window as any).AlphaOrbitalsExample = new AlphaOrbitalsExample();
|
||||
(window as any).AlphaOrbitalsExample.setDebugMode = setDebugMode;
|
||||
(window as any).AlphaOrbitalsExample.setTimingMode = setTimingMode;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
@@ -8,6 +8,7 @@ import { sortArray } from '../../mol-data/util';
|
||||
import { canComputeGrid3dOnGPU } from '../../mol-gl/compute/grid3d';
|
||||
import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
import { Task } from '../../mol-task';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
import { AlphaOrbital, createGrid, CubeGrid, CubeGridComputationParams, initCubeGrid } from './data-model';
|
||||
import { gpuComputeAlphaOrbitalsDensityGridValues } from './gpu/compute';
|
||||
|
||||
@@ -19,9 +20,9 @@ export function createSphericalCollocationDensityGrid(
|
||||
|
||||
let matrix: Float32Array;
|
||||
if (canComputeGrid3dOnGPU(webgl)) {
|
||||
// console.time('gpu');
|
||||
matrix = await gpuComputeAlphaOrbitalsDensityGridValues(ctx, webgl!, cubeGrid, orbitals);
|
||||
// console.timeEnd('gpu');
|
||||
if (isTimingMode) webgl.timer.mark('createSphericalCollocationDensityGrid');
|
||||
matrix = await gpuComputeAlphaOrbitalsDensityGridValues(ctx, webgl, cubeGrid, orbitals);
|
||||
if (isTimingMode) webgl.timer.markEnd('createSphericalCollocationDensityGrid');
|
||||
} else {
|
||||
throw new Error('Missing OES_texture_float WebGL extension.');
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Inspired by https://github.com/dgasmith/gau2grid.
|
||||
*
|
||||
@@ -10,12 +10,11 @@ import { sortArray } from '../../mol-data/util';
|
||||
import { canComputeGrid3dOnGPU } from '../../mol-gl/compute/grid3d';
|
||||
import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
import { Task } from '../../mol-task';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
import { sphericalCollocation } from './collocation';
|
||||
import { AlphaOrbital, createGrid, CubeGrid, CubeGridComputationParams, initCubeGrid } from './data-model';
|
||||
import { gpuComputeAlphaOrbitalsGridValues } from './gpu/compute';
|
||||
|
||||
// setDebugMode(true);
|
||||
|
||||
export function createSphericalCollocationGrid(
|
||||
params: CubeGridComputationParams, orbital: AlphaOrbital, webgl?: WebGLContext
|
||||
): Task<CubeGrid> {
|
||||
@@ -24,9 +23,9 @@ export function createSphericalCollocationGrid(
|
||||
|
||||
let matrix: Float32Array;
|
||||
if (canComputeGrid3dOnGPU(webgl)) {
|
||||
// console.time('gpu');
|
||||
matrix = await gpuComputeAlphaOrbitalsGridValues(ctx, webgl!, cubeGrid, orbital);
|
||||
// console.timeEnd('gpu');
|
||||
if (isTimingMode) webgl.timer.mark('createSphericalCollocationGrid');
|
||||
matrix = await gpuComputeAlphaOrbitalsGridValues(ctx, webgl, cubeGrid, orbital);
|
||||
if (isTimingMode) webgl.timer.markEnd('createSphericalCollocationGrid');
|
||||
} else {
|
||||
// console.time('cpu');
|
||||
matrix = await sphericalCollocation(cubeGrid, orbital, ctx);
|
||||
|
||||
@@ -71,6 +71,7 @@ export class GeometryExporterUI extends CollapsableControls<{}, State> {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
this._controls?.dispose();
|
||||
this._controls = void 0;
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ export class Mp4EncoderUI extends CollapsableControls<{}, State> {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
this._controls?.dispose();
|
||||
this._controls = void 0;
|
||||
}
|
||||
|
||||
@@ -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-02-27T12:49:36-08:00
|
||||
// Generated on 2022-06-26T14:02:35-07:00
|
||||
|
||||
/** All built-in and custom scalars, mapped to their actual values */
|
||||
export type Scalars = {
|
||||
@@ -659,6 +659,8 @@ export type CoreEntry = {
|
||||
readonly em_staining?: Maybe<ReadonlyArray<Maybe<EmStaining>>>;
|
||||
readonly em_vitrification?: Maybe<ReadonlyArray<Maybe<EmVitrification>>>;
|
||||
readonly entry?: Maybe<Entry>;
|
||||
/** Get all groups for this PDB entry. */
|
||||
readonly entry_groups?: Maybe<ReadonlyArray<Maybe<GroupEntry>>>;
|
||||
readonly exptl?: Maybe<ReadonlyArray<Maybe<Exptl>>>;
|
||||
readonly exptl_crystal?: Maybe<ReadonlyArray<Maybe<ExptlCrystal>>>;
|
||||
readonly exptl_crystal_grow?: Maybe<ReadonlyArray<Maybe<ExptlCrystalGrow>>>;
|
||||
@@ -703,6 +705,7 @@ export type CoreEntry = {
|
||||
readonly rcsb_associated_holdings?: Maybe<CurrentEntry>;
|
||||
readonly rcsb_binding_affinity?: Maybe<ReadonlyArray<Maybe<RcsbBindingAffinity>>>;
|
||||
readonly rcsb_entry_container_identifiers: RcsbEntryContainerIdentifiers;
|
||||
readonly rcsb_entry_group_membership?: Maybe<ReadonlyArray<Maybe<RcsbEntryGroupMembership>>>;
|
||||
readonly rcsb_entry_info: RcsbEntryInfo;
|
||||
readonly rcsb_external_references?: Maybe<ReadonlyArray<Maybe<RcsbExternalReferences>>>;
|
||||
/**
|
||||
@@ -851,6 +854,8 @@ export type CorePolymerEntity = {
|
||||
readonly pdbx_entity_src_syn?: Maybe<ReadonlyArray<Maybe<PdbxEntitySrcSyn>>>;
|
||||
/** Get all unique Pfam annotations associated with this molecular entity. */
|
||||
readonly pfams?: Maybe<ReadonlyArray<Maybe<CorePfam>>>;
|
||||
/** Get all groups for this PDB entity. */
|
||||
readonly polymer_entity_groups?: Maybe<ReadonlyArray<Maybe<GroupPolymerEntity>>>;
|
||||
/** Get all unique polymer instances (chains) for this molecular entity. */
|
||||
readonly polymer_entity_instances?: Maybe<ReadonlyArray<Maybe<CorePolymerEntityInstance>>>;
|
||||
/** Get a BIRD chemical components described in this molecular entity. */
|
||||
@@ -887,6 +892,7 @@ export type CorePolymerEntity = {
|
||||
readonly rcsb_polymer_entity_container_identifiers: RcsbPolymerEntityContainerIdentifiers;
|
||||
readonly rcsb_polymer_entity_feature?: Maybe<ReadonlyArray<Maybe<RcsbPolymerEntityFeature>>>;
|
||||
readonly rcsb_polymer_entity_feature_summary?: Maybe<ReadonlyArray<Maybe<RcsbPolymerEntityFeatureSummary>>>;
|
||||
readonly rcsb_polymer_entity_group_membership?: Maybe<ReadonlyArray<Maybe<RcsbPolymerEntityGroupMembership>>>;
|
||||
readonly rcsb_polymer_entity_keywords?: Maybe<RcsbPolymerEntityKeywords>;
|
||||
readonly rcsb_polymer_entity_name_com?: Maybe<ReadonlyArray<Maybe<RcsbPolymerEntityNameCom>>>;
|
||||
readonly rcsb_polymer_entity_name_sys?: Maybe<ReadonlyArray<Maybe<RcsbPolymerEntityNameSys>>>;
|
||||
@@ -3198,6 +3204,46 @@ export type GeneName = {
|
||||
readonly value?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type GroupEntry = {
|
||||
/** Get provenance associated with this group. */
|
||||
readonly group_provenance?: Maybe<GroupProvenance>;
|
||||
readonly rcsb_group_accession_info?: Maybe<RcsbGroupAccessionInfo>;
|
||||
readonly rcsb_group_container_identifiers: RcsbGroupContainerIdentifiers;
|
||||
readonly rcsb_group_info: RcsbGroupInfo;
|
||||
readonly rcsb_group_related?: Maybe<ReadonlyArray<Maybe<RcsbGroupRelated>>>;
|
||||
readonly rcsb_group_statistics?: Maybe<RcsbGroupStatistics>;
|
||||
/** A unique textual identifier for a group */
|
||||
readonly rcsb_id: Scalars['String'];
|
||||
};
|
||||
|
||||
export type GroupMembersAlignmentScores = {
|
||||
readonly query_coverage: Scalars['Int'];
|
||||
readonly query_length: Scalars['Int'];
|
||||
readonly target_coverage: Scalars['Int'];
|
||||
readonly target_length: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type GroupPolymerEntity = {
|
||||
/** Get provenance associated with this group. */
|
||||
readonly group_provenance?: Maybe<GroupProvenance>;
|
||||
readonly rcsb_group_accession_info?: Maybe<RcsbGroupAccessionInfo>;
|
||||
readonly rcsb_group_container_identifiers: RcsbGroupContainerIdentifiers;
|
||||
readonly rcsb_group_info: RcsbGroupInfo;
|
||||
readonly rcsb_group_related?: Maybe<ReadonlyArray<Maybe<RcsbGroupRelated>>>;
|
||||
readonly rcsb_group_statistics?: Maybe<RcsbGroupStatistics>;
|
||||
/** A unique textual identifier for a group */
|
||||
readonly rcsb_id: Scalars['String'];
|
||||
readonly rcsb_polymer_entity_group_members_rankings?: Maybe<ReadonlyArray<Maybe<RcsbPolymerEntityGroupMembersRankings>>>;
|
||||
readonly rcsb_polymer_entity_group_sequence_alignment?: Maybe<RcsbPolymerEntityGroupSequenceAlignment>;
|
||||
};
|
||||
|
||||
export type GroupProvenance = {
|
||||
readonly rcsb_group_aggregation_method?: Maybe<RcsbGroupAggregationMethod>;
|
||||
readonly rcsb_group_provenance_container_identifiers?: Maybe<RcsbGroupProvenanceContainerIdentifiers>;
|
||||
/** A unique textual identifier for a group provenance */
|
||||
readonly rcsb_id?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type InterfacePartnerFeatureAdditionalProperties = {
|
||||
/**
|
||||
* The additional property name.
|
||||
@@ -3220,6 +3266,17 @@ export type InterfacePartnerFeatureFeaturePositions = {
|
||||
readonly values?: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
||||
};
|
||||
|
||||
export type MethodDetails = {
|
||||
/** A description of special aspects of the clustering process */
|
||||
readonly description?: Maybe<Scalars['String']>;
|
||||
/** Defines the name of the description associated with the clustering process */
|
||||
readonly name?: Maybe<Scalars['String']>;
|
||||
/** Defines the type of the description associated with the clustering process */
|
||||
readonly type?: Maybe<Scalars['String']>;
|
||||
/** Defines the value associated with the clustering process */
|
||||
readonly value?: Maybe<Scalars['Float']>;
|
||||
};
|
||||
|
||||
export type PdbxAuditRevisionCategory = {
|
||||
/**
|
||||
* The category updated in the pdbx_audit_revision_category record.
|
||||
@@ -6779,6 +6836,12 @@ export type Query = {
|
||||
readonly entries?: Maybe<ReadonlyArray<Maybe<CoreEntry>>>;
|
||||
/** Get PDB entry given the PDB id. */
|
||||
readonly entry?: Maybe<CoreEntry>;
|
||||
/** Given a group ID get a group object formed by aggregating individual structures that share a degree of similarity */
|
||||
readonly entry_group?: Maybe<GroupEntry>;
|
||||
/** Given a list of group IDs get a list of group objects formed by aggregating structures that share a degree of similarity */
|
||||
readonly entry_groups?: Maybe<ReadonlyArray<Maybe<GroupEntry>>>;
|
||||
/** Given a group provenance ID get an object that describes aggregation method used to create groups */
|
||||
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. */
|
||||
@@ -6795,6 +6858,10 @@ export type Query = {
|
||||
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>;
|
||||
/** Given a group ID get a group object formed by aggregating polymer entities that share a degree of similarity */
|
||||
readonly polymer_entity_group?: Maybe<GroupPolymerEntity>;
|
||||
/** Given a list of group IDs get a list of group objects formed by aggregating polymer entities that share a degree of similarity */
|
||||
readonly polymer_entity_groups?: Maybe<ReadonlyArray<Maybe<GroupPolymerEntity>>>;
|
||||
/** Get a PDB polymer entity instance (chain), given the PDB ID and ENTITY INSTANCE ID. Here ENTITY INSTANCE ID identifies structural element in the asymmetric unit, e.g. 'A', 'B', etc. */
|
||||
readonly polymer_entity_instance?: Maybe<CorePolymerEntityInstance>;
|
||||
/** Get a list of PDB 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. */
|
||||
@@ -6869,6 +6936,24 @@ export type QueryEntryArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** Query root */
|
||||
export type QueryEntry_GroupArgs = {
|
||||
group_id: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
/** Query root */
|
||||
export type QueryEntry_GroupsArgs = {
|
||||
group_ids: ReadonlyArray<InputMaybe<Scalars['String']>>;
|
||||
};
|
||||
|
||||
|
||||
/** Query root */
|
||||
export type QueryGroup_ProvenanceArgs = {
|
||||
group_provenance_id: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
/** Query root */
|
||||
export type QueryInterfaceArgs = {
|
||||
assembly_id: Scalars['String'];
|
||||
@@ -6922,6 +7007,18 @@ export type QueryPolymer_EntityArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** Query root */
|
||||
export type QueryPolymer_Entity_GroupArgs = {
|
||||
group_id: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
/** Query root */
|
||||
export type QueryPolymer_Entity_GroupsArgs = {
|
||||
group_ids: ReadonlyArray<InputMaybe<Scalars['String']>>;
|
||||
};
|
||||
|
||||
|
||||
/** Query root */
|
||||
export type QueryPolymer_Entity_InstanceArgs = {
|
||||
asym_id: Scalars['String'];
|
||||
@@ -8666,6 +8763,25 @@ export type RcsbEntryContainerIdentifiers = {
|
||||
readonly water_entity_ids?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
|
||||
};
|
||||
|
||||
export type RcsbEntryGroupMembership = {
|
||||
/**
|
||||
* Method used to establish group membership
|
||||
*
|
||||
* Allowable values:
|
||||
* matching_deposit_group_id
|
||||
*
|
||||
*/
|
||||
readonly aggregation_method: Scalars['String'];
|
||||
/**
|
||||
* A unique identifier for a group of entries
|
||||
*
|
||||
* Examples:
|
||||
* G_1001001
|
||||
*
|
||||
*/
|
||||
readonly group_id: Scalars['String'];
|
||||
};
|
||||
|
||||
export type RcsbEntryInfo = {
|
||||
/** The number of assemblies defined for this entry including the deposited assembly. */
|
||||
readonly assembly_count?: Maybe<Scalars['Int']>;
|
||||
@@ -8893,6 +9009,127 @@ export type RcsbGenomicLineage = {
|
||||
readonly name?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbGroupAccessionInfo = {
|
||||
/** Identifies the version of the groups solution */
|
||||
readonly version: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type RcsbGroupAggregationMethod = {
|
||||
/** The details on a method used to calculate cluster solutions */
|
||||
readonly method: RcsbGroupAggregationMethodMethod;
|
||||
readonly similarity_criteria?: Maybe<RcsbGroupAggregationMethodSimilarityCriteria>;
|
||||
/**
|
||||
* Specifies the type of similarity criteria used to aggregate members into higher levels in the hierarchy
|
||||
*
|
||||
* Allowable values:
|
||||
* sequence_identity, matching_uniprot_accession, matching_deposit_group_id
|
||||
*
|
||||
*/
|
||||
readonly type: Scalars['String'];
|
||||
};
|
||||
|
||||
export type RcsbGroupAggregationMethodMethod = {
|
||||
/** Additional details describing the clustering process */
|
||||
readonly details?: Maybe<ReadonlyArray<Maybe<MethodDetails>>>;
|
||||
/**
|
||||
* The name of the software or the method used to calculate cluster solutions
|
||||
*
|
||||
* Allowable values:
|
||||
* mmseqs2, matching_reference_identity
|
||||
*
|
||||
*/
|
||||
readonly name: Scalars['String'];
|
||||
/**
|
||||
* The version of the software.
|
||||
*
|
||||
* Examples:
|
||||
* v1.0, 3.1-2, unknown
|
||||
*
|
||||
*/
|
||||
readonly version?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbGroupAggregationMethodSimilarityCriteria = {
|
||||
/**
|
||||
* A function or similarity measure that quantifies the similarity between two members
|
||||
*
|
||||
* Allowable values:
|
||||
* rmsd, sequence_identity
|
||||
*
|
||||
*/
|
||||
readonly similarity_function?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbGroupContainerIdentifiers = {
|
||||
/** A unique textual identifier for a group */
|
||||
readonly group_id: Scalars['String'];
|
||||
/** Member identifiers representing a group */
|
||||
readonly group_member_ids: ReadonlyArray<Maybe<Scalars['String']>>;
|
||||
/**
|
||||
* A unique group provenance identifier
|
||||
*
|
||||
* Allowable values:
|
||||
* provenance_sequence_identity, provenance_matching_uniprot_accession, provenance_matching_deposit_group_id
|
||||
*
|
||||
*/
|
||||
readonly group_provenance_id: Scalars['String'];
|
||||
/** Member identifiers representing a higher level in the groping hierarchy that has parent-child relationship */
|
||||
readonly parent_member_ids?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
|
||||
};
|
||||
|
||||
export type RcsbGroupInfo = {
|
||||
readonly group_description?: Maybe<Scalars['String']>;
|
||||
readonly group_members_count: Scalars['Int'];
|
||||
/**
|
||||
* Granularity of group members identifiers
|
||||
*
|
||||
* Allowable values:
|
||||
* assembly, entry, polymer_entity, polymer_entity_instance
|
||||
*
|
||||
*/
|
||||
readonly group_members_granularity: Scalars['String'];
|
||||
readonly group_name?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbGroupProvenanceContainerIdentifiers = {
|
||||
/**
|
||||
* A unique group provenance identifier
|
||||
*
|
||||
* Allowable values:
|
||||
* provenance_sequence_identity, provenance_matching_uniprot_accession, provenance_matching_deposit_group_id
|
||||
*
|
||||
*/
|
||||
readonly group_provenance_id: Scalars['String'];
|
||||
};
|
||||
|
||||
export type RcsbGroupRelated = {
|
||||
/**
|
||||
* A unique code assigned to a reference related the group
|
||||
*
|
||||
* Examples:
|
||||
* P69905
|
||||
*
|
||||
*/
|
||||
readonly resource_accession_code?: Maybe<Scalars['String']>;
|
||||
/**
|
||||
* Defines the type of the resource describing related references
|
||||
*
|
||||
* Examples:
|
||||
* UniProt
|
||||
*
|
||||
*/
|
||||
readonly resource_name?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbGroupStatistics = {
|
||||
/** The desired lower limit for the similarity between two members that belong to the same group */
|
||||
readonly similarity_cutoff?: Maybe<Scalars['Float']>;
|
||||
/** Similarity score between two most similar group members */
|
||||
readonly similarity_score_max?: Maybe<Scalars['Float']>;
|
||||
/** Similarity score between two least similar group members */
|
||||
readonly similarity_score_min?: Maybe<Scalars['Float']>;
|
||||
};
|
||||
|
||||
export type RcsbInterfaceContainerIdentifiers = {
|
||||
/** This item references an assembly in pdbx_struct_assembly */
|
||||
readonly assembly_id: Scalars['String'];
|
||||
@@ -9902,6 +10139,7 @@ export type RcsbPolymerEntity = {
|
||||
*
|
||||
*/
|
||||
readonly rcsb_multiple_source_flag?: Maybe<Scalars['String']>;
|
||||
readonly rcsb_polymer_name_combined?: Maybe<RcsbPolymerEntityRcsbPolymerNameCombined>;
|
||||
/**
|
||||
* The number of biological sources for the polymer entity. Multiple source contributions
|
||||
* may come from the same organism (taxonomy).
|
||||
@@ -10228,6 +10466,69 @@ export type RcsbPolymerEntityFeatureSummary = {
|
||||
readonly type?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityGroupMembersRankings = {
|
||||
readonly group_members: ReadonlyArray<Maybe<RcsbPolymerEntityGroupMembersRankingsGroupMembers>>;
|
||||
/**
|
||||
* Defines ranking option applicable to group members
|
||||
*
|
||||
* Allowable values:
|
||||
* coverage
|
||||
*
|
||||
*/
|
||||
readonly ranking_criteria_type: Scalars['String'];
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityGroupMembersRankingsGroupMembers = {
|
||||
readonly member_id: Scalars['String'];
|
||||
/** Quantifies the criteria used for ranking */
|
||||
readonly original_score?: Maybe<Scalars['Float']>;
|
||||
/** Reflects a relationship between group members such that, for any two members the first is ranked higher (smaller rank value) than the second */
|
||||
readonly rank: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityGroupMembership = {
|
||||
/**
|
||||
* Method used to establish group membership
|
||||
*
|
||||
* Allowable values:
|
||||
* sequence_identity, matching_uniprot_accession
|
||||
*
|
||||
*/
|
||||
readonly aggregation_method: Scalars['String'];
|
||||
/**
|
||||
* A unique identifier for a group of entities
|
||||
*
|
||||
* Examples:
|
||||
* 1_100, P00003
|
||||
*
|
||||
*/
|
||||
readonly group_id: Scalars['String'];
|
||||
/** Degree of similarity expressed as a floating-point number */
|
||||
readonly similarity_cutoff?: Maybe<Scalars['Float']>;
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityGroupSequenceAlignment = {
|
||||
/** Abstract reference where group members can be aligned to generate a MSA */
|
||||
readonly abstract_reference: RcsbPolymerEntityGroupSequenceAlignmentAbstractReference;
|
||||
/** Alignment with a core_entity canonical sequence */
|
||||
readonly group_members_alignment: ReadonlyArray<Maybe<RcsbPolymerEntityGroupSequenceAlignmentGroupMembersAlignment>>;
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityGroupSequenceAlignmentAbstractReference = {
|
||||
/** Abstract reference length */
|
||||
readonly length: Scalars['Int'];
|
||||
/** Sequence that represents the abstract reference */
|
||||
readonly sequence?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityGroupSequenceAlignmentGroupMembersAlignment = {
|
||||
/** Alignment region encoded as a triplet [query_begin, target_begin, length] */
|
||||
readonly aligned_regions: ReadonlyArray<Maybe<ReadonlyArray<Maybe<Scalars['Int']>>>>;
|
||||
readonly member_id: Scalars['String'];
|
||||
/** Alignment scores */
|
||||
readonly scores: GroupMembersAlignmentScores;
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityInstanceContainerIdentifiers = {
|
||||
/** Instance identifier for this container. */
|
||||
readonly asym_id: Scalars['String'];
|
||||
@@ -10346,6 +10647,13 @@ export type RcsbPolymerEntityRcsbMacromolecularNamesCombined = {
|
||||
readonly provenance_source?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbPolymerEntityRcsbPolymerNameCombined = {
|
||||
/** Protein name annotated by the UniProtKB or macromolecular name assigned by the PDB */
|
||||
readonly names?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
|
||||
/** Allowable values: PDB Preferred Name, PDB Description, UniProt Name. */
|
||||
readonly provenance_source?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type RcsbPolymerInstanceAnnotation = {
|
||||
/** An identifier for the annotation. */
|
||||
readonly annotation_id?: Maybe<Scalars['String']>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 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>
|
||||
@@ -30,7 +30,7 @@ import { PickData } from './passes/pick';
|
||||
import { PickHelper } from './passes/pick';
|
||||
import { ImagePass, ImageProps } from './passes/image';
|
||||
import { Sphere3D } from '../mol-math/geometry';
|
||||
import { isDebugMode } from '../mol-util/debug';
|
||||
import { isDebugMode, isTimingMode } from '../mol-util/debug';
|
||||
import { CameraHelperParams } from './helper/camera-helper';
|
||||
import { produce } from 'immer';
|
||||
import { HandleHelperParams } from './helper/handle-helper';
|
||||
@@ -372,12 +372,12 @@ namespace Canvas3D {
|
||||
const { repr, loci } = reprLoci;
|
||||
let changed = false;
|
||||
if (repr) {
|
||||
changed = repr.mark(loci, action);
|
||||
changed = repr.mark(loci, action) || changed;
|
||||
} else {
|
||||
changed = helper.handle.mark(loci, action);
|
||||
changed = helper.camera.mark(loci, action) || changed;
|
||||
reprRenderObjects.forEach((_, _repr) => { changed = _repr.mark(loci, action) || changed; });
|
||||
}
|
||||
changed = helper.handle.mark(loci, action) || changed;
|
||||
changed = helper.camera.mark(loci, action) || changed;
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -413,6 +413,7 @@ namespace Canvas3D {
|
||||
cam = stereoCamera;
|
||||
}
|
||||
|
||||
if (isTimingMode) webgl.timer.mark('Canvas3D.render');
|
||||
const ctx = { renderer, camera: cam, scene, helper };
|
||||
if (MultiSamplePass.isEnabled(p.multiSample)) {
|
||||
const forceOn = !cameraChanged && markingUpdated && !controls.isAnimating;
|
||||
@@ -420,6 +421,8 @@ namespace Canvas3D {
|
||||
} else {
|
||||
passes.draw.render(ctx, p, true);
|
||||
}
|
||||
if (isTimingMode) webgl.timer.markEnd('Canvas3D.render');
|
||||
|
||||
// if only marking has updated, do not set the flag to dirty
|
||||
pickHelper.dirty = pickHelper.dirty || shouldRender;
|
||||
didRender = true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -17,7 +17,7 @@ import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
import { GraphicsRenderVariantsBlended } from '../../mol-gl/webgl/render-item';
|
||||
import { Sphere3D } from '../../mol-math/geometry';
|
||||
import { Mat4, Vec3 } from '../../mol-math/linear-algebra';
|
||||
import { DataLoci, EmptyLoci, Loci } from '../../mol-model/loci';
|
||||
import { DataLoci, EmptyLoci, isEveryLoci, Loci } from '../../mol-model/loci';
|
||||
import { Shape } from '../../mol-model/shape';
|
||||
import { Visual } from '../../mol-repr/visual';
|
||||
import { ColorNames } from '../../mol-util/color/names';
|
||||
@@ -113,8 +113,10 @@ export class CameraHelper {
|
||||
|
||||
mark(loci: Loci, action: MarkerAction) {
|
||||
if (!MarkerActions.is(MarkerActions.Highlighting, action)) return false;
|
||||
if (!isCameraAxesLoci(loci)) return false;
|
||||
if (loci.data !== this) return false;
|
||||
if (!isEveryLoci(loci)) {
|
||||
if (!isCameraAxesLoci(loci)) return false;
|
||||
if (loci.data !== this) return false;
|
||||
}
|
||||
return Visual.mark(this.renderObject, loci, action, this.eachGroup);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ import produce from 'immer';
|
||||
import { Shape } from '../../mol-model/shape';
|
||||
import { PickingId } from '../../mol-geo/geometry/picking';
|
||||
import { Camera } from '../camera';
|
||||
import { DataLoci, EmptyLoci, Loci } from '../../mol-model/loci';
|
||||
import { DataLoci, EmptyLoci, isEveryLoci, Loci } from '../../mol-model/loci';
|
||||
import { MarkerAction, MarkerActions } from '../../mol-util/marker-action';
|
||||
import { Visual } from '../../mol-repr/visual';
|
||||
import { Interval } from '../../mol-data/int';
|
||||
@@ -121,8 +121,10 @@ export class HandleHelper {
|
||||
|
||||
mark(loci: Loci, action: MarkerAction) {
|
||||
if (!MarkerActions.is(MarkerActions.Highlighting, action)) return false;
|
||||
if (!isHandleLoci(loci)) return false;
|
||||
if (loci.data !== this) return false;
|
||||
if (!isEveryLoci(loci)) {
|
||||
if (!isHandleLoci(loci)) return false;
|
||||
if (loci.data !== this) return false;
|
||||
}
|
||||
return Visual.mark(this.renderObject, loci, action, this.eachGroup);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,47 +11,16 @@ import { Renderer } from '../../mol-gl/renderer';
|
||||
import { Scene } from '../../mol-gl/scene';
|
||||
import { Texture } from '../../mol-gl/webgl/texture';
|
||||
import { Camera, ICamera } from '../camera';
|
||||
import { QuadSchema, QuadValues } from '../../mol-gl/compute/util';
|
||||
import { DefineSpec, TextureSpec, UniformSpec, Values } from '../../mol-gl/renderable/schema';
|
||||
import { ComputeRenderable, createComputeRenderable } from '../../mol-gl/renderable';
|
||||
import { ShaderCode } from '../../mol-gl/shader-code';
|
||||
import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
import { Vec2 } from '../../mol-math/linear-algebra';
|
||||
import { Helper } from '../helper/helper';
|
||||
|
||||
import { quad_vert } from '../../mol-gl/shader/quad.vert';
|
||||
import { depthMerge_frag } from '../../mol-gl/shader/depth-merge.frag';
|
||||
import { StereoCamera } from '../camera/stereo';
|
||||
import { WboitPass } from './wboit';
|
||||
import { AntialiasingPass, PostprocessingPass, PostprocessingProps } from './postprocessing';
|
||||
import { MarkingPass, MarkingProps } from './marking';
|
||||
import { CopyRenderable, createCopyRenderable } from '../../mol-gl/compute/util';
|
||||
|
||||
const DepthMergeSchema = {
|
||||
...QuadSchema,
|
||||
tDepthPrimitives: TextureSpec('texture', 'depth', 'ushort', 'nearest'),
|
||||
tDepthVolumes: TextureSpec('texture', 'depth', 'ushort', 'nearest'),
|
||||
uTexSize: UniformSpec('v2'),
|
||||
dPackedDepth: DefineSpec('boolean'),
|
||||
};
|
||||
const DepthMergeShaderCode = ShaderCode('depth-merge', quad_vert, depthMerge_frag);
|
||||
type DepthMergeRenderable = ComputeRenderable<Values<typeof DepthMergeSchema>>
|
||||
|
||||
function getDepthMergeRenderable(ctx: WebGLContext, depthTexturePrimitives: Texture, depthTextureVolumes: Texture, packedDepth: boolean): DepthMergeRenderable {
|
||||
const values: Values<typeof DepthMergeSchema> = {
|
||||
...QuadValues,
|
||||
tDepthPrimitives: ValueCell.create(depthTexturePrimitives),
|
||||
tDepthVolumes: ValueCell.create(depthTextureVolumes),
|
||||
uTexSize: ValueCell.create(Vec2.create(depthTexturePrimitives.getWidth(), depthTexturePrimitives.getHeight())),
|
||||
dPackedDepth: ValueCell.create(packedDepth),
|
||||
};
|
||||
|
||||
const schema = { ...DepthMergeSchema };
|
||||
const renderItem = createComputeRenderItem(ctx, 'triangles', DepthMergeShaderCode, schema, values);
|
||||
|
||||
return createComputeRenderable(renderItem, values);
|
||||
}
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
type Props = {
|
||||
postprocessing: PostprocessingProps
|
||||
@@ -70,16 +39,13 @@ export class DrawPass {
|
||||
private readonly drawTarget: RenderTarget;
|
||||
|
||||
readonly colorTarget: RenderTarget;
|
||||
readonly depthTexture: Texture;
|
||||
readonly depthTexturePrimitives: Texture;
|
||||
readonly depthTextureTransparent: Texture;
|
||||
readonly depthTextureOpaque: Texture;
|
||||
|
||||
readonly packedDepth: boolean;
|
||||
|
||||
private depthTarget: RenderTarget;
|
||||
private depthTargetPrimitives: RenderTarget | null;
|
||||
private depthTargetVolumes: RenderTarget | null;
|
||||
private depthTextureVolumes: Texture;
|
||||
private depthMerge: DepthMergeRenderable;
|
||||
private depthTargetTransparent: RenderTarget;
|
||||
private depthTargetOpaque: RenderTarget | null;
|
||||
|
||||
private copyFboTarget: CopyRenderable;
|
||||
private copyFboPostprocessing: CopyRenderable;
|
||||
@@ -101,19 +67,15 @@ export class DrawPass {
|
||||
this.colorTarget = webgl.createRenderTarget(width, height, true, 'uint8', 'linear');
|
||||
this.packedDepth = !extensions.depthTexture;
|
||||
|
||||
this.depthTarget = webgl.createRenderTarget(width, height);
|
||||
this.depthTexture = this.depthTarget.texture;
|
||||
this.depthTargetTransparent = webgl.createRenderTarget(width, height);
|
||||
this.depthTextureTransparent = this.depthTargetTransparent.texture;
|
||||
|
||||
this.depthTargetPrimitives = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
|
||||
this.depthTargetVolumes = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
|
||||
this.depthTargetOpaque = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
|
||||
|
||||
this.depthTexturePrimitives = this.depthTargetPrimitives ? this.depthTargetPrimitives.texture : resources.texture('image-depth', 'depth', isWebGL2 ? 'float' : 'ushort', 'nearest');
|
||||
this.depthTextureVolumes = this.depthTargetVolumes ? this.depthTargetVolumes.texture : resources.texture('image-depth', 'depth', isWebGL2 ? 'float' : 'ushort', 'nearest');
|
||||
this.depthTextureOpaque = this.depthTargetOpaque ? this.depthTargetOpaque.texture : resources.texture('image-depth', 'depth', isWebGL2 ? 'float' : 'ushort', 'nearest');
|
||||
if (!this.packedDepth) {
|
||||
this.depthTexturePrimitives.define(width, height);
|
||||
this.depthTextureVolumes.define(width, height);
|
||||
this.depthTextureOpaque.define(width, height);
|
||||
}
|
||||
this.depthMerge = getDepthMergeRenderable(webgl, this.depthTexturePrimitives, this.depthTextureVolumes, this.packedDepth);
|
||||
|
||||
this.wboit = enableWboit ? new WboitPass(webgl, width, height) : undefined;
|
||||
this.marking = new MarkingPass(webgl, width, height);
|
||||
@@ -134,22 +96,14 @@ export class DrawPass {
|
||||
|
||||
if (width !== w || height !== h) {
|
||||
this.colorTarget.setSize(width, height);
|
||||
this.depthTarget.setSize(width, height);
|
||||
this.depthTargetTransparent.setSize(width, height);
|
||||
|
||||
if (this.depthTargetPrimitives) {
|
||||
this.depthTargetPrimitives.setSize(width, height);
|
||||
if (this.depthTargetOpaque) {
|
||||
this.depthTargetOpaque.setSize(width, height);
|
||||
} else {
|
||||
this.depthTexturePrimitives.define(width, height);
|
||||
this.depthTextureOpaque.define(width, height);
|
||||
}
|
||||
|
||||
if (this.depthTargetVolumes) {
|
||||
this.depthTargetVolumes.setSize(width, height);
|
||||
} else {
|
||||
this.depthTextureVolumes.define(width, height);
|
||||
}
|
||||
|
||||
ValueCell.update(this.depthMerge.values.uTexSize, Vec2.set(this.depthMerge.values.uTexSize.ref.value, width, height));
|
||||
|
||||
ValueCell.update(this.copyFboTarget.values.uTexSize, Vec2.set(this.copyFboTarget.values.uTexSize.ref.value, width, height));
|
||||
ValueCell.update(this.copyFboPostprocessing.values.uTexSize, Vec2.set(this.copyFboPostprocessing.values.uTexSize.ref.value, width, height));
|
||||
|
||||
@@ -163,20 +117,6 @@ export class DrawPass {
|
||||
}
|
||||
}
|
||||
|
||||
private _depthMerge() {
|
||||
const { state, gl } = this.webgl;
|
||||
|
||||
this.depthMerge.update();
|
||||
this.depthTarget.bind();
|
||||
state.disable(gl.BLEND);
|
||||
state.disable(gl.DEPTH_TEST);
|
||||
state.disable(gl.CULL_FACE);
|
||||
state.depthMask(false);
|
||||
state.clearColor(1, 1, 1, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
this.depthMerge.render();
|
||||
}
|
||||
|
||||
private _renderWboit(renderer: Renderer, camera: ICamera, scene: Scene, transparentBackground: boolean, postprocessingProps: PostprocessingProps) {
|
||||
if (!this.wboit?.supported) throw new Error('expected wboit to be supported');
|
||||
|
||||
@@ -184,38 +124,41 @@ export class DrawPass {
|
||||
renderer.clear(true);
|
||||
|
||||
// render opaque primitives
|
||||
this.depthTexturePrimitives.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
this.depthTextureOpaque.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
this.colorTarget.bind();
|
||||
renderer.clearDepth();
|
||||
renderer.renderWboitOpaque(scene.primitives, camera, null);
|
||||
|
||||
// render opaque volumes
|
||||
this.depthTextureVolumes.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
this.colorTarget.bind();
|
||||
renderer.clearDepth();
|
||||
renderer.renderWboitOpaque(scene.volumes, camera, this.depthTexturePrimitives);
|
||||
|
||||
// merge depth of opaque primitives and volumes
|
||||
this._depthMerge();
|
||||
|
||||
if (PostprocessingPass.isEnabled(postprocessingProps)) {
|
||||
if (PostprocessingPass.isOutlineEnabled(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);
|
||||
}
|
||||
|
||||
// render transparent primitives and volumes
|
||||
this.wboit.bind();
|
||||
renderer.renderWboitTransparent(scene.primitives, camera, this.depthTexture);
|
||||
renderer.renderWboitTransparent(scene.volumes, camera, this.depthTexture);
|
||||
if (scene.opacityAverage < 1 || scene.volumes.renderables.length > 0) {
|
||||
this.wboit.bind();
|
||||
if (scene.opacityAverage < 1) {
|
||||
renderer.renderWboitTransparent(scene.primitives, camera, this.depthTextureOpaque);
|
||||
}
|
||||
if (scene.volumes.renderables.length > 0) {
|
||||
renderer.renderWboitTransparent(scene.volumes, camera, this.depthTextureOpaque);
|
||||
}
|
||||
|
||||
// evaluate wboit
|
||||
if (PostprocessingPass.isEnabled(postprocessingProps)) {
|
||||
this.depthTexturePrimitives.attachFramebuffer(this.postprocessing.target.framebuffer, 'depth');
|
||||
this.postprocessing.target.bind();
|
||||
} else {
|
||||
this.depthTexturePrimitives.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
this.colorTarget.bind();
|
||||
// evaluate wboit
|
||||
if (PostprocessingPass.isEnabled(postprocessingProps)) {
|
||||
this.postprocessing.target.bind();
|
||||
} else {
|
||||
this.colorTarget.bind();
|
||||
}
|
||||
this.wboit.render();
|
||||
}
|
||||
this.wboit.render();
|
||||
}
|
||||
|
||||
private _renderBlended(renderer: Renderer, camera: ICamera, scene: Scene, toDrawingBuffer: boolean, transparentBackground: boolean, postprocessingProps: PostprocessingProps) {
|
||||
@@ -224,7 +167,7 @@ export class DrawPass {
|
||||
} else {
|
||||
this.colorTarget.bind();
|
||||
if (!this.packedDepth) {
|
||||
this.depthTexturePrimitives.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
this.depthTextureOpaque.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,47 +177,62 @@ export class DrawPass {
|
||||
if (!toDrawingBuffer) {
|
||||
// do a depth pass if not rendering to drawing buffer and
|
||||
// extensions.depthTexture is unsupported (i.e. depthTarget is set)
|
||||
if (this.depthTargetPrimitives) {
|
||||
this.depthTargetPrimitives.bind();
|
||||
renderer.clear(false);
|
||||
// TODO: this should only render opaque
|
||||
renderer.renderDepth(scene.primitives, camera, null);
|
||||
if (this.depthTargetOpaque) {
|
||||
this.depthTargetOpaque.bind();
|
||||
renderer.clearDepth(true);
|
||||
renderer.renderDepthOpaque(scene.primitives, camera, null);
|
||||
this.colorTarget.bind();
|
||||
}
|
||||
|
||||
// do direct-volume rendering
|
||||
if (!this.packedDepth) {
|
||||
this.depthTextureVolumes.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
||||
renderer.clearDepth(); // from previous frame
|
||||
}
|
||||
renderer.renderBlendedVolumeOpaque(scene.volumes, camera, this.depthTexturePrimitives);
|
||||
|
||||
// do volume depth pass if extensions.depthTexture is unsupported (i.e. depthTarget is set)
|
||||
if (this.depthTargetVolumes) {
|
||||
this.depthTargetVolumes.bind();
|
||||
renderer.clear(false);
|
||||
renderer.renderDepth(scene.volumes, camera, this.depthTexturePrimitives);
|
||||
this.colorTarget.bind();
|
||||
}
|
||||
|
||||
// merge depths from primitive and volume rendering
|
||||
this._depthMerge();
|
||||
this.colorTarget.bind();
|
||||
|
||||
if (PostprocessingPass.isEnabled(postprocessingProps)) {
|
||||
this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps);
|
||||
}
|
||||
renderer.renderBlendedVolumeTransparent(scene.volumes, camera, this.depthTexturePrimitives);
|
||||
if (!this.packedDepth) {
|
||||
this.depthTextureOpaque.detachFramebuffer(this.postprocessing.target.framebuffer, 'depth');
|
||||
} else {
|
||||
this.colorTarget.depthRenderbuffer?.detachFramebuffer(this.postprocessing.target.framebuffer);
|
||||
}
|
||||
|
||||
const target = PostprocessingPass.isEnabled(postprocessingProps)
|
||||
? this.postprocessing.target : this.colorTarget;
|
||||
if (!this.packedDepth) {
|
||||
this.depthTexturePrimitives.attachFramebuffer(target.framebuffer, 'depth');
|
||||
if (PostprocessingPass.isOutlineEnabled(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);
|
||||
|
||||
if (!this.packedDepth) {
|
||||
this.depthTextureOpaque.attachFramebuffer(this.postprocessing.target.framebuffer, 'depth');
|
||||
} else {
|
||||
this.colorTarget.depthRenderbuffer?.attachFramebuffer(this.postprocessing.target.framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (scene.volumes.renderables.length > 0) {
|
||||
const target = PostprocessingPass.isEnabled(postprocessingProps)
|
||||
? this.postprocessing.target : this.colorTarget;
|
||||
|
||||
if (!this.packedDepth) {
|
||||
this.depthTextureOpaque.detachFramebuffer(target.framebuffer, 'depth');
|
||||
} else {
|
||||
this.colorTarget.depthRenderbuffer?.detachFramebuffer(target.framebuffer);
|
||||
}
|
||||
target.bind();
|
||||
|
||||
renderer.renderBlendedVolume(scene.volumes, camera, this.depthTextureOpaque);
|
||||
|
||||
if (!this.packedDepth) {
|
||||
this.depthTextureOpaque.attachFramebuffer(target.framebuffer, 'depth');
|
||||
} else {
|
||||
this.colorTarget.depthRenderbuffer?.attachFramebuffer(target.framebuffer);
|
||||
}
|
||||
target.bind();
|
||||
}
|
||||
target.bind();
|
||||
}
|
||||
|
||||
renderer.renderBlendedTransparent(scene.primitives, camera, null);
|
||||
if (scene.opacityAverage < 1) {
|
||||
renderer.renderBlendedTransparent(scene.primitives, camera, null);
|
||||
}
|
||||
}
|
||||
|
||||
private _render(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, props: Props) {
|
||||
@@ -307,10 +265,9 @@ export class DrawPass {
|
||||
}
|
||||
|
||||
if (markingEnabled) {
|
||||
const markerAverage = scene.getMarkerAverage();
|
||||
if (markerAverage > 0) {
|
||||
if (scene.markerAverage > 0) {
|
||||
const markingDepthTest = props.marking.ghostEdgeStrength < 1;
|
||||
if (markingDepthTest && markerAverage !== 1) {
|
||||
if (markingDepthTest && scene.markerAverage !== 1) {
|
||||
this.marking.depthTarget.bind();
|
||||
renderer.clear(false, true);
|
||||
renderer.renderMarkingDepth(scene.primitives, camera, null);
|
||||
@@ -355,6 +312,7 @@ export class DrawPass {
|
||||
}
|
||||
|
||||
render(ctx: RenderContext, props: Props, toDrawingBuffer: boolean) {
|
||||
if (isTimingMode) this.webgl.timer.mark('DrawPass.render');
|
||||
const { renderer, camera, scene, helper } = ctx;
|
||||
renderer.setTransparentBackground(props.transparentBackground);
|
||||
renderer.setDrawingBufferSize(this.colorTarget.getWidth(), this.colorTarget.getHeight());
|
||||
@@ -366,6 +324,7 @@ export class DrawPass {
|
||||
} else {
|
||||
this._render(renderer, camera, scene, helper, toDrawingBuffer, props);
|
||||
}
|
||||
if (isTimingMode) this.webgl.timer.markEnd('DrawPass.render');
|
||||
}
|
||||
|
||||
getColorTarget(postprocessingProps: PostprocessingProps): RenderTarget {
|
||||
|
||||
@@ -18,6 +18,7 @@ import { quad_vert } from '../../mol-gl/shader/quad.vert';
|
||||
import { fxaa_frag } from '../../mol-gl/shader/fxaa.frag';
|
||||
import { Viewport } from '../camera/util';
|
||||
import { RenderTarget } from '../../mol-gl/webgl/render-target';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
export const FxaaParams = {
|
||||
edgeThresholdMin: PD.Numeric(0.0312, { min: 0.0312, max: 0.0833, step: 0.0001 }, { description: 'Trims the algorithm from processing darks.' }),
|
||||
@@ -83,6 +84,7 @@ export class FxaaPass {
|
||||
}
|
||||
|
||||
render(viewport: Viewport, target: RenderTarget | undefined) {
|
||||
if (isTimingMode) this.webgl.timer.mark('FxaaPass.render');
|
||||
if (target) {
|
||||
target.bind();
|
||||
} else {
|
||||
@@ -90,6 +92,7 @@ export class FxaaPass {
|
||||
}
|
||||
this.updateState(viewport);
|
||||
this.renderable.render();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('FxaaPass.render');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Viewport } from '../camera/util';
|
||||
import { RenderTarget } from '../../mol-gl/webgl/render-target';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import { edge_frag } from '../../mol-gl/shader/marking/edge.frag';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
export const MarkingParams = {
|
||||
enabled: PD.Boolean(true),
|
||||
@@ -117,6 +118,7 @@ export class MarkingPass {
|
||||
}
|
||||
|
||||
render(viewport: Viewport, target: RenderTarget | undefined) {
|
||||
if (isTimingMode) this.webgl.timer.mark('MarkingPass.render');
|
||||
this.edgesTarget.bind();
|
||||
this.setEdgeState(viewport);
|
||||
this.edge.render();
|
||||
@@ -128,6 +130,7 @@ export class MarkingPass {
|
||||
}
|
||||
this.setOverlayState(viewport);
|
||||
this.overlay.render();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('MarkingPass.render');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import { StereoCamera } from '../camera/stereo';
|
||||
import { quad_vert } from '../../mol-gl/shader/quad.vert';
|
||||
import { compose_frag } from '../../mol-gl/shader/compose.frag';
|
||||
import { MarkingProps } from './marking';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
const ComposeSchema = {
|
||||
...QuadSchema,
|
||||
@@ -126,6 +127,7 @@ export class MultiSamplePass {
|
||||
const { camera } = ctx;
|
||||
const { compose, composeTarget, drawPass, webgl } = this;
|
||||
const { gl, state } = webgl;
|
||||
if (isTimingMode) webgl.timer.mark('MultiSamplePass.renderMultiSample');
|
||||
|
||||
// based on the Multisample Anti-Aliasing Render Pass
|
||||
// contributed to three.js by bhouston / http://clara.io/
|
||||
@@ -198,12 +200,14 @@ export class MultiSamplePass {
|
||||
|
||||
camera.viewOffset.enabled = false;
|
||||
camera.update();
|
||||
if (isTimingMode) webgl.timer.markEnd('MultiSamplePass.renderMultiSample');
|
||||
}
|
||||
|
||||
private renderTemporalMultiSample(sampleIndex: number, ctx: RenderContext, props: Props, toDrawingBuffer: boolean) {
|
||||
const { camera } = ctx;
|
||||
const { compose, composeTarget, holdTarget, drawPass, webgl } = this;
|
||||
const { gl, state } = webgl;
|
||||
if (isTimingMode) webgl.timer.mark('MultiSamplePass.renderTemporalMultiSample');
|
||||
|
||||
// based on the Multisample Anti-Aliasing Render Pass
|
||||
// contributed to three.js by bhouston / http://clara.io/
|
||||
@@ -301,6 +305,7 @@ export class MultiSamplePass {
|
||||
|
||||
camera.viewOffset.enabled = false;
|
||||
camera.update();
|
||||
if (isTimingMode) webgl.timer.markEnd('MultiSamplePass.renderTemporalMultiSample');
|
||||
|
||||
return sampleIndex >= offsetList.length ? -2 : sampleIndex;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -7,11 +7,15 @@
|
||||
import { PickingId } from '../../mol-geo/geometry/picking';
|
||||
import { PickType, Renderer } from '../../mol-gl/renderer';
|
||||
import { Scene } from '../../mol-gl/scene';
|
||||
import { isWebGL2 } from '../../mol-gl/webgl/compat';
|
||||
import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
import { GraphicsRenderVariant } from '../../mol-gl/webgl/render-item';
|
||||
import { Framebuffer } from '../../mol-gl/webgl/framebuffer';
|
||||
import { RenderTarget } from '../../mol-gl/webgl/render-target';
|
||||
import { Renderbuffer } from '../../mol-gl/webgl/renderbuffer';
|
||||
import { Texture } from '../../mol-gl/webgl/texture';
|
||||
import { Vec3 } from '../../mol-math/linear-algebra';
|
||||
import { spiral2d } from '../../mol-math/misc';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
import { unpackRGBToInt, unpackRGBAToDepth } from '../../mol-util/number-packing';
|
||||
import { Camera, ICamera } from '../camera';
|
||||
import { StereoCamera } from '../camera/stereo';
|
||||
@@ -25,10 +29,24 @@ const NullId = Math.pow(2, 24) - 2;
|
||||
export type PickData = { id: PickingId, position: Vec3 }
|
||||
|
||||
export class PickPass {
|
||||
readonly objectPickTarget: RenderTarget;
|
||||
readonly instancePickTarget: RenderTarget;
|
||||
readonly groupPickTarget: RenderTarget;
|
||||
readonly depthPickTarget: RenderTarget;
|
||||
private readonly objectPickTarget: RenderTarget;
|
||||
private readonly instancePickTarget: RenderTarget;
|
||||
private readonly groupPickTarget: RenderTarget;
|
||||
private readonly depthPickTarget: RenderTarget;
|
||||
|
||||
private readonly framebuffer: Framebuffer;
|
||||
|
||||
private readonly objectPickTexture: Texture;
|
||||
private readonly instancePickTexture: Texture;
|
||||
private readonly groupPickTexture: Texture;
|
||||
private readonly depthPickTexture: Texture;
|
||||
|
||||
private readonly objectPickFramebuffer: Framebuffer;
|
||||
private readonly instancePickFramebuffer: Framebuffer;
|
||||
private readonly groupPickFramebuffer: Framebuffer;
|
||||
private readonly depthPickFramebuffer: Framebuffer;
|
||||
|
||||
private readonly depthRenderbuffer: Renderbuffer;
|
||||
|
||||
private pickWidth: number;
|
||||
private pickHeight: number;
|
||||
@@ -38,10 +56,89 @@ export class PickPass {
|
||||
this.pickWidth = Math.ceil(drawPass.colorTarget.getWidth() * pickScale);
|
||||
this.pickHeight = Math.ceil(drawPass.colorTarget.getHeight() * pickScale);
|
||||
|
||||
this.objectPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
this.instancePickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
this.groupPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
this.depthPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
const { resources, extensions: { drawBuffers }, gl } = webgl;
|
||||
|
||||
if (drawBuffers) {
|
||||
this.objectPickTexture = resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
this.objectPickTexture.define(this.pickWidth, this.pickHeight);
|
||||
|
||||
this.instancePickTexture = resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
this.instancePickTexture.define(this.pickWidth, this.pickHeight);
|
||||
|
||||
this.groupPickTexture = resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
this.groupPickTexture.define(this.pickWidth, this.pickHeight);
|
||||
|
||||
this.depthPickTexture = resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
this.depthPickTexture.define(this.pickWidth, this.pickHeight);
|
||||
|
||||
this.framebuffer = resources.framebuffer();
|
||||
|
||||
this.objectPickFramebuffer = resources.framebuffer();
|
||||
this.instancePickFramebuffer = resources.framebuffer();
|
||||
this.groupPickFramebuffer = resources.framebuffer();
|
||||
this.depthPickFramebuffer = resources.framebuffer();
|
||||
|
||||
this.framebuffer.bind();
|
||||
drawBuffers!.drawBuffers([
|
||||
drawBuffers!.COLOR_ATTACHMENT0,
|
||||
drawBuffers!.COLOR_ATTACHMENT1,
|
||||
drawBuffers!.COLOR_ATTACHMENT2,
|
||||
drawBuffers!.COLOR_ATTACHMENT3,
|
||||
]);
|
||||
|
||||
this.objectPickTexture.attachFramebuffer(this.framebuffer, 'color0');
|
||||
this.instancePickTexture.attachFramebuffer(this.framebuffer, 'color1');
|
||||
this.groupPickTexture.attachFramebuffer(this.framebuffer, 'color2');
|
||||
this.depthPickTexture.attachFramebuffer(this.framebuffer, 'color3');
|
||||
|
||||
this.depthRenderbuffer = isWebGL2(gl)
|
||||
? resources.renderbuffer('depth32f', 'depth', this.pickWidth, this.pickHeight)
|
||||
: resources.renderbuffer('depth16', 'depth', this.pickWidth, this.pickHeight);
|
||||
|
||||
this.depthRenderbuffer.attachFramebuffer(this.framebuffer);
|
||||
|
||||
this.objectPickTexture.attachFramebuffer(this.objectPickFramebuffer, 'color0');
|
||||
this.instancePickTexture.attachFramebuffer(this.instancePickFramebuffer, 'color0');
|
||||
this.groupPickTexture.attachFramebuffer(this.groupPickFramebuffer, 'color0');
|
||||
this.depthPickTexture.attachFramebuffer(this.depthPickFramebuffer, 'color0');
|
||||
} else {
|
||||
this.objectPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
this.instancePickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
this.groupPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
this.depthPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
|
||||
}
|
||||
}
|
||||
|
||||
bindObject() {
|
||||
if (this.webgl.extensions.drawBuffers) {
|
||||
this.objectPickFramebuffer.bind();
|
||||
} else {
|
||||
this.objectPickTarget.bind();
|
||||
}
|
||||
}
|
||||
|
||||
bindInstance() {
|
||||
if (this.webgl.extensions.drawBuffers) {
|
||||
this.instancePickFramebuffer.bind();
|
||||
} else {
|
||||
this.instancePickTarget.bind();
|
||||
}
|
||||
}
|
||||
|
||||
bindGroup() {
|
||||
if (this.webgl.extensions.drawBuffers) {
|
||||
this.groupPickFramebuffer.bind();
|
||||
} else {
|
||||
this.groupPickTarget.bind();
|
||||
}
|
||||
}
|
||||
|
||||
bindDepth() {
|
||||
if (this.webgl.extensions.drawBuffers) {
|
||||
this.depthPickFramebuffer.bind();
|
||||
} else {
|
||||
this.depthPickTarget.bind();
|
||||
}
|
||||
}
|
||||
|
||||
get drawingBufferHeight() {
|
||||
@@ -57,21 +154,30 @@ export class PickPass {
|
||||
this.pickWidth = pickWidth;
|
||||
this.pickHeight = pickHeight;
|
||||
|
||||
this.objectPickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
this.instancePickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
this.groupPickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
this.depthPickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
if (this.webgl.extensions.drawBuffers) {
|
||||
this.objectPickTexture.define(this.pickWidth, this.pickHeight);
|
||||
this.instancePickTexture.define(this.pickWidth, this.pickHeight);
|
||||
this.groupPickTexture.define(this.pickWidth, this.pickHeight);
|
||||
this.depthPickTexture.define(this.pickWidth, this.pickHeight);
|
||||
|
||||
this.depthRenderbuffer.setSize(this.pickWidth, this.pickHeight);
|
||||
} else {
|
||||
this.objectPickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
this.instancePickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
this.groupPickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
this.depthPickTarget.setSize(this.pickWidth, this.pickHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private renderVariant(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper, variant: GraphicsRenderVariant, pickType: number) {
|
||||
const depth = this.drawPass.depthTexturePrimitives;
|
||||
private renderVariant(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper, variant: 'pick' | 'depth', pickType: number) {
|
||||
renderer.clear(false);
|
||||
|
||||
renderer.update(camera);
|
||||
renderer.renderPick(scene.primitives, camera, variant, null, pickType);
|
||||
renderer.renderPick(scene.volumes, camera, variant, depth, pickType);
|
||||
renderer.renderPick(helper.handle.scene, camera, variant, null, pickType);
|
||||
|
||||
if (helper.handle.isEnabled) {
|
||||
renderer.renderPick(helper.handle.scene, camera, variant, null, pickType);
|
||||
}
|
||||
|
||||
if (helper.camera.isEnabled) {
|
||||
helper.camera.update(camera);
|
||||
@@ -81,18 +187,23 @@ export class PickPass {
|
||||
}
|
||||
|
||||
render(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper) {
|
||||
this.objectPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Object);
|
||||
if (this.webgl.extensions.drawBuffers) {
|
||||
this.framebuffer.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.None);
|
||||
} else {
|
||||
this.objectPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Object);
|
||||
|
||||
this.instancePickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Instance);
|
||||
this.instancePickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Instance);
|
||||
|
||||
this.groupPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Group);
|
||||
// printTexture(this.webgl, this.groupPickTarget.texture, { id: 'group' })
|
||||
this.groupPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Group);
|
||||
// printTexture(this.webgl, this.groupPickTarget.texture, { id: 'group' })
|
||||
|
||||
this.depthPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'depth', PickType.None);
|
||||
this.depthPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'depth', PickType.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,19 +258,21 @@ export class PickHelper {
|
||||
}
|
||||
|
||||
private syncBuffers() {
|
||||
if (isTimingMode) this.webgl.timer.mark('PickHelper.syncBuffers');
|
||||
const { pickX, pickY, pickWidth, pickHeight } = this;
|
||||
|
||||
this.pickPass.objectPickTarget.bind();
|
||||
this.pickPass.bindObject();
|
||||
this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.objectBuffer);
|
||||
|
||||
this.pickPass.instancePickTarget.bind();
|
||||
this.pickPass.bindInstance();
|
||||
this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.instanceBuffer);
|
||||
|
||||
this.pickPass.groupPickTarget.bind();
|
||||
this.pickPass.bindGroup();
|
||||
this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.groupBuffer);
|
||||
|
||||
this.pickPass.depthPickTarget.bind();
|
||||
this.pickPass.bindDepth();
|
||||
this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.depthBuffer);
|
||||
if (isTimingMode) this.webgl.timer.markEnd('PickHelper.syncBuffers');
|
||||
}
|
||||
|
||||
private getBufferIdx(x: number, y: number): number {
|
||||
@@ -178,11 +291,12 @@ export class PickHelper {
|
||||
}
|
||||
|
||||
private render(camera: Camera | StereoCamera) {
|
||||
if (isTimingMode) this.webgl.timer.mark('PickHelper.render');
|
||||
const { pickX, pickY, pickWidth, pickHeight, halfPickWidth } = this;
|
||||
const { renderer, scene, helper } = this;
|
||||
|
||||
renderer.setTransparentBackground(false);
|
||||
renderer.setDrawingBufferSize(this.pickPass.objectPickTarget.getWidth(), this.pickPass.objectPickTarget.getHeight());
|
||||
renderer.setDrawingBufferSize(pickWidth, pickHeight);
|
||||
renderer.setPixelRatio(this.pickScale);
|
||||
|
||||
if (StereoCamera.is(camera)) {
|
||||
@@ -197,6 +311,7 @@ export class PickHelper {
|
||||
}
|
||||
|
||||
this.dirty = false;
|
||||
if (isTimingMode) this.webgl.timer.markEnd('PickHelper.render');
|
||||
}
|
||||
|
||||
private identifyInternal(x: number, y: number, camera: Camera | StereoCamera): PickData | undefined {
|
||||
@@ -217,8 +332,10 @@ export class PickHelper {
|
||||
) return;
|
||||
|
||||
if (this.dirty) {
|
||||
if (isTimingMode) this.webgl.timer.mark('PickHelper.identify');
|
||||
this.render(camera);
|
||||
this.syncBuffers();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('PickHelper.identify');
|
||||
}
|
||||
|
||||
const xv = x - viewport.x;
|
||||
@@ -240,6 +357,7 @@ export class PickHelper {
|
||||
if (groupId === -1 || groupId === NullId) return;
|
||||
|
||||
const z = this.getDepth(xp, yp);
|
||||
// console.log('z', z);
|
||||
const position = Vec3.create(x, viewport.height - y, z);
|
||||
if (StereoCamera.is(camera)) {
|
||||
const halfWidth = Math.floor(viewport.width / 2);
|
||||
@@ -254,7 +372,7 @@ export class PickHelper {
|
||||
cameraUnproject(position, position, viewport, camera.inverseProjectionView);
|
||||
}
|
||||
|
||||
// console.log({ { objectId, instanceId, groupId }, position} );
|
||||
// console.log({ id: { objectId, instanceId, groupId }, position });
|
||||
return { id: { objectId, instanceId, groupId }, position };
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,12 @@ import { Framebuffer } from '../../mol-gl/webgl/framebuffer';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import { FxaaParams, FxaaPass } from './fxaa';
|
||||
import { SmaaParams, SmaaPass } from './smaa';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
const OutlinesSchema = {
|
||||
...QuadSchema,
|
||||
tDepth: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tDepthOpaque: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tDepthTransparent: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
uTexSize: UniformSpec('v2'),
|
||||
|
||||
dOrthographic: DefineSpec('number'),
|
||||
@@ -41,11 +43,15 @@ const OutlinesSchema = {
|
||||
};
|
||||
type OutlinesRenderable = ComputeRenderable<Values<typeof OutlinesSchema>>
|
||||
|
||||
function getOutlinesRenderable(ctx: WebGLContext, depthTexture: Texture): OutlinesRenderable {
|
||||
function getOutlinesRenderable(ctx: WebGLContext, depthTextureOpaque: Texture, depthTextureTransparent: Texture): OutlinesRenderable {
|
||||
const width = depthTextureOpaque.getWidth();
|
||||
const height = depthTextureOpaque.getHeight();
|
||||
|
||||
const values: Values<typeof OutlinesSchema> = {
|
||||
...QuadValues,
|
||||
tDepth: ValueCell.create(depthTexture),
|
||||
uTexSize: ValueCell.create(Vec2.create(depthTexture.getWidth(), depthTexture.getHeight())),
|
||||
tDepthOpaque: ValueCell.create(depthTextureOpaque),
|
||||
tDepthTransparent: ValueCell.create(depthTextureTransparent),
|
||||
uTexSize: ValueCell.create(Vec2.create(width, height)),
|
||||
|
||||
dOrthographic: ValueCell.create(0),
|
||||
uNear: ValueCell.create(1),
|
||||
@@ -183,7 +189,8 @@ const PostprocessingSchema = {
|
||||
...QuadSchema,
|
||||
tSsaoDepth: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tColor: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tDepth: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tDepthOpaque: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tDepthTransparent: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
tOutlines: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
|
||||
uTexSize: UniformSpec('v2'),
|
||||
|
||||
@@ -207,12 +214,13 @@ const PostprocessingSchema = {
|
||||
};
|
||||
type PostprocessingRenderable = ComputeRenderable<Values<typeof PostprocessingSchema>>
|
||||
|
||||
function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, depthTexture: Texture, outlinesTexture: Texture, ssaoDepthTexture: Texture): 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),
|
||||
tDepth: ValueCell.create(depthTexture),
|
||||
tDepthOpaque: ValueCell.create(depthTextureOpaque),
|
||||
tDepthTransparent: ValueCell.create(depthTextureTransparent),
|
||||
tOutlines: ValueCell.create(outlinesTexture),
|
||||
uTexSize: ValueCell.create(Vec2.create(colorTexture.getWidth(), colorTexture.getHeight())),
|
||||
|
||||
@@ -274,6 +282,10 @@ export class PostprocessingPass {
|
||||
return props.occlusion.name === 'on' || props.outline.name === 'on';
|
||||
}
|
||||
|
||||
static isOutlineEnabled(props: PostprocessingProps) {
|
||||
return props.outline.name === 'on';
|
||||
}
|
||||
|
||||
readonly target: RenderTarget;
|
||||
|
||||
private readonly outlinesTarget: RenderTarget;
|
||||
@@ -307,7 +319,7 @@ export class PostprocessingPass {
|
||||
}
|
||||
|
||||
constructor(private webgl: WebGLContext, private drawPass: DrawPass) {
|
||||
const { colorTarget, depthTexture } = drawPass;
|
||||
const { colorTarget, depthTextureTransparent, depthTextureOpaque } = drawPass;
|
||||
const width = colorTarget.getWidth();
|
||||
const height = colorTarget.getHeight();
|
||||
|
||||
@@ -320,7 +332,7 @@ export class PostprocessingPass {
|
||||
this.target = webgl.createRenderTarget(width, height, false, 'uint8', 'linear');
|
||||
|
||||
this.outlinesTarget = webgl.createRenderTarget(width, height, false);
|
||||
this.outlinesRenderable = getOutlinesRenderable(webgl, depthTexture);
|
||||
this.outlinesRenderable = getOutlinesRenderable(webgl, depthTextureOpaque, depthTextureTransparent);
|
||||
|
||||
this.randomHemisphereVector = [];
|
||||
for (let i = 0; i < 256; i++) {
|
||||
@@ -340,7 +352,7 @@ export class PostprocessingPass {
|
||||
const sh = Math.floor(height * this.ssaoScale);
|
||||
|
||||
this.downsampledDepthTarget = webgl.createRenderTarget(sw, sh, false, 'uint8', 'linear');
|
||||
this.downsampleDepthRenderable = createCopyRenderable(webgl, depthTexture);
|
||||
this.downsampleDepthRenderable = createCopyRenderable(webgl, depthTextureOpaque);
|
||||
|
||||
this.ssaoDepthTexture = webgl.resources.texture('image-uint8', 'rgba', 'ubyte', 'linear');
|
||||
this.ssaoDepthTexture.define(sw, sh);
|
||||
@@ -352,10 +364,10 @@ export class PostprocessingPass {
|
||||
|
||||
this.ssaoDepthTexture.attachFramebuffer(this.ssaoBlurSecondPassFramebuffer, 'color0');
|
||||
|
||||
this.ssaoRenderable = getSsaoRenderable(webgl, this.downsampleFactor === 1 ? depthTexture : this.downsampledDepthTarget.texture);
|
||||
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, depthTexture, this.outlinesTarget.texture, this.ssaoDepthTexture);
|
||||
this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTextureOpaque, depthTextureTransparent, this.outlinesTarget.texture, this.ssaoDepthTexture);
|
||||
}
|
||||
|
||||
setSize(width: number, height: number) {
|
||||
@@ -460,7 +472,7 @@ export class PostprocessingPass {
|
||||
this.ssaoDepthBlurProxyTexture.define(sw, sh);
|
||||
|
||||
if (this.ssaoScale === 1) {
|
||||
ValueCell.update(this.ssaoRenderable.values.tDepth, this.drawPass.depthTexture);
|
||||
ValueCell.update(this.ssaoRenderable.values.tDepth, this.drawPass.depthTextureTransparent);
|
||||
} else {
|
||||
ValueCell.update(this.ssaoRenderable.values.tDepth, this.downsampledDepthTarget.texture);
|
||||
}
|
||||
@@ -538,6 +550,7 @@ export class PostprocessingPass {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (props.outline.name === 'on') {
|
||||
@@ -574,6 +587,7 @@ export class PostprocessingPass {
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.renderable.render();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('PostprocessingPass.render');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { weights_frag } from '../../mol-gl/shader/smaa/weights.frag';
|
||||
import { edges_vert } from '../../mol-gl/shader/smaa/edges.vert';
|
||||
import { edges_frag } from '../../mol-gl/shader/smaa/edges.frag';
|
||||
import { Viewport } from '../camera/util';
|
||||
import { isDebugMode } from '../../mol-util/debug';
|
||||
import { isDebugMode, isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
export const SmaaParams = {
|
||||
edgeThreshold: PD.Numeric(0.1, { min: 0.05, max: 0.15, step: 0.01 }),
|
||||
@@ -120,6 +120,7 @@ export class SmaaPass {
|
||||
}
|
||||
|
||||
render(viewport: Viewport, target: RenderTarget | undefined) {
|
||||
if (isTimingMode) this.webgl.timer.mark('SmaaPass.render');
|
||||
this.edgesTarget.bind();
|
||||
this.updateState(viewport);
|
||||
this.edgesRenderable.render();
|
||||
@@ -135,8 +136,8 @@ export class SmaaPass {
|
||||
}
|
||||
this.updateState(viewport);
|
||||
this.blendRenderable.render();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('SmaaPass.render');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -17,7 +17,7 @@ import { quad_vert } from '../../mol-gl/shader/quad.vert';
|
||||
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 } from '../../mol-util/debug';
|
||||
import { isDebugMode, isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
const EvaluateWboitSchema = {
|
||||
...QuadSchema,
|
||||
@@ -71,6 +71,7 @@ export class WboitPass {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (isTimingMode) this.webgl.timer.mark('WboitPass.render');
|
||||
const { state, gl } = this.webgl;
|
||||
|
||||
state.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
@@ -78,6 +79,7 @@ export class WboitPass {
|
||||
|
||||
this.renderable.update();
|
||||
this.renderable.render();
|
||||
if (isTimingMode) this.webgl.timer.markEnd('WboitPass.render');
|
||||
}
|
||||
|
||||
setSize(width: number, height: number) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 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>
|
||||
@@ -11,11 +11,13 @@ import { Color } from '../../mol-util/color';
|
||||
import { Vec2, Vec3, Vec4 } from '../../mol-math/linear-algebra';
|
||||
import { LocationIterator } from '../util/location-iterator';
|
||||
import { NullLocation } from '../../mol-model/location';
|
||||
import { LocationColor, ColorTheme } from '../../mol-theme/color';
|
||||
import { Geometry } from './geometry';
|
||||
import { LocationColor, ColorTheme, ColorVolume } from '../../mol-theme/color';
|
||||
import { createNullTexture, Texture } from '../../mol-gl/webgl/texture';
|
||||
|
||||
export type ColorType = 'uniform' | 'instance' | 'group' | 'groupInstance' | 'vertex' | 'vertexInstance' | 'volume' | 'volumeInstance' | 'direct'
|
||||
export type ColorTypeLocation = 'uniform' | 'instance' | 'group' | 'groupInstance' | 'vertex' | 'vertexInstance';
|
||||
export type ColorTypeGrid = 'volume' | 'volumeInstance';
|
||||
export type ColorTypeDirect = 'direct';
|
||||
export type ColorType = ColorTypeLocation | ColorTypeGrid | ColorTypeDirect;
|
||||
|
||||
export type ColorData = {
|
||||
uColor: ValueCell<Vec3>,
|
||||
@@ -29,7 +31,7 @@ export type ColorData = {
|
||||
dUsePalette: ValueCell<boolean>,
|
||||
}
|
||||
|
||||
export function createColors(locationIt: LocationIterator, positionIt: LocationIterator, colorTheme: ColorTheme<any>, colorData?: ColorData): ColorData {
|
||||
export function createColors(locationIt: LocationIterator, positionIt: LocationIterator, colorTheme: ColorTheme<any, any>, colorData?: ColorData): ColorData {
|
||||
const data = _createColors(locationIt, positionIt, colorTheme, colorData);
|
||||
if (colorTheme.palette) {
|
||||
ValueCell.updateIfChanged(data.dUsePalette, true);
|
||||
@@ -40,16 +42,19 @@ export function createColors(locationIt: LocationIterator, positionIt: LocationI
|
||||
return data;
|
||||
}
|
||||
|
||||
function _createColors(locationIt: LocationIterator, positionIt: LocationIterator, colorTheme: ColorTheme<any>, colorData?: ColorData): ColorData {
|
||||
switch (Geometry.getGranularity(locationIt, colorTheme.granularity)) {
|
||||
function _createColors(locationIt: LocationIterator, positionIt: LocationIterator, colorTheme: ColorTheme<any, any>, colorData?: ColorData): ColorData {
|
||||
switch (colorTheme.granularity) {
|
||||
case 'uniform': return createUniformColor(locationIt, colorTheme.color, colorData);
|
||||
case 'instance': return createInstanceColor(locationIt, colorTheme.color, colorData);
|
||||
case 'instance':
|
||||
return locationIt.nonInstanceable
|
||||
? createGroupColor(locationIt, colorTheme.color, colorData)
|
||||
: createInstanceColor(locationIt, colorTheme.color, colorData);
|
||||
case 'group': return createGroupColor(locationIt, colorTheme.color, colorData);
|
||||
case 'groupInstance': return createGroupInstanceColor(locationIt, colorTheme.color, colorData);
|
||||
case 'vertex': return createVertexColor(positionIt, colorTheme.color, colorData);
|
||||
case 'vertexInstance': return createVertexInstanceColor(positionIt, colorTheme.color, colorData);
|
||||
case 'volume': return createGridColor((colorTheme as any).grid, 'volume', colorData);
|
||||
case 'volumeInstance': return createGridColor((colorTheme as any).grid, 'volumeInstance', colorData);
|
||||
case 'volume': return createGridColor(colorTheme.grid, 'volume', colorData);
|
||||
case 'volumeInstance': return createGridColor(colorTheme.grid, 'volumeInstance', colorData);
|
||||
case 'direct': return createDirectColor(colorData);
|
||||
}
|
||||
}
|
||||
@@ -207,12 +212,6 @@ function createVertexInstanceColor(locationIt: LocationIterator, color: Location
|
||||
|
||||
//
|
||||
|
||||
interface ColorVolume {
|
||||
colors: Texture
|
||||
dimension: Vec3
|
||||
transform: Vec4
|
||||
}
|
||||
|
||||
export function createGridColor(grid: ColorVolume, type: ColorType, colorData?: ColorData): ColorData {
|
||||
const { colors, dimension, transform } = grid;
|
||||
const width = colors.getWidth();
|
||||
|
||||
@@ -157,7 +157,7 @@ export namespace Cylinders {
|
||||
doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
@@ -242,6 +242,7 @@ export namespace Cylinders {
|
||||
uDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
dTransparentBackfaces: ValueCell.create(props.transparentBackfaces),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
};
|
||||
@@ -259,6 +260,7 @@ export namespace Cylinders {
|
||||
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.dTransparentBackfaces, props.transparentBackfaces);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
|
||||
@@ -625,7 +625,7 @@ export namespace Mesh {
|
||||
flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
@@ -701,6 +701,7 @@ export namespace Mesh {
|
||||
dFlipSided: ValueCell.create(props.flipSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
dTransparentBackfaces: ValueCell.create(props.transparentBackfaces),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
|
||||
@@ -721,6 +722,7 @@ export namespace Mesh {
|
||||
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.dTransparentBackfaces, props.transparentBackfaces);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ export namespace Spheres {
|
||||
doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
@@ -209,6 +209,7 @@ export namespace Spheres {
|
||||
uDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
dTransparentBackfaces: ValueCell.create(props.transparentBackfaces),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
};
|
||||
@@ -226,6 +227,7 @@ export namespace Spheres {
|
||||
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.dTransparentBackfaces, props.transparentBackfaces);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { accumulate_frag } from '../../../mol-gl/shader/compute/color-smoothing/
|
||||
import { accumulate_vert } from '../../../mol-gl/shader/compute/color-smoothing/accumulate.vert';
|
||||
import { isWebGL2 } from '../../../mol-gl/webgl/compat';
|
||||
import { TextureMeshValues } from '../../../mol-gl/renderable/texture-mesh';
|
||||
import { isTimingMode } from '../../../mol-util/debug';
|
||||
|
||||
export const ColorAccumulateSchema = {
|
||||
drawCount: ValueSpec('number'),
|
||||
@@ -255,6 +256,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
|
||||
const { drawBuffers } = webgl.extensions;
|
||||
if (!drawBuffers) throw new Error('need WebGL draw buffers');
|
||||
|
||||
if (isTimingMode) webgl.timer.mark('calcTextureMeshColorSmoothing');
|
||||
const { gl, resources, state, extensions: { colorBufferHalfFloat, textureHalfFloat } } = webgl;
|
||||
|
||||
const isInstanceType = input.colorType.endsWith('Instance');
|
||||
@@ -321,6 +323,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
|
||||
|
||||
const { uCurrentSlice, uCurrentX, uCurrentY } = accumulateRenderable.values;
|
||||
|
||||
if (isTimingMode) webgl.timer.mark('ColorAccumulate.render');
|
||||
setAccumulateDefaults(webgl);
|
||||
gl.viewport(0, 0, width, height);
|
||||
gl.scissor(0, 0, width, height);
|
||||
@@ -349,6 +352,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
|
||||
accumulateTexture.detachFramebuffer(framebuffer, 0);
|
||||
countTexture.detachFramebuffer(framebuffer, 1);
|
||||
drawBuffers.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE]);
|
||||
if (isTimingMode) webgl.timer.markEnd('ColorAccumulate.render');
|
||||
|
||||
// const accImage = new Float32Array(width * height * 4);
|
||||
// accumulateTexture.attachFramebuffer(framebuffer, 0);
|
||||
@@ -364,6 +368,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
|
||||
|
||||
// normalize
|
||||
|
||||
if (isTimingMode) webgl.timer.mark('ColorNormalize.render');
|
||||
if (!texture) texture = resources.texture('image-uint8', 'rgba', 'ubyte', 'linear');
|
||||
texture.define(width, height);
|
||||
|
||||
@@ -376,6 +381,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
|
||||
gl.scissor(0, 0, width, height);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
normalizeRenderable.render();
|
||||
if (isTimingMode) webgl.timer.markEnd('ColorNormalize.render');
|
||||
|
||||
// const normImage = new Uint8Array(width * height * 4);
|
||||
// texture.attachFramebuffer(framebuffer, 0);
|
||||
@@ -385,6 +391,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
|
||||
|
||||
const gridTransform = Vec4.create(min[0], min[1], min[2], scaleFactor);
|
||||
const type = isInstanceType ? 'volumeInstance' : 'volume';
|
||||
if (isTimingMode) webgl.timer.markEnd('calcTextureMeshColorSmoothing');
|
||||
|
||||
return { texture, gridDim, gridTexDim: Vec2.create(width, height), gridTransform, type };
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ 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';
|
||||
|
||||
export interface TextureMesh {
|
||||
readonly kind: 'texture-mesh',
|
||||
@@ -113,7 +114,7 @@ export namespace TextureMesh {
|
||||
flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
@@ -126,8 +127,8 @@ export namespace TextureMesh {
|
||||
createValuesSimple,
|
||||
updateValues,
|
||||
updateBoundingSphere,
|
||||
createRenderableState: BaseGeometry.createRenderableState,
|
||||
updateRenderableState: BaseGeometry.updateRenderableState,
|
||||
createRenderableState,
|
||||
updateRenderableState,
|
||||
createPositionIterator: () => LocationIterator(1, 1, 1, () => NullLocation)
|
||||
};
|
||||
|
||||
@@ -173,6 +174,7 @@ export namespace TextureMesh {
|
||||
dFlipSided: ValueCell.create(props.flipSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
dTransparentBackfaces: ValueCell.create(props.transparentBackfaces),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
|
||||
@@ -193,6 +195,7 @@ export namespace TextureMesh {
|
||||
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.dTransparentBackfaces, props.transparentBackfaces);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
@@ -209,4 +212,16 @@ export namespace TextureMesh {
|
||||
ValueCell.update(values.uInvariantBoundingSphere, Vec4.fromSphere(values.uInvariantBoundingSphere.ref.value, invariantBoundingSphere));
|
||||
}
|
||||
}
|
||||
|
||||
function createRenderableState(props: PD.Values<Params>): RenderableState {
|
||||
const state = BaseGeometry.createRenderableState(props);
|
||||
updateRenderableState(state, props);
|
||||
return state;
|
||||
}
|
||||
|
||||
function updateRenderableState(state: RenderableState, props: PD.Values<Params>) {
|
||||
BaseGeometry.updateRenderableState(state, props);
|
||||
state.opaque = state.opaque && !props.xrayShaded;
|
||||
state.writeDepth = state.opaque;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -29,6 +29,7 @@ export function applyTransparencyValue(array: Uint8Array, start: number, end: nu
|
||||
}
|
||||
|
||||
export function getTransparencyAverage(array: Uint8Array, count: number): number {
|
||||
if (count === 0 || array.length < count) return 0;
|
||||
let sum = 0;
|
||||
for (let i = 0; i < count; ++i) {
|
||||
sum += array[i];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
@@ -18,8 +18,9 @@ import { createComputeRenderItem } from '../webgl/render-item';
|
||||
import { createComputeRenderable } from '../renderable';
|
||||
import { isLittleEndian } from '../../mol-util/is-little-endian';
|
||||
import { RuntimeContext } from '../../mol-task';
|
||||
import { isTimingMode } from '../../mol-util/debug';
|
||||
|
||||
export function canComputeGrid3dOnGPU(webgl?: WebGLContext) {
|
||||
export function canComputeGrid3dOnGPU(webgl?: WebGLContext): webgl is WebGLContext {
|
||||
return !!webgl?.extensions.textureFloat;
|
||||
}
|
||||
|
||||
@@ -159,7 +160,8 @@ export function createGrid3dComputeRenderable<S extends RenderableSchema, P, CS>
|
||||
|
||||
const array = new Uint8Array(uWidth * uWidth * 4);
|
||||
if (spec.cumulative) {
|
||||
const { gl } = webgl;
|
||||
const { gl, state } = webgl;
|
||||
if (isTimingMode) webgl.timer.mark('Grid3dCompute.renderCumulative');
|
||||
|
||||
const states = spec.cumulative.states(params);
|
||||
|
||||
@@ -167,7 +169,7 @@ export function createGrid3dComputeRenderable<S extends RenderableSchema, P, CS>
|
||||
tex[1].define(uWidth, uWidth);
|
||||
|
||||
resetGl(webgl, uWidth);
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
state.clearColor(0, 0, 0, 0);
|
||||
|
||||
tex[0].attachFramebuffer(framebuffer, 'color0');
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
@@ -175,12 +177,13 @@ export function createGrid3dComputeRenderable<S extends RenderableSchema, P, CS>
|
||||
tex[1].attachFramebuffer(framebuffer, 'color0');
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
if (spec.cumulative.yieldPeriod) {
|
||||
if (spec.cumulative.yieldPeriod && !isTimingMode) {
|
||||
await ctx.update({ message: 'Computing...', isIndeterminate: false, current: 0, max: states.length });
|
||||
}
|
||||
|
||||
const yieldPeriod = Math.max(1, spec.cumulative.yieldPeriod ?? 1 | 0);
|
||||
|
||||
if (isTimingMode) webgl.timer.mark('Grid3dCompute.renderBatch');
|
||||
for (let i = 0; i < states.length; i++) {
|
||||
ValueCell.update(cells.tCumulativeSum, tex[(i + 1) % 2]);
|
||||
tex[i % 2].attachFramebuffer(framebuffer, 'color0');
|
||||
@@ -191,23 +194,31 @@ export function createGrid3dComputeRenderable<S extends RenderableSchema, P, CS>
|
||||
|
||||
if (spec.cumulative.yieldPeriod && i !== states.length - 1) {
|
||||
if (i % yieldPeriod === yieldPeriod - 1) {
|
||||
webgl.readPixels(0, 0, 1, 1, array);
|
||||
webgl.waitForGpuCommandsCompleteSync();
|
||||
if (isTimingMode) webgl.timer.markEnd('Grid3dCompute.renderBatch');
|
||||
if (isTimingMode) webgl.timer.mark('Grid3dCompute.renderBatch');
|
||||
}
|
||||
if (ctx.shouldUpdate) {
|
||||
if (ctx.shouldUpdate && !isTimingMode) {
|
||||
await ctx.update({ current: i + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isTimingMode) webgl.timer.markEnd('Grid3dCompute.renderBatch');
|
||||
if (isTimingMode) webgl.timer.markEnd('Grid3dCompute.renderCumulative');
|
||||
} else {
|
||||
if (isTimingMode) webgl.timer.mark('Grid3dCompute.render');
|
||||
tex[0].define(uWidth, uWidth);
|
||||
tex[0].attachFramebuffer(framebuffer, 'color0');
|
||||
framebuffer.bind();
|
||||
resetGl(webgl, uWidth);
|
||||
renderable.update();
|
||||
renderable.render();
|
||||
if (isTimingMode) webgl.timer.markEnd('Grid3dCompute.render');
|
||||
}
|
||||
|
||||
if (isTimingMode) webgl.timer.mark('Grid3dCompute.readPixels');
|
||||
webgl.readPixels(0, 0, uWidth, uWidth, array);
|
||||
if (isTimingMode) webgl.timer.markEnd('Grid3dCompute.readPixels');
|
||||
return new Float32Array(array.buffer, array.byteOffset, nx * ny * nz);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -19,6 +19,7 @@ import { isPowerOfTwo } from '../../../mol-math/misc';
|
||||
import { quad_vert } from '../../../mol-gl/shader/quad.vert';
|
||||
import { reduction_frag } from '../../../mol-gl/shader/histogram-pyramid/reduction.frag';
|
||||
import { isWebGL2 } from '../../webgl/compat';
|
||||
import { isTimingMode } from '../../../mol-util/debug';
|
||||
|
||||
const HistopyramidReductionSchema = {
|
||||
...QuadSchema,
|
||||
@@ -120,6 +121,7 @@ export interface HistogramPyramid {
|
||||
}
|
||||
|
||||
export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture, scale: Vec2, gridTexDim: Vec3): HistogramPyramid {
|
||||
if (isTimingMode) ctx.timer.mark('createHistogramPyramid');
|
||||
const { gl } = ctx;
|
||||
const w = inputTexture.getWidth();
|
||||
const h = inputTexture.getHeight();
|
||||
@@ -193,6 +195,7 @@ export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture,
|
||||
}
|
||||
|
||||
gl.finish();
|
||||
if (isTimingMode) ctx.timer.markEnd('createHistogramPyramid');
|
||||
|
||||
// printTexture(ctx, pyramidTex, 2)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -16,6 +16,7 @@ import { QuadSchema, QuadValues } from '../util';
|
||||
import { quad_vert } from '../../../mol-gl/shader/quad.vert';
|
||||
import { sum_frag } from '../../../mol-gl/shader/histogram-pyramid/sum.frag';
|
||||
import { isWebGL2 } from '../../webgl/compat';
|
||||
import { isTimingMode } from '../../../mol-util/debug';
|
||||
|
||||
const HistopyramidSumSchema = {
|
||||
...QuadSchema,
|
||||
@@ -66,6 +67,7 @@ const sumBytes = new Uint8Array(4);
|
||||
const sumInts = new Int32Array(4);
|
||||
|
||||
export function getHistopyramidSum(ctx: WebGLContext, pyramidTopTexture: Texture) {
|
||||
if (isTimingMode) ctx.timer.mark('getHistopyramidSum');
|
||||
const { gl, resources } = ctx;
|
||||
|
||||
const renderable = getHistopyramidSumRenderable(ctx, pyramidTopTexture);
|
||||
@@ -93,6 +95,7 @@ export function getHistopyramidSum(ctx: WebGLContext, pyramidTopTexture: Texture
|
||||
|
||||
ctx.readPixels(0, 0, 1, 1, isWebGL2(gl) ? sumInts : sumBytes);
|
||||
ctx.unbindFramebuffer();
|
||||
if (isTimingMode) ctx.timer.markEnd('getHistopyramidSum');
|
||||
|
||||
return isWebGL2(gl)
|
||||
? sumInts[0]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -16,6 +16,7 @@ import { QuadSchema, QuadValues } from '../util';
|
||||
import { getTriCount } from './tables';
|
||||
import { quad_vert } from '../../../mol-gl/shader/quad.vert';
|
||||
import { activeVoxels_frag } from '../../../mol-gl/shader/marching-cubes/active-voxels.frag';
|
||||
import { isTimingMode } from '../../../mol-util/debug';
|
||||
|
||||
const ActiveVoxelsSchema = {
|
||||
...QuadSchema,
|
||||
@@ -83,6 +84,7 @@ function setRenderingDefaults(ctx: WebGLContext) {
|
||||
}
|
||||
|
||||
export function calcActiveVoxels(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, isoValue: number, gridScale: Vec2) {
|
||||
if (isTimingMode) ctx.timer.mark('calcActiveVoxels');
|
||||
const { gl, resources } = ctx;
|
||||
const width = volumeData.getWidth();
|
||||
const height = volumeData.getHeight();
|
||||
@@ -115,6 +117,7 @@ export function calcActiveVoxels(ctx: WebGLContext, volumeData: Texture, gridDim
|
||||
// console.log('at', readTexture(ctx, activeVoxelsTex));
|
||||
|
||||
gl.finish();
|
||||
if (isTimingMode) ctx.timer.markEnd('calcActiveVoxels');
|
||||
|
||||
return activeVoxelsTex;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -19,6 +19,7 @@ import { quad_vert } from '../../../mol-gl/shader/quad.vert';
|
||||
import { isosurface_frag } from '../../../mol-gl/shader/marching-cubes/isosurface.frag';
|
||||
import { calcActiveVoxels } from './active-voxels';
|
||||
import { isWebGL2 } from '../../webgl/compat';
|
||||
import { isTimingMode } from '../../../mol-util/debug';
|
||||
|
||||
const IsosurfaceSchema = {
|
||||
...QuadSchema,
|
||||
@@ -122,6 +123,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
|
||||
const { drawBuffers } = ctx.extensions;
|
||||
if (!drawBuffers) throw new Error('need WebGL draw buffers');
|
||||
|
||||
if (isTimingMode) ctx.timer.mark('createIsosurfaceBuffers');
|
||||
const { gl, resources, extensions } = ctx;
|
||||
const { pyramidTex, height, levels, scale, count } = histogramPyramid;
|
||||
const width = pyramidTex.getWidth();
|
||||
@@ -192,6 +194,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
|
||||
renderable.render();
|
||||
|
||||
gl.finish();
|
||||
if (isTimingMode) ctx.timer.markEnd('createIsosurfaceBuffers');
|
||||
|
||||
return { vertexTexture, groupTexture, normalTexture, vertexCount: count };
|
||||
}
|
||||
@@ -208,20 +211,11 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
|
||||
* Implementation based on http://www.miaumiau.cat/2016/10/stream-compaction-in-webgl/
|
||||
*/
|
||||
export function extractIsosurface(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, gridTexScale: Vec2, transform: Mat4, isoValue: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3, vertexTexture?: Texture, groupTexture?: Texture, normalTexture?: Texture) {
|
||||
// console.time('calcActiveVoxels');
|
||||
if (isTimingMode) ctx.timer.mark('extractIsosurface');
|
||||
const activeVoxelsTex = calcActiveVoxels(ctx, volumeData, gridDim, gridTexDim, isoValue, gridTexScale);
|
||||
// ctx.waitForGpuCommandsCompleteSync();
|
||||
// console.timeEnd('calcActiveVoxels');
|
||||
|
||||
// console.time('createHistogramPyramid');
|
||||
const compacted = createHistogramPyramid(ctx, activeVoxelsTex, gridTexScale, gridTexDim);
|
||||
// ctx.waitForGpuCommandsCompleteSync();
|
||||
// console.timeEnd('createHistogramPyramid');
|
||||
|
||||
// console.time('createIsosurfaceBuffers');
|
||||
const gv = createIsosurfaceBuffers(ctx, activeVoxelsTex, volumeData, compacted, gridDim, gridTexDim, transform, isoValue, invert, packedGroup, axisOrder, vertexTexture, groupTexture, normalTexture);
|
||||
// ctx.waitForGpuCommandsCompleteSync();
|
||||
// console.timeEnd('createIsosurfaceBuffers');
|
||||
if (isTimingMode) ctx.timer.markEnd('extractIsosurface');
|
||||
|
||||
return gv;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -26,6 +26,7 @@ export const CylindersSchema = {
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
dTransparentBackfaces: DefineSpec('string', ['off', 'on', 'opaque']),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -22,6 +22,7 @@ export const MeshSchema = {
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
dTransparentBackfaces: DefineSpec('string', ['off', 'on', 'opaque']),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
meta: ValueSpec('unknown')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -153,7 +153,7 @@ export const GlobalUniformSchema = {
|
||||
|
||||
uXrayEdgeFalloff: UniformSpec('f'),
|
||||
|
||||
uRenderWboit: UniformSpec('b'),
|
||||
uRenderMask: UniformSpec('i'),
|
||||
uMarkingDepthTest: UniformSpec('b'),
|
||||
uMarkingType: UniformSpec('i'),
|
||||
uPickType: UniformSpec('i'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -23,6 +23,7 @@ export const SpheresSchema = {
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
dTransparentBackfaces: DefineSpec('string', ['off', 'on', 'opaque']),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -23,6 +23,7 @@ export const TextureMeshSchema = {
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
dTransparentBackfaces: DefineSpec('string', ['off', 'on', 'opaque']),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
meta: ValueSpec('unknown')
|
||||
|
||||
@@ -19,6 +19,7 @@ import { degToRad } from '../mol-math/misc';
|
||||
import { Texture, Textures } from './webgl/texture';
|
||||
import { arrayMapUpsert } from '../mol-util/array';
|
||||
import { clamp } from '../mol-math/interpolate';
|
||||
import { isTimingMode } from '../mol-util/debug';
|
||||
|
||||
export interface RendererStats {
|
||||
programCount: number
|
||||
@@ -54,18 +55,19 @@ interface Renderer {
|
||||
readonly props: Readonly<RendererProps>
|
||||
|
||||
clear: (toBackgroundColor: boolean, ignoreTransparentBackground?: boolean) => void
|
||||
clearDepth: () => void
|
||||
clearDepth: (packed?: boolean) => void
|
||||
update: (camera: ICamera) => void
|
||||
|
||||
renderPick: (group: Scene.Group, camera: ICamera, variant: GraphicsRenderVariant, depthTexture: Texture | null, pickType: PickType) => void
|
||||
renderPick: (group: Scene.Group, camera: ICamera, variant: 'pick' | 'depth', depthTexture: Texture | null, pickType: PickType) => void
|
||||
renderDepth: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderDepthOpaque: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderDepthTransparent: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderMarkingDepth: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderMarkingMask: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderBlended: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderBlendedOpaque: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderBlendedTransparent: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderBlendedVolumeOpaque: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
renderBlendedVolumeTransparent: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
|
||||
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
|
||||
|
||||
@@ -135,6 +137,18 @@ function getLight(props: RendererProps['light'], light?: Light): Light {
|
||||
}
|
||||
|
||||
namespace Renderer {
|
||||
const enum Flag {
|
||||
None = 0,
|
||||
BlendedFront = 1,
|
||||
BlendedBack = 2
|
||||
}
|
||||
|
||||
const enum Mask {
|
||||
All = 0,
|
||||
Opaque = 1,
|
||||
Transparent = 2,
|
||||
}
|
||||
|
||||
export function create(ctx: WebGLContext, props: Partial<RendererProps> = {}): Renderer {
|
||||
const { gl, state, stats } = ctx;
|
||||
const p = PD.merge(RendererParams, PD.getDefaultValues(RendererParams), props);
|
||||
@@ -146,7 +160,9 @@ namespace Renderer {
|
||||
|
||||
let transparentBackground = false;
|
||||
|
||||
const emptyDepthTexture = ctx.resources.texture('image-depth', 'depth', 'ushort', 'nearest');
|
||||
const emptyDepthTexture = ctx.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
emptyDepthTexture.define(1, 1);
|
||||
emptyDepthTexture.load({ array: new Uint8Array([255, 255, 255, 255]), width: 1, height: 1 });
|
||||
const sharedTexturesList: Textures = [
|
||||
['tDepth', emptyDepthTexture]
|
||||
];
|
||||
@@ -191,7 +207,7 @@ namespace Renderer {
|
||||
uFogFar: ValueCell.create(10000),
|
||||
uFogColor: ValueCell.create(bgColor),
|
||||
|
||||
uRenderWboit: ValueCell.create(false),
|
||||
uRenderMask: ValueCell.create(0),
|
||||
uMarkingDepthTest: ValueCell.create(false),
|
||||
uPickType: ValueCell.create(PickType.None),
|
||||
uMarkingType: ValueCell.create(MarkingType.None),
|
||||
@@ -220,7 +236,7 @@ namespace Renderer {
|
||||
|
||||
let globalUniformsNeedUpdate = true;
|
||||
|
||||
const renderObject = (r: GraphicsRenderable, variant: GraphicsRenderVariant) => {
|
||||
const renderObject = (r: GraphicsRenderable, variant: GraphicsRenderVariant, flag: Flag) => {
|
||||
if (r.state.disposed || !r.state.visible || (!r.state.pickable && variant === 'pick')) {
|
||||
return;
|
||||
}
|
||||
@@ -259,6 +275,24 @@ namespace Renderer {
|
||||
state.disable(gl.DEPTH_TEST);
|
||||
state.depthMask(false);
|
||||
}
|
||||
} else if (flag === Flag.BlendedFront) {
|
||||
state.enable(gl.CULL_FACE);
|
||||
if (r.values.dFlipSided?.ref.value) {
|
||||
state.frontFace(gl.CW);
|
||||
state.cullFace(gl.FRONT);
|
||||
} else {
|
||||
state.frontFace(gl.CCW);
|
||||
state.cullFace(gl.BACK);
|
||||
}
|
||||
} else if (flag === Flag.BlendedBack) {
|
||||
state.enable(gl.CULL_FACE);
|
||||
if (r.values.dFlipSided?.ref.value) {
|
||||
state.frontFace(gl.CW);
|
||||
state.cullFace(gl.BACK);
|
||||
} else {
|
||||
state.frontFace(gl.CCW);
|
||||
state.cullFace(gl.FRONT);
|
||||
}
|
||||
} else {
|
||||
if (r.values.uDoubleSided) {
|
||||
if (r.values.uDoubleSided.ref.value || r.values.hasReflection.ref.value) {
|
||||
@@ -271,14 +305,9 @@ namespace Renderer {
|
||||
state.disable(gl.CULL_FACE);
|
||||
}
|
||||
|
||||
if (r.values.dFlipSided) {
|
||||
if (r.values.dFlipSided.ref.value) {
|
||||
state.frontFace(gl.CW);
|
||||
state.cullFace(gl.FRONT);
|
||||
} else {
|
||||
state.frontFace(gl.CCW);
|
||||
state.cullFace(gl.BACK);
|
||||
}
|
||||
if (r.values.dFlipSided?.ref.value) {
|
||||
state.frontFace(gl.CW);
|
||||
state.cullFace(gl.FRONT);
|
||||
} else {
|
||||
// webgl default
|
||||
state.frontFace(gl.CCW);
|
||||
@@ -308,7 +337,7 @@ namespace Renderer {
|
||||
ValueCell.updateIfChanged(globalUniforms.uTransparentBackground, transparentBackground);
|
||||
};
|
||||
|
||||
const updateInternal = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null, renderWboit: boolean, markingDepthTest: boolean) => {
|
||||
const updateInternal = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null, renderMask: Mask, markingDepthTest: boolean) => {
|
||||
arrayMapUpsert(sharedTexturesList, 'tDepth', depthTexture || emptyDepthTexture);
|
||||
|
||||
ValueCell.update(globalUniforms.uModel, group.view);
|
||||
@@ -317,7 +346,7 @@ namespace Renderer {
|
||||
ValueCell.update(globalUniforms.uModelViewProjection, Mat4.mul(modelViewProjection, modelView, camera.projection));
|
||||
ValueCell.update(globalUniforms.uInvModelViewProjection, Mat4.invert(invModelViewProjection, modelViewProjection));
|
||||
|
||||
ValueCell.updateIfChanged(globalUniforms.uRenderWboit, renderWboit);
|
||||
ValueCell.updateIfChanged(globalUniforms.uRenderMask, renderMask);
|
||||
ValueCell.updateIfChanged(globalUniforms.uMarkingDepthTest, markingDepthTest);
|
||||
|
||||
state.enable(gl.SCISSOR_TEST);
|
||||
@@ -332,40 +361,81 @@ namespace Renderer {
|
||||
};
|
||||
|
||||
const renderPick = (group: Scene.Group, camera: ICamera, variant: GraphicsRenderVariant, depthTexture: Texture | null, pickType: PickType) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderPick');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
updateInternal(group, camera, depthTexture, Mask.All, false);
|
||||
ValueCell.updateIfChanged(globalUniforms.uPickType, pickType);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
if (!renderables[i].state.colorOnly) {
|
||||
renderObject(renderables[i], variant);
|
||||
renderObject(renderables[i], variant, Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderPick');
|
||||
};
|
||||
|
||||
const renderDepth = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderDepth');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
updateInternal(group, camera, depthTexture, Mask.All, false);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
renderObject(renderables[i], 'depth');
|
||||
renderObject(renderables[i], 'depth', Flag.None);
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDepth');
|
||||
};
|
||||
|
||||
const renderMarkingDepth = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
const renderDepthOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderDepthOpaque');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
updateInternal(group, camera, depthTexture, Mask.Opaque, false);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
if (r.state.opaque && r.values.transparencyAverage.ref.value !== 1 && !r.values.dXrayShaded?.ref.value) {
|
||||
renderObject(r, 'depth', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDepthOpaque');
|
||||
};
|
||||
|
||||
const renderDepthTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderDepthTransparent');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
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.state.opaque || r.values.transparencyAverage.ref.value > 0 || r.values.dXrayShaded?.ref.value) {
|
||||
renderObject(r, 'depth', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDepthTransparent');
|
||||
};
|
||||
|
||||
const renderMarkingDepth = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderMarkingDepth');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, Mask.All, false);
|
||||
ValueCell.updateIfChanged(globalUniforms.uMarkingType, MarkingType.Depth);
|
||||
|
||||
const { renderables } = group;
|
||||
@@ -373,17 +443,19 @@ namespace Renderer {
|
||||
const r = renderables[i];
|
||||
|
||||
if (r.values.markerAverage.ref.value !== 1) {
|
||||
renderObject(renderables[i], 'marking');
|
||||
renderObject(renderables[i], 'marking', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderMarkingDepth');
|
||||
};
|
||||
|
||||
const renderMarkingMask = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderMarkingMask');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, !!depthTexture);
|
||||
updateInternal(group, camera, depthTexture, Mask.All, !!depthTexture);
|
||||
ValueCell.updateIfChanged(globalUniforms.uMarkingType, MarkingType.Mask);
|
||||
|
||||
const { renderables } = group;
|
||||
@@ -391,9 +463,10 @@ namespace Renderer {
|
||||
const r = renderables[i];
|
||||
|
||||
if (r.values.markerAverage.ref.value > 0) {
|
||||
renderObject(renderables[i], 'marking');
|
||||
renderObject(renderables[i], 'marking', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderMarkingMask');
|
||||
};
|
||||
|
||||
const renderBlended = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
@@ -402,25 +475,30 @@ namespace Renderer {
|
||||
};
|
||||
|
||||
const renderBlendedOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderBlendedOpaque');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
updateInternal(group, camera, depthTexture, Mask.Opaque, false);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
if (r.state.opaque) {
|
||||
renderObject(r, 'colorBlended');
|
||||
renderObject(r, 'colorBlended', Flag.None);
|
||||
} else if (r.values.uDoubleSided?.ref.value && r.values.dTransparentBackfaces?.ref.value === 'opaque') {
|
||||
renderObject(r, 'colorBlended', Flag.BlendedBack);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderBlendedOpaque');
|
||||
};
|
||||
|
||||
const renderBlendedTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderBlendedTransparent');
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
|
||||
|
||||
const { renderables } = group;
|
||||
|
||||
@@ -435,63 +513,52 @@ namespace Renderer {
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
if (!r.state.opaque && r.state.writeDepth) {
|
||||
renderObject(r, 'colorBlended');
|
||||
renderObject(r, 'colorBlended', Flag.None);
|
||||
}
|
||||
}
|
||||
|
||||
state.depthMask(false);
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
if (!r.state.opaque && !r.state.writeDepth) {
|
||||
renderObject(r, 'colorBlended');
|
||||
if ((!r.state.opaque && !r.state.writeDepth) || r.values.transparencyAverage.ref.value > 0) {
|
||||
if (r.values.uDoubleSided?.ref.value) {
|
||||
// render frontfaces and backfaces separately to avoid artefacts
|
||||
if (r.values.dTransparentBackfaces?.ref.value !== 'opaque') {
|
||||
renderObject(r, 'colorBlended', Flag.BlendedBack);
|
||||
}
|
||||
renderObject(r, 'colorBlended', Flag.BlendedFront);
|
||||
} else {
|
||||
renderObject(r, 'colorBlended', Flag.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderBlendedTransparent');
|
||||
};
|
||||
|
||||
const renderBlendedVolumeOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
const renderBlendedVolume = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderBlendedVolume');
|
||||
state.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
state.enable(gl.BLEND);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
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 !== 1 && !r.values.dXrayShaded?.ref.value) {
|
||||
renderObject(r, 'colorBlended');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const renderBlendedVolumeTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
state.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
state.enable(gl.BLEND);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, 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.dXrayShaded?.ref.value) {
|
||||
renderObject(r, 'colorBlended');
|
||||
if (r.values.dGeometryType.ref.value === 'directVolume') {
|
||||
renderObject(r, 'colorBlended', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderBlendedVolume');
|
||||
};
|
||||
|
||||
const renderWboitOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderWboitOpaque');
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
updateInternal(group, camera, depthTexture, Mask.Opaque, false);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
@@ -500,14 +567,16 @@ namespace Renderer {
|
||||
// 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.dGeometryType.ref.value !== 'directVolume' && r.values.dPointStyle?.ref.value !== 'fuzzy' && !r.values.dXrayShaded?.ref.value) {
|
||||
renderObject(r, 'colorWboit');
|
||||
if ((alpha === 1 && r.values.transparencyAverage.ref.value !== 1 && r.values.dGeometryType.ref.value !== 'directVolume' && r.values.dPointStyle?.ref.value !== 'fuzzy' && !r.values.dXrayShaded?.ref.value) || r.values.dTransparentBackfaces?.ref.value === 'opaque') {
|
||||
renderObject(r, 'colorWboit', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderWboitOpaque');
|
||||
};
|
||||
|
||||
const renderWboitTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
|
||||
updateInternal(group, camera, depthTexture, true, false);
|
||||
if (isTimingMode) ctx.timer.mark('Renderer.renderWboitTransparent');
|
||||
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
@@ -517,9 +586,10 @@ namespace Renderer {
|
||||
// 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.dGeometryType.ref.value === 'directVolume' || r.values.dPointStyle?.ref.value === 'fuzzy' || !!r.values.uBackgroundColor || r.values.dXrayShaded?.ref.value) {
|
||||
renderObject(r, 'colorWboit');
|
||||
renderObject(r, 'colorWboit', Flag.None);
|
||||
}
|
||||
}
|
||||
if (isTimingMode) ctx.timer.markEnd('Renderer.renderWboitTransparent');
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -538,23 +608,31 @@ namespace Renderer {
|
||||
}
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
},
|
||||
clearDepth: () => {
|
||||
clearDepth: (packed = false) => {
|
||||
state.enable(gl.SCISSOR_TEST);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
if (packed) {
|
||||
state.colorMask(true, true, true, true);
|
||||
state.clearColor(1, 1, 1, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
} else {
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||||
}
|
||||
},
|
||||
update,
|
||||
|
||||
renderPick,
|
||||
renderDepth,
|
||||
renderDepthOpaque,
|
||||
renderDepthTransparent,
|
||||
renderMarkingDepth,
|
||||
renderMarkingMask,
|
||||
renderBlended,
|
||||
renderBlendedOpaque,
|
||||
renderBlendedTransparent,
|
||||
renderBlendedVolumeOpaque,
|
||||
renderBlendedVolumeTransparent,
|
||||
renderBlendedVolume,
|
||||
renderWboitOpaque,
|
||||
renderWboitTransparent,
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import { BoundaryHelper } from '../mol-math/geometry/boundary-helper';
|
||||
import { hash1 } from '../mol-data/util';
|
||||
import { GraphicsRenderable } from './renderable';
|
||||
import { GraphicsRenderVariants } from './webgl/render-item';
|
||||
import { clamp } from '../mol-math/interpolate';
|
||||
|
||||
const boundaryHelper = new BoundaryHelper('98');
|
||||
|
||||
@@ -79,7 +80,8 @@ interface Scene extends Object3D {
|
||||
has: (o: GraphicsRenderObject) => boolean
|
||||
clear: () => void
|
||||
forEach: (callbackFn: (value: GraphicsRenderable, key: GraphicsRenderObject) => void) => void
|
||||
getMarkerAverage: () => number
|
||||
readonly markerAverage: number
|
||||
readonly opacityAverage: number
|
||||
}
|
||||
|
||||
namespace Scene {
|
||||
@@ -99,6 +101,9 @@ namespace Scene {
|
||||
let boundingSphereDirty = true;
|
||||
let boundingSphereVisibleDirty = true;
|
||||
|
||||
let markerAverage = 0;
|
||||
let opacityAverage = 0;
|
||||
|
||||
const object3d = Object3D.create();
|
||||
const { view, position, direction, up } = object3d;
|
||||
|
||||
@@ -155,6 +160,7 @@ namespace Scene {
|
||||
}
|
||||
|
||||
renderables.sort(renderableSort);
|
||||
opacityAverage = calculateOpacityAverage();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -176,12 +182,42 @@ namespace Scene {
|
||||
const newVisibleHash = computeVisibleHash();
|
||||
if (newVisibleHash !== visibleHash) {
|
||||
boundingSphereVisibleDirty = true;
|
||||
opacityAverage = calculateOpacityAverage();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function calculateMarkerAverage() {
|
||||
if (primitives.length === 0) return 0;
|
||||
let count = 0;
|
||||
let markerAverage = 0;
|
||||
for (let i = 0, il = primitives.length; i < il; ++i) {
|
||||
if (!primitives[i].state.visible) continue;
|
||||
markerAverage += primitives[i].values.markerAverage.ref.value;
|
||||
count += 1;
|
||||
}
|
||||
return count > 0 ? markerAverage / count : 0;
|
||||
}
|
||||
|
||||
function calculateOpacityAverage() {
|
||||
if (primitives.length === 0) return 0;
|
||||
let count = 0;
|
||||
let opacityAverage = 0;
|
||||
for (let i = 0, il = primitives.length; i < il; ++i) {
|
||||
const p = primitives[i];
|
||||
if (!p.state.visible) continue;
|
||||
// TODO: simplify, handle in renderable.state???
|
||||
// uAlpha is updated in "render" so we need to recompute it here
|
||||
const alpha = clamp(p.values.alpha.ref.value * p.state.alphaFactor, 0, 1);
|
||||
const xray = p.values.dXrayShaded?.ref.value ? 0.5 : 1;
|
||||
opacityAverage += (1 - p.values.transparencyAverage.ref.value) * alpha * xray;
|
||||
count += 1;
|
||||
}
|
||||
return count > 0 ? opacityAverage / count : 0;
|
||||
}
|
||||
|
||||
return {
|
||||
view, position, direction, up,
|
||||
|
||||
@@ -207,6 +243,8 @@ namespace Scene {
|
||||
} else {
|
||||
syncVisibility();
|
||||
}
|
||||
markerAverage = calculateMarkerAverage();
|
||||
opacityAverage = calculateOpacityAverage();
|
||||
},
|
||||
add: (o: GraphicsRenderObject) => commitQueue.add(o),
|
||||
remove: (o: GraphicsRenderObject) => commitQueue.remove(o),
|
||||
@@ -220,6 +258,8 @@ namespace Scene {
|
||||
renderables[i].dispose();
|
||||
}
|
||||
renderables.length = 0;
|
||||
primitives.length = 0;
|
||||
volumes.length = 0;
|
||||
renderableMap.clear();
|
||||
boundingSphereDirty = true;
|
||||
boundingSphereVisibleDirty = true;
|
||||
@@ -245,16 +285,11 @@ namespace Scene {
|
||||
}
|
||||
return boundingSphereVisible;
|
||||
},
|
||||
getMarkerAverage() {
|
||||
if (primitives.length === 0 && volumes.length === 0) return 0;
|
||||
let markerAverage = 0;
|
||||
for (let i = 0, il = primitives.length; i < il; ++i) {
|
||||
markerAverage += primitives[i].values.markerAverage.ref.value;
|
||||
}
|
||||
for (let i = 0, il = volumes.length; i < il; ++i) {
|
||||
markerAverage += volumes[i].values.markerAverage.ref.value;
|
||||
}
|
||||
return markerAverage / (primitives.length + volumes.length);
|
||||
get markerAverage() {
|
||||
return markerAverage;
|
||||
},
|
||||
get opacityAverage() {
|
||||
return opacityAverage;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -236,6 +236,18 @@ function getDefinesCode(defines: ShaderDefines, ignore?: IgnoreDefine) {
|
||||
return lines.join('\n') + '\n';
|
||||
}
|
||||
|
||||
function getGlsl100VertPrefix(extensions: WebGLExtensions, shaderExtensions: ShaderExtensions) {
|
||||
const prefix: string[] = [];
|
||||
if (shaderExtensions.drawBuffers) {
|
||||
if (extensions.drawBuffers) {
|
||||
prefix.push('#define requiredDrawBuffers');
|
||||
} else if (shaderExtensions.drawBuffers === 'required') {
|
||||
throw new Error(`required 'GL_EXT_draw_buffers' extension not available`);
|
||||
}
|
||||
}
|
||||
return prefix.join('\n') + '\n';
|
||||
}
|
||||
|
||||
function getGlsl100FragPrefix(extensions: WebGLExtensions, shaderExtensions: ShaderExtensions) {
|
||||
const prefix: string[] = [
|
||||
'#extension GL_OES_standard_derivatives : enable'
|
||||
@@ -271,7 +283,7 @@ function getGlsl100FragPrefix(extensions: WebGLExtensions, shaderExtensions: Sha
|
||||
return prefix.join('\n') + '\n';
|
||||
}
|
||||
|
||||
const glsl300VertPrefix = `#version 300 es
|
||||
const glsl300VertPrefixCommon = `
|
||||
#define attribute in
|
||||
#define varying out
|
||||
#define texture2D texture
|
||||
@@ -288,24 +300,45 @@ const glsl300FragPrefixCommon = `
|
||||
#define depthTextureSupport
|
||||
`;
|
||||
|
||||
function getGlsl300VertPrefix(extensions: WebGLExtensions, shaderExtensions: ShaderExtensions) {
|
||||
const prefix = [
|
||||
'#version 300 es',
|
||||
];
|
||||
if (shaderExtensions.drawBuffers) {
|
||||
if (extensions.drawBuffers) {
|
||||
prefix.push('#define requiredDrawBuffers');
|
||||
}
|
||||
}
|
||||
if (extensions.noNonInstancedActiveAttribs) {
|
||||
prefix.push('#define noNonInstancedActiveAttribs');
|
||||
}
|
||||
prefix.push(glsl300VertPrefixCommon);
|
||||
return prefix.join('\n') + '\n';
|
||||
}
|
||||
|
||||
function getGlsl300FragPrefix(gl: WebGL2RenderingContext, extensions: WebGLExtensions, shaderExtensions: ShaderExtensions, outTypes: FragOutTypes) {
|
||||
const prefix = [
|
||||
'#version 300 es',
|
||||
`layout(location = 0) out highp ${outTypes[0] || 'vec4'} out_FragData0;`
|
||||
];
|
||||
|
||||
if (shaderExtensions.fragDepth) {
|
||||
prefix.push('#define enabledFragDepth');
|
||||
if (extensions.fragDepth) {
|
||||
prefix.push('#define enabledFragDepth');
|
||||
}
|
||||
}
|
||||
if (shaderExtensions.drawBuffers) {
|
||||
prefix.push('#define requiredDrawBuffers');
|
||||
const maxDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS) as number;
|
||||
for (let i = 1, il = maxDrawBuffers; i < il; ++i) {
|
||||
prefix.push(`layout(location = ${i}) out highp ${outTypes[i] || 'vec4'} out_FragData${i};`);
|
||||
if (extensions.drawBuffers) {
|
||||
prefix.push('#define requiredDrawBuffers');
|
||||
const maxDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS) as number;
|
||||
for (let i = 1, il = maxDrawBuffers; i < il; ++i) {
|
||||
prefix.push(`layout(location = ${i}) out highp ${outTypes[i] || 'vec4'} out_FragData${i};`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shaderExtensions.shaderTextureLod) {
|
||||
prefix.push('#define enabledShaderTextureLod');
|
||||
if (extensions.shaderTextureLod) {
|
||||
prefix.push('#define enabledShaderTextureLod');
|
||||
}
|
||||
}
|
||||
prefix.push(glsl300FragPrefixCommon);
|
||||
return prefix.join('\n') + '\n';
|
||||
@@ -318,7 +351,9 @@ function transformGlsl300Frag(frag: string) {
|
||||
export function addShaderDefines(gl: GLRenderingContext, extensions: WebGLExtensions, defines: ShaderDefines, shaders: ShaderCode): ShaderCode {
|
||||
const vertHeader = getDefinesCode(defines, shaders.ignoreDefine);
|
||||
const fragHeader = getDefinesCode(defines, shaders.ignoreDefine);
|
||||
const vertPrefix = isWebGL2(gl) ? glsl300VertPrefix : '';
|
||||
const vertPrefix = isWebGL2(gl)
|
||||
? getGlsl300VertPrefix(extensions, shaders.extensions)
|
||||
: getGlsl100VertPrefix(extensions, shaders.extensions);
|
||||
const fragPrefix = isWebGL2(gl)
|
||||
? getGlsl300FragPrefix(gl, extensions, shaders.extensions, shaders.outTypes)
|
||||
: getGlsl100FragPrefix(extensions, shaders.extensions);
|
||||
|
||||
@@ -5,5 +5,9 @@ if (interior) {
|
||||
} else {
|
||||
gl_FragColor.rgb *= 1.0 - uInteriorDarkening;
|
||||
}
|
||||
|
||||
#ifdef dTransparentBackfaces_opaque
|
||||
gl_FragColor.a = 1.0;
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
@@ -56,18 +56,22 @@ export const assign_color_varying = `
|
||||
vSubstance.rgb = mix(vec3(uMetalness, uRoughness, uBumpiness), vSubstance.rgb, vSubstance.a);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
if (uPickType == 1) {
|
||||
vColor = vec4(packIntToRGB(float(uObjectId)), 1.0);
|
||||
} else if (uPickType == 2) {
|
||||
vColor = vec4(packIntToRGB(aInstance), 1.0);
|
||||
} else {
|
||||
vColor = vec4(packIntToRGB(group), 1.0);
|
||||
}
|
||||
#ifdef requiredDrawBuffers
|
||||
vObject = vec4(packIntToRGB(float(uObjectId)), 1.0);
|
||||
vInstance = vec4(packIntToRGB(aInstance), 1.0);
|
||||
vGroup = vec4(packIntToRGB(group), 1.0);
|
||||
#else
|
||||
if (uPickType == 1) {
|
||||
vColor = vec4(packIntToRGB(float(uObjectId)), 1.0);
|
||||
} else if (uPickType == 2) {
|
||||
vColor = vec4(packIntToRGB(aInstance), 1.0);
|
||||
} else {
|
||||
vColor = vec4(packIntToRGB(group), 1.0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef dTransparency
|
||||
vGroup = group;
|
||||
|
||||
#if defined(dTransparencyType_groupInstance)
|
||||
vTransparency = readFromTexture(tTransparency, aInstance * float(uGroupCount) + group, uTransparencyTexDim).a;
|
||||
#elif defined(dTransparencyType_vertexInstance)
|
||||
|
||||
@@ -28,14 +28,35 @@ export const assign_material_color = `
|
||||
roughness = mix(roughness, vSubstance.g, vSubstance.a);
|
||||
bumpiness = mix(bumpiness, vSubstance.b, vSubstance.a);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
vec4 material = vColor;
|
||||
#elif defined(dRenderVariant_depth)
|
||||
#ifdef enabledFragDepth
|
||||
vec4 material = packDepthToRGBA(gl_FragDepthEXT);
|
||||
if (fragmentDepth > getDepth(gl_FragCoord.xy / uDrawingBufferSize)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
#ifndef dXrayShaded
|
||||
#if defined(dTransparency)
|
||||
float dta = 1.0 - vTransparency;
|
||||
if (vTransparency < 0.2) dta = 1.0; // hard cutoff looks better
|
||||
|
||||
if (uRenderMask == MaskTransparent && uAlpha * dta == 1.0) {
|
||||
discard;
|
||||
} else if (uRenderMask == MaskOpaque && uAlpha * dta < 1.0) {
|
||||
discard;
|
||||
}
|
||||
#else
|
||||
if (uRenderMask == MaskTransparent && uAlpha == 1.0) {
|
||||
discard;
|
||||
} else if (uRenderMask == MaskOpaque && uAlpha < 1.0) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
vec4 material = packDepthToRGBA(gl_FragCoord.z);
|
||||
if (uRenderMask == MaskOpaque) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 material = packDepthToRGBA(fragmentDepth);
|
||||
#elif defined(dRenderVariant_marking)
|
||||
vec4 material;
|
||||
if(uMarkingType == 1) {
|
||||
@@ -51,7 +72,7 @@ export const assign_material_color = `
|
||||
discard;
|
||||
float depthTest = 1.0;
|
||||
if (uMarkingDepthTest) {
|
||||
depthTest = (fragmentDepth >= getDepth(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0;
|
||||
depthTest = (fragmentDepth >= getDepthPacked(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0;
|
||||
}
|
||||
bool isHighlight = intMod(marker, 2.0) > 0.1;
|
||||
float viewZ = depthToViewZ(uIsOrtho, fragmentDepth, uNear, uFar);
|
||||
@@ -62,47 +83,41 @@ export const assign_material_color = `
|
||||
}
|
||||
#endif
|
||||
|
||||
// apply screendoor transparency
|
||||
#if defined(dTransparency)
|
||||
// apply per-group transparency
|
||||
#if defined(dTransparency) && (defined(dRenderVariant_pick) || defined(dRenderVariant_color))
|
||||
float ta = 1.0 - vTransparency;
|
||||
#if defined(dRenderVariant_colorWboit)
|
||||
if (vTransparency < 0.2) ta = 1.0; // hard cutoff looks better with wboit
|
||||
#endif
|
||||
if (vTransparency < 0.2) ta = 1.0; // hard cutoff looks better
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
if (ta < uPickingAlphaThreshold)
|
||||
discard; // ignore so the element below can be picked
|
||||
#else
|
||||
#elif defined(dRenderVariant_color)
|
||||
material.a *= ta;
|
||||
|
||||
#if defined(dRenderVariant_colorBlended)
|
||||
float at = 0.0;
|
||||
|
||||
// shift by view-offset during multi-sample rendering to allow for blending
|
||||
vec2 coord = gl_FragCoord.xy + uViewOffset * 0.25;
|
||||
|
||||
const mat4 thresholdMatrix = mat4(
|
||||
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
|
||||
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
|
||||
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
|
||||
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
|
||||
);
|
||||
int ci = int(intMod(coord.x, 4.0));
|
||||
int ri = int(intMod(coord.y, 4.0));
|
||||
#if __VERSION__ == 100
|
||||
vec4 i = vec4(float(ci * 4 + ri));
|
||||
vec4 v = thresholdMatrix[0] * vec4(equal(i, vec4(0.0, 1.0, 2.0, 3.0))) +
|
||||
thresholdMatrix[1] * vec4(equal(i, vec4(4.0, 5.0, 6.0, 7.0))) +
|
||||
thresholdMatrix[2] * vec4(equal(i, vec4(8.0, 9.0, 10.0, 11.0))) +
|
||||
thresholdMatrix[3] * vec4(equal(i, vec4(12.0, 13.0, 14.0, 15.0)));
|
||||
at = v.x + v.y + v.z + v.w;
|
||||
#else
|
||||
at = thresholdMatrix[ci][ri];
|
||||
#if defined(dTransparentBackfaces_off)
|
||||
if ((uRenderMask == MaskOpaque && material.a < 1.0) ||
|
||||
(uRenderMask == MaskTransparent && material.a == 1.0) ||
|
||||
(interior && material.a < 1.0)
|
||||
) {
|
||||
discard;
|
||||
}
|
||||
#elif defined(dTransparentBackfaces_on)
|
||||
if ((uRenderMask == MaskOpaque && material.a < 1.0) ||
|
||||
(uRenderMask == MaskTransparent && material.a == 1.0)
|
||||
) {
|
||||
discard;
|
||||
}
|
||||
#elif defined(dTransparentBackfaces_opaque)
|
||||
if (interior) {
|
||||
material.a = 1.0;
|
||||
} else if (
|
||||
(uRenderMask == MaskOpaque && material.a < 1.0) ||
|
||||
(uRenderMask == MaskTransparent && material.a == 1.0)
|
||||
) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ta < 0.99 && (ta < 0.01 || ta < at)) {
|
||||
discard;
|
||||
}
|
||||
#elif defined(dRenderVariant_colorWboit)
|
||||
material.a *= ta;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,12 @@ export const check_picking_alpha = `
|
||||
float viewZ = depthToViewZ(uIsOrtho, fragmentDepth, uNear, uFar);
|
||||
float fogFactor = smoothstep(uFogNear, uFogFar, abs(viewZ));
|
||||
float alpha = (1.0 - fogFactor) * uAlpha;
|
||||
if (uAlpha < uPickingAlphaThreshold || alpha < 0.1)
|
||||
discard; // ignore so the element below can be picked
|
||||
// if not opaque enough ignore so the element below can be picked
|
||||
if (uAlpha < uPickingAlphaThreshold || alpha < 0.1) {
|
||||
#ifdef dTransparentBackfaces_opaque
|
||||
if (!interior) discard;
|
||||
#else
|
||||
discard;
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
@@ -28,14 +28,25 @@ uniform float uBumpiness;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
#if __VERSION__ == 100
|
||||
varying vec4 vColor;
|
||||
#ifdef requiredDrawBuffers
|
||||
varying vec4 vObject;
|
||||
varying vec4 vInstance;
|
||||
varying vec4 vGroup;
|
||||
#else
|
||||
varying vec4 vColor;
|
||||
#endif
|
||||
#else
|
||||
flat in vec4 vColor;
|
||||
#ifdef requiredDrawBuffers
|
||||
flat in vec4 vObject;
|
||||
flat in vec4 vInstance;
|
||||
flat in vec4 vGroup;
|
||||
#else
|
||||
flat in vec4 vColor;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef dTransparency
|
||||
varying float vGroup;
|
||||
varying float vTransparency;
|
||||
#endif
|
||||
`;
|
||||
@@ -19,6 +19,8 @@ uniform float uBumpiness;
|
||||
uniform vec3 uColorGridDim;
|
||||
uniform vec4 uColorGridTransform;
|
||||
uniform sampler2D tColorGrid;
|
||||
#elif defined(dColorType_direct)
|
||||
varying vec4 vColor;
|
||||
#endif
|
||||
|
||||
#ifdef dUsePalette
|
||||
@@ -54,14 +56,25 @@ uniform float uBumpiness;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
#if __VERSION__ == 100
|
||||
varying vec4 vColor;
|
||||
#ifdef requiredDrawBuffers
|
||||
varying vec4 vObject;
|
||||
varying vec4 vInstance;
|
||||
varying vec4 vGroup;
|
||||
#else
|
||||
varying vec4 vColor;
|
||||
#endif
|
||||
#else
|
||||
flat out vec4 vColor;
|
||||
#ifdef requiredDrawBuffers
|
||||
flat out vec4 vObject;
|
||||
flat out vec4 vInstance;
|
||||
flat out vec4 vGroup;
|
||||
#else
|
||||
flat out vec4 vColor;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef dTransparency
|
||||
varying float vGroup;
|
||||
#if defined(dTransparencyType_groupInstance) || defined(dTransparencyType_vertexInstance)
|
||||
varying float vTransparency;
|
||||
uniform vec2 uTransparencyTexDim;
|
||||
|
||||
@@ -64,17 +64,24 @@ uniform float uXrayEdgeFalloff;
|
||||
|
||||
uniform mat4 uProjection;
|
||||
|
||||
uniform bool uRenderWboit;
|
||||
uniform int uRenderMask;
|
||||
uniform bool uMarkingDepthTest;
|
||||
|
||||
uniform sampler2D tDepth;
|
||||
uniform vec2 uDrawingBufferSize;
|
||||
|
||||
float getDepth(const in vec2 coords) {
|
||||
// always packed due to merged depth from primitives and volumes
|
||||
float getDepthPacked(const in vec2 coords) {
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
}
|
||||
|
||||
float getDepth(const in vec2 coords) {
|
||||
#ifdef depthTextureSupport
|
||||
return texture2D(tDepth, coords).r;
|
||||
#else
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
#endif
|
||||
}
|
||||
|
||||
float calcDepth(const in vec3 pos) {
|
||||
vec2 clipZW = pos.z * uProjection[2].zw + uProjection[3].zw;
|
||||
return 0.5 + 0.5 * clipZW.x / clipZW.y;
|
||||
|
||||
@@ -43,16 +43,10 @@ uniform int uPickType;
|
||||
varying vec3 vModelPosition;
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
#if __VERSION__ == 100
|
||||
attribute float aVertex;
|
||||
#define VertexID int(aVertex)
|
||||
#if defined(noNonInstancedActiveAttribs)
|
||||
#define VertexID gl_VertexID
|
||||
#else
|
||||
// not using gl_VertexID but aVertex to ensure there is an active attribute with divisor 0
|
||||
// since FF 85 this is not needed anymore but lets keep it for backwards compatibility
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1679693
|
||||
// see also note in src/mol-gl/webgl/render-item.ts
|
||||
attribute float aVertex;
|
||||
#define VertexID int(aVertex)
|
||||
// #define VertexID gl_VertexID
|
||||
#endif
|
||||
`;
|
||||
@@ -17,6 +17,10 @@ export const common = `
|
||||
#define dColorType_varying
|
||||
#endif
|
||||
|
||||
#define MaskAll 0
|
||||
#define MaskOpaque 1
|
||||
#define MaskTransparent 2
|
||||
|
||||
//
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
|
||||
export const wboit_write = `
|
||||
#if defined(dRenderVariant_colorWboit)
|
||||
if (!uRenderWboit) {
|
||||
if (uRenderMask == MaskOpaque) {
|
||||
if (preFogAlpha < 1.0) {
|
||||
discard;
|
||||
}
|
||||
} else if (uRenderWboit) {
|
||||
} else if (uRenderMask == MaskTransparent) {
|
||||
// the 'fragmentDepth > 0.99' check is to handle precision issues with packed depth
|
||||
if (preFogAlpha != 1.0 && (fragmentDepth < getDepth(gl_FragCoord.xy / uDrawingBufferSize) || fragmentDepth > 0.99)) {
|
||||
#ifdef dTransparentBackfaces_off
|
||||
if (interior) discard;
|
||||
#endif
|
||||
float alpha = gl_FragColor.a;
|
||||
float wboitWeight = alpha * clamp(pow(1.0 - fragmentDepth, 2.0), 0.01, 1.0);
|
||||
gl_FragColor = vec4(gl_FragColor.rgb * alpha * wboitWeight, alpha);
|
||||
|
||||
@@ -121,7 +121,14 @@ void main() {
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
#include check_picking_alpha
|
||||
gl_FragColor = material;
|
||||
#ifdef requiredDrawBuffers
|
||||
gl_FragColor = vObject;
|
||||
gl_FragData[1] = vInstance;
|
||||
gl_FragData[2] = vGroup;
|
||||
gl_FragData[3] = packDepthToRGBA(fragmentDepth);
|
||||
#else
|
||||
gl_FragColor = vColor;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_marking)
|
||||
|
||||
@@ -68,11 +68,10 @@ uniform float uFogFar;
|
||||
uniform vec3 uFogColor;
|
||||
|
||||
uniform float uAlpha;
|
||||
uniform float uPickingAlphaThreshold;
|
||||
uniform bool uTransparentBackground;
|
||||
uniform float uXrayEdgeFalloff;
|
||||
|
||||
uniform bool uRenderWboit;
|
||||
uniform int uRenderMask;
|
||||
|
||||
uniform float uNear;
|
||||
uniform float uFar;
|
||||
@@ -141,12 +140,7 @@ float transferFunction(float value) {
|
||||
|
||||
float getDepth(const in vec2 coords) {
|
||||
#ifdef depthTextureSupport
|
||||
if (!uRenderWboit) {
|
||||
// in case of opaque volumes (and depth texture support)
|
||||
return texture2D(tDepth, coords).r;
|
||||
} else {
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
}
|
||||
return texture2D(tDepth, coords).r;
|
||||
#else
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
#endif
|
||||
@@ -289,20 +283,24 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
material.rgb = mix(material.rgb, overpaint.rgb, overpaint.a);
|
||||
#endif
|
||||
|
||||
if (material.a >= 0.01) {
|
||||
#ifdef dPackedGroup
|
||||
// compute gradient by central differences
|
||||
gradient.x = textureVal(unitPos - dx).a - textureVal(unitPos + dx).a;
|
||||
gradient.y = textureVal(unitPos - dy).a - textureVal(unitPos + dy).a;
|
||||
gradient.z = textureVal(unitPos - dz).a - textureVal(unitPos + dz).a;
|
||||
#else
|
||||
gradient = cell.xyz * 2.0 - 1.0;
|
||||
#endif
|
||||
vec3 normal = -normalize(normalMatrix * normalize(gradient));
|
||||
#include apply_light_color
|
||||
} else {
|
||||
#ifdef dIgnoreLight
|
||||
gl_FragColor.rgb = material.rgb;
|
||||
}
|
||||
#else
|
||||
if (material.a >= 0.01) {
|
||||
#ifdef dPackedGroup
|
||||
// compute gradient by central differences
|
||||
gradient.x = textureVal(unitPos - dx).a - textureVal(unitPos + dx).a;
|
||||
gradient.y = textureVal(unitPos - dy).a - textureVal(unitPos + dy).a;
|
||||
gradient.z = textureVal(unitPos - dz).a - textureVal(unitPos + dz).a;
|
||||
#else
|
||||
gradient = cell.xyz * 2.0 - 1.0;
|
||||
#endif
|
||||
vec3 normal = -normalize(normalMatrix * normalize(gradient));
|
||||
#include apply_light_color
|
||||
} else {
|
||||
gl_FragColor.rgb = material.rgb;
|
||||
}
|
||||
#endif
|
||||
|
||||
gl_FragColor.a = material.a * uAlpha * uTransferScale;
|
||||
|
||||
|
||||
@@ -103,13 +103,21 @@ void main() {
|
||||
#if defined(dRenderVariant_pick)
|
||||
if (imageData.a < 0.3)
|
||||
discard;
|
||||
if (uPickType == 1) {
|
||||
#ifdef requiredDrawBuffers
|
||||
gl_FragColor = vec4(packIntToRGB(float(uObjectId)), 1.0);
|
||||
} else if (uPickType == 2) {
|
||||
gl_FragColor = vec4(packIntToRGB(vInstance), 1.0);
|
||||
} else {
|
||||
gl_FragColor = vec4(texture2D(tGroupTex, vUv).rgb, 1.0);
|
||||
}
|
||||
gl_FragData[1] = vec4(packIntToRGB(vInstance), 1.0);
|
||||
gl_FragData[2] = vec4(texture2D(tGroupTex, vUv).rgb, 1.0);
|
||||
gl_FragData[3] = packDepthToRGBA(gl_FragCoord.z);
|
||||
#else
|
||||
gl_FragColor = vColor;
|
||||
if (uPickType == 1) {
|
||||
gl_FragColor = vec4(packIntToRGB(float(uObjectId)), 1.0);
|
||||
} else if (uPickType == 2) {
|
||||
gl_FragColor = vec4(packIntToRGB(vInstance), 1.0);
|
||||
} else {
|
||||
gl_FragColor = vec4(texture2D(tGroupTex, vUv).rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
if (imageData.a < 0.05)
|
||||
discard;
|
||||
@@ -130,7 +138,7 @@ void main() {
|
||||
discard;
|
||||
float depthTest = 1.0;
|
||||
if (uMarkingDepthTest) {
|
||||
depthTest = (fragmentDepth >= getDepth(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0;
|
||||
depthTest = (fragmentDepth >= getDepthPacked(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0;
|
||||
}
|
||||
bool isHighlight = intMod(marker, 2.0) > 0.1;
|
||||
gl_FragColor = vec4(0.0, depthTest, isHighlight ? 1.0 : 0.0, 1.0);
|
||||
|
||||
@@ -21,7 +21,14 @@ void main(){
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
#include check_picking_alpha
|
||||
gl_FragColor = material;
|
||||
#ifdef requiredDrawBuffers
|
||||
gl_FragColor = vObject;
|
||||
gl_FragData[1] = vInstance;
|
||||
gl_FragData[2] = vGroup;
|
||||
gl_FragData[3] = packDepthToRGBA(fragmentDepth);
|
||||
#else
|
||||
gl_FragColor = vColor;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_marking)
|
||||
|
||||
@@ -37,7 +37,14 @@ void main() {
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
#include check_picking_alpha
|
||||
gl_FragColor = material;
|
||||
#ifdef requiredDrawBuffers
|
||||
gl_FragColor = vObject;
|
||||
gl_FragData[1] = vInstance;
|
||||
gl_FragData[2] = vGroup;
|
||||
gl_FragData[3] = packDepthToRGBA(fragmentDepth);
|
||||
#else
|
||||
gl_FragColor = vColor;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_marking)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
|
||||
@author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
export const outlines_frag = `
|
||||
@@ -9,7 +10,8 @@ precision highp float;
|
||||
precision highp int;
|
||||
precision highp sampler2D;
|
||||
|
||||
uniform sampler2D tDepth;
|
||||
uniform sampler2D tDepthOpaque;
|
||||
uniform sampler2D tDepthTransparent;
|
||||
uniform vec2 uTexSize;
|
||||
|
||||
uniform float uNear;
|
||||
@@ -27,8 +29,16 @@ float getViewZ(const in float depth) {
|
||||
#endif
|
||||
}
|
||||
|
||||
float getDepth(const in vec2 coords) {
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
float getDepthOpaque(const in vec2 coords) {
|
||||
#ifdef depthTextureSupport
|
||||
return texture2D(tDepthOpaque, coords).r;
|
||||
#else
|
||||
return unpackRGBAToDepth(texture2D(tDepthOpaque, coords));
|
||||
#endif
|
||||
}
|
||||
|
||||
float getDepthTransparent(const in vec2 coords) {
|
||||
return unpackRGBAToDepth(texture2D(tDepthTransparent, coords));
|
||||
}
|
||||
|
||||
bool isBackground(const in float depth) {
|
||||
@@ -41,8 +51,11 @@ void main(void) {
|
||||
vec2 coords = gl_FragCoord.xy / uTexSize;
|
||||
vec2 invTexSize = 1.0 / uTexSize;
|
||||
|
||||
float selfDepth = getDepth(coords);
|
||||
float selfViewZ = isBackground(selfDepth) ? backgroundViewZ : getViewZ(getDepth(coords));
|
||||
float selfDepthOpaque = getDepthOpaque(coords);
|
||||
float selfViewZOpaque = isBackground(selfDepthOpaque) ? backgroundViewZ : getViewZ(selfDepthOpaque);
|
||||
|
||||
float selfDepthTransparent = getDepthTransparent(coords);
|
||||
float selfViewZTransparent = isBackground(selfDepthTransparent) ? backgroundViewZ : getViewZ(selfDepthTransparent);
|
||||
|
||||
float outline = 1.0;
|
||||
float bestDepth = 1.0;
|
||||
@@ -50,12 +63,22 @@ void main(void) {
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
vec2 sampleCoords = coords + vec2(float(x), float(y)) * invTexSize;
|
||||
float sampleDepth = getDepth(sampleCoords);
|
||||
float sampleViewZ = isBackground(sampleDepth) ? backgroundViewZ : getViewZ(sampleDepth);
|
||||
|
||||
if (abs(selfViewZ - sampleViewZ) > uMaxPossibleViewZDiff && selfDepth > sampleDepth && sampleDepth <= bestDepth) {
|
||||
float sampleDepthOpaque = getDepthOpaque(sampleCoords);
|
||||
float sampleDepthTransparent = getDepthTransparent(sampleCoords);
|
||||
|
||||
float sampleViewZOpaque = isBackground(sampleDepthOpaque) ? backgroundViewZ : getViewZ(sampleDepthOpaque);
|
||||
if (abs(selfViewZOpaque - sampleViewZOpaque) > uMaxPossibleViewZDiff && selfDepthOpaque > sampleDepthOpaque && sampleDepthOpaque <= bestDepth) {
|
||||
outline = 0.0;
|
||||
bestDepth = sampleDepth;
|
||||
bestDepth = sampleDepthOpaque;
|
||||
}
|
||||
|
||||
if (sampleDepthTransparent < sampleDepthOpaque) {
|
||||
float sampleViewZTransparent = isBackground(sampleDepthTransparent) ? backgroundViewZ : getViewZ(sampleDepthTransparent);
|
||||
if (abs(selfViewZTransparent - sampleViewZTransparent) > uMaxPossibleViewZDiff && selfDepthTransparent > sampleDepthTransparent && sampleDepthTransparent <= bestDepth) {
|
||||
outline = 0.0;
|
||||
bestDepth = sampleDepthTransparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,14 @@ void main(){
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
#include check_picking_alpha
|
||||
gl_FragColor = material;
|
||||
#ifdef requiredDrawBuffers
|
||||
gl_FragColor = vObject;
|
||||
gl_FragData[1] = vInstance;
|
||||
gl_FragData[2] = vGroup;
|
||||
gl_FragData[3] = packDepthToRGBA(fragmentDepth);
|
||||
#else
|
||||
gl_FragColor = vColor;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_marking)
|
||||
|
||||
@@ -12,7 +12,8 @@ precision highp sampler2D;
|
||||
|
||||
uniform sampler2D tSsaoDepth;
|
||||
uniform sampler2D tColor;
|
||||
uniform sampler2D tDepth;
|
||||
uniform sampler2D tDepthOpaque;
|
||||
uniform sampler2D tDepthTransparent;
|
||||
uniform sampler2D tOutlines;
|
||||
uniform vec2 uTexSize;
|
||||
|
||||
@@ -40,19 +41,27 @@ float getViewZ(const in float depth) {
|
||||
#endif
|
||||
}
|
||||
|
||||
float getDepth(const in vec2 coords) {
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
float getDepthOpaque(const in vec2 coords) {
|
||||
#ifdef depthTextureSupport
|
||||
return texture2D(tDepthOpaque, coords).r;
|
||||
#else
|
||||
return unpackRGBAToDepth(texture2D(tDepthOpaque, coords));
|
||||
#endif
|
||||
}
|
||||
|
||||
float getDepthTransparent(const in vec2 coords) {
|
||||
return unpackRGBAToDepth(texture2D(tDepthTransparent, coords));
|
||||
}
|
||||
|
||||
bool isBackground(const in float depth) {
|
||||
return depth == 1.0;
|
||||
}
|
||||
|
||||
float getOutline(const in vec2 coords, out float closestTexel) {
|
||||
float getOutline(const in vec2 coords, const in float opaqueDepth, out float closestTexel) {
|
||||
float backgroundViewZ = uFar + 3.0 * uMaxPossibleViewZDiff;
|
||||
vec2 invTexSize = 1.0 / uTexSize;
|
||||
|
||||
float selfDepth = getDepth(coords);
|
||||
float selfDepth = min(opaqueDepth, getDepthTransparent(coords));
|
||||
float selfViewZ = isBackground(selfDepth) ? backgroundViewZ : getViewZ(selfDepth);
|
||||
|
||||
float outline = 1.0;
|
||||
@@ -68,14 +77,15 @@ float getOutline(const in vec2 coords, out float closestTexel) {
|
||||
vec4 sampleOutlineCombined = texture2D(tOutlines, sampleCoords);
|
||||
float sampleOutline = sampleOutlineCombined.r;
|
||||
float sampleOutlineDepth = unpackRGToUnitInterval(sampleOutlineCombined.gb);
|
||||
float sampleOutlineViewZ = isBackground(sampleOutlineDepth) ? backgroundViewZ : getViewZ(sampleOutlineDepth);
|
||||
|
||||
if (sampleOutline == 0.0 && sampleOutlineDepth < closestTexel && abs(selfViewZ - sampleOutlineDepth) > uMaxPossibleViewZDiff) {
|
||||
if (sampleOutline == 0.0 && sampleOutlineDepth < closestTexel && abs(selfViewZ - sampleOutlineViewZ) > uMaxPossibleViewZDiff) {
|
||||
outline = 0.0;
|
||||
closestTexel = sampleOutlineDepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
return outline;
|
||||
return closestTexel < opaqueDepth ? outline : 1.0;
|
||||
}
|
||||
|
||||
float getSsao(vec2 coords) {
|
||||
@@ -95,11 +105,11 @@ void main(void) {
|
||||
|
||||
float viewDist;
|
||||
float fogFactor;
|
||||
float opaqueDepth = getDepthOpaque(coords);
|
||||
|
||||
#ifdef dOcclusionEnable
|
||||
float depth = getDepth(coords);
|
||||
if (!isBackground(depth)) {
|
||||
viewDist = abs(getViewZ(depth));
|
||||
if (!isBackground(opaqueDepth)) {
|
||||
viewDist = abs(getViewZ(opaqueDepth));
|
||||
fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
|
||||
float occlusionFactor = getSsao(coords + uOcclusionOffset);
|
||||
if (!uTransparentBackground) {
|
||||
@@ -113,16 +123,15 @@ void main(void) {
|
||||
// outline needs to be handled after occlusion to keep them clean
|
||||
#ifdef dOutlineEnable
|
||||
float closestTexel;
|
||||
float outline = getOutline(coords, closestTexel);
|
||||
|
||||
float outline = getOutline(coords, opaqueDepth, closestTexel);
|
||||
if (outline == 0.0) {
|
||||
color.rgb = mix(uOutlineColor, color.rgb, outline);
|
||||
viewDist = abs(getViewZ(closestTexel));
|
||||
fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
|
||||
if (!uTransparentBackground) {
|
||||
color.rgb = mix(color.rgb, uFogColor, fogFactor);
|
||||
color.rgb = mix(uOutlineColor, uFogColor, fogFactor);
|
||||
} else {
|
||||
color.a = 1.0 - fogFactor;
|
||||
color.rgb = mix(uOutlineColor, color.rgb, fogFactor);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -86,7 +86,14 @@ void main(void){
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
#include check_picking_alpha
|
||||
gl_FragColor = material;
|
||||
#ifdef requiredDrawBuffers
|
||||
gl_FragColor = vObject;
|
||||
gl_FragData[1] = vInstance;
|
||||
gl_FragData[2] = vGroup;
|
||||
gl_FragData[3] = packDepthToRGBA(fragmentDepth);
|
||||
#else
|
||||
gl_FragColor = vColor;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_marking)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
|
||||
@@ -51,7 +51,15 @@ bool outsideBounds(const in vec2 p) {
|
||||
}
|
||||
|
||||
float getDepth(const in vec2 coords) {
|
||||
return outsideBounds(coords) ? 1.0 : unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
if (outsideBounds(coords)) {
|
||||
return 1.0;
|
||||
} else {
|
||||
#ifdef depthTextureSupport
|
||||
return texture2D(tDepth, coords).r;
|
||||
#else
|
||||
return unpackRGBAToDepth(texture2D(tDepth, coords));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
vec3 normalFromDepth(const in float depth, const in float depth1, const in float depth2, vec2 offset1, vec2 offset2) {
|
||||
|
||||
@@ -36,7 +36,9 @@ void main(){
|
||||
#include assign_material_color
|
||||
|
||||
if (vTexCoord.x > 1.0) {
|
||||
gl_FragColor = vec4(uBackgroundColor, uBackgroundOpacity * material.a);
|
||||
#if defined(dRenderVariant_color)
|
||||
material = vec4(uBackgroundColor, uBackgroundOpacity * material.a);
|
||||
#endif
|
||||
} else {
|
||||
// retrieve signed distance
|
||||
float sdf = texture2D(tFont, vTexCoord).a + uBorderWidth;
|
||||
@@ -49,24 +51,35 @@ void main(){
|
||||
a = pow(a, 1.0 / gamma);
|
||||
|
||||
if (a < 0.5) discard;
|
||||
material.a *= a;
|
||||
|
||||
// add border
|
||||
float t = 0.5 + uBorderWidth;
|
||||
if (uBorderWidth > 0.0 && sdf < t) {
|
||||
material.xyz = mix(uBorderColor, material.xyz, smoothstep(t - w, t, sdf));
|
||||
}
|
||||
#if defined(dRenderVariant_color)
|
||||
material.a *= a;
|
||||
|
||||
gl_FragColor = material;
|
||||
// add border
|
||||
float t = 0.5 + uBorderWidth;
|
||||
if (uBorderWidth > 0.0 && sdf < t) {
|
||||
material.xyz = mix(uBorderColor, material.xyz, smoothstep(t - w, t, sdf));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(dRenderVariant_pick)
|
||||
#include check_picking_alpha
|
||||
#ifdef requiredDrawBuffers
|
||||
gl_FragColor = vObject;
|
||||
gl_FragData[1] = vInstance;
|
||||
gl_FragData[2] = vGroup;
|
||||
gl_FragData[3] = packDepthToRGBA(fragmentDepth);
|
||||
#else
|
||||
gl_FragColor = vColor;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_marking)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_color)
|
||||
gl_FragColor = material;
|
||||
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
#include wboit_write
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -320,6 +320,101 @@ export function getSRGB(gl: GLRenderingContext): COMPAT_sRGB | null {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
/** A WebGLQuery object, which is the currently active query for the given target. */
|
||||
CURRENT_QUERY: number
|
||||
/** A GLuint64EXT containing the query result. */
|
||||
QUERY_RESULT: number
|
||||
/** A GLboolean indicating whether or not a query result is available. */
|
||||
QUERY_RESULT_AVAILABLE: number
|
||||
/** Elapsed time (in nanoseconds). */
|
||||
TIME_ELAPSED: number
|
||||
/** The current time. */
|
||||
TIMESTAMP: number
|
||||
/** A GLboolean indicating whether or not the GPU performed any disjoint operation. */
|
||||
GPU_DISJOINT: number
|
||||
|
||||
/** Creates a new WebGLTimerQueryEXT. */
|
||||
createQuery: () => WebGLQuery
|
||||
/** Deletes a given WebGLTimerQueryEXT. */
|
||||
deleteQuery: (query: WebGLQuery) => void
|
||||
/** Returns true if a given object is a valid WebGLTimerQueryEXT. */
|
||||
isQuery: (query: WebGLQuery) => boolean
|
||||
/** The timer starts when all commands prior to beginQueryEXT have been fully executed. */
|
||||
beginQuery: (target: number, query: WebGLQuery) => void
|
||||
/** The timer stops when all commands prior to endQueryEXT have been fully executed. */
|
||||
endQuery: (target: number) => void
|
||||
/** Records the current time into the corresponding query object. */
|
||||
queryCounter: (query: WebGLQuery, target: number) => void
|
||||
/** Returns information about a query target. */
|
||||
getQuery: (target: number, pname: number) => WebGLQuery | number
|
||||
/** Return the state of a query object. */
|
||||
getQueryParameter: (query: WebGLQuery, pname: number) => number | boolean
|
||||
}
|
||||
|
||||
export function getDisjointTimerQuery(gl: GLRenderingContext): COMPAT_disjoint_timer_query | null {
|
||||
if (isWebGL2(gl)) {
|
||||
// Firefox has EXT_disjoint_timer_query in webgl2
|
||||
const ext = gl.getExtension('EXT_disjoint_timer_query_webgl2') || gl.getExtension('EXT_disjoint_timer_query');
|
||||
if (ext === null) return null;
|
||||
return {
|
||||
QUERY_COUNTER_BITS: ext.QUERY_COUNTER_BITS_EXT,
|
||||
CURRENT_QUERY: gl.CURRENT_QUERY,
|
||||
QUERY_RESULT: gl.QUERY_RESULT,
|
||||
QUERY_RESULT_AVAILABLE: gl.QUERY_RESULT_AVAILABLE,
|
||||
TIME_ELAPSED: ext.TIME_ELAPSED_EXT,
|
||||
TIMESTAMP: ext.TIMESTAMP_EXT,
|
||||
GPU_DISJOINT: ext.GPU_DISJOINT_EXT,
|
||||
|
||||
createQuery: gl.createQuery.bind(gl),
|
||||
deleteQuery: gl.deleteQuery.bind(gl),
|
||||
isQuery: gl.isQuery.bind(gl),
|
||||
beginQuery: gl.beginQuery.bind(gl),
|
||||
endQuery: gl.endQuery.bind(gl),
|
||||
queryCounter: ext.queryCounterEXT.bind(ext),
|
||||
getQuery: gl.getQuery.bind(gl),
|
||||
getQueryParameter: gl.getQueryParameter.bind(gl),
|
||||
};
|
||||
} else {
|
||||
const ext = gl.getExtension('EXT_disjoint_timer_query');
|
||||
if (ext === null) return null;
|
||||
return {
|
||||
QUERY_COUNTER_BITS: ext.QUERY_COUNTER_BITS_EXT,
|
||||
CURRENT_QUERY: ext.CURRENT_QUERY_EXT,
|
||||
QUERY_RESULT: ext.QUERY_RESULT_EXT,
|
||||
QUERY_RESULT_AVAILABLE: ext.QUERY_RESULT_AVAILABLE_EXT,
|
||||
TIME_ELAPSED: ext.TIME_ELAPSED_EXT,
|
||||
TIMESTAMP: ext.TIMESTAMP_EXT,
|
||||
GPU_DISJOINT: ext.GPU_DISJOINT_EXT,
|
||||
|
||||
createQuery: ext.createQueryEXT.bind(ext),
|
||||
deleteQuery: ext.deleteQueryEXT.bind(ext),
|
||||
isQuery: ext.isQueryEXT.bind(ext),
|
||||
beginQuery: ext.beginQueryEXT.bind(ext),
|
||||
endQuery: ext.endQueryEXT.bind(ext),
|
||||
queryCounter: ext.queryCounterEXT.bind(ext),
|
||||
getQuery: ext.getQueryEXT.bind(ext),
|
||||
getQueryParameter: ext.getQueryObjectEXT.bind(ext),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function getNoNonInstancedActiveAttribs(gl: GLRenderingContext): boolean {
|
||||
if (!isWebGL2(gl)) return false;
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
const ffMatch = window.navigator.userAgent.match(/Firefox\/([0-9]+)\./);
|
||||
if (!ffMatch) return true;
|
||||
|
||||
const ffVersion = parseInt(ffMatch[1]);
|
||||
// supported since FF 85 (https://bugzilla.mozilla.org/show_bug.cgi?id=1679693)
|
||||
return ffVersion >= 85;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const TextureTestVertShader = `
|
||||
|
||||
@@ -17,6 +17,7 @@ import { BehaviorSubject } from 'rxjs';
|
||||
import { now } from '../../mol-util/now';
|
||||
import { Texture, TextureFilter } from './texture';
|
||||
import { ComputeRenderable } from '../renderable';
|
||||
import { createTimer, WebGLTimer } from './timer';
|
||||
|
||||
export function getGLContext(canvas: HTMLCanvasElement, attribs?: WebGLContextAttributes & { preferWebGl1?: boolean }): GLRenderingContext | null {
|
||||
function get(id: 'webgl' | 'experimental-webgl' | 'webgl2') {
|
||||
@@ -186,6 +187,7 @@ export interface WebGLContext {
|
||||
readonly state: WebGLState
|
||||
readonly stats: WebGLStats
|
||||
readonly resources: WebGLResources
|
||||
readonly timer: WebGLTimer
|
||||
|
||||
readonly maxTextureSize: number
|
||||
readonly max3dTextureSize: number
|
||||
@@ -221,6 +223,7 @@ export function createContext(gl: GLRenderingContext, props: Partial<{ pixelScal
|
||||
const state = createState(gl);
|
||||
const stats = createStats();
|
||||
const resources = createResources(gl, state, stats, extensions);
|
||||
const timer = createTimer(gl, extensions);
|
||||
|
||||
const parameters = {
|
||||
maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE) as number,
|
||||
@@ -289,6 +292,7 @@ export function createContext(gl: GLRenderingContext, props: Partial<{ pixelScal
|
||||
state,
|
||||
stats,
|
||||
resources,
|
||||
timer,
|
||||
|
||||
get maxTextureSize() { return parameters.maxTextureSize; },
|
||||
get max3dTextureSize() { return parameters.max3dTextureSize; },
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @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 } 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 = {
|
||||
@@ -25,6 +25,9 @@ export type WebGLExtensions = {
|
||||
drawBuffers: COMPAT_draw_buffers | null
|
||||
shaderTextureLod: COMPAT_shader_texture_lod | null
|
||||
sRGB: COMPAT_sRGB | null
|
||||
disjointTimerQuery: COMPAT_disjoint_timer_query | null
|
||||
|
||||
noNonInstancedActiveAttribs: boolean
|
||||
}
|
||||
|
||||
export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
|
||||
@@ -99,6 +102,12 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
|
||||
if (isDebugMode && sRGB === null) {
|
||||
console.log('Could not find support for "sRGB"');
|
||||
}
|
||||
const disjointTimerQuery = getDisjointTimerQuery(gl);
|
||||
if (isDebugMode && disjointTimerQuery === null) {
|
||||
console.log('Could not find support for "disjoint_timer_query"');
|
||||
}
|
||||
|
||||
const noNonInstancedActiveAttribs = getNoNonInstancedActiveAttribs(gl);
|
||||
|
||||
return {
|
||||
instancedArrays,
|
||||
@@ -118,5 +127,8 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
|
||||
drawBuffers,
|
||||
shaderTextureLod,
|
||||
sRGB,
|
||||
disjointTimerQuery,
|
||||
|
||||
noNonInstancedActiveAttribs,
|
||||
};
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code';
|
||||
import { WebGLState } from './state';
|
||||
import { WebGLExtensions } from './extensions';
|
||||
import { getUniformSetters, UniformsList, getUniformType, UniformSetters } from './uniform';
|
||||
import { getUniformSetters, UniformsList, getUniformType, UniformSetters, isArrayUniform } from './uniform';
|
||||
import { AttributeBuffers, getAttribType } from './buffer';
|
||||
import { TextureId, Textures } from './texture';
|
||||
import { idFactory } from '../../mol-util/id-factory';
|
||||
@@ -41,7 +41,14 @@ function getLocations(gl: GLRenderingContext, program: WebGLProgram, schema: Ren
|
||||
// unused attributes will result in a `-1` location which is usually fine
|
||||
// if (loc === -1) console.info(`Could not get attribute location for '${k}'`);
|
||||
locations[k] = loc;
|
||||
} else if (spec.type === 'uniform' || spec.type === 'texture') {
|
||||
} else if (spec.type === 'uniform') {
|
||||
let loc = gl.getUniformLocation(program, k);
|
||||
// headless-gl requires a '[0]' suffix for array uniforms (https://github.com/stackgl/headless-gl/issues/170)
|
||||
if (loc === null && isArrayUniform(spec.kind)) loc = gl.getUniformLocation(program, k + '[0]');
|
||||
// unused uniforms will result in a `null` location which is usually fine
|
||||
// if (loc === null) console.info(`Could not get uniform location for '${k}'`);
|
||||
locations[k] = loc as number;
|
||||
} else if (spec.type === 'texture') {
|
||||
const loc = gl.getUniformLocation(program, k);
|
||||
// unused uniforms will result in a `null` location which is usually fine
|
||||
// if (loc === null) console.info(`Could not get uniform location for '${k}'`);
|
||||
|
||||
@@ -112,12 +112,7 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
|
||||
const { instancedArrays, vertexArrayObject } = ctx.extensions;
|
||||
|
||||
// emulate gl_VertexID when needed
|
||||
// if (!ctx.isWebGL2 && values.uVertexCount) {
|
||||
// not using gl_VertexID in WebGL2 but aVertex to ensure there is an active attribute with divisor 0
|
||||
// since FF 85 this is not needed anymore but lets keep it for backwards compatibility
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1679693
|
||||
// see also note in src/mol-gl/shader/chunks/common-vert-params.glsl.ts
|
||||
if (values.uVertexCount) {
|
||||
if (values.uVertexCount && !ctx.extensions.noNonInstancedActiveAttribs) {
|
||||
const vertexCount = values.uVertexCount.ref.value;
|
||||
(values as any).aVertex = ValueCell.create(fillSerial(new Float32Array(vertexCount)));
|
||||
(schema as any).aVertex = AttributeSpec('float32', 1, 0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -9,6 +9,7 @@ import { createNullTexture, Texture, TextureFilter } from './texture';
|
||||
import { createNullFramebuffer, Framebuffer } from './framebuffer';
|
||||
import { WebGLResources } from './resources';
|
||||
import { GLRenderingContext, isWebGL2 } from './compat';
|
||||
import { Renderbuffer } from './renderbuffer';
|
||||
|
||||
const getNextRenderTargetId = idFactory();
|
||||
|
||||
@@ -16,6 +17,7 @@ export interface RenderTarget {
|
||||
readonly id: number
|
||||
readonly texture: Texture
|
||||
readonly framebuffer: Framebuffer
|
||||
readonly depthRenderbuffer: Renderbuffer | null
|
||||
|
||||
getWidth: () => number
|
||||
getHeight: () => number
|
||||
@@ -54,6 +56,7 @@ export function createRenderTarget(gl: GLRenderingContext, resources: WebGLResou
|
||||
id: getNextRenderTargetId(),
|
||||
texture: targetTexture,
|
||||
framebuffer,
|
||||
depthRenderbuffer,
|
||||
|
||||
getWidth: () => _width,
|
||||
getHeight: () => _height,
|
||||
@@ -90,6 +93,7 @@ export function createNullRenderTarget(gl: GLRenderingContext): RenderTarget {
|
||||
id: getNextRenderTargetId(),
|
||||
texture: createNullTexture(gl),
|
||||
framebuffer: createNullFramebuffer(),
|
||||
depthRenderbuffer: null,
|
||||
|
||||
getWidth: () => 0,
|
||||
getHeight: () => 0,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -40,6 +40,7 @@ export interface Renderbuffer {
|
||||
|
||||
bind: () => void
|
||||
attachFramebuffer: (framebuffer: Framebuffer) => void
|
||||
detachFramebuffer: (framebuffer: Framebuffer) => void
|
||||
setSize: (width: number, height: number) => void
|
||||
reset: () => void
|
||||
destroy: () => void
|
||||
@@ -78,6 +79,12 @@ export function createRenderbuffer(gl: GLRenderingContext, format: RenderbufferF
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, _attachment, gl.RENDERBUFFER, _renderbuffer);
|
||||
if (isDebugMode) checkFramebufferStatus(gl);
|
||||
},
|
||||
detachFramebuffer: (framebuffer: Framebuffer) => {
|
||||
framebuffer.bind();
|
||||
bind();
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, _attachment, gl.RENDERBUFFER, null);
|
||||
if (isDebugMode) checkFramebufferStatus(gl);
|
||||
},
|
||||
setSize: (width: number, height: number) => {
|
||||
_width = width;
|
||||
_height = height;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -44,6 +44,10 @@ export type WebGLState = {
|
||||
cullFace: (mode: number) => void
|
||||
/** sets whether writing into the depth buffer is enabled or disabled */
|
||||
depthMask: (flag: boolean) => void
|
||||
/** specifies the depth value used when clearing depth buffer, used when calling `gl.clear` */
|
||||
clearDepth: (depth: number) => void
|
||||
/** sets the depth comparison function */
|
||||
depthFunc: (func: number) => void
|
||||
/** sets which color components to enable or to disable */
|
||||
colorMask: (red: boolean, green: boolean, blue: boolean, alpha: boolean) => void
|
||||
/** specifies the color values used when clearing color buffers, used when calling `gl.clear`, clamped to [0, 1] */
|
||||
@@ -58,6 +62,8 @@ export type WebGLState = {
|
||||
blendEquation: (mode: number) => void
|
||||
/** set the RGB blend equation and alpha blend equation separately, determines how a new pixel is combined with an existing */
|
||||
blendEquationSeparate: (modeRGB: number, modeAlpha: number) => void
|
||||
/** specifies the source and destination blending factors, clamped to [0, 1] */
|
||||
blendColor: (red: number, green: number, blue: number, alpha: number) => void
|
||||
|
||||
enableVertexAttrib: (index: number) => void
|
||||
clearVertexAttribsState: () => void
|
||||
@@ -72,6 +78,8 @@ export function createState(gl: GLRenderingContext): WebGLState {
|
||||
let currentFrontFace = gl.getParameter(gl.FRONT_FACE);
|
||||
let currentCullFace = gl.getParameter(gl.CULL_FACE_MODE);
|
||||
let currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK);
|
||||
let currentClearDepth = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
|
||||
let currentDepthFunc = gl.getParameter(gl.DEPTH_FUNC);
|
||||
let currentColorMask = gl.getParameter(gl.COLOR_WRITEMASK);
|
||||
let currentClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
|
||||
|
||||
@@ -79,6 +87,7 @@ export function createState(gl: GLRenderingContext): WebGLState {
|
||||
let currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB);
|
||||
let currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA);
|
||||
let currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA);
|
||||
let currentBlendColor = gl.getParameter(gl.BLEND_COLOR);
|
||||
|
||||
let currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB);
|
||||
let currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA);
|
||||
@@ -129,6 +138,18 @@ export function createState(gl: GLRenderingContext): WebGLState {
|
||||
currentDepthMask = flag;
|
||||
}
|
||||
},
|
||||
clearDepth: (depth: number) => {
|
||||
if (depth !== currentClearDepth) {
|
||||
gl.clearDepth(depth);
|
||||
currentClearDepth = depth;
|
||||
}
|
||||
},
|
||||
depthFunc: (func: number) => {
|
||||
if (func !== currentDepthFunc) {
|
||||
gl.depthFunc(func);
|
||||
currentDepthFunc = func;
|
||||
}
|
||||
},
|
||||
colorMask: (red: boolean, green: boolean, blue: boolean, alpha: boolean) => {
|
||||
if (red !== currentColorMask[0] || green !== currentColorMask[1] || blue !== currentColorMask[2] || alpha !== currentColorMask[3]) {
|
||||
gl.colorMask(red, green, blue, alpha);
|
||||
@@ -166,7 +187,6 @@ export function createState(gl: GLRenderingContext): WebGLState {
|
||||
currentBlendDstAlpha = dstAlpha;
|
||||
}
|
||||
},
|
||||
|
||||
blendEquation: (mode: number) => {
|
||||
if (mode !== currentBlendEqRGB || mode !== currentBlendEqAlpha) {
|
||||
gl.blendEquation(mode);
|
||||
@@ -181,6 +201,15 @@ export function createState(gl: GLRenderingContext): WebGLState {
|
||||
currentBlendEqAlpha = modeAlpha;
|
||||
}
|
||||
},
|
||||
blendColor: (red: number, green: number, blue: number, alpha: number) => {
|
||||
if (red !== currentBlendColor[0] || green !== currentBlendColor[1] || blue !== currentBlendColor[2] || alpha !== currentBlendColor[3]) {
|
||||
gl.blendColor(red, green, blue, alpha);
|
||||
currentBlendColor[0] = red;
|
||||
currentBlendColor[1] = green;
|
||||
currentBlendColor[2] = blue;
|
||||
currentBlendColor[3] = alpha;
|
||||
}
|
||||
},
|
||||
|
||||
enableVertexAttrib: (index: number) => {
|
||||
gl.enableVertexAttribArray(index);
|
||||
@@ -199,6 +228,8 @@ export function createState(gl: GLRenderingContext): WebGLState {
|
||||
currentFrontFace = gl.getParameter(gl.FRONT_FACE);
|
||||
currentCullFace = gl.getParameter(gl.CULL_FACE_MODE);
|
||||
currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK);
|
||||
currentClearDepth = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
|
||||
currentDepthFunc = gl.getParameter(gl.DEPTH_FUNC);
|
||||
currentColorMask = gl.getParameter(gl.COLOR_WRITEMASK);
|
||||
currentClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
|
||||
|
||||
@@ -206,6 +237,7 @@ export function createState(gl: GLRenderingContext): WebGLState {
|
||||
currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB);
|
||||
currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA);
|
||||
currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA);
|
||||
currentBlendColor = gl.getParameter(gl.BLEND_COLOR);
|
||||
|
||||
currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB);
|
||||
currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA);
|
||||
|
||||
@@ -238,6 +238,10 @@ export function createTexture(gl: GLRenderingContext, extensions: WebGLExtension
|
||||
throw new Error(`texture kind '${kind}' and type '${_type}' are incompatible`);
|
||||
}
|
||||
|
||||
if (!extensions.depthTexture && _format === 'depth') {
|
||||
throw new Error(`extension 'WEBGL_depth_texture' needed for 'depth' texture format`);
|
||||
}
|
||||
|
||||
const target = getTarget(gl, kind);
|
||||
const filter = getFilter(gl, _filter);
|
||||
const format = getFormat(gl, _format, _type);
|
||||
|
||||
194
src/mol-gl/webgl/timer.ts
Normal file
194
src/mol-gl/webgl/timer.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { GLRenderingContext } from './compat';
|
||||
import { WebGLExtensions } from './extensions';
|
||||
|
||||
export type TimerResult = {
|
||||
readonly label: string
|
||||
readonly timeElapsed: number
|
||||
readonly children: TimerResult[]
|
||||
}
|
||||
|
||||
function getQuery(extensions: WebGLExtensions) {
|
||||
return extensions.disjointTimerQuery ? extensions.disjointTimerQuery.createQuery() : null;
|
||||
}
|
||||
|
||||
export type WebGLTimer = {
|
||||
/** Check with GPU for finished timers. */
|
||||
resolve: () => TimerResult[]
|
||||
mark: (label: string) => void
|
||||
markEnd: (label: string) => void
|
||||
clear: () => void
|
||||
destroy: () => void
|
||||
}
|
||||
|
||||
type Measure = { label: string, queries: WebGLQuery[], children: Measure[], root: boolean, timeElapsed?: number };
|
||||
type QueryResult = { timeElapsed?: number, refCount: number };
|
||||
|
||||
export function createTimer(gl: GLRenderingContext, extensions: WebGLExtensions): WebGLTimer {
|
||||
const dtq = extensions.disjointTimerQuery;
|
||||
|
||||
const queries = new Map<WebGLQuery, QueryResult>();
|
||||
const pending = new Map<string, Measure>();
|
||||
const stack: Measure[] = [];
|
||||
|
||||
let measures: Measure[] = [];
|
||||
let current: WebGLQuery | null = null;
|
||||
|
||||
const clear = () => {
|
||||
if (!dtq) return;
|
||||
|
||||
queries.forEach((_, query) => {
|
||||
dtq.deleteQuery(query);
|
||||
});
|
||||
pending.clear();
|
||||
measures = [];
|
||||
current = null;
|
||||
};
|
||||
|
||||
const add = () => {
|
||||
if (!dtq) return;
|
||||
|
||||
const query = getQuery(extensions);
|
||||
if (!query) return;
|
||||
|
||||
dtq.beginQuery(dtq.TIME_ELAPSED, query);
|
||||
pending.forEach((measure, _) => {
|
||||
measure.queries.push(query);
|
||||
});
|
||||
queries.set(query, { refCount: pending.size });
|
||||
current = query;
|
||||
};
|
||||
|
||||
return {
|
||||
resolve: () => {
|
||||
const results: TimerResult[] = [];
|
||||
if (!dtq || !measures.length) return results;
|
||||
// console.log('resolve');
|
||||
queries.forEach((result, query) => {
|
||||
if (result.timeElapsed !== undefined) return;
|
||||
|
||||
const available = dtq.getQueryParameter(query, dtq.QUERY_RESULT_AVAILABLE);
|
||||
const disjoint = gl.getParameter(dtq.GPU_DISJOINT);
|
||||
|
||||
if (available && !disjoint) {
|
||||
const timeElapsed = dtq.getQueryParameter(query, dtq.QUERY_RESULT) as number;
|
||||
result.timeElapsed = timeElapsed;
|
||||
// console.log('timeElapsed', result.timeElapsed);
|
||||
}
|
||||
|
||||
if (available || disjoint) {
|
||||
dtq.deleteQuery(query);
|
||||
}
|
||||
});
|
||||
|
||||
const unresolved: Measure[] = [];
|
||||
for (const measure of measures) {
|
||||
if (measure.queries.every(q => queries.get(q)?.timeElapsed !== undefined)) {
|
||||
let timeElapsed = 0;
|
||||
for (const query of measure.queries) {
|
||||
const result = queries.get(query)!;
|
||||
timeElapsed += result.timeElapsed!;
|
||||
result.refCount -= 1;
|
||||
}
|
||||
measure.timeElapsed = timeElapsed;
|
||||
if (measure.root) {
|
||||
const children: TimerResult[] = [];
|
||||
const add = (measures: Measure[], children: TimerResult[]) => {
|
||||
for (const measure of measures) {
|
||||
const result: TimerResult = {
|
||||
label: measure.label,
|
||||
timeElapsed: measure.timeElapsed!,
|
||||
children: []
|
||||
};
|
||||
children.push(result);
|
||||
add(measure.children, result.children);
|
||||
}
|
||||
};
|
||||
add(measure.children, children);
|
||||
results.push({ label: measure.label, timeElapsed, children });
|
||||
}
|
||||
} else {
|
||||
unresolved.push(measure);
|
||||
}
|
||||
}
|
||||
measures = unresolved;
|
||||
|
||||
queries.forEach((result, query) => {
|
||||
if (result.refCount === 0) {
|
||||
queries.delete(query);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
},
|
||||
mark: (label: string) => {
|
||||
if (!dtq) return;
|
||||
|
||||
if (pending.has(label)) {
|
||||
throw new Error(`Timer mark for '${label}' already exists`);
|
||||
}
|
||||
|
||||
if (current !== null) {
|
||||
dtq.endQuery(dtq.TIME_ELAPSED);
|
||||
}
|
||||
const measure: Measure = { label, queries: [], children: [], root: current === null };
|
||||
pending.set(label, measure);
|
||||
|
||||
if (stack.length) {
|
||||
stack[stack.length - 1].children.push(measure);
|
||||
}
|
||||
stack.push(measure);
|
||||
|
||||
add();
|
||||
},
|
||||
markEnd: (label: string) => {
|
||||
if (!dtq) return;
|
||||
|
||||
const measure = pending.get(label);
|
||||
if (!measure) {
|
||||
throw new Error(`Timer mark for '${label}' does not exist`);
|
||||
}
|
||||
|
||||
if (stack.pop()?.label !== label) {
|
||||
throw new Error(`Timer mark for '${label}' has pending nested mark`);
|
||||
}
|
||||
|
||||
dtq.endQuery(dtq.TIME_ELAPSED);
|
||||
pending.delete(label);
|
||||
measures.push(measure);
|
||||
|
||||
if (pending.size > 0) {
|
||||
add();
|
||||
} else {
|
||||
current = null;
|
||||
}
|
||||
},
|
||||
clear,
|
||||
destroy: () => {
|
||||
clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function formatTimerResult(result: TimerResult) {
|
||||
const timeElapsed = result.timeElapsed / 1000 / 1000;
|
||||
return `${result.label} ${timeElapsed.toFixed(2)}ms`;
|
||||
}
|
||||
|
||||
export function printTimerResults(results: TimerResult[]) {
|
||||
return results.map(r => {
|
||||
const f = formatTimerResult(r);
|
||||
if (r.children.length) {
|
||||
console.groupCollapsed(f);
|
||||
printTimerResults(r.children);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.log(f);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -42,6 +42,10 @@ export function getUniformType(gl: GLRenderingContext, kind: UniformKind) {
|
||||
}
|
||||
}
|
||||
|
||||
export function isArrayUniform(kind: UniformKind) {
|
||||
return kind.endsWith('[]');
|
||||
}
|
||||
|
||||
export type UniformSetter = (gl: GLRenderingContext, location: number, value: any) => void
|
||||
export type UniformSetters = { [k: string]: UniformSetter }
|
||||
|
||||
|
||||
@@ -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.357, IHM 1.17, MA 1.3.6.
|
||||
* Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.359, IHM 1.17, MA 1.4.1.
|
||||
*
|
||||
* @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.357, IHM 1.17, MA 1.3.6.
|
||||
* Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.359, IHM 1.17, MA 1.4.1.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'CifCore' schema file. Dictionary versions: CifCore 3.1.0.
|
||||
*
|
||||
|
||||
@@ -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.357, IHM 1.17, MA 1.3.6.
|
||||
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.359, IHM 1.17, MA 1.4.1.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
@@ -916,8 +916,7 @@ export const mmCIF_Schema = {
|
||||
*/
|
||||
entity_poly_seq: {
|
||||
/**
|
||||
* This data item is a pointer to _entity_poly.entity_id in the
|
||||
* ENTITY_POLY category.
|
||||
* This data item is a pointer to _entity.id in the ENTITY category.
|
||||
*/
|
||||
entity_id: str,
|
||||
/**
|
||||
@@ -4889,7 +4888,7 @@ export const mmCIF_Schema = {
|
||||
* The name of the database containing reference information about
|
||||
* this entity or biological unit.
|
||||
*/
|
||||
db_name: Aliased<'UNP' | 'GB' | 'OrthoDB' | 'NCBI' | 'JGI' | 'Other'>(str),
|
||||
db_name: Aliased<'UNP' | 'GB' | 'OrthoDB' | 'NCBI' | 'JGI' | 'Phytozyme' | 'Other'>(str),
|
||||
/**
|
||||
* The code for this entity or biological unit or for a closely
|
||||
* related entity or biological unit in the named database.
|
||||
@@ -4939,7 +4938,7 @@ export const mmCIF_Schema = {
|
||||
/**
|
||||
* The type of data held in the dataset.
|
||||
*/
|
||||
content_type: Aliased<'target' | 'template structure' | 'polymeric template library' | 'spatial restraints' | 'target-template alignment' | 'coevolution MSA' | 'model coordinates' | 'other'>(str),
|
||||
content_type: Aliased<'target' | 'template structure' | 'polymeric template library' | 'spatial restraints' | 'target-template alignment' | 'coevolution MSA' | 'model coordinates' | 'input structure' | 'reference database' | 'other'>(str),
|
||||
/**
|
||||
* Details for other content types.
|
||||
*/
|
||||
|
||||
@@ -122,7 +122,7 @@ async function parseBinary(taskCtx: RuntimeContext, data: Uint8Array, name: stri
|
||||
}
|
||||
|
||||
export function parseDx(data: string | Uint8Array, name: string) {
|
||||
return Task.create<Result<DxFile>>('Parse Cube', taskCtx => {
|
||||
return Task.create<Result<DxFile>>('Parse DX', taskCtx => {
|
||||
if (typeof data === 'string') return parseText(taskCtx, data, name);
|
||||
return parseBinary(taskCtx, data, name);
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@ import { ValueSpec, AttributeSpec, UniformSpec, TextureSpec, DefineSpec, Values
|
||||
import { gaussianDensity_vert } from '../../../mol-gl/shader/gaussian-density.vert';
|
||||
import { gaussianDensity_frag } from '../../../mol-gl/shader/gaussian-density.frag';
|
||||
import { Framebuffer } from '../../../mol-gl/webgl/framebuffer';
|
||||
import { isTimingMode } from '../../../mol-util/debug';
|
||||
|
||||
const GaussianDensitySchema = {
|
||||
drawCount: ValueSpec('number'),
|
||||
@@ -85,11 +86,17 @@ export function GaussianDensityTexture(webgl: WebGLContext, position: PositionDa
|
||||
}
|
||||
|
||||
export function GaussianDensityTexture2d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, powerOfTwo: boolean, props: GaussianDensityProps, oldTexture?: Texture): GaussianDensityTextureData {
|
||||
return finalizeGaussianDensityTexture(calcGaussianDensityTexture2d(webgl, position, box, radius, powerOfTwo, props, oldTexture));
|
||||
if (isTimingMode) webgl.timer.mark('GaussianDensityTexture2d');
|
||||
const data = calcGaussianDensityTexture2d(webgl, position, box, radius, powerOfTwo, props, oldTexture);
|
||||
if (isTimingMode) webgl.timer.markEnd('GaussianDensityTexture2d');
|
||||
return finalizeGaussianDensityTexture(data);
|
||||
}
|
||||
|
||||
export function GaussianDensityTexture3d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, oldTexture?: Texture): GaussianDensityTextureData {
|
||||
return finalizeGaussianDensityTexture(calcGaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture));
|
||||
if (isTimingMode) webgl.timer.mark('GaussianDensityTexture3d');
|
||||
const data = calcGaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture);
|
||||
if (isTimingMode) webgl.timer.markEnd('GaussianDensityTexture3d');
|
||||
return finalizeGaussianDensityTexture(data);
|
||||
}
|
||||
|
||||
function finalizeGaussianDensityTexture({ texture, scale, bbox, gridDim, gridTexDim, gridTexScale, radiusFactor, resolution, maxRadius }: _GaussianDensityTextureData): GaussianDensityTextureData {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 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>
|
||||
@@ -172,7 +172,7 @@ function build(data: PositionData, boundary: Boundary, cellSizeOrCount?: Vec3 |
|
||||
const expandedBox = Box3D.expand(Box3D(), boundary.box, Vec3.create(0.5, 0.5, 0.5));
|
||||
const { indices } = data;
|
||||
|
||||
const S = Box3D.size(Vec3.zero(), expandedBox);
|
||||
const S = Box3D.size(Vec3(), expandedBox);
|
||||
let delta, size;
|
||||
|
||||
const elementCount = OrderedSet.size(indices);
|
||||
@@ -180,7 +180,7 @@ function build(data: PositionData, boundary: Boundary, cellSizeOrCount?: Vec3 |
|
||||
const cellCount = typeof cellSizeOrCount === 'number' ? cellSizeOrCount : 32;
|
||||
const cellSize = Array.isArray(cellSizeOrCount) && cellSizeOrCount;
|
||||
|
||||
if (cellSize) {
|
||||
if (cellSize && !Vec3.isZero(cellSize)) {
|
||||
size = [Math.ceil(S[0] / cellSize[0]), Math.ceil(S[1] / cellSize[1]), Math.ceil(S[2] / cellSize[2])];
|
||||
delta = cellSize;
|
||||
} else if (elementCount > 0) {
|
||||
|
||||
@@ -28,6 +28,7 @@ class FormatRegistry<T> {
|
||||
}
|
||||
|
||||
isApplicable(model: Model) {
|
||||
if (!this.map.has(model.sourceData.kind)) return false;
|
||||
const isApplicable = this.applicable.get(model.sourceData.kind);
|
||||
return isApplicable ? isApplicable(model) : true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 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>
|
||||
@@ -92,7 +92,7 @@ function addHelices(cat: StructConf, coordinates: CoordinateType, map: Secondary
|
||||
const element: SecondaryStructure.Helix = {
|
||||
kind: 'helix',
|
||||
flags: type,
|
||||
type_id: conf_type_id.valueKind(i) === Column.ValueKind.Present ? conf_type_id.value(i) : 'HELIX_P',
|
||||
type_id: conf_type_id.valueKind(i) === Column.ValueKind.Present ? conf_type_id.value(i) : 'helx_p',
|
||||
helix_class: pdbx_PDB_helix_class.value(i),
|
||||
details: details.valueKind(i) === Column.ValueKind.Present ? details.value(i) : void 0
|
||||
};
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2017-2022 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 { SecondaryStructureType } from '../types';
|
||||
import { ResidueIndex } from '../indexing';
|
||||
import { mmCIF_Schema } from '../../../../mol-io/reader/cif/schema/mmcif';
|
||||
|
||||
/** Secondary structure "indexed" by residues. */
|
||||
interface SecondaryStructure {
|
||||
@@ -37,7 +39,7 @@ namespace SecondaryStructure {
|
||||
export interface Helix {
|
||||
kind: 'helix',
|
||||
flags: SecondaryStructureType,
|
||||
type_id: string, // TODO: use aliased type?
|
||||
type_id: mmCIF_Schema['struct_conf']['conf_type_id']['T'],
|
||||
helix_class: string,
|
||||
details?: string
|
||||
}
|
||||
|
||||
@@ -501,48 +501,50 @@ export namespace SecondaryStructureType {
|
||||
NA = 0x20000000, // not applicable/available
|
||||
}
|
||||
|
||||
export const SecondaryStructureMmcif: { [value: string]: number } = {
|
||||
HELX_LH_27_P: Flag.Helix | Flag.LeftHanded | Flag.Helix27, // left-handed 2-7 helix (protein)
|
||||
HELX_LH_3T_P: Flag.Helix | Flag.LeftHanded | Flag.Helix3Ten, // left-handed 3-10 helix (protein)
|
||||
HELX_LH_AL_P: Flag.Helix | Flag.LeftHanded | Flag.HelixAlpha, // left-handed alpha helix (protein)
|
||||
HELX_LH_A_N: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixA, // left-handed A helix (nucleic acid)
|
||||
HELX_LH_B_N: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixB, // left-handed B helix (nucleic acid)
|
||||
HELX_LH_GA_P: Flag.Helix | Flag.LeftHanded | Flag.HelixGamma, // left-handed gamma helix (protein)
|
||||
HELX_LH_N: Flag.DoubleHelix | Flag.LeftHanded, // left-handed helix with type not specified (nucleic acid)
|
||||
HELX_LH_OM_P: Flag.Helix | Flag.LeftHanded | Flag.HelixOmega, // left-handed omega helix (protein)
|
||||
HELX_LH_OT_N: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixOther, // left-handed helix with type that does not conform to an accepted category (nucleic acid)
|
||||
HELX_LH_OT_P: Flag.Helix | Flag.LeftHanded | Flag.HelixOther, // left-handed helix with type that does not conform to an accepted category (protein)
|
||||
HELX_LH_P: Flag.Helix | Flag.LeftHanded, // left-handed helix with type not specified (protein)
|
||||
HELX_LH_PI_P: Flag.Helix | Flag.LeftHanded | Flag.HelixPi, // left-handed pi helix (protein)
|
||||
HELX_LH_PP_P: Flag.Helix | Flag.LeftHanded | Flag.HelixPolyproline, // left-handed polyproline helix (protein)
|
||||
HELX_LH_Z_N: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixZ, // left-handed Z helix (nucleic acid)
|
||||
HELX_N: Flag.DoubleHelix, // helix with handedness and type not specified (nucleic acid)
|
||||
HELX_OT_N: Flag.DoubleHelix, // helix with handedness and type that do not conform to an accepted category (nucleic acid)
|
||||
HELX_OT_P: Flag.Helix, // helix with handedness and type that do not conform to an accepted category (protein)
|
||||
HELX_P: Flag.Helix, // helix with handedness and type not specified (protein)
|
||||
HELX_RH_27_P: Flag.Helix | Flag.RightHanded | Flag.Helix27, // right-handed 2-7 helix (protein)
|
||||
HELX_RH_3T_P: Flag.Helix | Flag.RightHanded | Flag.Helix3Ten, // right-handed 3-10 helix (protein)
|
||||
HELX_RH_AL_P: Flag.Helix | Flag.RightHanded | Flag.HelixAlpha, // right-handed alpha helix (protein)
|
||||
HELX_RH_A_N: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixA, // right-handed A helix (nucleic acid)
|
||||
HELX_RH_B_N: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixB, // right-handed B helix (nucleic acid)
|
||||
HELX_RH_GA_P: Flag.Helix | Flag.RightHanded | Flag.HelixGamma, // right-handed gamma helix (protein)
|
||||
HELX_RH_N: Flag.DoubleHelix | Flag.RightHanded, // right-handed helix with type not specified (nucleic acid)
|
||||
HELX_RH_OM_P: Flag.Helix | Flag.RightHanded | Flag.HelixOmega, // right-handed omega helix (protein)
|
||||
HELX_RH_OT_N: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixOther, // right-handed helix with type that does not conform to an accepted category (nucleic acid)
|
||||
HELX_RH_OT_P: Flag.Helix | Flag.RightHanded | Flag.HelixOther, // right-handed helix with type that does not conform to an accepted category (protein)
|
||||
HELX_RH_P: Flag.Helix | Flag.RightHanded, // right-handed helix with type not specified (protein)
|
||||
HELX_RH_PI_P: Flag.Helix | Flag.RightHanded | Flag.HelixPi, // right-handed pi helix (protein)
|
||||
HELX_RH_PP_P: Flag.Helix | Flag.RightHanded | Flag.HelixPolyproline, // right-handed polyproline helix (protein)
|
||||
HELX_RH_Z_N: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixZ, // right-handed Z helix (nucleic acid)
|
||||
STRN: Flag.Beta | Flag.BetaStrand, // beta strand (protein)
|
||||
TURN_OT_P: Flag.Turn | Flag.TurnOther, // turn with type that does not conform to an accepted category (protein)
|
||||
TURN_P: Flag.Turn, // turn with type not specified (protein)
|
||||
TURN_TY1P_P: Flag.Turn | Flag.InverseTurn | Flag.Turn1, // type I prime turn (protein)
|
||||
TURN_TY1_P: Flag.Turn | Flag.ClassicTurn | Flag.Turn1, // type I turn (protein)
|
||||
TURN_TY2P_P: Flag.Turn | Flag.InverseTurn | Flag.Turn2, // type II prime turn (protein)
|
||||
TURN_TY2_P: Flag.Turn | Flag.ClassicTurn | Flag.Turn2, // type II turn (protein)
|
||||
TURN_TY3P_P: Flag.Turn | Flag.InverseTurn | Flag.Turn3, // type III prime turn (protein)
|
||||
TURN_TY3_P: Flag.Turn | Flag.ClassicTurn | Flag.Turn3, // type III turn (protein)
|
||||
export const SecondaryStructureMmcif: { [value in mmCIF_Schema['struct_conf']['conf_type_id']['T']]: number } = {
|
||||
helx_lh_27_p: Flag.Helix | Flag.LeftHanded | Flag.Helix27, // left-handed 2-7 helix (protein)
|
||||
helx_lh_3t_p: Flag.Helix | Flag.LeftHanded | Flag.Helix3Ten, // left-handed 3-10 helix (protein)
|
||||
helx_lh_al_p: Flag.Helix | Flag.LeftHanded | Flag.HelixAlpha, // left-handed alpha helix (protein)
|
||||
helx_lh_a_n: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixA, // left-handed A helix (nucleic acid)
|
||||
helx_lh_b_n: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixB, // left-handed B helix (nucleic acid)
|
||||
helx_lh_ga_p: Flag.Helix | Flag.LeftHanded | Flag.HelixGamma, // left-handed gamma helix (protein)
|
||||
helx_lh_n: Flag.DoubleHelix | Flag.LeftHanded, // left-handed helix with type not specified (nucleic acid)
|
||||
helx_lh_om_p: Flag.Helix | Flag.LeftHanded | Flag.HelixOmega, // left-handed omega helix (protein)
|
||||
helx_lh_ot_n: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixOther, // left-handed helix with type that does not conform to an accepted category (nucleic acid)
|
||||
helx_lh_ot_p: Flag.Helix | Flag.LeftHanded | Flag.HelixOther, // left-handed helix with type that does not conform to an accepted category (protein)
|
||||
helx_lh_p: Flag.Helix | Flag.LeftHanded, // left-handed helix with type not specified (protein)
|
||||
helx_lh_pi_p: Flag.Helix | Flag.LeftHanded | Flag.HelixPi, // left-handed pi helix (protein)
|
||||
helx_lh_pp_p: Flag.Helix | Flag.LeftHanded | Flag.HelixPolyproline, // left-handed polyproline helix (protein)
|
||||
helx_lh_z_n: Flag.DoubleHelix | Flag.LeftHanded | Flag.DoubleHelixZ, // left-handed Z helix (nucleic acid)
|
||||
helx_n: Flag.DoubleHelix, // helix with handedness and type not specified (nucleic acid)
|
||||
helx_ot_n: Flag.DoubleHelix, // helix with handedness and type that do not conform to an accepted category (nucleic acid)
|
||||
helx_ot_p: Flag.Helix, // helix with handedness and type that do not conform to an accepted category (protein)
|
||||
helx_p: Flag.Helix, // helix with handedness and type not specified (protein)
|
||||
helx_rh_27_p: Flag.Helix | Flag.RightHanded | Flag.Helix27, // right-handed 2-7 helix (protein)
|
||||
helx_rh_3t_p: Flag.Helix | Flag.RightHanded | Flag.Helix3Ten, // right-handed 3-10 helix (protein)
|
||||
helx_rh_al_p: Flag.Helix | Flag.RightHanded | Flag.HelixAlpha, // right-handed alpha helix (protein)
|
||||
helx_rh_a_n: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixA, // right-handed A helix (nucleic acid)
|
||||
helx_rh_b_n: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixB, // right-handed B helix (nucleic acid)
|
||||
helx_rh_ga_p: Flag.Helix | Flag.RightHanded | Flag.HelixGamma, // right-handed gamma helix (protein)
|
||||
helx_rh_n: Flag.DoubleHelix | Flag.RightHanded, // right-handed helix with type not specified (nucleic acid)
|
||||
helx_rh_om_p: Flag.Helix | Flag.RightHanded | Flag.HelixOmega, // right-handed omega helix (protein)
|
||||
helx_rh_ot_n: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixOther, // right-handed helix with type that does not conform to an accepted category (rhcleic acid)
|
||||
helx_rh_ot_p: Flag.Helix | Flag.RightHanded | Flag.HelixOther, // right-handed helix with type that does not conform to an accepted category (protein)
|
||||
helx_rh_p: Flag.Helix | Flag.RightHanded, // right-handed helix with type not specified (protein)
|
||||
helx_rh_pi_p: Flag.Helix | Flag.RightHanded | Flag.HelixPi, // right-handed pi helix (protein)
|
||||
helx_rh_pp_p: Flag.Helix | Flag.RightHanded | Flag.HelixPolyproline, // right-handed polyproline helix (protein)
|
||||
helx_rh_z_n: Flag.DoubleHelix | Flag.RightHanded | Flag.DoubleHelixZ, // right-handed Z helix (nucleic acid)
|
||||
strn: Flag.Beta | Flag.BetaStrand, // beta strand (protein)
|
||||
turn_ot_p: Flag.Turn | Flag.TurnOther, // turn with type that does not conform to an accepted category (protein)
|
||||
turn_p: Flag.Turn, // turn with type not specified (protein)
|
||||
turn_ty1p_p: Flag.Turn | Flag.InverseTurn | Flag.Turn1, // type I prime turn (protein)
|
||||
turn_ty1_p: Flag.Turn | Flag.ClassicTurn | Flag.Turn1, // type I turn (protein)
|
||||
turn_ty2p_p: Flag.Turn | Flag.InverseTurn | Flag.Turn2, // type II prime turn (protein)
|
||||
turn_ty2_p: Flag.Turn | Flag.ClassicTurn | Flag.Turn2, // type II turn (protein)
|
||||
turn_ty3p_p: Flag.Turn | Flag.InverseTurn | Flag.Turn3, // type III prime turn (protein)
|
||||
turn_ty3_p: Flag.Turn | Flag.ClassicTurn | Flag.Turn3, // type III turn (protein)
|
||||
bend: Flag.Bend, // region with high backbone curvature without specific hydrogen bonding, a bend at residue i occurs when the angle between C$\_alpha(i)-C_\alpha(i-2) and C_\alpha(i+2) - C_\alpha(i)$ is greater than 70 degrees (protein)
|
||||
other: Flag.None, // secondary structure type that does not conform to an accepted category, random coil (protein)
|
||||
};
|
||||
|
||||
export const SecondaryStructurePdb: { [value: string]: number } = {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated ion names params file. Names extracted from CCD components.
|
||||
*
|
||||
* @author molstar/chem-comp-dict/create-table cli
|
||||
* @author molstar/chem-comp-dict/create-ions cli
|
||||
*/
|
||||
|
||||
export const IonNames = new Set(['118', '119', '543', '1AL', '1CU', '2FK', '2HP', '2OF', '3CO', '3MT', '3NI', '3OF', '3P8', '4MO', '4PU', '4TI', '6MO', 'ACT', 'AG', 'AL', 'ALF', 'AM', 'ATH', 'AU', 'AU3', 'AUC', 'AZI', 'BA', 'BCT', 'BEF', 'BF4', 'BO4', 'BR', 'BS3', 'BSY', 'CA', 'CAC', 'CD', 'CD1', 'CD3', 'CD5', 'CE', 'CF', 'CHT', 'CL', 'CO', 'CO3', 'CO5', 'CON', 'CR', 'CS', 'CSB', 'CU', 'CU1', 'CU3', 'CUA', 'CUZ', 'CYN', 'DME', 'DMI', 'DSC', 'DTI', 'DY', 'E4N', 'EDR', 'EMC', 'ER3', 'EU', 'EU3', 'F', 'FE', 'FE2', 'FPO', 'GA', 'GD3', 'GEP', 'HAI', 'HG', 'HGC', 'IN', 'IOD', 'IR', 'IR3', 'IRI', 'IUM', 'K', 'KO4', 'LA', 'LCO', 'LCP', 'LI', 'LU', 'MAC', 'MG', 'MH2', 'MH3', 'MLI', 'MMC', 'MN', 'MN3', 'MN5', 'MN6', 'MO1', 'MO2', 'MO3', 'MO4', 'MO5', 'MO6', 'MOO', 'MOS', 'MOW', 'MW1', 'MW2', 'MW3', 'NA', 'NA2', 'NA5', 'NA6', 'NAO', 'NAW', 'ND', 'NET', 'NH4', 'NI', 'NI1', 'NI2', 'NI3', 'NO2', 'NO3', 'NRU', 'O4M', 'OAA', 'OC1', 'OC2', 'OC3', 'OC4', 'OC5', 'OC6', 'OC7', 'OC8', 'OCL', 'OCM', 'OCN', 'OCO', 'OF1', 'OF2', 'OF3', 'OH', 'OS', 'OS4', 'OXL', 'PB', 'PBM', 'PD', 'PDV', 'PER', 'PI', 'PO3', 'PO4', 'PR', 'PT', 'PT4', 'PTN', 'RB', 'RH3', 'RHD', 'RU', 'SB', 'SCN', 'SE4', 'SEK', 'SM', 'SMO', 'SO3', 'SO4', 'SR', 'T1A', 'TB', 'TBA', 'TCN', 'TEA', 'TH', 'THE', 'TL', 'TMA', 'TRA', 'UNX', 'V', 'VN3', 'VO4', 'W', 'WO5', 'Y1', 'YB', 'YB2', 'YH', 'YT3', 'ZCM', 'ZN', 'ZN2', 'ZN3', 'ZNO', 'ZO3', 'ZR', 'NCO', 'OHX']);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -329,7 +329,46 @@ const CharmmSaccharideNames: { [k: string]: string[] } = {
|
||||
Neu5Ac: ['ANE5AC', 'BNE5AC'],
|
||||
};
|
||||
|
||||
export const SaccharideCompIdMap = (function () {
|
||||
/**
|
||||
* From http://glycam.org/docs/othertoolsservice/2016/06/09/3d-snfg-list-of-residue-names/#GLYCAM
|
||||
*/
|
||||
const GlycamSaccharideNames: { [k: string]: string[] } = {
|
||||
Glc: ['0GA', '0GB', '1GA', '1GB', '2GA', '2GB', '3GA', '3GB', '4GA', '4GB', '6GA', '6GB', 'ZGA', 'ZGB', 'YGA', 'YGB', 'XGA', 'XGB', 'WGA', 'WGB', 'VGA', 'VGB', 'UGA', 'UGB', 'TGA', 'TGB', 'SGA', 'SGB', 'RGA', 'RGB', 'QGA', 'QGB', 'PGA', 'PGB', '0gA', '0gB', '1gA', '1gB', '2gA', '2gB', '3gA', '3gB', '4gA', '4gB', '6gA', '6gB', 'ZgA', 'ZgB', 'YgA', 'YgB', 'XgA', 'XgB', 'WgA', 'WgB', 'VgA', 'VgB', 'UgA', 'UgB', 'TgA', 'TgB', 'SgA', 'SgB', 'RgA', 'RgB', 'QgA', 'QgB', 'PgA', 'PgB'],
|
||||
GlcNAc: ['0YA', '0YB', '1YA', '1YB', '3YA', '3YB', '4YA', '4YB', '6YA', '6YB', 'WYA', 'WYB', 'VYA', 'VYB', 'UYA', 'UYB', 'QYA', 'QYB', '0yA', '0yB', '1yA', '1yB', '3yA', '3yB', '4yA', '4yB', '6yA', '6yB', 'WyA', 'WyB', 'VyA', 'VyB', 'UyA', 'UyB', 'QyA', 'QyB', '0YS', '0Ys', '3YS', '3Ys', '4YS', '4Ys', '6YS', '6Ys', 'QYS', 'QYs', 'UYS', 'UYs', 'VYS', 'VYs', 'WYS', 'WYs', '0yS', '0ys', '3yS', '3ys', '4yS', '4ys'],
|
||||
GlcA: ['0ZA', '0ZB', '1ZA', '1ZB', '2ZA', '2ZB', '3ZA', '3ZB', '4ZA', '4ZB', 'ZZA', 'ZZB', 'YZA', 'YZB', 'WZA', 'WZB', 'TZA', 'TZB', '0zA', '0zB', '1zA', '1zB', '2zA', '2zB', '3zA', '3zB', '4zA', '4zB', 'ZzA', 'ZzB', 'YzA', 'YzB', 'WzA', 'WzB', 'TzA', 'TzB', '0ZBP'],
|
||||
GlcN: ['0YN', '3YN', '4YN', '6YN', 'WYN', 'VYN', 'UYN', 'QYN', '3Yn', '4Yn', 'WYn', '0Yn', '0YP', '3YP', '4YP', '6YP', 'WYP', 'VYP', 'UYP', 'QYP', '0Yp', '3Yp', '4Yp', 'WYp'],
|
||||
Man: ['0MA', '0MB', '1MA', '1MB', '2MA', '2MB', '3MA', '3MB', '4MA', '4MB', '6MA', '6MB', 'ZMA', 'ZMB', 'YMA', 'YMB', 'XMA', 'XMB', 'WMA', 'WMB', 'VMA', 'VMB', 'UMA', 'UMB', 'TMA', 'TMB', 'SMA', 'SMB', 'RMA', 'RMB', 'QMA', 'QMB', 'PMA', 'PMB', '0mA', '0mB', '1mA', '1mB', '2mA', '2mB', '3mA', '3mB', '4mA', '4mB', '6mA', '6mB', 'ZmA', 'ZmB', 'YmA', 'YmB', 'XmA', 'XmB', 'WmA', 'WmB', 'VmA', 'VmB', 'UmA', 'UmB', 'TmA', 'TmB', 'SmA', 'SmB', 'RmA', 'RmB', 'QmA', 'QmB', 'PmA', 'PmB'],
|
||||
ManNAc: ['0WA', '0WB', '1WA', '1WB', '3WA', '3WB', '4WA', '4WB', '6WA', '6WB', 'WWA', 'WWB', 'VWA', 'VWB', 'UWA', 'UWB', 'QWA', 'QWB', '0wA', '0wB', '1wA', '1wB', '3wA', '3wB', '4wA', '4wB', '6wA', '6wB', 'WwA', 'WwB', 'VwA', 'VwB', 'UwA', 'UwB', 'QwA', 'QwB'],
|
||||
Ara: ['0AA', '0AB', '1AA', '1AB', '2AA', '2AB', '3AA', '3AB', '4AA', '4AB', 'ZAA', 'ZAB', 'YAA', 'YAB', 'WAA', 'WAB', 'TAA', 'TAB', '0AD', '0AU', '1AD', '1AU', '2AD', '2AU', '3AD', '3AU', '5AD', '5AU', 'ZAD', 'ZAU', '0aA', '0aB', '1aA', '1aB', '2aA', '2aB', '3aA', '3aB', '4aA', '4aB', 'ZaA', 'ZaB', 'YaA', 'YaB', 'WaA', 'WaB', 'TaA', 'TaB', '0aD', '0aU', '1aD', '1aU', '2aD', '2aU', '3aD', '3aU', '5aD', '5aU', 'ZaD', 'ZaU'],
|
||||
Gal: ['0LA', '0LB', '1LA', '1LB', '2LA', '2LB', '3LA', '3LB', '4LA', '4LB', '6LA', '6LB', 'ZLA', 'ZLB', 'YLA', 'YLB', 'XLA', 'XLB', 'WLA', 'WLB', 'VLA', 'VLB', 'ULA', 'ULB', 'TLA', 'TLB', 'SLA', 'SLB', 'RLA', 'RLB', 'QLA', 'QLB', 'PLA', 'PLB', '0lA', '0lB', '1lA', '1lB', '2lA', '2lB', '3lA', '3lB', '4lA', '4lB', '6lA', '6lB', 'ZlA', 'ZlB', 'YlA', 'YlB', 'XlA', 'XlB', 'WlA', 'WlB', 'VlA', 'VlB', 'UlA', 'UlB', 'TlA', 'TlB', 'SlA', 'SlB', 'RlA', 'RlB', 'QlA', 'QlB', 'PlA', 'PlB'],
|
||||
GalNAc: ['0VA', '0VB', '1VA', '1VB', '3VA', '3VB', '4VA', '4VB', '6VA', '6VB', 'WVA', 'WVB', 'VVA', 'VVB', 'UVA', 'UVB', 'QVA', 'QVB', '0vA', '0vB', '1vA', '1vB', '3vA', '3vB', '4vA', '4vB', '6vA', '6vB', 'WvA', 'WvB', 'VvA', 'VvB', 'UvA', 'UvB', 'QvA', 'QvB'],
|
||||
GalA: ['0OA', '0OB', '1OA', '1OB', '2OA', '2OB', '3OA', '3OB', '4OA', '4OB', 'ZOA', 'ZOB', 'YOA', 'YOB', 'WOA', 'WOB', 'TOA', 'TOB', '0oA', '0oB', '1oA', '1oB', '2oA', '2oB', '3oA', '3oB', '4oA', '4oB', 'ZoA', 'ZoB', 'YoA', 'YoB', 'WoA', 'WoB', 'ToA', 'ToB'],
|
||||
Gul: ['0KA', '0KB', '1KA', '1KB', '2KA', '2KB', '3KA', '3KB', '4KA', '4KB', '6KA', '6KB', 'ZKA', 'ZKB', 'YKA', 'YKB', 'XKA', 'XKB', 'WKA', 'WKB', 'VKA', 'VKB', 'UKA', 'UKB', 'TKA', 'TKB', 'SKA', 'SKB', 'RKA', 'RKB', 'QKA', 'QKB', 'PKA', 'PKB', '0kA', '0kB', '1kA', '1kB', '2kA', '2kB', '3kA', '3kB', '4kA', '4kB', '6kA', '6kB', 'ZkA', 'ZkB', 'YkA', 'YkB', 'XkA', 'XkB', 'WkA', 'WkB', 'VkA', 'VkB', 'UkA', 'UkB', 'TkA', 'TkB', 'SkA', 'SkB', 'RkA', 'RkB', 'QkA', 'QkB', 'PkA', 'PkB'],
|
||||
Alt: ['0EA', '0EB', '1EA', '1EB', '2EA', '2EB', '3EA', '3EB', '4EA', '4EB', '6EA', '6EB', 'ZEA', 'ZEB', 'YEA', 'YEB', 'XEA', 'XEB', 'WEA', 'WEB', 'VEA', 'VEB', 'UEA', 'UEB', 'TEA', 'TEB', 'SEA', 'SEB', 'REA', 'REB', 'QEA', 'QEB', 'PEA', 'PEB', '0eA', '0eB', '1eA', '1eB', '2eA', '2eB', '3eA', '3eB', '4eA', '4eB', '6eA', '6eB', 'ZeA', 'ZeB', 'YeA', 'YeB', 'XeA', 'XeB', 'WeA', 'WeB', 'VeA', 'VeB', 'UeA', 'UeB', 'TeA', 'TeB', 'SeA', 'SeB', 'ReA', 'ReB', 'QeA', 'QeB', 'PeA', 'PeB'],
|
||||
All: ['0NA', '0NB', '1NA', '1NB', '2NA', '2NB', '3NA', '3NB', '4NA', '4NB', '6NA', '6NB', 'ZNA', 'ZNB', 'YNA', 'YNB', 'XNA', 'XNB', 'WNA', 'WNB', 'VNA', 'VNB', 'UNA', 'UNB', 'TNA', 'TNB', 'SNA', 'SNB', 'RNA', 'RNB', 'QNA', 'QNB', 'PNA', 'PNB', '0nA', '0nB', '1nA', '1nB', '2nA', '2nB', '3nA', '3nB', '4nA', '4nB', '6nA', '6nB', 'ZnA', 'ZnB', 'YnA', 'YnB', 'XnA', 'XnB', 'WnA', 'WnB', 'VnA', 'VnB', 'UnA', 'UnB', 'TnA', 'TnB', 'SnA', 'SnB', 'RnA', 'RnB', 'QnA', 'QnB', 'PnA', 'PnB'],
|
||||
Tal: ['0TA', '0TB', '1TA', '1TB', '2TA', '2TB', '3TA', '3TB', '4TA', '4TB', '6TA', '6TB', 'ZTA', 'ZTB', 'YTA', 'YTB', 'XTA', 'XTB', 'WTA', 'WTB', 'VTA', 'VTB', 'UTA', 'UTB', 'TTA', 'TTB', 'STA', 'STB', 'RTA', 'RTB', 'QTA', 'QTB', 'PTA', 'PTB', '0tA', '0tB', '1tA', '1tB', '2tA', '2tB', '3tA', '3tB', '4tA', '4tB', '6tA', '6tB', 'ZtA', 'ZtB', 'YtA', 'YtB', 'XtA', 'XtB', 'WtA', 'WtB', 'VtA', 'VtB', 'UtA', 'UtB', 'TtA', 'TtB', 'StA', 'StB', 'RtA', 'RtB', 'QtA', 'QtB', 'PtA', 'PtB'],
|
||||
Ido: ['0IA', '0IB', '1IA', '1IB', '2IA', '2IB', '3IA', '3IB', '4IA', '4IB', '6IA', '6IB', 'ZIA', 'ZIB', 'YIA', 'YIB', 'XIA', 'XIB', 'WIA', 'WIB', 'VIA', 'VIB', 'UIA', 'UIB', 'TIA', 'TIB', 'SIA', 'SIB', 'RIA', 'RIB', 'QIA', 'QIB', 'PIA', 'PIB', '0iA', '0iB', '1iA', '1iB', '2iA', '2iB', '3iA', '3iB', '4iA', '4iB', '6iA', '6iB', 'ZiA', 'ZiB', 'YiA', 'YiB', 'XiA', 'XiB', 'WiA', 'WiB', 'ViA', 'ViB', 'UiA', 'UiB', 'TiA', 'TiB', 'SiA', 'SiB', 'RiA', 'RiB', 'QiA', 'QiB', 'PiA', 'PiB'],
|
||||
IdoA: ['0UA', '0UB', '1UA', '1UB', '2UA', '2UB', '3UA', '3UB', '4UA', '4UB', 'ZUA', 'ZUB', 'YUA', 'YUB', 'WUA', 'WUB', 'TUA', 'TUB', '0uA', '0uB', '1uA', '1uB', '2uA', '2uB', '3uA', '3uB', '4uA', '4uB', 'ZuA', 'ZuB', 'YuA', 'YuB', 'WuA', 'WuB', 'TuA', 'TuB', 'YuAP'],
|
||||
Fuc: ['0FA', '0FB', '1FA', '1FB', '2FA', '2FB', '3FA', '3FB', '4FA', '4FB', 'ZFA', 'ZFB', 'YFA', 'YFB', 'WFA', 'WFB', 'TFA', 'TFB', '0fA', '0fB', '1fA', '1fB', '2fA', '2fB', '3fA', '3fB', '4fA', '4fB', 'ZfA', 'ZfB', 'YfA', 'YfB', 'WfA', 'WfB', 'TfA', 'TfB'],
|
||||
Rha: ['0HA', '0HB', '1HA', '1HB', '2HA', '2HB', '3HA', '3HB', '4HA', '4HB', 'ZHA', 'ZHB', 'YHA', 'YHB', 'WHA', 'WHB', 'THA', 'THB', '0hA', '0hB', '1hA', '1hB', '2hA', '2hB', '3hA', '3hB', '4hA', '4hB', 'ZhA', 'ZhB', 'YhA', 'YhB', 'WhA', 'WhB', 'ThA', 'ThB'],
|
||||
Qui: ['0QA', '0QB', '1QA', '1QB', '2QA', '2QB', '3QA', '3QB', '4QA', '4QB', 'ZQA', 'ZQB', 'YQA', 'YQB', 'WQA', 'WQB', 'TQA', 'TQB', '0qA', '0qB', '1qA', '1qB', '2qA', '2qB', '3qA', '3qB', '4qA', '4qB', 'ZqA', 'ZqB', 'YqA', 'YqB', 'WqA', 'WqB', 'TqA', 'TqB'],
|
||||
Lyx: ['0DA', '0DB', '1DA', '1DB', '2DA', '2DB', '3DA', '3DB', '4DA', '4DB', 'ZDA', 'ZDB', 'YDA', 'YDB', 'WDA', 'WDB', 'TDA', 'TDB', '0DD', '0DU', '1DD', '1DU', '2DD', '2DU', '3DD', '3DU', '5DD', '5DU', 'ZDD', 'ZDU', '0dA', '0dB', '1dA', '1dB', '2dA', '2dB', '3dA', '3dB', '4dA', '4dB', 'ZdA', 'ZdB', 'YdA', 'YdB', 'WdA', 'WdB', 'TdA', 'TdB', '0dD', '0dU', '1dD', '1dU', '2dD', '2dU', '3dD', '3dU', '5dD', '5dU', 'ZdD', 'ZdU'],
|
||||
Xyl: ['0XA', '0XB', '1XA', '1XB', '2XA', '2XB', '3XA', '3XB', '4XA', '4XB', 'ZXA', 'ZXB', 'YXA', 'YXB', 'WXA', 'WXB', 'TXA', 'TXB', '0XD', '0XU', '1XD', '1XU', '2XD', '2XU', '3XD', '3XU', '5XD', '5XU', 'ZXD', 'ZXU', '0xA', '0xB', '1xA', '1xB', '2xA', '2xB', '3xA', '3xB', '4xA', '4xB', 'ZxA', 'ZxB', 'YxA', 'YxB', 'WxA', 'WxB', 'TxA', 'TxB', '0xD', '0xU', '1xD', '1xU', '2xD', '2xU', '3xD', '3xU', '5xD', '5xU', 'ZxD', 'ZxU'],
|
||||
Rib: ['0RA', '0RB', '1RA', '1RB', '2RA', '2RB', '3RA', '3RB', '4RA', '4RB', 'ZRA', 'ZRB', 'YRA', 'YRB', 'WRA', 'WRB', 'TRA', 'TRB', '0RD', '0RU', '1RD', '1RU', '2RD', '2RU', '3RD', '3RU', '5RD', '5RU', 'ZRD', 'ZRU', '0rA', '0rB', '1rA', '1rB', '2rA', '2rB', '3rA', '3rB', '4rA', '4rB', 'ZrA', 'ZrB', 'YrA', 'YrB', 'WrA', 'WrB', 'TrA', 'TrB', '0rD', '0rU', '1rD', '1rU', '2rD', '2rU', '3rD', '3rU', '5rD', '5rU', 'ZrD', 'ZrU'],
|
||||
Fru: ['0CA', '0CB', '1CA', '1CB', '2CA', '2CB', '3CA', '3CB', '4CA', '4CB', '5CA', '5CB', 'WCA', 'WCB', '0CD', '0CU', '1CD', '1CU', '2CD', '2CU', '3CD', '3CU', '4CD', '4CU', '6CD', '6CU', 'WCD', 'WCU', 'VCD', 'VCU', 'UCD', 'UCU', 'QCD', 'QCU', '0cA', '0cB', '1cA', '1cB', '2cA', '2cB', '3cA', '3cB', '4cA', '4cB', '5cA', '5cB', 'WcA', 'WcB', '0cD', '0cU', '1cD', '1cU', '2cD', '2cU', '3cD', '3cU', '4cD', '4cU', '6cD', '6cU', 'WcD', 'WcU', 'VcD', 'VcU', 'UcD', 'UcU', 'QcD', 'QcU'],
|
||||
Tag: ['0JA', '0JB', '1JA', '1JB', '2JA', '2JB', '3JA', '3JB', '4JA', '4JB', '5JA', '5JB', 'WJA', 'WJB', '0JD', '0JU', '1JD', '1JU', '2JD', '2JU', '3JD', '3JU', '4JD', '4JU', '6JD', '6JU', 'WJD', 'WJU', 'VJD', 'VJU', 'UJD', 'UJU', 'QJD', 'QJU', '0jA', '0jB', '1jA', '1jB', '2jA', '2jB', '3jA', '3jB', '4jA', '4jB', '5jA', '5jB', 'WjA', 'WjB', '0jD', '0jU', '1jD', '1jU', '2jD', '2jU', '3jD', '3jU', '4jD', '4jU', '6jD', '6jU', 'WjD', 'WjU', 'VjD', 'VjU', 'UjD', 'UjU', 'QjD', 'QjU'],
|
||||
Sor: ['0BA', '0BB', '1BA', '1BB', '2BA', '2BB', '3BA', '3BB', '4BA', '4BB', '5BA', '5BB', 'WBA', 'WBB', '0BD', '0BU', '1BD', '1BU', '2BD', '2BU', '3BD', '3BU', '4BD', '4BU', '6BD', '6BU', 'WBD', 'WBU', 'VBD', 'VBU', 'UBD', 'UBU', 'QBD', 'QBU', '0bA', '0bB', '1bA', '1bB', '2bA', '2bB', '3bA', '3bB', '4bA', '4bB', '5bA', '5bB', 'WbA', 'WbB', '0bD', '0bU', '1bD', '1bU', '2bD', '2bU', '3bD', '3bU', '4bD', '4bU', '6bD', '6bU', 'WbD', 'WbU', 'VbD', 'VbU', 'UbD', 'UbU', 'QbD', 'QbU'],
|
||||
Psi: ['0PA', '0PB', '1PA', '1PB', '2PA', '2PB', '3PA', '3PB', '4PA', '4PB', '5PA', '5PB', 'WPA', 'WPB', '0PD', '0PU', '1PD', '1PU', '2PD', '2PU', '3PD', '3PU', '4PD', '4PU', '6PD', '6PU', 'WPD', 'WPU', 'VPD', 'VPU', 'UPD', 'UPU', 'QPD', 'QPU', '0pA', '0pB', '1pA', '1pB', '2pA', '2pB', '3pA', '3pB', '4pA', '4pB', '5pA', '5pB', 'WpA', 'WpB', '0pD', '0pU', '1pD', '1pU', '2pD', '2pU', '3pD', '3pU', '4pD', '4pU', '6pD', '6pU', 'WpD', 'WpU', 'VpD', 'VpU', 'UpD', 'UpU', 'QpD', 'QpU'],
|
||||
Neu5Ac: ['0SA', '0SB', '4SA', '4SB', '7SA', '7SB', '8SA', '8SB', '9SA', '9SB', 'ASA', 'ASB', 'BSA', 'BSB', 'CSA', 'CSB', 'DSA', 'DSB', 'ESA', 'ESB', 'FSA', 'FSB', 'GSA', 'GSB', 'HSA', 'HSB', 'ISA', 'ISB', 'JSA', 'JSB', 'KSA', 'KSB', '0sA', '0sB', '4sA', '4sB', '7sA', '7sB', '8sA', '8sB', '9sA', '9sB', 'AsA', 'AsB', 'BsA', 'BsB', 'CsA', 'CsB', 'DsA', 'DsB', 'EsA', 'EsB', 'FsA', 'FsB', 'GsA', 'GsB', 'HsA', 'HsB', 'IsA', 'IsB', 'JsA', 'JsB', 'KsA', 'KsB'],
|
||||
Neu5Gc: ['0GL', '4GL', '7GL', '8GL', '9GL', 'CGL', 'DGL', 'EGL', 'FGL', 'GGL', 'HGL', 'IGL', 'JGL', 'KGL', '0gL', '4gL', '7gL', '8gL', '9gL', 'AgL', 'BgL', 'CgL', 'DgL', 'EgL', 'FgL', 'GgL', 'HgL', 'IgL', 'JgL', 'KgL'],
|
||||
Tyv: ['0TV', '0Tv', '1TV', '1Tv', '2TV', '2Tv', '4TV', '4Tv', 'YTV', 'YTv', '0tV', '0tv', '1tV', '1tv', '2tV', '2tv', '4tV', '4tv', 'YtV', 'Ytv'],
|
||||
Abe: ['0AE', '2AE', '4AE', 'YGa', '0AF', '2AF', '4AF', 'YAF'],
|
||||
Bac: ['0BC', '3BC', '0bC', '3bC'],
|
||||
Kdn: ['0KN', '4KN', '5KN', '7KN', '8KN', '9KN', 'AKN', 'BKN', 'CKN', 'DKN', 'EKN', 'FKN', 'GKN', 'HKN', 'IKN', 'JKN', 'KKN', 'LKN', 'MKN', 'NKN', 'OKN', 'PKN', 'QKN', 'RKN', 'SKN', 'TKN', 'UKN', 'VKN', 'WKN', 'XKN', 'YKN', '0Kn', '4Kn', '5Kn', '7Kn', '8Kn', '9Kn', 'AKn', 'BKn', 'CKn', 'DKn', 'EKn', 'FKn', 'GKn', 'HKn', 'IKn', 'JKn', 'KKn', 'LKn', 'MKn', 'NKn', 'OKn', 'PKn', 'QKn', 'RKn', 'SKn', 'TKn', 'UKn', 'VKn', 'WKn', 'XKn', 'YKn'],
|
||||
Kdo: ['0KO', '4KO', '5KO', '7KO', '8KO', 'AKO', 'BKO', 'CKO', 'DKO', 'EKO', 'FKO', 'GKO', 'HKO', 'IKO', 'JKO', 'KKO', '0Ko', '4Ko', '5Ko', '7Ko', '8Ko', 'AKo', 'BKo', 'CKo', 'DKo', 'EKo', 'FKo', 'GKo', 'HKo', 'IKo', 'JKo', 'KKo'],
|
||||
};
|
||||
|
||||
const DefaultSaccharideCompIdMap = (function () {
|
||||
const map = new Map<string, SaccharideComponent>();
|
||||
for (let i = 0, il = Monosaccharides.length; i < il; ++i) {
|
||||
const saccharide = Monosaccharides[i];
|
||||
@@ -347,6 +386,16 @@ export const SaccharideCompIdMap = (function () {
|
||||
map.set(charmm[j], saccharide);
|
||||
}
|
||||
}
|
||||
|
||||
const glycam = GlycamSaccharideNames[saccharide.abbr];
|
||||
if (glycam) {
|
||||
for (let j = 0, jl = glycam.length; j < jl; ++j) {
|
||||
// On collision, use PDB name as default.
|
||||
if (!map.has(glycam[j])) {
|
||||
map.set(glycam[j], saccharide);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SaccharideNames.forEach(name => {
|
||||
if (!map.has(name)) map.set(name, UnknownSaccharideComponent);
|
||||
@@ -354,4 +403,47 @@ export const SaccharideCompIdMap = (function () {
|
||||
return map;
|
||||
})();
|
||||
|
||||
const GlycamSaccharideCompIdMap = (function () {
|
||||
const map = new Map<string, SaccharideComponent>();
|
||||
for (let i = 0, il = Monosaccharides.length; i < il; ++i) {
|
||||
const saccharide = Monosaccharides[i];
|
||||
|
||||
const common = CommonSaccharideNames[saccharide.abbr];
|
||||
if (common) {
|
||||
for (let j = 0, jl = common.length; j < jl; ++j) {
|
||||
map.set(common[j], saccharide);
|
||||
}
|
||||
}
|
||||
|
||||
const charmm = CharmmSaccharideNames[saccharide.abbr];
|
||||
if (charmm) {
|
||||
for (let j = 0, jl = charmm.length; j < jl; ++j) {
|
||||
map.set(charmm[j], saccharide);
|
||||
}
|
||||
}
|
||||
|
||||
const glycam = GlycamSaccharideNames[saccharide.abbr];
|
||||
if (glycam) {
|
||||
for (let j = 0, jl = glycam.length; j < jl; ++j) {
|
||||
// On collision, use PDB name as default.
|
||||
if (!map.has(glycam[j])) {
|
||||
map.set(glycam[j], saccharide);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SaccharideNames.forEach(name => {
|
||||
if (!map.has(name)) map.set(name, UnknownSaccharideComponent);
|
||||
});
|
||||
return map;
|
||||
})();
|
||||
|
||||
export type SaccharideCompIdMapType = 'default' | 'glycam'
|
||||
|
||||
export function setSaccharideCompIdMapType(type: SaccharideCompIdMapType) {
|
||||
SaccharideCompIdMap = type === 'default' ? DefaultSaccharideCompIdMap : GlycamSaccharideCompIdMap;
|
||||
}
|
||||
|
||||
export let SaccharideCompIdMap = DefaultSaccharideCompIdMap;
|
||||
|
||||
export type SaccharideComponentMap = ReadonlyMap<string, SaccharideComponent>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 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>
|
||||
* @author Aliaksei Chareshneu <chareshneu.tech@gmail.com>
|
||||
*/
|
||||
|
||||
import { StateTransforms } from '../transforms';
|
||||
@@ -182,7 +183,6 @@ export const CubeProvider = DataFormatProvider({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
type DsCifParams = { entryId?: string | string[] };
|
||||
|
||||
export const DscifProvider = DataFormatProvider({
|
||||
@@ -197,16 +197,21 @@ export const DscifProvider = DataFormatProvider({
|
||||
parse: async (plugin, data, params?: DsCifParams) => {
|
||||
const cifCell = await plugin.build().to(data).apply(StateTransforms.Data.ParseCif).commit();
|
||||
const b = plugin.build().to(cifCell);
|
||||
const blocks = cifCell.obj!.data.blocks.slice(1); // zero block contains query meta-data
|
||||
const blocks = cifCell.obj!.data.blocks;
|
||||
|
||||
if (blocks.length !== 1 && blocks.length !== 2) throw new Error('unknown number of blocks');
|
||||
if (blocks.length === 0) throw new Error('no data blocks');
|
||||
|
||||
const volumes: StateObjectSelector<PluginStateObject.Volume.Data>[] = [];
|
||||
let i = 0;
|
||||
for (const block of blocks) {
|
||||
// Skip "server" data block.
|
||||
if (block.header.toUpperCase() === 'SERVER') continue;
|
||||
|
||||
const entryId = Array.isArray(params?.entryId) ? params?.entryId[i] : params?.entryId;
|
||||
volumes.push(b.apply(StateTransforms.Volume.VolumeFromDensityServerCif, { blockHeader: block.header, entryId }).selector);
|
||||
i++;
|
||||
if (block.categories['volume_data_3d_info']?.rowCount > 0) {
|
||||
volumes.push(b.apply(StateTransforms.Volume.VolumeFromDensityServerCif, { blockHeader: block.header, entryId }).selector);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
await b.commit();
|
||||
|
||||
@@ -15,6 +15,7 @@ import { PluginContext } from '../../mol-plugin/context';
|
||||
import { Assembly, Symmetry } from '../../mol-model/structure/model/properties/symmetry';
|
||||
import { PluginStateObject as SO } from '../objects';
|
||||
import { ModelSymmetry } from '../../mol-model-formats/structure/property/symmetry';
|
||||
import { assertUnreachable } from '../../mol-util/type-helpers';
|
||||
|
||||
const CommonStructureParams = {
|
||||
dynamicBonds: PD.Optional(PD.Boolean(false, { description: 'Ensure bonds are recalculated upon model changes. Also enables calculation of inter-unit bonds in water molecules and ions.' })),
|
||||
@@ -188,6 +189,6 @@ export namespace RootStructureDefinition {
|
||||
return buildSymmetryAssembly(ctx, model, params.params.generators, symmetry, props);
|
||||
}
|
||||
|
||||
throw new Error(`Unknown represetation type: ${(params as any).name}`);
|
||||
assertUnreachable(params);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import { Icon, ArrowRightSvg, ArrowDropDownSvg } from './controls/icons';
|
||||
|
||||
export const PluginReactContext = React.createContext(void 0 as any as PluginUIContext);
|
||||
|
||||
export abstract class PluginUIComponent<P = {}, S = {}, SS = {}> extends React.Component<P, S, SS> {
|
||||
export abstract class PluginUIComponent<P = {}, S = {}, SS = {}> extends React.Component<P & { children?: any }, S, SS> {
|
||||
static contextType = PluginReactContext;
|
||||
readonly plugin: PluginUIContext;
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: bo
|
||||
render() {
|
||||
const isAnimating = this.plugin.behaviors.state.isAnimating.value;
|
||||
|
||||
if (!this.state.show || (isAnimating && !this.state.label)) return null;
|
||||
if (!this.state.show || (isAnimating && !this.state.label) || !this.plugin.config.get(PluginConfig.Viewport.ShowTrajectoryControls)) return null;
|
||||
|
||||
return <div className='msp-traj-controls'>
|
||||
{!isAnimating && <IconButton svg={SkipPreviousSvg} title='First Model' onClick={this.reset} disabled={isAnimating} />}
|
||||
|
||||
@@ -92,7 +92,7 @@ export class CombinedColorControl extends React.PureComponent<ParamProps<PD.Colo
|
||||
}
|
||||
}
|
||||
|
||||
let _colors: React.ReactFragment | undefined = void 0;
|
||||
let _colors: any = void 0;
|
||||
export function ColorOptions() {
|
||||
if (_colors) return _colors;
|
||||
_colors = <>{DefaultColorSwatch.map(v =>
|
||||
|
||||
@@ -21,7 +21,8 @@ export class ControlGroup extends React.Component<{
|
||||
onHeaderClick?: () => void,
|
||||
noTopMargin?: boolean,
|
||||
childrenClassName?: string,
|
||||
maxHeight?: string
|
||||
maxHeight?: string,
|
||||
children?: any
|
||||
}, { isExpanded: boolean }> {
|
||||
state = { isExpanded: !!this.props.initialExpanded };
|
||||
|
||||
@@ -335,7 +336,7 @@ export class ToggleButton extends React.PureComponent<ToggleButtonProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export class ExpandGroup extends React.PureComponent<{ header: string, headerStyle?: React.CSSProperties, initiallyExpanded?: boolean, accent?: boolean, noOffset?: boolean, marginTop?: 0 | string, headerLeftMargin?: string }, { isExpanded: boolean }> {
|
||||
export class ExpandGroup extends React.PureComponent<{ children?: any, header: string, headerStyle?: React.CSSProperties, initiallyExpanded?: boolean, accent?: boolean, noOffset?: boolean, marginTop?: 0 | string, headerLeftMargin?: string }, { isExpanded: boolean }> {
|
||||
state = { isExpanded: !!this.props.initiallyExpanded };
|
||||
|
||||
toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded });
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user