Compare commits

...

57 Commits

Author SHA1 Message Date
Alexander Rose
c5871e9025 3.8.2 2022-05-22 08:36:50 -07:00
Alexander Rose
f26911b358 changelog 2022-05-22 08:31:57 -07:00
Alexander Rose
3a595b80b5 package updates 2022-05-22 08:30:15 -07:00
Alexander Rose
45760ddd41 fix Scene.opacityAverage not handling xray shaded 2022-05-22 08:22:39 -07:00
Alexander Rose
447d068bf1 3.8.1 2022-05-14 11:59:03 -07:00
Alexander Rose
7e1642a4a3 changelog 2022-05-14 11:53:55 -07:00
Alexander Rose
7781267e78 package updates 2022-05-14 11:53:18 -07:00
Alexander Rose
f824fdcfed improve scene marker/opacity average calculation 2022-05-14 11:43:24 -07:00
Alexander Rose
79dd441967 Merge pull request #436 from JonStargaryen/master
Fix Polymer Chain Instance Coloring
2022-05-09 22:41:33 -07:00
Sebastian Bittrich
9dcf9c0785 CHANGELOG 2022-05-09 15:58:22 -07:00
Sebastian Bittrich
83569462c6 fix instance coloring 2022-05-09 15:53:26 -07:00
Alexander Rose
947e169c3a Merge pull request #434 from JonStargaryen/master
proposed fix for headless-gl issues
2022-05-06 22:29:40 -07:00
Sebastian Bittrich
e6b36c52d1 CHANGELOG 2022-05-06 09:11:40 -07:00
Sebastian Bittrich
7fed3b84fa Merge remote-tracking branch 'upstream/master' 2022-05-06 09:08:53 -07:00
Sebastian Bittrich
cbc941f193 simplify array uniform check 2022-05-06 09:08:22 -07:00
Alexander Rose
a7ef0fb85f add interesting pdb entry 2022-05-05 22:41:16 -07:00
Alexander Rose
d10c36eaf5 fix issues with marking camera/handle helper 2022-05-05 22:40:52 -07:00
Sebastian Bittrich
e4c3a66753 proposed fix for headless-gl issues 2022-05-04 11:50:42 -07:00
Alexander Rose
f58f2cdc90 3.8.0 2022-04-30 16:11:07 -07:00
Alexander Rose
8f2676e91e schema updates 2022-04-30 16:05:30 -07:00
Alexander Rose
89d397898e changelog 2022-04-30 15:24:26 -07:00
Alexander Rose
2dc32be9ee Merge pull request #427 from molstar/transparent-object-outline
Transparent object outline
2022-04-30 15:08:46 -07:00
Alexander Rose
769220bd82 Merge pull request #421 from molstar/color-theme-typing
better color theme typing
2022-04-30 15:06:06 -07:00
Alexander Rose
c75aa5dd52 improve transparency & outlines
- proper per-group transparency with wboit off
- fixed outlines with transparent backgound
2022-04-30 12:53:14 -07:00
Alexander Rose
88f1cfd8c4 fix ignoreLight for direct-volume with webgl1 2022-04-30 09:24:39 -07:00
Alexander Rose
108279c1aa add clearDepth & blendColor to WebGLState 2022-04-30 08:42:01 -07:00
Alexander Rose
8150490aac Merge branch 'master' of https://github.com/molstar/molstar into transparent-object-outline 2022-04-30 08:39:16 -07:00
Alexander Rose
9497aa6362 package updates 2022-04-30 08:38:07 -07:00
Alexander Rose
3769da48a1 handle building GridLookup3D with zero cell size 2022-04-29 20:18:40 -07:00
Alexander Rose
3c21fcd53a fix FormatRegistry.isApplicable
- was returning true for unregistered formats
2022-04-29 20:16:09 -07:00
Alexander Rose
102ef2795d handle outlines for per-group transparency
- fix allowTransparentBackfaces for per-group transparency
2022-04-23 23:02:11 -07:00
Alexander Rose
0befa253c2 add WebGLState.depthFunc 2022-04-23 20:07:41 -07:00
Alexander Rose
87189cee58 support outlines for transparent objects
- cleanup of renderer and draw pass
2022-04-23 15:19:01 -07:00
Alexander Rose
3284f13fc6 fix spec of emptyDepthTexture in Renderer 2022-04-23 15:17:20 -07:00
Alexander Rose
70d219b120 improve Renderer.renderPick typing 2022-04-23 15:13:38 -07:00
Alexander Rose
a5ed3a08ea add Scene.getOpacityAverage 2022-04-23 15:12:16 -07:00
Alexander Rose
3665e7e999 expose RenderTarget.depthRenderbuffer 2022-04-23 15:10:40 -07:00
Alexander Rose
9b583b23ae add Renderbuffer.detachFramebuffer 2022-04-23 15:10:16 -07:00
Alexander Rose
d602415e98 check if WEBGL_depth_texture is supported 2022-04-23 15:09:44 -07:00
Alexander Rose
2c49a423e2 type assertion 2022-04-21 19:47:13 -07:00
Alexander Rose
8a266e70c8 fix handling of struct_conf mmCIF field (#425) 2022-04-21 19:46:50 -07:00
Alexander Rose
0df3bcd65d document supported file formats 2022-04-19 17:43:33 -07:00
dsehnal
f5ecf5648e 3.7.0 2022-04-13 20:04:01 +02:00
dsehnal
821f82fc3f changelog 2022-04-13 20:01:04 +02:00
David Sehnal
92305fe628 Merge pull request #420 from molstar/transparentBackfaces
improve transparentBackfaces handling
2022-04-13 19:57:29 +02:00
David Sehnal
17fe57b8a5 Merge pull request #423 from jpattle/option-to-disable-drag-overlay
Added an option to disable the drag overlay
2022-04-13 16:31:21 +02:00
Jason Pattle
47433a51d3 Added an option to the components spec to allow disabling of the drag-and-drop overlap for Molstar that loads files into the viewer. By default the drag overlay is enabled, just as it was before 2022-04-13 15:00:03 +01:00
Alexander Rose
e090827ced Merge branch 'master' of https://github.com/molstar/molstar into transparentBackfaces 2022-04-10 13:20:22 -07:00
Alexander Rose
856e6a8b74 use ColorTypeLocation as default
- for backwards compatibility
- most used
2022-04-09 19:27:06 -07:00
Alexander Rose
a813b4d40e Merge branch 'master' of https://github.com/molstar/molstar into color-theme-typing 2022-04-09 16:53:17 -07:00
dsehnal
98afc27442 fix react typing 2022-04-09 21:24:14 +02:00
Alexander Rose
9d4f28a395 fix type deps 2022-04-09 11:36:17 -07:00
Alexander Rose
50266d9a56 package updates 2022-04-09 11:20:28 -07:00
Alexander Rose
602a532cf2 better color theme typing 2022-04-09 10:38:03 -07:00
Alexander Rose
b23d610c94 improve transparentBackfaces handling
- off: don't show (default)
- on: show with transparency
- opaque: show fully opaque
2022-04-09 10:17:41 -07:00
Alexander Rose
119c43d527 fix xrayShaded for texture-mesh geometries 2022-04-09 10:04:06 -07:00
Alexander Rose
124feeb790 color theme tweaks
- add optional grid property
- handle dColorType_direct for non direct-volume shaders
2022-04-09 09:57:31 -07:00
70 changed files with 23942 additions and 22765 deletions

View File

@@ -6,6 +6,40 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased]
## [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 +61,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
View 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

