mirror of
https://github.com/molstar/molstar.git
synced 2026-06-05 22:31:26 +08:00
Compare commits
26 Commits
v3.0.0-dev
...
v3.0.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d4f6bb5d9 | ||
|
|
b3a4e1976d | ||
|
|
ab4a24d8ab | ||
|
|
7c93e9f834 | ||
|
|
90ea8cfebd | ||
|
|
7fc1866dac | ||
|
|
bb520ff424 | ||
|
|
f9d2e20cb9 | ||
|
|
6f13b67bf1 | ||
|
|
f37026a980 | ||
|
|
74f123265b | ||
|
|
ccfae65b01 | ||
|
|
bcfaef77c9 | ||
|
|
0b6243c0d1 | ||
|
|
472866d8ec | ||
|
|
471163f3d8 | ||
|
|
ab6106896d | ||
|
|
7ca624d04b | ||
|
|
bd3d18f43f | ||
|
|
21eb21b6dd | ||
|
|
24ad38e260 | ||
|
|
53bac83dff | ||
|
|
ab1578f667 | ||
|
|
4e70301b62 | ||
|
|
76ed2e9e11 | ||
|
|
504406eb22 |
13
CHANGELOG.md
13
CHANGELOG.md
@@ -6,6 +6,19 @@ Note that since we don't clearly distinguish between a public and private interf
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v3.0.0-dev.7] - 2021-12-20
|
||||
|
||||
- Reduce number of created programs/shaders
|
||||
- Support specifying variants when creating graphics render-items
|
||||
- Change double-side shader param from define to uniform
|
||||
- Remove dMarkerType shader define (use uMarker as needed)
|
||||
- Support to ignore defines depending on the shader variant
|
||||
- Combine pickObject/pickInstance/pickGroup shader variants into one
|
||||
- Combine markingDepth/markingMask shader variants into one
|
||||
- Correctly set shader define flags for overpaint, transparency, substance, clipping
|
||||
- [Breaking] Add per-object clip rendering properties (variant/objects)
|
||||
- ``SimpleSettingsParams.clipping.variant/objects`` and ``RendererParams.clip`` were removed
|
||||
|
||||
## [v3.0.0-dev.6] - 2021-12-19
|
||||
|
||||
- Enable temporal multi-sampling by default
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "3.0.0-dev.6",
|
||||
"version": "3.0.0-dev.7",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "molstar",
|
||||
"version": "3.0.0-dev.6",
|
||||
"version": "3.0.0-dev.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/argparse": "^2.0.10",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "3.0.0-dev.6",
|
||||
"version": "3.0.0-dev.7",
|
||||
"description": "A comprehensive macromolecular library.",
|
||||
"homepage": "https://github.com/molstar/molstar#readme",
|
||||
"repository": {
|
||||
|
||||
@@ -26,7 +26,7 @@ export const MAQualityAssessment = PluginBehavior.create<{ autoAttach: boolean,
|
||||
description: 'Data included in Model Archive files.'
|
||||
},
|
||||
ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean, showTooltip: boolean }> {
|
||||
private provider = QualityAssessmentProvider
|
||||
private provider = QualityAssessmentProvider;
|
||||
|
||||
private labelProvider = {
|
||||
label: (loci: Loci): string | undefined => {
|
||||
@@ -36,7 +36,7 @@ export const MAQualityAssessment = PluginBehavior.create<{ autoAttach: boolean,
|
||||
qmeanLabel(loci),
|
||||
].filter(l => !!l).join('</br>');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
register(): void {
|
||||
DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor);
|
||||
|
||||
@@ -39,6 +39,7 @@ import { Helper } from './helper/helper';
|
||||
import { Passes } from './passes/passes';
|
||||
import { shallowEqual } from '../mol-util';
|
||||
import { MarkingParams } from './passes/marking';
|
||||
import { GraphicsRenderVariantsBlended, GraphicsRenderVariantsWboit } from '../mol-gl/webgl/render-item';
|
||||
|
||||
export const Canvas3DParams = {
|
||||
camera: PD.Group({
|
||||
@@ -296,7 +297,7 @@ namespace Canvas3D {
|
||||
let height = 128;
|
||||
updateViewport();
|
||||
|
||||
const scene = Scene.create(webgl);
|
||||
const scene = Scene.create(webgl, passes.draw.wboitEnabled ? GraphicsRenderVariantsWboit : GraphicsRenderVariantsBlended);
|
||||
|
||||
const camera = new Camera({
|
||||
position: Vec3.create(0, 0, 100),
|
||||
|
||||
@@ -18,6 +18,7 @@ import { TransformData } from '../../mol-geo/geometry/transform-data';
|
||||
import { sphereVertexCount } from '../../mol-geo/primitive/sphere';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
import { Geometry } from '../../mol-geo/geometry/geometry';
|
||||
import { GraphicsRenderVariantsBlended } from '../../mol-gl/webgl/render-item';
|
||||
|
||||
export const DebugHelperParams = {
|
||||
sceneBoundingSpheres: PD.Boolean(false, { description: 'Show full scene bounding spheres.' }),
|
||||
@@ -41,7 +42,7 @@ export class BoundingSphereHelper {
|
||||
private visibleSceneData: BoundingSphereData | undefined;
|
||||
|
||||
constructor(ctx: WebGLContext, parent: Scene, props: Partial<DebugHelperProps>) {
|
||||
this.scene = Scene.create(ctx);
|
||||
this.scene = Scene.create(ctx, GraphicsRenderVariantsBlended);
|
||||
this.parent = parent;
|
||||
this._props = { ...PD.getDefaultValues(DebugHelperParams), ...props };
|
||||
}
|
||||
@@ -160,5 +161,5 @@ const instanceMaterialId = getNextMaterialId();
|
||||
|
||||
function createBoundingSphereRenderObject(mesh: Mesh, color: Color, materialId: number, transform?: TransformData) {
|
||||
const values = Mesh.Utils.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false }, color, 1, transform);
|
||||
return createRenderObject('mesh', values, { disposed: false, visible: true, alphaFactor: 1, pickable: false, colorOnly: false, opaque: false, writeDepth: false, noClip: false }, materialId);
|
||||
return createRenderObject('mesh', values, { disposed: false, visible: true, alphaFactor: 1, pickable: false, colorOnly: false, opaque: false, writeDepth: false }, materialId);
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import { PickingId } from '../../mol-geo/geometry/picking';
|
||||
import { GraphicsRenderObject } from '../../mol-gl/render-object';
|
||||
import { Scene } from '../../mol-gl/scene';
|
||||
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';
|
||||
@@ -58,7 +59,7 @@ export class CameraHelper {
|
||||
private renderObject: GraphicsRenderObject | undefined;
|
||||
|
||||
constructor(private webgl: WebGLContext, props: Partial<CameraHelperProps> = {}) {
|
||||
this.scene = Scene.create(webgl);
|
||||
this.scene = Scene.create(webgl, GraphicsRenderVariantsBlended);
|
||||
|
||||
this.camera = new Camera();
|
||||
Vec3.set(this.camera.up, 0, 1, 0);
|
||||
@@ -75,7 +76,6 @@ export class CameraHelper {
|
||||
this.scene.clear();
|
||||
const params = { ...props.axes.params, scale: props.axes.params.scale * this.webgl.pixelRatio };
|
||||
this.renderObject = createAxesRenderObject(params);
|
||||
this.renderObject.state.noClip = true;
|
||||
this.scene.add(this.renderObject);
|
||||
this.scene.commit();
|
||||
|
||||
@@ -201,7 +201,7 @@ function createAxesMesh(scale: number, mesh?: Mesh) {
|
||||
const x = Vec3.scale(Vec3(), Vec3.unitX, scale);
|
||||
const y = Vec3.scale(Vec3(), Vec3.unitY, scale);
|
||||
const z = Vec3.scale(Vec3(), Vec3.unitZ, scale);
|
||||
const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments: 32 };
|
||||
const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments: 32 };
|
||||
|
||||
state.currentGroup = CameraHelperAxis.None;
|
||||
addSphere(state, Vec3.origin, radius, 2);
|
||||
|
||||
@@ -24,6 +24,7 @@ import { DataLoci, EmptyLoci, 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';
|
||||
import { GraphicsRenderVariantsBlended } from '../../mol-gl/webgl/render-item';
|
||||
|
||||
const HandleParams = {
|
||||
...Mesh.Params,
|
||||
@@ -72,7 +73,6 @@ export class HandleHelper {
|
||||
this.scene.clear();
|
||||
const params = { ...props.handle.params, scale: props.handle.params.scale * this.webgl.pixelRatio };
|
||||
this.renderObject = createHandleRenderObject(params);
|
||||
this.renderObject.state.noClip = true;
|
||||
this.scene.add(this.renderObject);
|
||||
this.scene.commit();
|
||||
|
||||
@@ -127,7 +127,7 @@ export class HandleHelper {
|
||||
}
|
||||
|
||||
constructor(private webgl: WebGLContext, props: Partial<HandleHelperProps> = {}) {
|
||||
this.scene = Scene.create(webgl);
|
||||
this.scene = Scene.create(webgl, GraphicsRenderVariantsBlended);
|
||||
this.setProps(props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { PickingId } from '../../mol-geo/geometry/picking';
|
||||
import { Renderer } from '../../mol-gl/renderer';
|
||||
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';
|
||||
@@ -64,35 +64,35 @@ export class PickPass {
|
||||
}
|
||||
}
|
||||
|
||||
private renderVariant(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper, variant: GraphicsRenderVariant) {
|
||||
private renderVariant(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper, variant: GraphicsRenderVariant, pickType: number) {
|
||||
const depth = this.drawPass.depthTexturePrimitives;
|
||||
renderer.clear(false);
|
||||
|
||||
renderer.update(camera);
|
||||
renderer.renderPick(scene.primitives, camera, variant, null);
|
||||
renderer.renderPick(scene.volumes, camera, variant, depth);
|
||||
renderer.renderPick(helper.handle.scene, camera, variant, null);
|
||||
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) {
|
||||
helper.camera.update(camera);
|
||||
renderer.update(helper.camera.camera);
|
||||
renderer.renderPick(helper.camera.scene, helper.camera.camera, variant, null);
|
||||
renderer.renderPick(helper.camera.scene, helper.camera.camera, variant, null, pickType);
|
||||
}
|
||||
}
|
||||
|
||||
render(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper) {
|
||||
this.objectPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pickObject');
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Object);
|
||||
|
||||
this.instancePickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pickInstance');
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Instance);
|
||||
|
||||
this.groupPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pickGroup');
|
||||
this.renderVariant(renderer, camera, scene, helper, 'pick', PickType.Group);
|
||||
// printTexture(this.webgl, this.groupPickTarget.texture, { id: 'group' })
|
||||
|
||||
this.depthPickTarget.bind();
|
||||
this.renderVariant(renderer, camera, scene, helper, 'depth');
|
||||
this.renderVariant(renderer, camera, scene, helper, 'depth', PickType.None);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ function getSsaoRenderable(ctx: WebGLContext, depthTexture: Texture): SsaoRender
|
||||
tDepth: ValueCell.create(depthTexture),
|
||||
|
||||
uSamples: ValueCell.create([0.0, 0.0, 1.0]),
|
||||
dNSamples: ValueCell.create(1),
|
||||
dNSamples: ValueCell.create(32),
|
||||
|
||||
uProjection: ValueCell.create(Mat4.identity()),
|
||||
uInvProjection: ValueCell.create(Mat4.identity()),
|
||||
@@ -133,7 +133,7 @@ function getSsaoBlurRenderable(ctx: WebGLContext, ssaoDepthTexture: Texture, dir
|
||||
uTexSize: ValueCell.create(Vec2.create(ssaoDepthTexture.getWidth(), ssaoDepthTexture.getHeight())),
|
||||
|
||||
uKernel: ValueCell.create([0.0]),
|
||||
dOcclusionKernelSize: ValueCell.create(1),
|
||||
dOcclusionKernelSize: ValueCell.create(15),
|
||||
|
||||
uBlurDirectionX: ValueCell.create(direction === 'horizontal' ? 1 : 0),
|
||||
uBlurDirectionY: ValueCell.create(direction === 'vertical' ? 1 : 0),
|
||||
@@ -226,7 +226,7 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d
|
||||
|
||||
uMaxPossibleViewZDiff: ValueCell.create(0.5),
|
||||
|
||||
dOcclusionEnable: ValueCell.create(false),
|
||||
dOcclusionEnable: ValueCell.create(true),
|
||||
|
||||
dOutlineEnable: ValueCell.create(false),
|
||||
dOutlineScale: ValueCell.create(1),
|
||||
|
||||
@@ -201,7 +201,7 @@ function getWeightsRenderable(ctx: WebGLContext, edgesTexture: Texture): Weights
|
||||
uTexSizeInv: ValueCell.create(Vec2.create(1 / width, 1 / height)),
|
||||
uViewport: ValueCell.create(Vec4()),
|
||||
|
||||
dMaxSearchSteps: ValueCell.create(8),
|
||||
dMaxSearchSteps: ValueCell.create(16),
|
||||
};
|
||||
|
||||
// Note: loading image textures requires `HTMLImageElement` to be available
|
||||
|
||||
@@ -17,6 +17,7 @@ import { UniformColorTheme } from '../../mol-theme/color/uniform';
|
||||
import { UniformSizeTheme } from '../../mol-theme/size/uniform';
|
||||
import { smoothstep } from '../../mol-math/interpolate';
|
||||
import { Material } from '../../mol-util/material';
|
||||
import { Clip } from '../../mol-util/clip';
|
||||
|
||||
export const VisualQualityInfo = {
|
||||
'custom': {},
|
||||
@@ -81,6 +82,7 @@ export namespace BaseGeometry {
|
||||
alpha: PD.Numeric(1, { min: 0, max: 1, step: 0.01 }, { label: 'Opacity', isEssential: true, description: 'How opaque/transparent the representation is rendered.' }),
|
||||
quality: PD.Select<VisualQuality>('auto', VisualQualityOptions, { isEssential: true, description: 'Visual/rendering quality of the representation.' }),
|
||||
material: Material.getParam(),
|
||||
clip: PD.Group(Clip.Params),
|
||||
};
|
||||
export type Params = typeof Params
|
||||
|
||||
@@ -97,6 +99,7 @@ export namespace BaseGeometry {
|
||||
}
|
||||
|
||||
export function createValues(props: PD.Values<Params>, counts: Counts) {
|
||||
const clip = Clip.getClip(props.clip);
|
||||
return {
|
||||
alpha: ValueCell.create(props.alpha),
|
||||
uAlpha: ValueCell.create(props.alpha),
|
||||
@@ -107,6 +110,14 @@ export namespace BaseGeometry {
|
||||
uRoughness: ValueCell.create(props.material.roughness),
|
||||
uBumpiness: ValueCell.create(props.material.bumpiness),
|
||||
dLightCount: ValueCell.create(1),
|
||||
|
||||
dClipObjectCount: ValueCell.create(clip.objects.count),
|
||||
dClipVariant: ValueCell.create(clip.variant),
|
||||
uClipObjectType: ValueCell.create(clip.objects.type),
|
||||
uClipObjectInvert: ValueCell.create(clip.objects.invert),
|
||||
uClipObjectPosition: ValueCell.create(clip.objects.position),
|
||||
uClipObjectRotation: ValueCell.create(clip.objects.rotation),
|
||||
uClipObjectScale: ValueCell.create(clip.objects.scale),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -115,6 +126,15 @@ export namespace BaseGeometry {
|
||||
ValueCell.updateIfChanged(values.uMetalness, props.material.metalness);
|
||||
ValueCell.updateIfChanged(values.uRoughness, props.material.roughness);
|
||||
ValueCell.updateIfChanged(values.uBumpiness, props.material.bumpiness);
|
||||
|
||||
const clip = Clip.getClip(props.clip);
|
||||
ValueCell.update(values.dClipObjectCount, clip.objects.count);
|
||||
ValueCell.update(values.dClipVariant, clip.variant);
|
||||
ValueCell.update(values.uClipObjectType, clip.objects.type);
|
||||
ValueCell.update(values.uClipObjectInvert, clip.objects.invert);
|
||||
ValueCell.update(values.uClipObjectPosition, clip.objects.position);
|
||||
ValueCell.update(values.uClipObjectRotation, clip.objects.rotation);
|
||||
ValueCell.update(values.uClipObjectScale, clip.objects.scale);
|
||||
}
|
||||
|
||||
export function createRenderableState(props: Partial<PD.Values<Params>> = {}): RenderableState {
|
||||
@@ -127,7 +147,6 @@ export namespace BaseGeometry {
|
||||
colorOnly: false,
|
||||
opaque,
|
||||
writeDepth: opaque,
|
||||
noClip: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -10,18 +10,13 @@ import { TextureImage, createTextureImage } from '../../mol-gl/renderable/util';
|
||||
import { Clipping } from '../../mol-theme/clipping';
|
||||
|
||||
export type ClippingData = {
|
||||
dClipObjectCount: ValueCell<number>,
|
||||
dClipVariant: ValueCell<string>,
|
||||
|
||||
tClipping: ValueCell<TextureImage<Uint8Array>>
|
||||
uClippingTexDim: ValueCell<Vec2>
|
||||
dClipping: ValueCell<boolean>,
|
||||
}
|
||||
|
||||
export function applyClippingGroups(array: Uint8Array, start: number, end: number, groups: Clipping.Groups) {
|
||||
for (let i = start; i < end; ++i) {
|
||||
array[i] = groups;
|
||||
}
|
||||
array.fill(groups, start, end);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,9 +33,6 @@ export function createClipping(count: number, clippingData?: ClippingData): Clip
|
||||
return clippingData;
|
||||
} else {
|
||||
return {
|
||||
dClipObjectCount: ValueCell.create(0),
|
||||
dClipVariant: ValueCell.create('instance'),
|
||||
|
||||
tClipping: ValueCell.create(clipping),
|
||||
uClippingTexDim: ValueCell.create(Vec2.create(clipping.width, clipping.height)),
|
||||
dClipping: ValueCell.create(count > 0),
|
||||
@@ -53,12 +45,10 @@ export function createEmptyClipping(clippingData?: ClippingData): ClippingData {
|
||||
if (clippingData) {
|
||||
ValueCell.update(clippingData.tClipping, emptyClippingTexture);
|
||||
ValueCell.update(clippingData.uClippingTexDim, Vec2.create(1, 1));
|
||||
ValueCell.updateIfChanged(clippingData.dClipping, false);
|
||||
return clippingData;
|
||||
} else {
|
||||
return {
|
||||
dClipObjectCount: ValueCell.create(0),
|
||||
dClipVariant: ValueCell.create('instance'),
|
||||
|
||||
tClipping: ValueCell.create(emptyClippingTexture),
|
||||
uClippingTexDim: ValueCell.create(Vec2.create(1, 1)),
|
||||
dClipping: ValueCell.create(false),
|
||||
|
||||
@@ -236,7 +236,7 @@ export namespace Cylinders {
|
||||
|
||||
...BaseGeometry.createValues(props, counts),
|
||||
uSizeFactor: ValueCell.create(props.sizeFactor * props.sizeAspectRatio),
|
||||
dDoubleSided: ValueCell.create(props.doubleSided),
|
||||
uDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
@@ -253,7 +253,7 @@ export namespace Cylinders {
|
||||
function updateValues(values: CylindersValues, props: PD.Values<Params>) {
|
||||
BaseGeometry.updateValues(values, props);
|
||||
ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor * props.sizeAspectRatio);
|
||||
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
|
||||
@@ -307,7 +307,7 @@ export namespace DirectVolume {
|
||||
dPackedGroup: directVolume.packedGroup,
|
||||
dSingleLayer: ValueCell.create(singleLayer),
|
||||
|
||||
dDoubleSided: ValueCell.create(props.doubleSided),
|
||||
uDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dFlatShaded: ValueCell.create(props.flatShaded),
|
||||
dFlipSided: ValueCell.create(props.flipSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
@@ -323,7 +323,7 @@ export namespace DirectVolume {
|
||||
|
||||
function updateValues(values: DirectVolumeValues, props: PD.Values<Params>) {
|
||||
BaseGeometry.updateValues(values, props);
|
||||
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded);
|
||||
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
|
||||
@@ -240,7 +240,7 @@ export namespace Lines {
|
||||
...BaseGeometry.createValues(props, counts),
|
||||
uSizeFactor: ValueCell.create(props.sizeFactor),
|
||||
dLineSizeAttenuation: ValueCell.create(props.lineSizeAttenuation),
|
||||
dDoubleSided: ValueCell.create(true),
|
||||
uDoubleSided: ValueCell.create(true),
|
||||
dFlipSided: ValueCell.create(false),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ export type MarkerData = {
|
||||
uMarker: ValueCell<number>,
|
||||
tMarker: ValueCell<TextureImage<Uint8Array>>
|
||||
uMarkerTexDim: ValueCell<Vec2>
|
||||
dMarkerType: ValueCell<string>,
|
||||
markerAverage: ValueCell<number>
|
||||
markerStatus: ValueCell<number>
|
||||
}
|
||||
@@ -66,7 +65,6 @@ export function createMarkers(count: number, markerData?: MarkerData): MarkerDat
|
||||
ValueCell.updateIfChanged(markerData.uMarker, 0);
|
||||
ValueCell.update(markerData.tMarker, markers);
|
||||
ValueCell.update(markerData.uMarkerTexDim, Vec2.create(markers.width, markers.height));
|
||||
ValueCell.updateIfChanged(markerData.dMarkerType, status === -1 ? 'groupInstance' : 'uniform');
|
||||
ValueCell.updateIfChanged(markerData.markerAverage, average);
|
||||
ValueCell.updateIfChanged(markerData.markerStatus, status);
|
||||
return markerData;
|
||||
@@ -77,7 +75,6 @@ export function createMarkers(count: number, markerData?: MarkerData): MarkerDat
|
||||
uMarkerTexDim: ValueCell.create(Vec2.create(markers.width, markers.height)),
|
||||
markerAverage: ValueCell.create(average),
|
||||
markerStatus: ValueCell.create(status),
|
||||
dMarkerType: ValueCell.create('uniform'),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -88,7 +85,6 @@ export function createEmptyMarkers(markerData?: MarkerData): MarkerData {
|
||||
ValueCell.updateIfChanged(markerData.uMarker, 0);
|
||||
ValueCell.update(markerData.tMarker, emptyMarkerTexture);
|
||||
ValueCell.update(markerData.uMarkerTexDim, Vec2.create(1, 1));
|
||||
ValueCell.updateIfChanged(markerData.dMarkerType, 'uniform');
|
||||
ValueCell.updateIfChanged(markerData.markerAverage, 0);
|
||||
ValueCell.updateIfChanged(markerData.markerStatus, 0);
|
||||
return markerData;
|
||||
@@ -99,7 +95,6 @@ export function createEmptyMarkers(markerData?: MarkerData): MarkerData {
|
||||
uMarkerTexDim: ValueCell.create(Vec2.create(1, 1)),
|
||||
markerAverage: ValueCell.create(0),
|
||||
markerStatus: ValueCell.create(0),
|
||||
dMarkerType: ValueCell.create('uniform'),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -693,7 +693,7 @@ export namespace Mesh {
|
||||
...transform,
|
||||
|
||||
...BaseGeometry.createValues(props, counts),
|
||||
dDoubleSided: ValueCell.create(props.doubleSided),
|
||||
uDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dFlatShaded: ValueCell.create(props.flatShaded),
|
||||
dFlipSided: ValueCell.create(props.flipSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
@@ -713,7 +713,7 @@ export namespace Mesh {
|
||||
|
||||
function updateValues(values: MeshValues, props: PD.Values<Params>) {
|
||||
BaseGeometry.updateValues(values, props);
|
||||
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded);
|
||||
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
|
||||
@@ -203,7 +203,7 @@ export namespace Spheres {
|
||||
|
||||
...BaseGeometry.createValues(props, counts),
|
||||
uSizeFactor: ValueCell.create(props.sizeFactor),
|
||||
dDoubleSided: ValueCell.create(props.doubleSided),
|
||||
uDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
@@ -220,7 +220,7 @@ export namespace Spheres {
|
||||
function updateValues(values: SpheresValues, props: PD.Values<Params>) {
|
||||
BaseGeometry.updateValues(values, props);
|
||||
ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor);
|
||||
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
|
||||
@@ -165,7 +165,7 @@ export namespace TextureMesh {
|
||||
...transform,
|
||||
|
||||
...BaseGeometry.createValues(props, counts),
|
||||
dDoubleSided: ValueCell.create(props.doubleSided),
|
||||
uDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dFlatShaded: ValueCell.create(props.flatShaded),
|
||||
dFlipSided: ValueCell.create(props.flipSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
@@ -186,7 +186,7 @@ export namespace TextureMesh {
|
||||
|
||||
function updateValues(values: TextureMeshValues, props: PD.Values<Params>) {
|
||||
BaseGeometry.updateValues(values, props);
|
||||
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded);
|
||||
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
|
||||
@@ -53,17 +53,17 @@ describe('renderer', () => {
|
||||
scene.commit();
|
||||
expect(ctx.stats.resourceCounts.attribute).toBe(ctx.isWebGL2 ? 4 : 5);
|
||||
expect(ctx.stats.resourceCounts.texture).toBe(8);
|
||||
expect(ctx.stats.resourceCounts.vertexArray).toBe(ctx.extensions.vertexArrayObject ? 8 : 0);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(8);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(16);
|
||||
expect(ctx.stats.resourceCounts.vertexArray).toBe(ctx.extensions.vertexArrayObject ? 5 : 0);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(5);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(10);
|
||||
|
||||
scene.remove(points);
|
||||
scene.commit();
|
||||
expect(ctx.stats.resourceCounts.attribute).toBe(0);
|
||||
expect(ctx.stats.resourceCounts.texture).toBe(0);
|
||||
expect(ctx.stats.resourceCounts.vertexArray).toBe(0);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(8);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(16);
|
||||
expect(ctx.stats.resourceCounts.program).toBe(5);
|
||||
expect(ctx.stats.resourceCounts.shader).toBe(10);
|
||||
|
||||
ctx.resources.destroy();
|
||||
expect(ctx.stats.resourceCounts.program).toBe(0);
|
||||
|
||||
@@ -16,6 +16,7 @@ import { TextValues, TextRenderable } from './renderable/text';
|
||||
import { TextureMeshValues, TextureMeshRenderable } from './renderable/texture-mesh';
|
||||
import { ImageValues, ImageRenderable } from './renderable/image';
|
||||
import { CylindersRenderable, CylindersValues } from './renderable/cylinders';
|
||||
import { GraphicsRenderVariant } from './webgl/render-item';
|
||||
|
||||
const getNextId = idFactory(0, 0x7FFFFFFF);
|
||||
|
||||
@@ -48,17 +49,17 @@ export function createRenderObject<T extends RenderObjectType>(type: T, values:
|
||||
return { id: getNextId(), type, values, state, materialId } as GraphicsRenderObject<T>;
|
||||
}
|
||||
|
||||
export function createRenderable<T extends RenderObjectType>(ctx: WebGLContext, o: GraphicsRenderObject<T>): Renderable<any> {
|
||||
export function createRenderable<T extends RenderObjectType>(ctx: WebGLContext, o: GraphicsRenderObject<T>, variants: GraphicsRenderVariant[]): Renderable<any> {
|
||||
switch (o.type) {
|
||||
case 'mesh': return MeshRenderable(ctx, o.id, o.values as MeshValues, o.state, o.materialId);
|
||||
case 'points': return PointsRenderable(ctx, o.id, o.values as PointsValues, o.state, o.materialId);
|
||||
case 'spheres': return SpheresRenderable(ctx, o.id, o.values as SpheresValues, o.state, o.materialId);
|
||||
case 'cylinders': return CylindersRenderable(ctx, o.id, o.values as CylindersValues, o.state, o.materialId);
|
||||
case 'text': return TextRenderable(ctx, o.id, o.values as TextValues, o.state, o.materialId);
|
||||
case 'lines': return LinesRenderable(ctx, o.id, o.values as LinesValues, o.state, o.materialId);
|
||||
case 'direct-volume': return DirectVolumeRenderable(ctx, o.id, o.values as DirectVolumeValues, o.state, o.materialId);
|
||||
case 'image': return ImageRenderable(ctx, o.id, o.values as ImageValues, o.state, o.materialId);
|
||||
case 'texture-mesh': return TextureMeshRenderable(ctx, o.id, o.values as TextureMeshValues, o.state, o.materialId);
|
||||
case 'mesh': return MeshRenderable(ctx, o.id, o.values as MeshValues, o.state, o.materialId, variants);
|
||||
case 'points': return PointsRenderable(ctx, o.id, o.values as PointsValues, o.state, o.materialId, variants);
|
||||
case 'spheres': return SpheresRenderable(ctx, o.id, o.values as SpheresValues, o.state, o.materialId, variants);
|
||||
case 'cylinders': return CylindersRenderable(ctx, o.id, o.values as CylindersValues, o.state, o.materialId, variants);
|
||||
case 'text': return TextRenderable(ctx, o.id, o.values as TextValues, o.state, o.materialId, variants);
|
||||
case 'lines': return LinesRenderable(ctx, o.id, o.values as LinesValues, o.state, o.materialId, variants);
|
||||
case 'direct-volume': return DirectVolumeRenderable(ctx, o.id, o.values as DirectVolumeValues, o.state, o.materialId, variants);
|
||||
case 'image': return ImageRenderable(ctx, o.id, o.values as ImageValues, o.state, o.materialId, variants);
|
||||
case 'texture-mesh': return TextureMeshRenderable(ctx, o.id, o.values as TextureMeshValues, o.state, o.materialId, variants);
|
||||
}
|
||||
throw new Error('unsupported type');
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ export type RenderableState = {
|
||||
colorOnly: boolean
|
||||
opaque: boolean
|
||||
writeDepth: boolean
|
||||
noClip: boolean
|
||||
}
|
||||
|
||||
export interface Renderable<T extends RenderableValues> {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec, GlobalTextureSchema, UniformSpec } from './schema';
|
||||
import { CylindersShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -23,7 +23,7 @@ export const CylindersSchema = {
|
||||
elements: ElementsSpec('uint32'),
|
||||
|
||||
padding: ValueSpec('number'),
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
@@ -32,12 +32,12 @@ export const CylindersSchema = {
|
||||
export type CylindersSchema = typeof CylindersSchema
|
||||
export type CylindersValues = Values<CylindersSchema>
|
||||
|
||||
export function CylindersRenderable(ctx: WebGLContext, id: number, values: CylindersValues, state: RenderableState, materialId: number): Renderable<CylindersValues> {
|
||||
export function CylindersRenderable(ctx: WebGLContext, id: number, values: CylindersValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<CylindersValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...CylindersSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = CylindersShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { AttributeSpec, Values, UniformSpec, GlobalUniformSchema, InternalSchema, TextureSpec, ElementsSpec, DefineSpec, InternalValues, GlobalTextureSchema, BaseSchema } from './schema';
|
||||
import { DirectVolumeShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -46,7 +46,7 @@ export const DirectVolumeSchema = {
|
||||
uUnitToCartn: UniformSpec('m4'),
|
||||
dPackedGroup: DefineSpec('boolean'),
|
||||
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
dFlatShaded: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
@@ -55,7 +55,7 @@ export const DirectVolumeSchema = {
|
||||
export type DirectVolumeSchema = typeof DirectVolumeSchema
|
||||
export type DirectVolumeValues = Values<DirectVolumeSchema>
|
||||
|
||||
export function DirectVolumeRenderable(ctx: WebGLContext, id: number, values: DirectVolumeValues, state: RenderableState, materialId: number): Renderable<DirectVolumeValues> {
|
||||
export function DirectVolumeRenderable(ctx: WebGLContext, id: number, values: DirectVolumeValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<DirectVolumeValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...DirectVolumeSchema };
|
||||
if (!ctx.isWebGL2) {
|
||||
// workaround for webgl1 limitation that loop counters need to be `const`
|
||||
@@ -65,6 +65,6 @@ export function DirectVolumeRenderable(ctx: WebGLContext, id: number, values: Di
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = DirectVolumeShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { AttributeSpec, Values, GlobalUniformSchema, InternalSchema, TextureSpec, ElementsSpec, DefineSpec, InternalValues, BaseSchema, UniformSpec, GlobalTextureSchema } from './schema';
|
||||
import { ImageShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -29,12 +29,12 @@ export const ImageSchema = {
|
||||
export type ImageSchema = typeof ImageSchema
|
||||
export type ImageValues = Values<ImageSchema>
|
||||
|
||||
export function ImageRenderable(ctx: WebGLContext, id: number, values: ImageValues, state: RenderableState, materialId: number): Renderable<ImageValues> {
|
||||
export function ImageRenderable(ctx: WebGLContext, id: number, values: ImageValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<ImageValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...ImageSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = ImageShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec, InternalValues, GlobalTextureSchema } from './schema';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec, InternalValues, GlobalTextureSchema, UniformSpec } from './schema';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
import { LinesShaderCode } from '../shader-code';
|
||||
|
||||
@@ -20,19 +20,19 @@ export const LinesSchema = {
|
||||
aEnd: AttributeSpec('float32', 3, 0),
|
||||
elements: ElementsSpec('uint32'),
|
||||
dLineSizeAttenuation: DefineSpec('boolean'),
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
};
|
||||
export type LinesSchema = typeof LinesSchema
|
||||
export type LinesValues = Values<LinesSchema>
|
||||
|
||||
export function LinesRenderable(ctx: WebGLContext, id: number, values: LinesValues, state: RenderableState, materialId: number): Renderable<LinesValues> {
|
||||
export function LinesRenderable(ctx: WebGLContext, id: number, values: LinesValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<LinesValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...LinesSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = LinesShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, ElementsSpec, DefineSpec, Values, InternalSchema, InternalValues, GlobalTextureSchema, ValueSpec, UniformSpec } from './schema';
|
||||
import { MeshShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -18,7 +18,7 @@ export const MeshSchema = {
|
||||
aNormal: AttributeSpec('float32', 3, 0),
|
||||
elements: ElementsSpec('uint32'),
|
||||
dFlatShaded: DefineSpec('boolean'),
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
@@ -29,13 +29,13 @@ export const MeshSchema = {
|
||||
export type MeshSchema = typeof MeshSchema
|
||||
export type MeshValues = Values<MeshSchema>
|
||||
|
||||
export function MeshRenderable(ctx: WebGLContext, id: number, values: MeshValues, state: RenderableState, materialId: number): Renderable<MeshValues> {
|
||||
export function MeshRenderable(ctx: WebGLContext, id: number, values: MeshValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<MeshValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...MeshSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = MeshShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, InternalValues, GlobalTextureSchema } from './schema';
|
||||
import { PointsShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -22,12 +22,12 @@ export const PointsSchema = {
|
||||
export type PointsSchema = typeof PointsSchema
|
||||
export type PointsValues = Values<PointsSchema>
|
||||
|
||||
export function PointsRenderable(ctx: WebGLContext, id: number, values: PointsValues, state: RenderableState, materialId: number): Renderable<PointsValues> {
|
||||
export function PointsRenderable(ctx: WebGLContext, id: number, values: PointsValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<PointsValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...PointsSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = PointsShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'points', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'points', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -135,12 +135,6 @@ export const GlobalUniformSchema = {
|
||||
|
||||
uTransparentBackground: UniformSpec('b'),
|
||||
|
||||
uClipObjectType: UniformSpec('i[]'),
|
||||
uClipObjectInvert: UniformSpec('b[]'),
|
||||
uClipObjectPosition: UniformSpec('v3[]'),
|
||||
uClipObjectRotation: UniformSpec('v4[]'),
|
||||
uClipObjectScale: UniformSpec('v3[]'),
|
||||
|
||||
uLightDirection: UniformSpec('v3[]'),
|
||||
uLightColor: UniformSpec('v3[]'),
|
||||
uAmbientColor: UniformSpec('v3'),
|
||||
@@ -161,6 +155,8 @@ export const GlobalUniformSchema = {
|
||||
|
||||
uRenderWboit: UniformSpec('b'),
|
||||
uMarkingDepthTest: UniformSpec('b'),
|
||||
uMarkingType: UniformSpec('i'),
|
||||
uPickType: UniformSpec('i'),
|
||||
} as const;
|
||||
export type GlobalUniformSchema = typeof GlobalUniformSchema
|
||||
export type GlobalUniformValues = Values<GlobalUniformSchema>
|
||||
@@ -207,7 +203,6 @@ export const MarkerSchema = {
|
||||
uMarker: UniformSpec('f'),
|
||||
uMarkerTexDim: UniformSpec('v2'),
|
||||
tMarker: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
|
||||
dMarkerType: DefineSpec('string', ['uniform', 'groupInstance']),
|
||||
markerAverage: ValueSpec('number'),
|
||||
markerStatus: ValueSpec('number'),
|
||||
} as const;
|
||||
@@ -255,9 +250,6 @@ export type SubstanceSchema = typeof SubstanceSchema
|
||||
export type SubstanceValues = Values<SubstanceSchema>
|
||||
|
||||
export const ClippingSchema = {
|
||||
dClipObjectCount: DefineSpec('number'),
|
||||
dClipVariant: DefineSpec('string', ['instance', 'pixel']),
|
||||
|
||||
uClippingTexDim: UniformSpec('v2'),
|
||||
tClipping: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
|
||||
dClipping: DefineSpec('boolean'),
|
||||
@@ -275,6 +267,14 @@ export const BaseSchema = {
|
||||
|
||||
dLightCount: DefineSpec('number'),
|
||||
|
||||
dClipObjectCount: DefineSpec('number'),
|
||||
dClipVariant: DefineSpec('string', ['instance', 'pixel']),
|
||||
uClipObjectType: UniformSpec('i[]'),
|
||||
uClipObjectInvert: UniformSpec('b[]'),
|
||||
uClipObjectPosition: UniformSpec('v3[]'),
|
||||
uClipObjectRotation: UniformSpec('v4[]'),
|
||||
uClipObjectScale: UniformSpec('v3[]'),
|
||||
|
||||
aInstance: AttributeSpec('float32', 1, 1),
|
||||
/**
|
||||
* final per-instance transform calculated for instance `i` as
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec, GlobalTextureSchema, UniformSpec } from './schema';
|
||||
import { SpheresShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -20,7 +20,7 @@ export const SpheresSchema = {
|
||||
elements: ElementsSpec('uint32'),
|
||||
|
||||
padding: ValueSpec('number'),
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
@@ -29,12 +29,12 @@ export const SpheresSchema = {
|
||||
export type SpheresSchema = typeof SpheresSchema
|
||||
export type SpheresValues = Values<SpheresSchema>
|
||||
|
||||
export function SpheresRenderable(ctx: WebGLContext, id: number, values: SpheresValues, state: RenderableState, materialId: number): Renderable<SpheresValues> {
|
||||
export function SpheresRenderable(ctx: WebGLContext, id: number, values: SpheresValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<SpheresValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...SpheresSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = SpheresShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, Values, InternalSchema, SizeSchema, InternalValues, TextureSpec, ElementsSpec, ValueSpec, GlobalTextureSchema } from './schema';
|
||||
import { TextShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -35,12 +35,12 @@ export const TextSchema = {
|
||||
export type TextSchema = typeof TextSchema
|
||||
export type TextValues = Values<TextSchema>
|
||||
|
||||
export function TextRenderable(ctx: WebGLContext, id: number, values: TextValues, state: RenderableState, materialId: number): Renderable<TextValues> {
|
||||
export function TextRenderable(ctx: WebGLContext, id: number, values: TextValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<TextValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...TextSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = TextShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { createGraphicsRenderItem, GraphicsRenderVariant } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, DefineSpec, Values, InternalSchema, InternalValues, UniformSpec, TextureSpec, GlobalTextureSchema, ValueSpec } from './schema';
|
||||
import { MeshShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
@@ -19,7 +19,7 @@ export const TextureMeshSchema = {
|
||||
tNormal: TextureSpec('texture', 'rgb', 'float', 'nearest'),
|
||||
|
||||
dFlatShaded: DefineSpec('boolean'),
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
uDoubleSided: UniformSpec('b'),
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
@@ -31,13 +31,13 @@ export const TextureMeshSchema = {
|
||||
export type TextureMeshSchema = typeof TextureMeshSchema
|
||||
export type TextureMeshValues = Values<TextureMeshSchema>
|
||||
|
||||
export function TextureMeshRenderable(ctx: WebGLContext, id: number, values: TextureMeshValues, state: RenderableState, materialId: number): Renderable<TextureMeshValues> {
|
||||
export function TextureMeshRenderable(ctx: WebGLContext, id: number, values: TextureMeshValues, state: RenderableState, materialId: number, variants: GraphicsRenderVariant[]): Renderable<TextureMeshValues> {
|
||||
const schema = { ...GlobalUniformSchema, ...GlobalTextureSchema, ...InternalSchema, ...TextureMeshSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
};
|
||||
const shaderCode = MeshShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId, variants);
|
||||
|
||||
return createRenderable(renderItem, values, state);
|
||||
}
|
||||
@@ -8,15 +8,13 @@ import { Viewport } from '../mol-canvas3d/camera/util';
|
||||
import { ICamera } from '../mol-canvas3d/camera';
|
||||
import { Scene } from './scene';
|
||||
import { WebGLContext } from './webgl/context';
|
||||
import { Mat4, Vec3, Vec4, Vec2, Quat } from '../mol-math/linear-algebra';
|
||||
import { Mat4, Vec3, Vec4, Vec2 } from '../mol-math/linear-algebra';
|
||||
import { GraphicsRenderable } from './renderable';
|
||||
import { Color } from '../mol-util/color';
|
||||
import { ValueCell, deepEqual } from '../mol-util';
|
||||
import { GlobalUniformValues } from './renderable/schema';
|
||||
import { GraphicsRenderVariant } from './webgl/render-item';
|
||||
import { ParamDefinition as PD } from '../mol-util/param-definition';
|
||||
import { Clipping } from '../mol-theme/clipping';
|
||||
import { stringToWords } from '../mol-util/string';
|
||||
import { degToRad } from '../mol-math/misc';
|
||||
import { createNullTexture, Texture, Textures } from './webgl/texture';
|
||||
import { arrayMapUpsert } from '../mol-util/array';
|
||||
@@ -38,6 +36,19 @@ export interface RendererStats {
|
||||
instancedDrawCount: number
|
||||
}
|
||||
|
||||
export const enum PickType {
|
||||
None = 0,
|
||||
Object = 1,
|
||||
Instance = 2,
|
||||
Group = 3,
|
||||
}
|
||||
|
||||
export const enum MarkingType {
|
||||
None = 0,
|
||||
Depth = 1,
|
||||
Mask = 2,
|
||||
}
|
||||
|
||||
interface Renderer {
|
||||
readonly stats: RendererStats
|
||||
readonly props: Readonly<RendererProps>
|
||||
@@ -46,7 +57,7 @@ interface Renderer {
|
||||
clearDepth: () => void
|
||||
update: (camera: ICamera) => void
|
||||
|
||||
renderPick: (group: Scene.Group, camera: ICamera, variant: GraphicsRenderVariant, depthTexture: Texture | null) => void
|
||||
renderPick: (group: Scene.Group, camera: ICamera, variant: GraphicsRenderVariant, depthTexture: Texture | null, pickType: PickType) => void
|
||||
renderDepth: (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
|
||||
@@ -97,20 +108,6 @@ export const RendererParams = {
|
||||
}] }),
|
||||
ambientColor: PD.Color(Color.fromNormalizedRgb(1.0, 1.0, 1.0)),
|
||||
ambientIntensity: PD.Numeric(0.4, { min: 0.0, max: 1.0, step: 0.01 }),
|
||||
|
||||
clip: PD.Group({
|
||||
variant: PD.Select('instance', PD.arrayToOptions<Clipping.Variant>(['instance', 'pixel'])),
|
||||
objects: PD.ObjectList({
|
||||
type: PD.Select('plane', PD.objectToOptions(Clipping.Type, t => stringToWords(t))),
|
||||
invert: PD.Boolean(false),
|
||||
position: PD.Vec3(Vec3()),
|
||||
rotation: PD.Group({
|
||||
axis: PD.Vec3(Vec3.create(1, 0, 0)),
|
||||
angle: PD.Numeric(0, { min: -180, max: 180, step: 1 }, { description: 'Angle in Degrees' }),
|
||||
}, { isExpanded: true }),
|
||||
scale: PD.Vec3(Vec3.create(1, 1, 1)),
|
||||
}, o => stringToWords(o.type))
|
||||
})
|
||||
};
|
||||
export type RendererProps = PD.Values<typeof RendererParams>
|
||||
|
||||
@@ -137,47 +134,11 @@ function getLight(props: RendererProps['light'], light?: Light): Light {
|
||||
return { count: props.length, direction, color };
|
||||
}
|
||||
|
||||
type Clip = {
|
||||
variant: Clipping.Variant
|
||||
objects: {
|
||||
count: number
|
||||
type: number[]
|
||||
invert: boolean[]
|
||||
position: number[]
|
||||
rotation: number[]
|
||||
scale: number[]
|
||||
}
|
||||
}
|
||||
|
||||
const tmpQuat = Quat();
|
||||
function getClip(props: RendererProps['clip'], clip?: Clip): Clip {
|
||||
const { type, invert, position, rotation, scale } = clip?.objects || {
|
||||
type: (new Array(5)).fill(1),
|
||||
invert: (new Array(5)).fill(false),
|
||||
position: (new Array(5 * 3)).fill(0),
|
||||
rotation: (new Array(5 * 4)).fill(0),
|
||||
scale: (new Array(5 * 3)).fill(1),
|
||||
};
|
||||
for (let i = 0, il = props.objects.length; i < il; ++i) {
|
||||
const p = props.objects[i];
|
||||
type[i] = Clipping.Type[p.type];
|
||||
invert[i] = p.invert;
|
||||
Vec3.toArray(p.position, position, i * 3);
|
||||
Quat.toArray(Quat.setAxisAngle(tmpQuat, p.rotation.axis, degToRad(p.rotation.angle)), rotation, i * 4);
|
||||
Vec3.toArray(p.scale, scale, i * 3);
|
||||
}
|
||||
return {
|
||||
variant: props.variant,
|
||||
objects: { count: props.objects.length, type, invert, position, rotation, scale }
|
||||
};
|
||||
}
|
||||
|
||||
namespace Renderer {
|
||||
export function create(ctx: WebGLContext, props: Partial<RendererProps> = {}): Renderer {
|
||||
const { gl, state, stats, extensions: { fragDepth } } = ctx;
|
||||
const p = PD.merge(RendererParams, PD.getDefaultValues(RendererParams), props);
|
||||
const light = getLight(p.light);
|
||||
const clip = getClip(p.clip);
|
||||
|
||||
const viewport = Viewport();
|
||||
const drawingBufferSize = Vec2.create(gl.drawingBufferWidth, gl.drawingBufferHeight);
|
||||
@@ -232,15 +193,11 @@ namespace Renderer {
|
||||
|
||||
uRenderWboit: ValueCell.create(false),
|
||||
uMarkingDepthTest: ValueCell.create(false),
|
||||
uPickType: ValueCell.create(PickType.None),
|
||||
uMarkingType: ValueCell.create(MarkingType.None),
|
||||
|
||||
uTransparentBackground: ValueCell.create(false),
|
||||
|
||||
uClipObjectType: ValueCell.create(clip.objects.type),
|
||||
uClipObjectInvert: ValueCell.create(clip.objects.invert),
|
||||
uClipObjectPosition: ValueCell.create(clip.objects.position),
|
||||
uClipObjectRotation: ValueCell.create(clip.objects.rotation),
|
||||
uClipObjectScale: ValueCell.create(clip.objects.scale),
|
||||
|
||||
uLightDirection: ValueCell.create(light.direction),
|
||||
uLightColor: ValueCell.create(light.color),
|
||||
uAmbientColor: ValueCell.create(ambientColor),
|
||||
@@ -264,26 +221,11 @@ namespace Renderer {
|
||||
let globalUniformsNeedUpdate = true;
|
||||
|
||||
const renderObject = (r: GraphicsRenderable, variant: GraphicsRenderVariant) => {
|
||||
if (r.state.disposed || !r.state.visible || (!r.state.pickable && variant[0] === 'p')) {
|
||||
if (r.state.disposed || !r.state.visible || (!r.state.pickable && variant === 'pick')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let definesNeedUpdate = false;
|
||||
if (r.state.noClip) {
|
||||
if (r.values.dClipObjectCount.ref.value !== 0) {
|
||||
ValueCell.update(r.values.dClipObjectCount, 0);
|
||||
definesNeedUpdate = true;
|
||||
}
|
||||
} else {
|
||||
if (r.values.dClipObjectCount.ref.value !== clip.objects.count) {
|
||||
ValueCell.update(r.values.dClipObjectCount, clip.objects.count);
|
||||
definesNeedUpdate = true;
|
||||
}
|
||||
if (r.values.dClipVariant.ref.value !== clip.variant) {
|
||||
ValueCell.update(r.values.dClipVariant, clip.variant);
|
||||
definesNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
if (r.values.dLightCount.ref.value !== light.count) {
|
||||
ValueCell.update(r.values.dLightCount, light.count);
|
||||
definesNeedUpdate = true;
|
||||
@@ -304,7 +246,7 @@ namespace Renderer {
|
||||
}
|
||||
|
||||
if (r.values.dRenderMode) { // indicates direct-volume
|
||||
if ((variant[0] === 'p' || variant === 'depth') && r.values.dRenderMode.ref.value === 'volume') {
|
||||
if ((variant === 'pick' || variant === 'depth') && r.values.dRenderMode.ref.value === 'volume') {
|
||||
return; // no picking/depth in volume mode
|
||||
}
|
||||
|
||||
@@ -324,8 +266,8 @@ namespace Renderer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (r.values.dDoubleSided) {
|
||||
if (r.values.dDoubleSided.ref.value || r.values.hasReflection.ref.value) {
|
||||
if (r.values.uDoubleSided) {
|
||||
if (r.values.uDoubleSided.ref.value || r.values.hasReflection.ref.value) {
|
||||
state.disable(gl.CULL_FACE);
|
||||
} else {
|
||||
state.enable(gl.CULL_FACE);
|
||||
@@ -395,12 +337,13 @@ namespace Renderer {
|
||||
state.currentRenderItemId = -1;
|
||||
};
|
||||
|
||||
const renderPick = (group: Scene.Group, camera: ICamera, variant: GraphicsRenderVariant, depthTexture: Texture | null) => {
|
||||
const renderPick = (group: Scene.Group, camera: ICamera, variant: GraphicsRenderVariant, depthTexture: Texture | null, pickType: PickType) => {
|
||||
state.disable(gl.BLEND);
|
||||
state.enable(gl.DEPTH_TEST);
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
ValueCell.updateIfChanged(globalUniforms.uPickType, pickType);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
@@ -429,13 +372,14 @@ namespace Renderer {
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, false);
|
||||
ValueCell.updateIfChanged(globalUniforms.uMarkingType, MarkingType.Depth);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
|
||||
if (r.values.markerAverage.ref.value !== 1) {
|
||||
renderObject(renderables[i], 'markingDepth');
|
||||
renderObject(renderables[i], 'marking');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -446,13 +390,14 @@ namespace Renderer {
|
||||
state.depthMask(true);
|
||||
|
||||
updateInternal(group, camera, depthTexture, false, !!depthTexture);
|
||||
ValueCell.updateIfChanged(globalUniforms.uMarkingType, MarkingType.Mask);
|
||||
|
||||
const { renderables } = group;
|
||||
for (let i = 0, il = renderables.length; i < il; ++i) {
|
||||
const r = renderables[i];
|
||||
|
||||
if (r.values.markerAverage.ref.value > 0) {
|
||||
renderObject(renderables[i], 'markingMask');
|
||||
renderObject(renderables[i], 'marking');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -686,15 +631,6 @@ namespace Renderer {
|
||||
Vec3.scale(ambientColor, Color.toArrayNormalized(p.ambientColor, ambientColor, 0), p.ambientIntensity);
|
||||
ValueCell.update(globalUniforms.uAmbientColor, ambientColor);
|
||||
}
|
||||
|
||||
if (props.clip !== undefined && !deepEqual(props.clip, p.clip)) {
|
||||
p.clip = props.clip;
|
||||
Object.assign(clip, getClip(props.clip, clip));
|
||||
ValueCell.update(globalUniforms.uClipObjectPosition, clip.objects.position);
|
||||
ValueCell.update(globalUniforms.uClipObjectRotation, clip.objects.rotation);
|
||||
ValueCell.update(globalUniforms.uClipObjectScale, clip.objects.scale);
|
||||
ValueCell.update(globalUniforms.uClipObjectType, clip.objects.type);
|
||||
}
|
||||
},
|
||||
setViewport: (x: number, y: number, width: number, height: number) => {
|
||||
gl.viewport(x, y, width, height);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
@@ -15,6 +15,7 @@ import { arraySetRemove } from '../mol-util/array';
|
||||
import { BoundaryHelper } from '../mol-math/geometry/boundary-helper';
|
||||
import { hash1 } from '../mol-data/util';
|
||||
import { GraphicsRenderable } from './renderable';
|
||||
import { GraphicsRenderVariants } from './webgl/render-item';
|
||||
|
||||
const boundaryHelper = new BoundaryHelper('98');
|
||||
|
||||
@@ -43,8 +44,8 @@ function calculateBoundingSphere(renderables: GraphicsRenderable[], boundingSphe
|
||||
}
|
||||
|
||||
function renderableSort(a: GraphicsRenderable, b: GraphicsRenderable) {
|
||||
const drawProgramIdA = a.getProgram('colorBlended').id;
|
||||
const drawProgramIdB = b.getProgram('colorBlended').id;
|
||||
const drawProgramIdA = (a.getProgram('colorBlended') || a.getProgram('colorWboit')).id;
|
||||
const drawProgramIdB = (b.getProgram('colorBlended') || a.getProgram('colorWboit')).id;
|
||||
const materialIdA = a.materialId;
|
||||
const materialIdB = b.materialId;
|
||||
|
||||
@@ -85,7 +86,7 @@ namespace Scene {
|
||||
readonly renderables: ReadonlyArray<GraphicsRenderable>
|
||||
}
|
||||
|
||||
export function create(ctx: WebGLContext): Scene {
|
||||
export function create(ctx: WebGLContext, variants = GraphicsRenderVariants): Scene {
|
||||
const renderableMap = new Map<GraphicsRenderObject, GraphicsRenderable>();
|
||||
const renderables: GraphicsRenderable[] = [];
|
||||
const boundingSphere = Sphere3D();
|
||||
@@ -102,7 +103,7 @@ namespace Scene {
|
||||
|
||||
function add(o: GraphicsRenderObject) {
|
||||
if (!renderableMap.has(o)) {
|
||||
const renderable = createRenderable(ctx, o);
|
||||
const renderable = createRenderable(ctx, o, variants);
|
||||
renderables.push(renderable);
|
||||
if (o.type === 'direct-volume') {
|
||||
volumes.push(renderable);
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface ShaderExtensions {
|
||||
}
|
||||
|
||||
type FragOutTypes = { [k in number]: 'vec4' | 'ivec4' }
|
||||
type IgnoreDefine = (name: string, variant: string, defines: ShaderDefines) => boolean
|
||||
|
||||
export interface ShaderCode {
|
||||
readonly id: number
|
||||
@@ -32,6 +33,7 @@ export interface ShaderCode {
|
||||
readonly extensions: ShaderExtensions
|
||||
/** Fragment shader output type only applicable for webgl2 */
|
||||
readonly outTypes: FragOutTypes
|
||||
readonly ignoreDefine?: IgnoreDefine
|
||||
}
|
||||
|
||||
import { apply_fog } from './shader/chunks/apply-fog.glsl';
|
||||
@@ -143,35 +145,56 @@ function preprocess(str: string, defines: ShaderDefines) {
|
||||
return unrollLoops(replaceCounts(str, defines));
|
||||
}
|
||||
|
||||
export function ShaderCode(name: string, vert: string, frag: string, extensions: ShaderExtensions = {}, outTypes: FragOutTypes = {}): ShaderCode {
|
||||
return { id: shaderCodeId(), name, vert: addIncludes(vert), frag: addIncludes(frag), extensions, outTypes };
|
||||
export function ShaderCode(name: string, vert: string, frag: string, extensions: ShaderExtensions = {}, outTypes: FragOutTypes = {}, ignoreDefine?: IgnoreDefine): ShaderCode {
|
||||
return { id: shaderCodeId(), name, vert: addIncludes(vert), frag: addIncludes(frag), extensions, outTypes, ignoreDefine };
|
||||
}
|
||||
|
||||
// Note: `drawBuffers` need to be 'optional' for wboit
|
||||
|
||||
function ignoreDefine(name: string, variant: string, defines: ShaderDefines): boolean {
|
||||
if (variant.startsWith('color')) {
|
||||
if (name === 'dLightCount') {
|
||||
return !!defines.dIgnoreLight?.ref.value;
|
||||
}
|
||||
} else {
|
||||
return [
|
||||
'dColorType', 'dUsePalette',
|
||||
'dLightCount',
|
||||
'dOverpaintType', 'dOverpaint',
|
||||
'dSubstanceType', 'dSubstance',
|
||||
].includes(name);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
function ignoreDefineUnlit(name: string, variant: string, defines: ShaderDefines): boolean {
|
||||
if (name === 'dLightCount') return true;
|
||||
return ignoreDefine(name, variant, defines);
|
||||
};
|
||||
|
||||
import { points_vert } from './shader/points.vert';
|
||||
import { points_frag } from './shader/points.frag';
|
||||
export const PointsShaderCode = ShaderCode('points', points_vert, points_frag, { drawBuffers: 'optional' });
|
||||
export const PointsShaderCode = ShaderCode('points', points_vert, points_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit);
|
||||
|
||||
import { spheres_vert } from './shader/spheres.vert';
|
||||
import { spheres_frag } from './shader/spheres.frag';
|
||||
export const SpheresShaderCode = ShaderCode('spheres', spheres_vert, spheres_frag, { fragDepth: 'required', drawBuffers: 'optional' });
|
||||
export const SpheresShaderCode = ShaderCode('spheres', spheres_vert, spheres_frag, { fragDepth: 'required', drawBuffers: 'optional' }, {}, ignoreDefine);
|
||||
|
||||
import { cylinders_vert } from './shader/cylinders.vert';
|
||||
import { cylinders_frag } from './shader/cylinders.frag';
|
||||
export const CylindersShaderCode = ShaderCode('cylinders', cylinders_vert, cylinders_frag, { fragDepth: 'required', drawBuffers: 'optional' });
|
||||
export const CylindersShaderCode = ShaderCode('cylinders', cylinders_vert, cylinders_frag, { fragDepth: 'required', drawBuffers: 'optional' }, {}, ignoreDefine);
|
||||
|
||||
import { text_vert } from './shader/text.vert';
|
||||
import { text_frag } from './shader/text.frag';
|
||||
export const TextShaderCode = ShaderCode('text', text_vert, text_frag, { drawBuffers: 'optional' });
|
||||
export const TextShaderCode = ShaderCode('text', text_vert, text_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit);
|
||||
|
||||
import { lines_vert } from './shader/lines.vert';
|
||||
import { lines_frag } from './shader/lines.frag';
|
||||
export const LinesShaderCode = ShaderCode('lines', lines_vert, lines_frag, { drawBuffers: 'optional' });
|
||||
export const LinesShaderCode = ShaderCode('lines', lines_vert, lines_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit);
|
||||
|
||||
import { mesh_vert } from './shader/mesh.vert';
|
||||
import { mesh_frag } from './shader/mesh.frag';
|
||||
export const MeshShaderCode = ShaderCode('mesh', mesh_vert, mesh_frag, { drawBuffers: 'optional' });
|
||||
export const MeshShaderCode = ShaderCode('mesh', mesh_vert, mesh_frag, { drawBuffers: 'optional' }, {}, ignoreDefine);
|
||||
|
||||
import { directVolume_vert } from './shader/direct-volume.vert';
|
||||
import { directVolume_frag } from './shader/direct-volume.frag';
|
||||
@@ -179,7 +202,7 @@ export const DirectVolumeShaderCode = ShaderCode('direct-volume', directVolume_v
|
||||
|
||||
import { image_vert } from './shader/image.vert';
|
||||
import { image_frag } from './shader/image.frag';
|
||||
export const ImageShaderCode = ShaderCode('image', image_vert, image_frag, { drawBuffers: 'optional' });
|
||||
export const ImageShaderCode = ShaderCode('image', image_vert, image_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit);
|
||||
|
||||
//
|
||||
|
||||
@@ -187,10 +210,14 @@ export type ShaderDefines = {
|
||||
[k: string]: ValueCell<DefineType>
|
||||
}
|
||||
|
||||
function getDefinesCode(defines: ShaderDefines) {
|
||||
function getDefinesCode(defines: ShaderDefines, ignore?: IgnoreDefine) {
|
||||
if (defines === undefined) return '';
|
||||
const variant = (defines.dRenderVariant?.ref.value || '') as string;
|
||||
|
||||
const lines = [];
|
||||
for (const name in defines) {
|
||||
if (ignore?.(name, variant, defines)) continue;
|
||||
|
||||
const define = defines[name];
|
||||
const v = define.ref.value;
|
||||
if (v !== undefined) {
|
||||
@@ -288,7 +315,8 @@ function transformGlsl300Frag(frag: string) {
|
||||
}
|
||||
|
||||
export function addShaderDefines(gl: GLRenderingContext, extensions: WebGLExtensions, defines: ShaderDefines, shaders: ShaderCode): ShaderCode {
|
||||
const header = getDefinesCode(defines);
|
||||
const vertHeader = getDefinesCode(defines, shaders.ignoreDefine);
|
||||
const fragHeader = getDefinesCode(defines, shaders.ignoreDefine);
|
||||
const vertPrefix = isWebGL2(gl) ? glsl300VertPrefix : '';
|
||||
const fragPrefix = isWebGL2(gl)
|
||||
? getGlsl300FragPrefix(gl, extensions, shaders.extensions, shaders.outTypes)
|
||||
@@ -297,8 +325,8 @@ export function addShaderDefines(gl: GLRenderingContext, extensions: WebGLExtens
|
||||
return {
|
||||
id: shaderCodeId(),
|
||||
name: shaders.name,
|
||||
vert: `${vertPrefix}${header}${preprocess(shaders.vert, defines)}`,
|
||||
frag: `${fragPrefix}${header}${preprocess(frag, defines)}`,
|
||||
vert: `${vertPrefix}${vertHeader}${preprocess(shaders.vert, defines)}`,
|
||||
frag: `${fragPrefix}${fragHeader}${preprocess(frag, defines)}`,
|
||||
extensions: shaders.extensions,
|
||||
outTypes: shaders.outTypes
|
||||
};
|
||||
|
||||
@@ -12,7 +12,9 @@ export const apply_light_color = `
|
||||
if (uBumpFrequency > 0.0 && uBumpAmplitude > 0.0) {
|
||||
vec3 bumpNormal = perturbNormal(-vViewPosition, normal, fbm(vModelPosition * uBumpFrequency), (uBumpAmplitude * bumpiness) / uBumpFrequency);
|
||||
#ifdef enabledFragDepth
|
||||
if (!any(isNaN(bumpNormal))) normal = bumpNormal;
|
||||
if (!isNaN(bumpNormal.x) && !isNaN(bumpNormal.y) && !isNaN(bumpNormal.z)) {
|
||||
normal = bumpNormal;
|
||||
}
|
||||
#else
|
||||
normal = bumpNormal;
|
||||
#endif
|
||||
|
||||
@@ -56,13 +56,13 @@ export const assign_color_varying = `
|
||||
vSubstance.rgb = mix(vec3(uMetalness, uRoughness, uBumpiness), vSubstance.rgb, vSubstance.a);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
#if defined(dRenderVariant_pickObject)
|
||||
if (uPickType == 1) {
|
||||
vColor = vec4(encodeFloatRGB(float(uObjectId)), 1.0);
|
||||
#elif defined(dRenderVariant_pickInstance)
|
||||
} else if (uPickType == 2) {
|
||||
vColor = vec4(encodeFloatRGB(aInstance), 1.0);
|
||||
#elif defined(dRenderVariant_pickGroup)
|
||||
} else {
|
||||
vColor = vec4(encodeFloatRGB(group), 1.0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef dTransparency
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const assign_marker_varying = `
|
||||
#if defined(dMarkerType_groupInstance)
|
||||
#if defined(dRenderVariant_color) || defined(dRenderVariant_marking)
|
||||
vMarker = readFromTexture(tMarker, aInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
#endif
|
||||
`;
|
||||
@@ -1,10 +1,9 @@
|
||||
export const assign_material_color = `
|
||||
#if defined(dRenderVariant_color) || defined(dRenderVariant_marking)
|
||||
#if defined(dMarkerType_uniform)
|
||||
float marker = uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
float marker = floor(vMarker * 255.0 + 0.5); // rounding required to work on some cards on win
|
||||
#endif
|
||||
float marker = uMarker;
|
||||
if (uMarker == -1.0) {
|
||||
marker = floor(vMarker * 255.0 + 0.5); // rounding required to work on some cards on win
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(dRenderVariant_color)
|
||||
@@ -37,27 +36,30 @@ export const assign_material_color = `
|
||||
#else
|
||||
vec4 material = packDepthToRGBA(gl_FragCoord.z);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_markingDepth)
|
||||
if (marker > 0.0)
|
||||
discard;
|
||||
#ifdef enabledFragDepth
|
||||
vec4 material = packDepthToRGBA(gl_FragDepthEXT);
|
||||
#else
|
||||
vec4 material = packDepthToRGBA(gl_FragCoord.z);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_markingMask)
|
||||
if (marker == 0.0)
|
||||
discard;
|
||||
float depthTest = 1.0;
|
||||
if (uMarkingDepthTest) {
|
||||
depthTest = (fragmentDepth >= getDepth(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0;
|
||||
#elif defined(dRenderVariant_marking)
|
||||
vec4 material;
|
||||
if(uMarkingType == 1) {
|
||||
if (marker > 0.0)
|
||||
discard;
|
||||
#ifdef enabledFragDepth
|
||||
material = packDepthToRGBA(gl_FragDepthEXT);
|
||||
#else
|
||||
material = packDepthToRGBA(gl_FragCoord.z);
|
||||
#endif
|
||||
} else {
|
||||
if (marker == 0.0)
|
||||
discard;
|
||||
float depthTest = 1.0;
|
||||
if (uMarkingDepthTest) {
|
||||
depthTest = (fragmentDepth >= getDepth(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0;
|
||||
}
|
||||
bool isHighlight = intMod(marker, 2.0) > 0.1;
|
||||
float viewZ = depthToViewZ(uIsOrtho, fragmentDepth, uNear, uFar);
|
||||
float fogFactor = smoothstep(uFogNear, uFogFar, abs(viewZ));
|
||||
if (fogFactor == 1.0)
|
||||
discard;
|
||||
material = vec4(0.0, depthTest, isHighlight ? 1.0 : 0.0, 1.0 - fogFactor);
|
||||
}
|
||||
bool isHighlight = intMod(marker, 2.0) > 0.1;
|
||||
float viewZ = depthToViewZ(uIsOrtho, fragmentDepth, uNear, uFar);
|
||||
float fogFactor = smoothstep(uFogNear, uFogFar, abs(viewZ));
|
||||
if (fogFactor == 1.0)
|
||||
discard;
|
||||
vec4 material = vec4(0.0, depthTest, isHighlight ? 1.0 : 0.0, 1.0 - fogFactor);
|
||||
#endif
|
||||
|
||||
// apply screendoor transparency
|
||||
|
||||
@@ -14,6 +14,11 @@ uniform float uBumpiness;
|
||||
varying vec4 vColor;
|
||||
#endif
|
||||
|
||||
#ifdef dUsePalette
|
||||
uniform sampler2D tPalette;
|
||||
varying float vPaletteV;
|
||||
#endif
|
||||
|
||||
#ifdef dOverpaint
|
||||
varying vec4 vOverpaint;
|
||||
#endif
|
||||
@@ -33,9 +38,4 @@ uniform float uBumpiness;
|
||||
varying float vGroup;
|
||||
varying float vTransparency;
|
||||
#endif
|
||||
|
||||
#ifdef dUsePalette
|
||||
uniform sampler2D tPalette;
|
||||
varying float vPaletteV;
|
||||
#endif
|
||||
`;
|
||||
@@ -21,6 +21,10 @@ uniform float uBumpiness;
|
||||
uniform sampler2D tColorGrid;
|
||||
#endif
|
||||
|
||||
#ifdef dUsePalette
|
||||
varying float vPaletteV;
|
||||
#endif
|
||||
|
||||
#ifdef dOverpaint
|
||||
#if defined(dOverpaintType_groupInstance) || defined(dOverpaintType_vertexInstance)
|
||||
varying vec4 vOverpaint;
|
||||
@@ -70,8 +74,4 @@ uniform float uBumpiness;
|
||||
uniform sampler2D tTransparencyGrid;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef dUsePalette
|
||||
varying float vPaletteV;
|
||||
#endif
|
||||
`;
|
||||
@@ -3,6 +3,9 @@ uniform int uObjectId;
|
||||
uniform int uInstanceCount;
|
||||
uniform int uGroupCount;
|
||||
|
||||
uniform int uPickType;
|
||||
uniform int uMarkingType;
|
||||
|
||||
#if dClipObjectCount != 0
|
||||
uniform int uClipObjectType[dClipObjectCount];
|
||||
uniform bool uClipObjectInvert[dClipObjectCount];
|
||||
@@ -25,9 +28,8 @@ uniform float uHighlightStrength;
|
||||
uniform float uSelectStrength;
|
||||
uniform int uMarkerPriority;
|
||||
|
||||
#if defined(dMarkerType_uniform)
|
||||
#if defined(dRenderVariant_color) || defined(dRenderVariant_marking)
|
||||
uniform float uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
#if __VERSION__ == 100
|
||||
varying float vMarker;
|
||||
#else
|
||||
@@ -52,6 +54,7 @@ uniform float uAlpha;
|
||||
uniform float uPickingAlphaThreshold;
|
||||
uniform bool uTransparentBackground;
|
||||
|
||||
uniform bool uDoubleSided;
|
||||
uniform float uInteriorDarkening;
|
||||
uniform bool uInteriorColorFlag;
|
||||
uniform vec3 uInteriorColor;
|
||||
|
||||
@@ -8,6 +8,9 @@ uniform int uInstanceCount;
|
||||
uniform int uGroupCount;
|
||||
uniform vec4 uInvariantBoundingSphere;
|
||||
|
||||
uniform bool uDoubleSided;
|
||||
uniform int uPickType;
|
||||
|
||||
#if dClipObjectCount != 0
|
||||
uniform int uClipObjectType[dClipObjectCount];
|
||||
uniform bool uClipObjectInvert[dClipObjectCount];
|
||||
@@ -26,9 +29,8 @@ uniform vec4 uInvariantBoundingSphere;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(dMarkerType_uniform)
|
||||
#if defined(dRenderVariant_color) || defined(dRenderVariant_marking)
|
||||
uniform float uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
uniform vec2 uMarkerTexDim;
|
||||
uniform sampler2D tMarker;
|
||||
#if __VERSION__ == 100
|
||||
|
||||
@@ -5,14 +5,6 @@ export const common = `
|
||||
#define dRenderVariant_color
|
||||
#endif
|
||||
|
||||
#if defined(dRenderVariant_pickObject) || defined(dRenderVariant_pickInstance) || defined(dRenderVariant_pickGroup)
|
||||
#define dRenderVariant_pick
|
||||
#endif
|
||||
|
||||
#if defined(dRenderVariant_markingDepth) || defined(dRenderVariant_markingMask)
|
||||
#define dRenderVariant_marking
|
||||
#endif
|
||||
|
||||
#if defined(dColorType_instance) || defined(dColorType_group) || defined(dColorType_groupInstance) || defined(dColorType_vertex) || defined(dColorType_vertexInstance)
|
||||
#define dColorType_texture
|
||||
#endif
|
||||
@@ -215,8 +207,8 @@ float depthToViewZ(const in float isOrtho, const in float linearClipZ, const in
|
||||
a20 * b03 - a21 * b01 + a22 * b00) / det;
|
||||
}
|
||||
|
||||
#define isNaN(x) ( (x) != (x) )
|
||||
#define isInf(x) ( (x) == (x)+1. )
|
||||
#define isNaN(x) ((x) != (x))
|
||||
#define isInf(x) ((x) == (x) + 1.0)
|
||||
#else
|
||||
#define transpose2(m) transpose(m)
|
||||
#define transpose3(m) transpose(m)
|
||||
|
||||
@@ -80,7 +80,7 @@ bool CylinderImpostor(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef dDoubleSided
|
||||
if (uDoubleSided) {
|
||||
// body inside
|
||||
h = -h;
|
||||
t = (-k1 - h) / k2;
|
||||
@@ -92,7 +92,7 @@ bool CylinderImpostor(
|
||||
}
|
||||
|
||||
// TODO: handle inside caps???
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,12 +57,9 @@ uniform float uHighlightStrength;
|
||||
uniform float uSelectStrength;
|
||||
uniform int uMarkerPriority;
|
||||
|
||||
#if defined(dMarkerType_uniform)
|
||||
uniform float uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
uniform vec2 uMarkerTexDim;
|
||||
uniform sampler2D tMarker;
|
||||
#endif
|
||||
uniform float uMarker;
|
||||
uniform vec2 uMarkerTexDim;
|
||||
uniform sampler2D tMarker;
|
||||
|
||||
uniform float uMetalness;
|
||||
uniform float uRoughness;
|
||||
@@ -82,6 +79,8 @@ uniform vec3 uInteriorColor;
|
||||
bool interior;
|
||||
|
||||
uniform bool uRenderWboit;
|
||||
uniform bool uDoubleSided;
|
||||
uniform int uPickType;
|
||||
|
||||
uniform float uNear;
|
||||
uniform float uFar;
|
||||
@@ -275,17 +274,19 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(dRenderVariant_pickObject)
|
||||
return vec4(encodeFloatRGB(float(uObjectId)), 1.0);
|
||||
#elif defined(dRenderVariant_pickInstance)
|
||||
return vec4(encodeFloatRGB(vInstance), 1.0);
|
||||
#elif defined(dRenderVariant_pickGroup)
|
||||
#ifdef dPackedGroup
|
||||
return vec4(textureGroup(floor(isoPos * uGridDim + 0.5) / uGridDim).rgb, 1.0);
|
||||
#else
|
||||
vec3 g = floor(isoPos * uGridDim + 0.5);
|
||||
return vec4(encodeFloatRGB(g.z + g.y * uGridDim.z + g.x * uGridDim.z * uGridDim.y), 1.0);
|
||||
#endif
|
||||
#if defined(dRenderVariant_pick)
|
||||
if (uPickType == 1) {
|
||||
return vec4(encodeFloatRGB(float(uObjectId)), 1.0);
|
||||
} else if (uPickType == 2) {
|
||||
return vec4(encodeFloatRGB(vInstance), 1.0);
|
||||
} else {
|
||||
#ifdef dPackedGroup
|
||||
return vec4(textureGroup(floor(isoPos * uGridDim + 0.5) / uGridDim).rgb, 1.0);
|
||||
#else
|
||||
vec3 g = floor(isoPos * uGridDim + 0.5);
|
||||
return vec4(encodeFloatRGB(g.z + g.y * uGridDim.z + g.x * uGridDim.z * uGridDim.y), 1.0);
|
||||
#endif
|
||||
}
|
||||
#elif defined(dRenderVariant_depth)
|
||||
#ifdef enabledFragDepth
|
||||
return packDepthToRGBA(gl_FragDepthEXT);
|
||||
@@ -331,13 +332,13 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
bool flipped = value > uIsoValue.y;
|
||||
#endif
|
||||
interior = value < uIsoValue.x && flipped;
|
||||
#ifndef dDoubleSided
|
||||
if (uDoubleSided) {
|
||||
if (interior) {
|
||||
prevValue = value;
|
||||
pos += step;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
vec3 vViewPosition = mvPosition.xyz;
|
||||
vec4 material = vec4(color, uAlpha);
|
||||
|
||||
@@ -371,12 +372,11 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
#include apply_light_color
|
||||
#endif
|
||||
|
||||
#if defined(dMarkerType_uniform)
|
||||
float marker = uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
float marker = uMarker;
|
||||
if (uMarker == -1.0) {
|
||||
marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win
|
||||
#endif
|
||||
}
|
||||
#include apply_interior_color
|
||||
#include apply_marker_color
|
||||
|
||||
@@ -439,18 +439,17 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
|
||||
gl_FragColor.a = material.a * uAlpha * uTransferScale;
|
||||
|
||||
#if defined(dMarkerType_uniform)
|
||||
float marker = uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
float marker = uMarker;
|
||||
if (uMarker == -1.0) {
|
||||
#ifdef dPackedGroup
|
||||
float group = decodeFloatRGB(textureGroup(floor(unitPos * uGridDim + 0.5) / uGridDim).rgb);
|
||||
#else
|
||||
vec3 g = floor(unitPos * uGridDim + 0.5);
|
||||
float group = g.z + g.y * uGridDim.z + g.x * uGridDim.z * uGridDim.y;
|
||||
#endif
|
||||
float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win
|
||||
#endif
|
||||
}
|
||||
#include apply_marker_color
|
||||
|
||||
preFogAlphaBlended = (1.0 - preFogAlphaBlended) * gl_FragColor.a + preFogAlphaBlended;
|
||||
|
||||
@@ -104,30 +104,29 @@ void main() {
|
||||
#if defined(dRenderVariant_pick)
|
||||
if (imageData.a < 0.3)
|
||||
discard;
|
||||
#if defined(dRenderVariant_pickObject)
|
||||
if (uPickType == 1) {
|
||||
gl_FragColor = vec4(encodeFloatRGB(float(uObjectId)), 1.0);
|
||||
#elif defined(dRenderVariant_pickInstance)
|
||||
} else if (uPickType == 2) {
|
||||
gl_FragColor = vec4(encodeFloatRGB(vInstance), 1.0);
|
||||
#elif defined(dRenderVariant_pickGroup)
|
||||
} else {
|
||||
gl_FragColor = vec4(texture2D(tGroupTex, vUv).rgb, 1.0);
|
||||
#endif
|
||||
}
|
||||
#elif defined(dRenderVariant_depth)
|
||||
if (imageData.a < 0.05)
|
||||
discard;
|
||||
gl_FragColor = packDepthToRGBA(gl_FragCoord.z);
|
||||
#elif defined(dRenderVariant_marking)
|
||||
#if defined(dMarkerType_uniform)
|
||||
float marker = uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
float marker = uMarker;
|
||||
if (uMarker == -1.0) {
|
||||
float group = decodeFloatRGB(texture2D(tGroupTex, vUv).rgb);
|
||||
float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win
|
||||
#endif
|
||||
#if defined(dRenderVariant_markingDepth)
|
||||
}
|
||||
if (uMarkingType == 1) {
|
||||
if (marker > 0.0 || imageData.a < 0.05)
|
||||
discard;
|
||||
gl_FragColor = packDepthToRGBA(gl_FragCoord.z);
|
||||
#elif defined(dRenderVariant_markingMask)
|
||||
} else {
|
||||
if (marker == 0.0 || imageData.a < 0.05)
|
||||
discard;
|
||||
float depthTest = 1.0;
|
||||
@@ -136,20 +135,19 @@ void main() {
|
||||
}
|
||||
bool isHighlight = intMod(marker, 2.0) > 0.1;
|
||||
gl_FragColor = vec4(0.0, depthTest, isHighlight ? 1.0 : 0.0, 1.0);
|
||||
#endif
|
||||
}
|
||||
#elif defined(dRenderVariant_color)
|
||||
if (imageData.a < 0.05)
|
||||
discard;
|
||||
gl_FragColor = imageData;
|
||||
gl_FragColor.a *= uAlpha;
|
||||
|
||||
#if defined(dMarkerType_uniform)
|
||||
float marker = uMarker;
|
||||
#elif defined(dMarkerType_groupInstance)
|
||||
float marker = uMarker;
|
||||
if (uMarker == -1.0) {
|
||||
float group = decodeFloatRGB(texture2D(tGroupTex, vUv).rgb);
|
||||
float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a;
|
||||
marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win
|
||||
#endif
|
||||
}
|
||||
|
||||
#include apply_marker_color
|
||||
#include apply_fog
|
||||
|
||||
@@ -50,9 +50,7 @@ void main() {
|
||||
vec3 normal = -faceNormal;
|
||||
#else
|
||||
vec3 normal = -normalize(vNormal);
|
||||
#ifdef dDoubleSided
|
||||
normal = normal * (float(frontFacing) * 2.0 - 1.0);
|
||||
#endif
|
||||
if (uDoubleSided) normal *= float(frontFacing) * 2.0 - 1.0;
|
||||
#endif
|
||||
#include apply_light_color
|
||||
#endif
|
||||
|
||||
@@ -46,8 +46,10 @@ void main(){
|
||||
#endif
|
||||
mat3 normalMatrix = transpose3(inverse3(mat3(modelView)));
|
||||
vec3 transformedNormal = normalize(normalMatrix * normalize(normal));
|
||||
#if defined(dFlipSided) && !defined(dDoubleSided) // TODO checking dDoubleSided should not be required, ASR
|
||||
transformedNormal = -transformedNormal;
|
||||
#if defined(dFlipSided)
|
||||
if (!uDoubleSided) { // TODO checking uDoubleSided should not be required, ASR
|
||||
transformedNormal = -transformedNormal;
|
||||
}
|
||||
#endif
|
||||
vNormal = transformedNormal;
|
||||
}
|
||||
|
||||
@@ -66,10 +66,9 @@ void main(void){
|
||||
#include clip_pixel
|
||||
|
||||
bool flag = Impostor(cameraPos, cameraNormal);
|
||||
#ifndef dDoubleSided
|
||||
if (interior)
|
||||
discard;
|
||||
#endif
|
||||
if (!uDoubleSided) {
|
||||
if (interior) discard;
|
||||
}
|
||||
|
||||
vec3 vViewPosition = cameraPos;
|
||||
gl_FragDepthEXT = calcDepth(vViewPosition);
|
||||
|
||||
@@ -49,13 +49,15 @@ export interface RenderItem<T extends string> {
|
||||
|
||||
//
|
||||
|
||||
const GraphicsRenderVariant = { 'colorBlended': '', 'colorWboit': '', 'pickObject': '', 'pickInstance': '', 'pickGroup': '', 'depth': '', 'markingDepth': '', 'markingMask': '' };
|
||||
const GraphicsRenderVariant = { colorBlended: '', colorWboit: '', pick: '', depth: '', marking: '' };
|
||||
export type GraphicsRenderVariant = keyof typeof GraphicsRenderVariant
|
||||
const GraphicsRenderVariants = Object.keys(GraphicsRenderVariant) as GraphicsRenderVariant[];
|
||||
export const GraphicsRenderVariants = Object.keys(GraphicsRenderVariant) as GraphicsRenderVariant[];
|
||||
export const GraphicsRenderVariantsBlended = GraphicsRenderVariants.filter(v => v !== 'colorWboit');
|
||||
export const GraphicsRenderVariantsWboit = GraphicsRenderVariants.filter(v => v !== 'colorBlended');
|
||||
|
||||
const ComputeRenderVariant = { 'compute': '' };
|
||||
const ComputeRenderVariant = { compute: '' };
|
||||
export type ComputeRenderVariant = keyof typeof ComputeRenderVariant
|
||||
const ComputeRenderVariants = Object.keys(ComputeRenderVariant) as ComputeRenderVariant[];
|
||||
export const ComputeRenderVariants = Object.keys(ComputeRenderVariant) as ComputeRenderVariant[];
|
||||
|
||||
function createProgramVariant(ctx: WebGLContext, variant: string, defineValues: DefineValues, shaderCode: ShaderCode, schema: RenderableSchema) {
|
||||
defineValues = { ...defineValues, dRenderVariant: ValueCell.create(variant) };
|
||||
@@ -90,8 +92,8 @@ function resetValueChanges(valueChanges: ValueChanges) {
|
||||
//
|
||||
|
||||
export type GraphicsRenderItem = RenderItem<GraphicsRenderVariant>
|
||||
export function createGraphicsRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId: number) {
|
||||
return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, GraphicsRenderVariants);
|
||||
export function createGraphicsRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId: number, variants: GraphicsRenderVariant[]) {
|
||||
return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, variants);
|
||||
}
|
||||
|
||||
export type ComputeRenderItem = RenderItem<ComputeRenderVariant>
|
||||
|
||||
@@ -105,7 +105,12 @@ export function createResources(gl: GLRenderingContext, state: WebGLState, stats
|
||||
const programCache = createReferenceCache(
|
||||
(props: ProgramProps) => {
|
||||
const array = [props.shaderCode.id];
|
||||
Object.keys(props.defineValues).forEach(k => array.push(hashString(k), defineValueHash(props.defineValues[k].ref.value)));
|
||||
const variant = (props.defineValues.dRenderVariant?.ref.value || '') as string;
|
||||
Object.keys(props.defineValues).forEach(k => {
|
||||
if (!props.shaderCode.ignoreDefine?.(k, variant, props.defineValues)) {
|
||||
array.push(hashString(k), defineValueHash(props.defineValues[k].ref.value));
|
||||
}
|
||||
});
|
||||
return hashFnv32a(array).toString();
|
||||
},
|
||||
(props: ProgramProps) => wrap('program', createProgram(gl, state, extensions, getShader, props)),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
@@ -346,6 +346,25 @@ namespace Quat {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)
|
||||
*/
|
||||
export function exactEquals(a: Quat, b: Quat) {
|
||||
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the quaternions have approximately the same elements in the same position.
|
||||
*/
|
||||
export function equals(a: Quat, b: Quat) {
|
||||
const a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
|
||||
const b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
|
||||
return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
|
||||
Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
|
||||
Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
|
||||
Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)));
|
||||
}
|
||||
|
||||
export function add(out: Quat, a: Quat, b: Quat) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { VisualQualityOptions } from '../../../mol-geo/geometry/base';
|
||||
@@ -32,6 +33,7 @@ import { setStructureTransparency } from '../../helpers/structure-transparency';
|
||||
import { StructureFocusRepresentation } from '../../../mol-plugin/behavior/dynamic/selection/structure-focus-representation';
|
||||
import { setStructureSubstance } from '../../helpers/structure-substance';
|
||||
import { Material } from '../../../mol-util/material';
|
||||
import { Clip } from '../../../mol-util/clip';
|
||||
|
||||
export { StructureComponentManager };
|
||||
|
||||
@@ -70,23 +72,25 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
|
||||
await this.plugin.state.updateBehavior(StructureFocusRepresentation, p => {
|
||||
p.ignoreHydrogens = !options.showHydrogens;
|
||||
p.material = options.materialStyle;
|
||||
p.clip = options.clipObjects;
|
||||
});
|
||||
if (interactionChanged) await this.updateInterationProps();
|
||||
});
|
||||
}
|
||||
|
||||
private updateReprParams(update: StateBuilder.Root, component: StructureComponentRef) {
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material } = this.state.options;
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const ignoreHydrogens = !showHydrogens;
|
||||
for (const r of component.representations) {
|
||||
if (r.cell.transform.transformer !== StructureRepresentation3D) continue;
|
||||
|
||||
const params = r.cell.transform.params as StateTransformer.Params<StructureRepresentation3D>;
|
||||
if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || params.type.params.quality !== quality || !shallowEqual(params.type.params.material, material)) {
|
||||
if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || params.type.params.quality !== quality || !shallowEqual(params.type.params.material, material) || !PD.areEqual(Clip.Params, params.type.params.clip, clip)) {
|
||||
update.to(r.cell).update(old => {
|
||||
old.type.params.ignoreHydrogens = ignoreHydrogens;
|
||||
old.type.params.quality = quality;
|
||||
old.type.params.material = material;
|
||||
old.type.params.clip = clip;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -305,9 +309,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
|
||||
addRepresentation(components: ReadonlyArray<StructureComponentRef>, type: string) {
|
||||
if (components.length === 0) return;
|
||||
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material } = this.state.options;
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const ignoreHydrogens = !showHydrogens;
|
||||
const typeParams = { ignoreHydrogens, quality, material };
|
||||
const typeParams = { ignoreHydrogens, quality, material, clip };
|
||||
|
||||
return this.plugin.dataTransaction(async () => {
|
||||
for (const component of components) {
|
||||
@@ -342,9 +346,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
|
||||
const xs = structures || this.currentStructures;
|
||||
if (xs.length === 0) return;
|
||||
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material } = this.state.options;
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const ignoreHydrogens = !showHydrogens;
|
||||
const typeParams = { ignoreHydrogens, quality, material };
|
||||
const typeParams = { ignoreHydrogens, quality, material, clip };
|
||||
|
||||
const componentKey = UUID.create22();
|
||||
for (const s of xs) {
|
||||
@@ -455,6 +459,7 @@ namespace StructureComponentManager {
|
||||
showHydrogens: PD.Boolean(true, { description: 'Toggle display of hydrogen atoms in representations' }),
|
||||
visualQuality: PD.Select('auto', VisualQualityOptions, { description: 'Control the visual/rendering quality of representations' }),
|
||||
materialStyle: Material.getParam(),
|
||||
clipObjects: PD.Group(Clip.Params),
|
||||
interactions: PD.Group(InteractionsProvider.defaultParams, { label: 'Non-covalent Interactions' }),
|
||||
};
|
||||
export type Options = PD.Values<typeof OptionsParams>
|
||||
|
||||
@@ -62,7 +62,6 @@ const SimpleSettingsParams = {
|
||||
}, { isFlat: true }),
|
||||
clipping: PD.Group<any>({
|
||||
...Canvas3DParams.cameraClipping.params,
|
||||
...(Canvas3DParams.renderer.params.clip as any).params as any
|
||||
}, { pivot: 'radius' }),
|
||||
layout: PD.MultiSelect([] as LayoutOptions[], PD.objectToOptions(LayoutOptions)),
|
||||
};
|
||||
@@ -110,7 +109,6 @@ const SimpleSettingsMapping = ParamMapping({
|
||||
},
|
||||
clipping: {
|
||||
...canvas.cameraClipping,
|
||||
...canvas.renderer.clip
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -128,10 +126,6 @@ const SimpleSettingsMapping = ParamMapping({
|
||||
radius: s.clipping.radius,
|
||||
far: s.clipping.far,
|
||||
};
|
||||
canvas.renderer.clip = {
|
||||
variant: s.clipping.variant,
|
||||
objects: s.clipping.objects,
|
||||
};
|
||||
|
||||
props.layout = s.layout;
|
||||
},
|
||||
|
||||
@@ -19,6 +19,7 @@ import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
|
||||
import { PluginCommands } from '../../../commands';
|
||||
import { PluginContext } from '../../../context';
|
||||
import { Material } from '../../../../mol-util/material';
|
||||
import { Clip } from '../../../../mol-util/clip';
|
||||
|
||||
const StructureFocusRepresentationParams = (plugin: PluginContext) => {
|
||||
const reprParams = StateTransforms.Representation.StructureRepresentation3D.definition.params!(void 0, plugin) as PD.Params;
|
||||
@@ -44,6 +45,7 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => {
|
||||
excludeTargetFromSurroundings: PD.Boolean(false, { label: 'Exclude Target', description: 'Exclude the focus "target" from the surroudings component.' }),
|
||||
ignoreHydrogens: PD.Boolean(false),
|
||||
material: Material.getParam(),
|
||||
clip: PD.Group(Clip.Params),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -69,7 +71,7 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber
|
||||
...this.params.targetParams,
|
||||
type: {
|
||||
name: reprParams.type.name,
|
||||
params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens, material: this.params.material }
|
||||
params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens, material: this.params.material, clip: this.params.clip }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ export const DefaultPluginSpec = (): PluginSpec => ({
|
||||
PluginSpec.Action(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D),
|
||||
PluginSpec.Action(StateTransforms.Representation.OverpaintStructureRepresentation3DFromScript),
|
||||
PluginSpec.Action(StateTransforms.Representation.TransparencyStructureRepresentation3DFromScript),
|
||||
PluginSpec.Action(StateTransforms.Representation.ClippingStructureRepresentation3DFromScript),
|
||||
PluginSpec.Action(StateTransforms.Representation.SubstanceStructureRepresentation3DFromScript),
|
||||
|
||||
PluginSpec.Action(AssignColorVolume),
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Visual {
|
||||
export function mark(renderObject: GraphicsRenderObject | undefined, loci: Loci, action: MarkerAction, lociApply: LociApply, previous?: PreviousMark) {
|
||||
if (!renderObject || isEmptyLoci(loci)) return false;
|
||||
|
||||
const { tMarker, dMarkerType, uMarker, markerAverage, markerStatus, uGroupCount, instanceCount } = renderObject.values;
|
||||
const { tMarker, uMarker, markerAverage, markerStatus, uGroupCount, instanceCount } = renderObject.values;
|
||||
const count = uGroupCount.ref.value * instanceCount.ref.value;
|
||||
const { array } = tMarker.ref.value;
|
||||
const currentStatus = markerStatus.ref.value as MarkerInfo['status'];
|
||||
@@ -135,7 +135,6 @@ namespace Visual {
|
||||
}
|
||||
ValueCell.updateIfChanged(uMarker, status);
|
||||
if (status === -1) ValueCell.update(tMarker, tMarker.ref.value);
|
||||
ValueCell.updateIfChanged(dMarkerType, status === -1 ? 'groupInstance' : 'uniform');
|
||||
ValueCell.updateIfChanged(markerAverage, average);
|
||||
ValueCell.updateIfChanged(markerStatus, status);
|
||||
}
|
||||
@@ -158,7 +157,7 @@ namespace Visual {
|
||||
export function setOverpaint(renderObject: GraphicsRenderObject | undefined, overpaint: Overpaint, lociApply: LociApply, clear: boolean, smoothing?: SmoothingContext) {
|
||||
if (!renderObject) return;
|
||||
|
||||
const { tOverpaint, dOverpaintType, uGroupCount, instanceCount } = renderObject.values;
|
||||
const { tOverpaint, dOverpaintType, dOverpaint, uGroupCount, instanceCount } = renderObject.values;
|
||||
const count = uGroupCount.ref.value * instanceCount.ref.value;
|
||||
|
||||
// ensure texture has right size
|
||||
@@ -181,6 +180,7 @@ namespace Visual {
|
||||
}
|
||||
ValueCell.update(tOverpaint, tOverpaint.ref.value);
|
||||
ValueCell.updateIfChanged(dOverpaintType, 'groupInstance');
|
||||
ValueCell.updateIfChanged(dOverpaint, overpaint.layers.length > 0);
|
||||
|
||||
if (overpaint.layers.length === 0) return;
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Visual {
|
||||
export function setTransparency(renderObject: GraphicsRenderObject | undefined, transparency: Transparency, lociApply: LociApply, clear: boolean, smoothing?: SmoothingContext) {
|
||||
if (!renderObject) return;
|
||||
|
||||
const { tTransparency, dTransparencyType, transparencyAverage, uGroupCount, instanceCount } = renderObject.values;
|
||||
const { tTransparency, dTransparencyType, transparencyAverage, dTransparency, uGroupCount, instanceCount } = renderObject.values;
|
||||
const count = uGroupCount.ref.value * instanceCount.ref.value;
|
||||
|
||||
// ensure texture has right size and variant
|
||||
@@ -229,6 +229,7 @@ namespace Visual {
|
||||
ValueCell.update(tTransparency, tTransparency.ref.value);
|
||||
ValueCell.updateIfChanged(transparencyAverage, getTransparencyAverage(array, count));
|
||||
ValueCell.updateIfChanged(dTransparencyType, 'groupInstance');
|
||||
ValueCell.updateIfChanged(dTransparency, transparency.layers.length > 0);
|
||||
|
||||
if (transparency.layers.length === 0) return;
|
||||
|
||||
@@ -255,7 +256,7 @@ namespace Visual {
|
||||
export function setSubstance(renderObject: GraphicsRenderObject | undefined, substance: Substance, lociApply: LociApply, clear: boolean, smoothing?: SmoothingContext) {
|
||||
if (!renderObject) return;
|
||||
|
||||
const { tSubstance, dSubstanceType, uGroupCount, instanceCount } = renderObject.values;
|
||||
const { tSubstance, dSubstanceType, dSubstance, uGroupCount, instanceCount } = renderObject.values;
|
||||
const count = uGroupCount.ref.value * instanceCount.ref.value;
|
||||
|
||||
// ensure texture has right size
|
||||
@@ -278,6 +279,7 @@ namespace Visual {
|
||||
}
|
||||
ValueCell.update(tSubstance, tSubstance.ref.value);
|
||||
ValueCell.updateIfChanged(dSubstanceType, 'groupInstance');
|
||||
ValueCell.updateIfChanged(dSubstance, substance.layers.length > 0);
|
||||
|
||||
if (substance.layers.length === 0) return;
|
||||
|
||||
@@ -304,11 +306,12 @@ namespace Visual {
|
||||
export function setClipping(renderObject: GraphicsRenderObject | undefined, clipping: Clipping, lociApply: LociApply, clear: boolean) {
|
||||
if (!renderObject) return;
|
||||
|
||||
const { tClipping, uGroupCount, instanceCount } = renderObject.values;
|
||||
const { tClipping, dClipping, uGroupCount, instanceCount } = renderObject.values;
|
||||
const count = uGroupCount.ref.value * instanceCount.ref.value;
|
||||
const { layers } = clipping;
|
||||
|
||||
// ensure texture has right size
|
||||
createClipping(clipping.layers.length ? count : 0, renderObject.values);
|
||||
createClipping(layers.length ? count : 0, renderObject.values);
|
||||
const { array } = tClipping.ref.value;
|
||||
|
||||
// clear if requested
|
||||
@@ -324,6 +327,7 @@ namespace Visual {
|
||||
lociApply(loci, apply, false);
|
||||
}
|
||||
ValueCell.update(tClipping, tClipping.ref.value);
|
||||
ValueCell.updateIfChanged(dClipping, clipping.layers.length > 0);
|
||||
}
|
||||
|
||||
export function setTransform(renderObject: GraphicsRenderObject | undefined, transform?: Mat4, instanceTransforms?: Float32Array | null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -11,9 +11,11 @@ import { BitFlags } from '../mol-util/bit-flags';
|
||||
|
||||
export { Clipping };
|
||||
|
||||
type Clipping = { readonly layers: ReadonlyArray<Clipping.Layer> }
|
||||
type Clipping = {
|
||||
readonly layers: ReadonlyArray<Clipping.Layer>
|
||||
}
|
||||
|
||||
function Clipping(layers: ReadonlyArray<Clipping.Layer>): Clipping {
|
||||
function Clipping(layers: Clipping['layers']): Clipping {
|
||||
return { layers };
|
||||
}
|
||||
|
||||
@@ -83,20 +85,7 @@ namespace Clipping {
|
||||
}
|
||||
}
|
||||
|
||||
/** Clip object types */
|
||||
export const Type = {
|
||||
none: 0, // to switch clipping off
|
||||
plane: 1,
|
||||
sphere: 2,
|
||||
cube: 3,
|
||||
cylinder: 4,
|
||||
infiniteCone: 5,
|
||||
};
|
||||
|
||||
export type Variant = 'instance' | 'pixel'
|
||||
|
||||
export function areEqual(cA: Clipping, cB: Clipping) {
|
||||
if (cA.layers.length === 0 && cB.layers.length === 0) return true;
|
||||
if (cA.layers.length !== cB.layers.length) return false;
|
||||
for (let i = 0, il = cA.layers.length; i < il; ++i) {
|
||||
if (cA.layers[i].groups !== cB.layers[i].groups) return false;
|
||||
@@ -105,11 +94,13 @@ namespace Clipping {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Check if layers empty */
|
||||
export function isEmpty(clipping: Clipping) {
|
||||
return clipping.layers.length === 0;
|
||||
}
|
||||
|
||||
export function remap(clipping: Clipping, structure: Structure) {
|
||||
/** Remap layers */
|
||||
export function remap(clipping: Clipping, structure: Structure): Clipping {
|
||||
const layers: Clipping.Layer[] = [];
|
||||
for (const layer of clipping.layers) {
|
||||
let { loci, groups } = layer;
|
||||
@@ -121,6 +112,7 @@ namespace Clipping {
|
||||
return { layers };
|
||||
}
|
||||
|
||||
/** Merge layers */
|
||||
export function merge(clipping: Clipping): Clipping {
|
||||
if (isEmpty(clipping)) return clipping;
|
||||
const { structure } = clipping.layers[0].loci;
|
||||
@@ -144,6 +136,7 @@ namespace Clipping {
|
||||
return { layers };
|
||||
}
|
||||
|
||||
/** Filter layers */
|
||||
export function filter(clipping: Clipping, filter: Structure): Clipping {
|
||||
if (isEmpty(clipping)) return clipping;
|
||||
const { structure } = clipping.layers[0].loci;
|
||||
|
||||
114
src/mol-util/clip.ts
Normal file
114
src/mol-util/clip.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { Quat, Vec3 } from '../mol-math/linear-algebra';
|
||||
import { degToRad } from '../mol-math/misc';
|
||||
import { ParamDefinition as PD } from './param-definition';
|
||||
import { stringToWords } from './string';
|
||||
|
||||
export interface Clip {
|
||||
variant: Clip.Variant,
|
||||
objects: Clip.Objects
|
||||
}
|
||||
|
||||
export function Clip() {
|
||||
|
||||
}
|
||||
|
||||
export namespace Clip {
|
||||
/** Clip object types */
|
||||
export const Type = {
|
||||
none: 0, // to switch clipping off
|
||||
plane: 1,
|
||||
sphere: 2,
|
||||
cube: 3,
|
||||
cylinder: 4,
|
||||
infiniteCone: 5,
|
||||
};
|
||||
|
||||
export type Variant = 'instance' | 'pixel'
|
||||
|
||||
export type Objects = {
|
||||
count: number
|
||||
type: number[]
|
||||
invert: boolean[]
|
||||
position: number[]
|
||||
rotation: number[]
|
||||
scale: number[]
|
||||
}
|
||||
|
||||
export const Params = {
|
||||
variant: PD.Select('pixel', PD.arrayToOptions<Variant>(['instance', 'pixel'])),
|
||||
objects: PD.ObjectList({
|
||||
type: PD.Select('plane', PD.objectToOptions(Type, t => stringToWords(t))),
|
||||
invert: PD.Boolean(false),
|
||||
position: PD.Vec3(Vec3()),
|
||||
rotation: PD.Group({
|
||||
axis: PD.Vec3(Vec3.create(1, 0, 0)),
|
||||
angle: PD.Numeric(0, { min: -180, max: 180, step: 1 }, { description: 'Angle in Degrees' }),
|
||||
}, { isExpanded: true }),
|
||||
scale: PD.Vec3(Vec3.create(1, 1, 1)),
|
||||
}, o => stringToWords(o.type))
|
||||
};
|
||||
export type Params = typeof Params
|
||||
export type Props = PD.Values<Params>
|
||||
|
||||
function createClipObjects() {
|
||||
return {
|
||||
count: 0,
|
||||
type: (new Array(5)).fill(1),
|
||||
invert: (new Array(5)).fill(false),
|
||||
position: (new Array(5 * 3)).fill(0),
|
||||
rotation: (new Array(5 * 4)).fill(0),
|
||||
scale: (new Array(5 * 3)).fill(1),
|
||||
};
|
||||
}
|
||||
|
||||
const qA = Quat();
|
||||
const qB = Quat();
|
||||
const vA = Vec3();
|
||||
const vB = Vec3();
|
||||
|
||||
export function getClip(props: Props, clip?: Clip): Clip {
|
||||
const { type, invert, position, rotation, scale } = clip?.objects || createClipObjects();
|
||||
for (let i = 0, il = props.objects.length; i < il; ++i) {
|
||||
const p = props.objects[i];
|
||||
type[i] = Type[p.type];
|
||||
invert[i] = p.invert;
|
||||
Vec3.toArray(p.position, position, i * 3);
|
||||
Quat.toArray(Quat.setAxisAngle(qA, p.rotation.axis, degToRad(p.rotation.angle)), rotation, i * 4);
|
||||
Vec3.toArray(p.scale, scale, i * 3);
|
||||
}
|
||||
return {
|
||||
variant: props.variant,
|
||||
objects: { count: props.objects.length, type, invert, position, rotation, scale }
|
||||
};
|
||||
}
|
||||
|
||||
export function areEqual(cA: Clip, cB: Clip) {
|
||||
if (cA.variant !== cB.variant) return false;
|
||||
if (cA.objects.count !== cB.objects.count) return false;
|
||||
|
||||
const oA = cA.objects, oB = cB.objects;
|
||||
for (let i = 0, il = oA.count; i < il; ++i) {
|
||||
if (oA.invert[i] !== oB.invert[i]) return false;
|
||||
if (oA.type[i] !== oB.type[i]) return false;
|
||||
|
||||
Vec3.fromArray(vA, oA.position, i * 3);
|
||||
Vec3.fromArray(vB, oB.position, i * 3);
|
||||
if (!Vec3.equals(vA, vB)) return false;
|
||||
|
||||
Vec3.fromArray(vA, oA.scale, i * 3);
|
||||
Vec3.fromArray(vB, oB.scale, i * 3);
|
||||
if (!Vec3.equals(vA, vB)) return false;
|
||||
|
||||
Quat.fromArray(qA, oA.rotation, i * 4);
|
||||
Quat.fromArray(qB, oB.rotation, i * 4);
|
||||
if (!Quat.equals(qA, qB)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user