diff --git a/src/mol-canvas3d/helper/bounding-sphere-helper.ts b/src/mol-canvas3d/helper/bounding-sphere-helper.ts index 9ac4938e9e08261c004bf059b02306a335427314..c3272d840f4a26240a0ef4ae42cc8ba8821ddd75 100644 --- a/src/mol-canvas3d/helper/bounding-sphere-helper.ts +++ b/src/mol-canvas3d/helper/bounding-sphere-helper.ts @@ -138,5 +138,5 @@ function createBoundingSphereMesh(boundingSphere: Sphere3D, mesh?: Mesh) { function createBoundingSphereRenderObject(mesh: Mesh, color: Color, transform?: TransformData) { const values = Mesh.Utils.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false }, color, 1, transform) - return createRenderObject('mesh', values, { visible: true, pickable: false, opaque: false }) + return createRenderObject('mesh', values, { visible: true, alphaFactor: 1, pickable: false, opaque: false }) } \ No newline at end of file diff --git a/src/mol-geo/geometry/base.ts b/src/mol-geo/geometry/base.ts index 2729048b8d9230efa2deb8bd9e453152132b228f..eabbbc2454694f7f9e6696f68401f1d23f3ad782 100644 --- a/src/mol-geo/geometry/base.ts +++ b/src/mol-geo/geometry/base.ts @@ -60,6 +60,7 @@ export namespace BaseGeometry { export function createValues(props: PD.Values<Params>, counts: Counts) { return { + alpha: ValueCell.create(props.alpha), uAlpha: ValueCell.create(props.alpha), uHighlightColor: ValueCell.create(Color.toArrayNormalized(props.highlightColor, Vec3.zero(), 0)), uSelectColor: ValueCell.create(Color.toArrayNormalized(props.selectColor, Vec3.zero(), 0)), @@ -76,19 +77,20 @@ export namespace BaseGeometry { if (Color.fromNormalizedArray(values.uSelectColor.ref.value, 0) !== props.selectColor) { ValueCell.update(values.uSelectColor, Color.toArrayNormalized(props.selectColor, values.uSelectColor.ref.value, 0)) } - ValueCell.updateIfChanged(values.uAlpha, props.alpha) + ValueCell.updateIfChanged(values.alpha, props.alpha) // `uAlpha` is set in renderable.render ValueCell.updateIfChanged(values.dUseFog, props.useFog) } export function createRenderableState(props: Partial<PD.Values<Params>> = {}): RenderableState { return { visible: true, + alphaFactor: 1, pickable: true, opaque: props.alpha === undefined ? true : props.alpha === 1 } } export function updateRenderableState(state: RenderableState, props: PD.Values<Params>) { - state.opaque = props.alpha === 1 + state.opaque = props.alpha * state.alphaFactor >= 1 } } \ No newline at end of file diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts index 5803a9a1846c2f86363deb1f713c081821242339..314d75f0bd3dc31c67d860fd296c56e969a8c4b1 100644 --- a/src/mol-gl/_spec/renderer.spec.ts +++ b/src/mol-gl/_spec/renderer.spec.ts @@ -80,6 +80,7 @@ function createPoints() { uInstanceCount: ValueCell.create(1), uGroupCount: ValueCell.create(3), + alpha: ValueCell.create(1.0), drawCount: ValueCell.create(3), instanceCount: ValueCell.create(1), matrix: ValueCell.create(m4), @@ -96,6 +97,7 @@ function createPoints() { } const state: RenderableState = { visible: true, + alphaFactor: 1, pickable: true, opaque: true } diff --git a/src/mol-gl/renderable.ts b/src/mol-gl/renderable.ts index f61ca5f5bdadf2ff118757df8cb22bdca3ffedfa..34f0eee4159c8750f94c7eabc9669119e7b4a6b8 100644 --- a/src/mol-gl/renderable.ts +++ b/src/mol-gl/renderable.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ @@ -9,11 +9,13 @@ import { RenderableValues, Values, RenderableSchema } from './renderable/schema' import { RenderVariant, RenderItem } from './webgl/render-item'; import { ValueCell } from 'mol-util'; import { idFactory } from 'mol-util/id-factory'; +import { clamp } from 'mol-math/interpolate'; const getNextRenderableId = idFactory() export type RenderableState = { visible: boolean + alphaFactor: number pickable: boolean opaque: boolean } @@ -36,6 +38,9 @@ export function createRenderable<T extends Values<RenderableSchema>>(renderItem: state, render: (variant: RenderVariant) => { + if (values.uAlpha && values.alpha) { + ValueCell.updateIfChanged(values.uAlpha, clamp(values.alpha.ref.value * state.alphaFactor, 0, 1)) + } if (values.uPickable) { ValueCell.updateIfChanged(values.uPickable, state.pickable ? 1 : 0) } diff --git a/src/mol-gl/renderable/direct-volume.ts b/src/mol-gl/renderable/direct-volume.ts index 3a2ca5fbd32ecad7ae529eb2b1814c4858420ab8..eb94c44996943bdd529c67c93898f25375b9009c 100644 --- a/src/mol-gl/renderable/direct-volume.ts +++ b/src/mol-gl/renderable/direct-volume.ts @@ -33,6 +33,8 @@ export const DirectVolumeSchema = { drawCount: ValueSpec('number'), instanceCount: ValueSpec('number'), + alpha: ValueSpec('number'), + matrix: ValueSpec('m4'), transform: ValueSpec('float32'), extraTransform: ValueSpec('float32'), diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index 4a0fce48c914b64e57884188c71006c2ad18191a..28e36306fe14d52b691e0da71cbc5781e3702da1 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -228,6 +228,9 @@ export const BaseSchema = { */ aTransform: AttributeSpec('float32', 16, 1), + /** + * final alpha, calculated as `values.alpha * state.alpha` + */ uAlpha: UniformSpec('f'), uInstanceCount: UniformSpec('i'), uGroupCount: UniformSpec('i'), @@ -238,6 +241,9 @@ export const BaseSchema = { drawCount: ValueSpec('number'), instanceCount: ValueSpec('number'), + /** base alpha, see uAlpha */ + alpha: ValueSpec('number'), + /** global transform, see aTransform */ matrix: ValueSpec('m4'), /** base per-instance transform, see aTransform */ diff --git a/src/mol-math/geometry/gaussian-density/gpu.ts b/src/mol-math/geometry/gaussian-density/gpu.ts index 17dfac6f8a379d6729d6a251b46eec0982bdef34..2f91bcd1af1f8228fc22c7979abb0a1493b63a13 100644 --- a/src/mol-math/geometry/gaussian-density/gpu.ts +++ b/src/mol-math/geometry/gaussian-density/gpu.ts @@ -232,6 +232,7 @@ function getGaussianDensityRenderObject(webgl: WebGLContext, drawCount: number, } const state: RenderableState = { visible: true, + alphaFactor: 1, pickable: false, opaque: true } diff --git a/src/mol-repr/representation.ts b/src/mol-repr/representation.ts index 6bd5457b1bbc1831cf68c8c237c1b7dd337f0624..3dbdc3f7656d8a8481ea08b29a7582d2afbf76ea 100644 --- a/src/mol-repr/representation.ts +++ b/src/mol-repr/representation.ts @@ -141,6 +141,8 @@ namespace Representation { export interface State { /** Controls if the representation's renderobjects are rendered or not */ visible: boolean + /** A factor applied to alpha value of the representation's renderobjects */ + alphaFactor: number /** Controls if the representation's renderobjects are pickable or not */ pickable: boolean /** Controls if the representation's renderobjects are synced automatically with GPU or not */ @@ -149,10 +151,11 @@ namespace Representation { transform: Mat4 } export function createState(): State { - return { visible: false, pickable: false, syncManually: false, transform: Mat4.identity(), /* instanceTransforms: new Float32Array(Mat4.identity()) */ } + return { visible: false, alphaFactor: 0, pickable: false, syncManually: false, transform: Mat4.identity() } } export function updateState(state: State, update: Partial<State>) { if (update.visible !== undefined) state.visible = update.visible + if (update.alphaFactor !== undefined) state.alphaFactor = update.alphaFactor if (update.pickable !== undefined) state.pickable = update.pickable if (update.syncManually !== undefined) state.syncManually = update.syncManually if (update.transform !== undefined) Mat4.copy(state.transform, update.transform) @@ -318,6 +321,7 @@ namespace Representation { }, setState: (state: Partial<State>) => { if (state.visible !== undefined) Visual.setVisibility(renderObject, state.visible) + if (state.alphaFactor !== undefined) Visual.setAlphaFactor(renderObject, state.alphaFactor) if (state.pickable !== undefined) Visual.setPickable(renderObject, state.pickable) if (state.transform !== undefined) Visual.setTransform(renderObject, state.transform) diff --git a/src/mol-repr/shape/representation.ts b/src/mol-repr/shape/representation.ts index aa125cfab9e327489d907f93586317d2490b6028..a22a0e5051c2897c9c3d2a348deeb3f77e961cdf 100644 --- a/src/mol-repr/shape/representation.ts +++ b/src/mol-repr/shape/representation.ts @@ -193,6 +193,7 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa setState(state: Partial<Representation.State>) { if (_renderObject) { if (state.visible !== undefined) Visual.setVisibility(_renderObject, state.visible) + if (state.alphaFactor !== undefined) Visual.setAlphaFactor(_renderObject, state.alphaFactor) if (state.pickable !== undefined) Visual.setPickable(_renderObject, state.pickable) if (state.transform !== undefined) Visual.setTransform(_renderObject, state.transform) } diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts index 456361a7b2a8aa3c08b09cb308d11da993260b8c..eae9e3c26b47e479af0d082bc4968ba03e1fe278 100644 --- a/src/mol-repr/structure/complex-visual.ts +++ b/src/mol-repr/structure/complex-visual.ts @@ -199,6 +199,9 @@ export function ComplexVisual<G extends Geometry, P extends ComplexParams & Geom setVisibility(visible: boolean) { Visual.setVisibility(renderObject, visible) }, + setAlphaFactor(alphaFactor: number) { + Visual.setAlphaFactor(renderObject, alphaFactor) + }, setPickable(pickable: boolean) { Visual.setPickable(renderObject, pickable) }, diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts index 439bf2c60fcae5bc7f078f5636c1a45f3026a233..c21157b2ab36cd433b113be9009d8a116277c1c8 100644 --- a/src/mol-repr/structure/units-visual.ts +++ b/src/mol-repr/structure/units-visual.ts @@ -245,6 +245,9 @@ export function UnitsVisual<G extends Geometry, P extends UnitsParams & Geometry setVisibility(visible: boolean) { Visual.setVisibility(renderObject, visible) }, + setAlphaFactor(alphaFactor: number) { + Visual.setAlphaFactor(renderObject, alphaFactor) + }, setPickable(pickable: boolean) { Visual.setPickable(renderObject, pickable) }, diff --git a/src/mol-repr/visual.ts b/src/mol-repr/visual.ts index bfb82dbec4aad8936483f5c0ecfc024b85099d9c..5bfef7954e8e0e1c88c28873b8186e4280d76465 100644 --- a/src/mol-repr/visual.ts +++ b/src/mol-repr/visual.ts @@ -33,6 +33,7 @@ interface Visual<D, P extends PD.Params> { getLoci: (pickingId: PickingId) => Loci mark: (loci: Loci, action: MarkerAction) => boolean setVisibility: (visible: boolean) => void + setAlphaFactor: (alphaFactor: number) => void setPickable: (pickable: boolean) => void setTransform: (matrix?: Mat4, instanceMatrices?: Float32Array | null) => void setOverpaint: (layers: Overpaint.Layers) => void @@ -43,6 +44,10 @@ namespace Visual { if (renderObject) renderObject.state.visible = visible } + export function setAlphaFactor(renderObject: GraphicsRenderObject | undefined, alphaFactor: number) { + if (renderObject) renderObject.state.alphaFactor = alphaFactor + } + export function setPickable(renderObject: GraphicsRenderObject | undefined, pickable: boolean) { if (renderObject) renderObject.state.pickable = pickable } diff --git a/src/mol-repr/volume/representation.ts b/src/mol-repr/volume/representation.ts index c83d92defbb00389914668e86f2ab441a4e825c1..926f70f2ed5b28455b7f6be9eea4876cf701942b 100644 --- a/src/mol-repr/volume/representation.ts +++ b/src/mol-repr/volume/representation.ts @@ -185,6 +185,9 @@ export function VolumeVisual<G extends Geometry, P extends VolumeParams & Geomet setVisibility(visible: boolean) { Visual.setVisibility(renderObject, visible) }, + setAlphaFactor(alphaFactor: number) { + Visual.setAlphaFactor(renderObject, alphaFactor) + }, setPickable(pickable: boolean) { Visual.setPickable(renderObject, pickable) },