View File

@@ -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)

45082
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "molstar",
"version": "3.6.2",
"version": "3.8.2",
"description": "A comprehensive macromolecular library.",
"homepage": "https://github.com/molstar/molstar#readme",
"repository": {
@@ -94,42 +94,42 @@
"@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.4.11",
"@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.8",
"@graphql-codegen/typescript-operations": "^2.4.0",
"@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": "^27.5.1",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.4",
"@typescript-eslint/eslint-plugin": "^5.25.0",
"@typescript-eslint/parser": "^5.25.0",
"benchmark": "^2.1.4",
"concurrently": "^7.0.0",
"concurrently": "^7.2.0",
"cpx2": "^4.2.0",
"crypto-browserify": "^3.12.0",
"css-loader": "^6.7.1",
"eslint": "^8.11.0",
"eslint": "^8.16.0",
"extra-watch-webpack-plugin": "^1.0.3",
"file-loader": "^6.2.0",
"fs-extra": "^10.0.1",
"graphql": "^16.3.0",
"fs-extra": "^10.1.0",
"graphql": "^16.5.0",
"http-server": "^14.1.0",
"jest": "^27.5.1",
"jest": "^28.1.0",
"mini-css-extract-plugin": "^2.6.0",
"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.1.0",
"react-dom": "^18.1.0",
"sass": "^1.52.1",
"sass-loader": "^13.0.0",
"simple-git": "^3.7.1",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.1",
"ts-jest": "^27.1.3",
"typescript": "^4.6.3",
"webpack": "^5.70.0",
"ts-jest": "^28.0.2",
"typescript": "^4.6.4",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
},
"dependencies": {
@@ -137,26 +137,26 @@
"@types/benchmark": "^2.1.1",
"@types/compression": "1.7.2",
"@types/express": "^4.17.13",
"@types/node": "^16.11.26",
"@types/node": "^16.11.36",
"@types/node-fetch": "^2.6.1",
"@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",
"immer": "^9.0.14",
"immutable": "^4.0.0",
"node-fetch": "^2.6.7",
"rxjs": "^7.5.5",
"swagger-ui-dist": "^4.6.2",
"tslib": "^2.3.1",
"swagger-ui-dist": "^4.11.1",
"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"
}
}

View File

@@ -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, ', ')});

View File

@@ -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';

View File

@@ -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':

View File

@@ -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-04-30T15:35:08-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,55 @@ 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 GroupMembersAlignmentAlignedRegions = {
/** Aligned region length */
readonly length: Scalars['Int'];
/** Entity seqeunce start position */
readonly query_begin: Scalars['Int'];
/** NCBI sequence start position */
readonly target_begin: Scalars['Int'];
};
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 +3275,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 +6845,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 +6867,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 +6945,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 +7016,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 +8772,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 +9018,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 +10148,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 +10475,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;
/** List of alignments with core_entity canonical sequences */
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 = {
/** Aligned region */
readonly aligned_regions: ReadonlyArray<Maybe<GroupMembersAlignmentAlignedRegions>>;
readonly member_id?: Maybe<Scalars['String']>;
/** Alignment scores */
readonly scores: GroupMembersAlignmentScores;
};
export type RcsbPolymerEntityInstanceContainerIdentifiers = {
/** Instance identifier for this container. */
readonly asym_id: Scalars['String'];
@@ -10346,6 +10656,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']>;

View File

@@ -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>
@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -11,48 +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);
}
type Props = {
postprocessing: PostprocessingProps
marking: MarkingProps
@@ -70,16 +38,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 +66,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 +95,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 +116,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 +123,37 @@ 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();
renderer.renderWboitTransparent(scene.primitives, camera, this.depthTextureOpaque);
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 +162,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,44 +172,38 @@ 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);
}
}
target.bind();
renderer.renderBlendedVolume(scene.volumes, camera, this.depthTextureOpaque);
}
renderer.renderBlendedTransparent(scene.primitives, camera, null);
@@ -307,10 +239,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);

View File

@@ -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>
*/
@@ -8,7 +8,6 @@ import { PickingId } from '../../mol-geo/geometry/picking';
import { PickType, Renderer } from '../../mol-gl/renderer';
import { Scene } from '../../mol-gl/scene';
import { WebGLContext } from '../../mol-gl/webgl/context';
import { GraphicsRenderVariant } from '../../mol-gl/webgl/render-item';
import { RenderTarget } from '../../mol-gl/webgl/render-target';
import { Vec3 } from '../../mol-math/linear-algebra';
import { spiral2d } from '../../mol-math/misc';
@@ -64,13 +63,11 @@ export class PickPass {
}
}
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.camera.isEnabled) {

View File

@@ -30,7 +30,8 @@ import { SmaaParams, SmaaPass } from './smaa';
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 +42,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 +188,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 +213,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 +281,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 +318,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 +331,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 +351,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 +363,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 +471,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);
}

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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];

View File

@@ -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'),
};

View File

@@ -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')

View File

@@ -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'),

View File

@@ -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'),
};

View File

@@ -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')

View File

@@ -54,18 +54,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 +136,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 +159,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 +206,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 +235,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 +274,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 +304,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 +336,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 +345,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);
@@ -336,13 +364,13 @@ namespace Renderer {
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);
}
}
};
@@ -352,11 +380,43 @@ namespace Renderer {
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);
}
};
const renderDepthOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
state.disable(gl.BLEND);
state.enable(gl.DEPTH_TEST);
state.depthMask(true);
updateInternal(group, camera, depthTexture, Mask.Opaque, false);
const { renderables } = group;
for (let i = 0, il = renderables.length; i < il; ++i) {
const r = renderables[i];
if (r.state.opaque && r.values.transparencyAverage.ref.value !== 1 && !r.values.dXrayShaded?.ref.value) {
renderObject(r, 'depth', Flag.None);
}
}
};
const renderDepthTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
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);
}
}
};
@@ -365,7 +425,7 @@ namespace Renderer {
state.enable(gl.DEPTH_TEST);
state.depthMask(true);
updateInternal(group, camera, depthTexture, false, false);
updateInternal(group, camera, depthTexture, Mask.All, false);
ValueCell.updateIfChanged(globalUniforms.uMarkingType, MarkingType.Depth);
const { renderables } = group;
@@ -373,7 +433,7 @@ namespace Renderer {
const r = renderables[i];
if (r.values.markerAverage.ref.value !== 1) {
renderObject(renderables[i], 'marking');
renderObject(renderables[i], 'marking', Flag.None);
}
}
};
@@ -383,7 +443,7 @@ namespace Renderer {
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,7 +451,7 @@ namespace Renderer {
const r = renderables[i];
if (r.values.markerAverage.ref.value > 0) {
renderObject(renderables[i], 'marking');
renderObject(renderables[i], 'marking', Flag.None);
}
}
};
@@ -406,13 +466,15 @@ namespace Renderer {
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);
}
}
};
@@ -420,7 +482,7 @@ namespace Renderer {
const renderBlendedTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
state.enable(gl.DEPTH_TEST);
updateInternal(group, camera, depthTexture, false, false);
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
const { renderables } = group;
@@ -435,53 +497,38 @@ 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);
}
}
}
};
const renderBlendedVolumeOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
const renderBlendedVolume = (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);
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);
}
}
};
@@ -491,7 +538,7 @@ namespace Renderer {
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 +547,14 @@ 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);
}
}
};
const renderWboitTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
updateInternal(group, camera, depthTexture, true, false);
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
const { renderables } = group;
for (let i = 0, il = renderables.length; i < il; ++i) {
@@ -517,7 +564,7 @@ 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);
}
}
};
@@ -538,23 +585,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,

View File

@@ -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),
@@ -245,16 +283,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;
},
};
}

View File

@@ -5,5 +5,9 @@ if (interior) {
} else {
gl_FragColor.rgb *= 1.0 - uInteriorDarkening;
}
#ifdef dTransparentBackfaces_opaque
gl_FragColor.a = 1.0;
#endif
}
`;

View File

@@ -31,11 +31,34 @@ export const assign_material_color = `
#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 +74,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 +85,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

View File

@@ -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
}
`;

View File

@@ -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

View File

@@ -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;

View File

@@ -17,6 +17,10 @@ export const common = `
#define dColorType_varying
#endif
#define MaskAll 0
#define MaskOpaque 1
#define MaskTransparent 2
//
#define PI 3.14159265

View File

@@ -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);

View File

@@ -72,7 +72,7 @@ uniform float uPickingAlphaThreshold;
uniform bool uTransparentBackground;
uniform float uXrayEdgeFalloff;
uniform bool uRenderWboit;
uniform int uRenderMask;
uniform float uNear;
uniform float uFar;
@@ -141,12 +141,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 +284,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;

View File

@@ -130,7 +130,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);

View File

@@ -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;
}
}
}
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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}'`);

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 }

View File

@@ -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.358, IHM 1.17, MA 1.4.0.
*
* @author molstar/ciftools package
*/

View File

@@ -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.358, IHM 1.17, MA 1.4.0.
*
* @author molstar/ciftools package
*/

View File

@@ -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.
*

View File

@@ -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.358, IHM 1.17, MA 1.4.0.
*
* @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,
/**
@@ -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.
*/

View File

@@ -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);
});

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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
};

View File

@@ -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
}

View File

@@ -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 } = {

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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 =>

View File

@@ -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 });

View File

@@ -23,7 +23,7 @@ import { Asset } from '../mol-util/assets';
import { BehaviorSubject } from 'rxjs';
import { useBehavior } from './hooks/use-behavior';
export class Plugin extends React.Component<{ plugin: PluginUIContext }, {}> {
export class Plugin extends React.Component<{ plugin: PluginUIContext, children?: any }, {}> {
region(kind: 'left' | 'right' | 'bottom' | 'main', element: JSX.Element) {
return <div className={`msp-layout-region msp-layout-${kind}`}>
<div className='msp-layout-static'>
@@ -39,7 +39,7 @@ export class Plugin extends React.Component<{ plugin: PluginUIContext }, {}> {
}
}
export class PluginContextContainer extends React.Component<{ plugin: PluginUIContext }> {
export class PluginContextContainer extends React.Component<{ plugin: PluginUIContext, children?: any }> {
render() {
return <PluginReactContext.Provider value={this.props.plugin}>
<div className='msp-plugin'>
@@ -159,7 +159,7 @@ class Layout extends PluginUIComponent {
{layout.showControls && controls.bottom !== 'none' && this.region('bottom', controls.bottom || Log)}
</div>
{!this.plugin.spec.components?.hideTaskOverlay && <OverlayTaskProgress />}
<DragOverlay plugin={this.plugin} showDragOverlay={this.showDragOverlay} />
{!this.plugin.spec.components?.disableDragOverlay && <DragOverlay plugin={this.plugin} showDragOverlay={this.showDragOverlay} />}
</div>
</div>;
}

View File

@@ -24,7 +24,8 @@ interface PluginUISpec extends PluginSpec {
view?: React.ComponentClass,
controls?: React.ComponentClass
},
hideTaskOverlay?: boolean
hideTaskOverlay?: boolean,
disableDragOverlay?: boolean,
},
}

View File

@@ -37,7 +37,7 @@ export class BindingsHelp extends React.PureComponent<{ bindings: { [k: string]:
}
}
export class HelpText extends React.PureComponent {
export class HelpText extends React.PureComponent<{ children?: any }> {
render() {
return <div className='msp-help-text'>
<div>{this.props.children}</div>
@@ -45,7 +45,7 @@ export class HelpText extends React.PureComponent {
}
}
export class HelpGroup extends React.PureComponent<{ header: string, initiallyExpanded?: boolean }, { isExpanded: boolean }> {
export class HelpGroup extends React.PureComponent<{ children?: any, header: string, initiallyExpanded?: boolean }, { isExpanded: boolean }> {
state = {
header: this.props.header,
isExpanded: !!this.props.initiallyExpanded

View File

@@ -57,7 +57,7 @@ export interface QualityProps {
doubleSided: boolean
xrayShaded: boolean
alpha: number
allowTransparentBackfaces: boolean
transparentBackfaces: 'off' | 'on' | 'opaque'
}
export const DefaultQualityThresholds = {
@@ -193,7 +193,7 @@ export function getQualityProps(props: Partial<QualityProps>, data?: any) {
resolution = Math.max(resolution, volume / 500_000_000);
resolution = Math.min(resolution, 20);
if (!props.allowTransparentBackfaces && ((props.alpha !== undefined && props.alpha < 1) || !!props.xrayShaded)) {
if (props.transparentBackfaces === 'off' && ((props.alpha !== undefined && props.alpha < 1) || !!props.xrayShaded)) {
doubleSided = false;
}

View File

@@ -32,7 +32,7 @@ export async function createImage(ctx: VisualContext, volume: Volume, theme: The
const isoVal = Volume.IsoValue.toAbsolute(isoValue, volume.grid.stats).absoluteValue;
// TODO more color themes
const color = theme.color.color(NullLocation, false);
const color = 'color' in theme.color ? theme.color.color(NullLocation, false) : Color(0xffffff);
const [r, g, b] = Color.toRgbNormalized(color);
const {

View File

@@ -1,12 +1,12 @@
/**
* 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 { Color } from '../mol-util/color';
import { Location } from '../mol-model/location';
import { ColorType } from '../mol-geo/geometry/color-data';
import { ColorType, ColorTypeDirect, ColorTypeGrid, ColorTypeLocation } from '../mol-geo/geometry/color-data';
import { CarbohydrateSymbolColorThemeProvider } from './color/carbohydrate-symbol';
import { UniformColorThemeProvider } from './color/uniform';
import { deepEqual } from '../mol-util';
@@ -35,16 +35,22 @@ import { OperatorHklColorThemeProvider } from './color/operator-hkl';
import { PartialChargeColorThemeProvider } from './color/partial-charge';
import { AtomIdColorThemeProvider } from './color/atom-id';
import { EntityIdColorThemeProvider } from './color/entity-id';
import { TextureFilter } from '../mol-gl/webgl/texture';
import { Texture, TextureFilter } from '../mol-gl/webgl/texture';
import { VolumeValueColorThemeProvider } from './color/volume-value';
import { Vec3, Vec4 } from '../mol-math/linear-algebra';
export type LocationColor = (location: Location, isSecondary: boolean) => Color
export interface ColorVolume {
colors: Texture
dimension: Vec3
transform: Vec4
}
export { ColorTheme };
interface ColorTheme<P extends PD.Params> {
readonly factory: ColorTheme.Factory<P>
readonly granularity: ColorType
readonly color: LocationColor
type ColorThemeShared<P extends PD.Params, G extends ColorType> = {
readonly factory: ColorTheme.Factory<P, G>
readonly props: Readonly<PD.Values<P>>
/**
* if palette is defined, 24bit RGB color value normalized to interval [0, 1]
@@ -56,6 +62,26 @@ interface ColorTheme<P extends PD.Params> {
readonly description?: string
readonly legend?: Readonly<ScaleLegend | TableLegend>
}
type ColorThemeLocation<P extends PD.Params> = {
readonly granularity: ColorTypeLocation
readonly color: LocationColor
} & ColorThemeShared<P, ColorTypeLocation>
type ColorThemeGrid<P extends PD.Params> = {
readonly granularity: ColorTypeGrid
readonly grid: ColorVolume
} & ColorThemeShared<P, ColorTypeGrid>
type ColorThemeDirect<P extends PD.Params> = {
readonly granularity: ColorTypeDirect
} & ColorThemeShared<P, ColorTypeDirect>
type ColorTheme<P extends PD.Params, G extends ColorType = ColorTypeLocation> =
G extends ColorTypeLocation ? ColorThemeLocation<P> :
G extends ColorTypeGrid ? ColorThemeGrid<P> :
G extends ColorTypeDirect ? ColorThemeDirect<P> : never
namespace ColorTheme {
export const enum Category {
Atom = 'Atom Property',
@@ -74,7 +100,7 @@ namespace ColorTheme {
export const PaletteScale = (1 << 24) - 1;
export type Props = { [k: string]: any }
export type Factory<P extends PD.Params> = (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P>
export type Factory<P extends PD.Params, G extends ColorType> = (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P, G>
export const EmptyFactory = () => Empty;
const EmptyColor = Color(0xCCCCCC);
export const Empty: ColorTheme<{}> = {
@@ -84,16 +110,16 @@ namespace ColorTheme {
props: {}
};
export function areEqual(themeA: ColorTheme<any>, themeB: ColorTheme<any>) {
export function areEqual(themeA: ColorTheme<any, any>, themeB: ColorTheme<any, any>) {
return themeA.contextHash === themeB.contextHash && themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props);
}
export interface Provider<P extends PD.Params = any, Id extends string = string> extends ThemeProvider<ColorTheme<P>, P, Id> { }
export interface Provider<P extends PD.Params = any, Id extends string = string, G extends ColorType = ColorType> extends ThemeProvider<ColorTheme<P, G>, P, Id, G> { }
export const EmptyProvider: Provider<{}> = { name: '', label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true };
export type Registry = ThemeRegistry<ColorTheme<any>>
export type Registry = ThemeRegistry<ColorTheme<any, any>>
export function createRegistry() {
return new ThemeRegistry(BuiltIn as { [k: string]: Provider<any> }, EmptyProvider);
return new ThemeRegistry(BuiltIn as { [k: string]: Provider<any, any, any> }, EmptyProvider);
}
export const BuiltIn = {

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2021-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -9,8 +9,8 @@ import { Color, ColorScale } from '../../mol-util/color';
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { ThemeDataContext } from '../theme';
import { ColorNames } from '../../mol-util/color/names';
import { ColorTypeDirect } from '../../mol-geo/geometry/color-data';
const DefaultColor = Color(0xCCCCCC);
const Description = 'Assign color based on the given value of a volume cell.';
export const VolumeValueColorThemeParams = {
@@ -30,7 +30,7 @@ export function getVolumeValueColorThemeParams(ctx: ThemeDataContext) {
return VolumeValueColorThemeParams; // TODO return copy
}
export function VolumeValueColorTheme(ctx: ThemeDataContext, props: PD.Values<VolumeValueColorThemeParams>): ColorTheme<VolumeValueColorThemeParams> {
export function VolumeValueColorTheme(ctx: ThemeDataContext, props: PD.Values<VolumeValueColorThemeParams>): ColorTheme<VolumeValueColorThemeParams, ColorTypeDirect> {
const scale = ColorScale.create({ domain: [0, 1], listOrName: props.colorList.colors });
const colors: Color[] = [];
@@ -43,7 +43,6 @@ export function VolumeValueColorTheme(ctx: ThemeDataContext, props: PD.Values<Vo
return {
factory: VolumeValueColorTheme,
granularity: 'direct',
color: () => DefaultColor,
props: props,
description: Description,
legend: scale.legend,

View File

@@ -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 Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -12,6 +12,7 @@ import { ParamDefinition as PD } from '../mol-util/param-definition';
import { Shape } from '../mol-model/shape';
import { CustomProperty } from '../mol-model-props/common/custom-property';
import { objectForEach } from '../mol-util/object';
import { ColorType } from '../mol-geo/geometry/color-data';
export interface ThemeRegistryContext {
colorThemeRegistry: ColorTheme.Registry
@@ -28,7 +29,7 @@ export interface ThemeDataContext {
export { Theme };
interface Theme {
color: ColorTheme<any>
color: ColorTheme<any, any>
size: SizeTheme<any>
// label: LabelTheme // TODO
}
@@ -65,7 +66,7 @@ namespace Theme {
//
export interface ThemeProvider<T extends ColorTheme<P> | SizeTheme<P>, P extends PD.Params, Id extends string = string> {
export interface ThemeProvider<T extends ColorTheme<P, G> | SizeTheme<P>, P extends PD.Params, Id extends string = string, G extends ColorType = ColorType> {
readonly name: Id
readonly label: string
readonly category: string
@@ -83,7 +84,7 @@ function getTypes(list: { name: string, provider: ThemeProvider<any, any> }[]) {
return list.map(e => [e.name, e.provider.label, e.provider.category] as [string, string, string]);
}
export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> {
export class ThemeRegistry<T extends ColorTheme<any, any> | SizeTheme<any>> {
private _list: { name: string, provider: ThemeProvider<T, any> }[] = [];
private _map = new Map<string, ThemeProvider<T, any>>();
private _name = new Map<ThemeProvider<T, any>, string>();